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
constraints
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? :/
Andreas
Patrick