Andreas L Delmelle wrote:

Hi all,

Hello everyone ;-)

I've been doing some thinking myself about the separation between element-list creation and actual line-breaking, and went wandering through the related sources. Just checking here if my initial estimates are correct.

At first glance, a possible separation seems already prepared in some way: LineLM.createLineBreaks() is already a separate method, so could in theory be called independently from LineLM.collectInlineKnuthElements () --maybe depending on a boolean switch passed into LineLM.getNextKnuthElements() (as a first step?)

The only gotcha seems to be the TODO on lines 580-582 in LineLayoutManager, where the 'available IPD' is passed into collectInlineKnuthElements(). Following the path of this variable, it is afterwards only used to create a lineFiller to use for the first/last lines in the paragraph, only in case of non-centered alignment. The min/opt/max values of the filler are used to calculate the width for the first/last penalties and/or glues added in Paragraph.startSequence() / .endSequence(). That's the only influence that 'available IPD' has on the created element list.

The only elements invalidated by a later IPD change seem to be those start- or end-of-paragraph elements, but they could be either replaced or adjusted by the breaker. Provided, of course, that they are made distinguishable from the other elements --either by marking them, or providing accessors for Paragraph.ignoreAtStart and .ignoreAtEnd (?)

If I see it correctly, what we want to go towards is a two-phased approach:

1) getBaseKnuthElements()
   (or: collectKnuthElements())
   the lower level LM constructs its base element list completely,
   and passes it up to the ancestor LM for inspection and detection
   of content-width constraints (and other constraints, like forced
   breaks and keeps, widows/orphans)

2) processElementList(from, to, context, alignment)
   (would correspond to the current getNextKnuthElements(), if called
    with 'from' equal to zero, and 'to' equal to list.size())
   the higher level LM issues repeated requests to the lower
   level LM to return element sublists from A to B, but now
   including the line-breaks, when given certain ipd- and alignment

Why not keep getNextKnuthElements() wich does the line breaking depending on a boolean switch ? Then depending on wether the element list already exists, the (modified) collectKnuthElements() method is called.

This is my perspective for the auto-table layout, since I am implementing a new LayoutManager method called determineMinMaxTextWidths() which returns an object containing the two values needed to calculate optimum column widths. These values will go up the hierarchy up to the TableLM where the optimal column widths will be determined. So no need to return the actual element lists, right ?

and it's step 2) that offers a possibility to restart the breaking from one arbitrary element up to another.

The start(from) and end(to) element for the sublists could be estimated, based on the content-width, line-height and the context's ipd/bpd-constraints:
if minimum-line-height X allows L lines to be stacked in BP direction
=> room for a maximum of (L * available-IPD) in unbroken content-width

If the actual last element that fits in the context turns out not to be the last element of the sublist, a pointer should be kept to the first element in the remainder of the processed list for which baseList.indexOf() does not return -1, in order to obtain the start element for the next call.

As such, before making each 'processElementList(from, to, ...)' request, the higher level LM gets a chance to update the layout- context if there is a change in available IPD --for instance due to a (deferred) side-float, or a change in page-master and/or reference- orientation.

The breaker, on the other hand, could suspend or interrupt the process, for instance upon encountering a start-float, so that the next iteration starts with the float's element list (= finish current line, return control to the higher level LM, treat the float, if necessary update layout-context's ipd, and resume the breaking in the updated context) If the float fits on the page, then this should offer a reasonable guarantee that it will end up starting on the line following the one that contains its anchor.

Am I making things too simple? Too complicated? :/



Reply via email to