aboutsummaryrefslogtreecommitdiffstats
path: root/src/documentation/content/xdocs/DnI/getnextbreakposs.xml
diff options
context:
space:
mode:
Diffstat (limited to 'src/documentation/content/xdocs/DnI/getnextbreakposs.xml')
-rw-r--r--src/documentation/content/xdocs/DnI/getnextbreakposs.xml1227
1 files changed, 1227 insertions, 0 deletions
diff --git a/src/documentation/content/xdocs/DnI/getnextbreakposs.xml b/src/documentation/content/xdocs/DnI/getnextbreakposs.xml
new file mode 100644
index 000000000..96bd64390
--- /dev/null
+++ b/src/documentation/content/xdocs/DnI/getnextbreakposs.xml
@@ -0,0 +1,1227 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<!-- $Id$ -->
+
+<!--
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "docbookx.dtd">
+ -->
+
+ <chapter>
+ <title>Phase 2a: The <literal>getNextBreakPoss</literal> call
+tree</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para> <itemizedlist spacing="compact">
+ <listitem>
+ <para>Create a new layout context for the children.</para>
+ </listitem>
+ <listitem>
+ <para>Then process the flow: loop until the flow is exhausted
+(isFinished()): <itemizedlist spacing="compact">
+ <listitem>
+ <para>Get the next possible breakpoint (getNextBreakPoss).
+<itemizedlist spacing="compact">
+ <listitem>
+ <para>Loop until the list of child layout
+managers is exhausted: <itemizedlist spacing="compact">
+ <listitem>
+ <para> Get a child layout manager
+(AbstractLayoutManager.getChildLM). The current child layout manager
+is returned until it is finished. Then the layout manager for the next
+child is returned.</para>
+ </listitem>
+ <listitem>
+ <para> Create a new layout context for
+the children.</para>
+ </listitem>
+ <listitem>
+ <para> If the child layout manager is
+not finished, get the next possible breakpoint
+(getNextBreakPoss).</para>
+ </listitem>
+ <listitem>
+ <para> If a breakpoint is returned,
+break the loop and return the breakpoint.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>This finishes a page.</para>
+ </listitem>
+ <listitem>
+ <para>Get the next possible breakpoint
+(getNextBreakPoss) (<emphasis>continued</emphasis>) <itemizedlist spacing="compact">
+ <listitem>
+ <para>Loop until the list of child layout
+managers is exhausted: (<emphasis>continued</emphasis>) <itemizedlist spacing="compact">
+ <listitem>
+ <para>Else if no breakpoint is returned,
+do the next cycle with the next child layout manager.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Mark the layout manager as finished (the
+list of child layout managers is exhausted).</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>At this point a complete (pseudo)tree of possible break
+points for a page has been collected.</para>
+
+ </section>
+
+ <section>
+ <title>How do layout managers get layout managers for the child
+FO nodes?</title>
+
+<para>Child layout managers are created and retrieved in the method
+<literal>AbstractLayoutManager.getChildLM</literal>.</para>
+
+<para>The layout manager has a layout strategy, which has an
+<literal>AddLMVisitor</literal> object, which is responsible for
+creating layout managers for the FO nodes.</para>
+
+<para>The layout manager gets the layout manager for its next child from its
+<literal>LMIter</literal> object <literal>childLMIter</literal>. This
+<literal>LMIter</literal> object contains an iterator over the
+children of the layout manager's FO node. It behaves itself as an
+iterator over the list of layout managers for the children. It
+constructs those layout managers when needed, in its
+<literal>preLoadNext</literal> method. It does so by calling the
+layout strategy's <literal>AddLMVisitor</literal> object's
+<literal>addLayoutManager</literal> method. The
+<literal>LMIter</literal> object gets the layout strategy via the
+current layout manager, which it knows.</para>
+
+<para><literal>AddLMVisitor</literal>'s <literal>addLayoutManager</literal>
+method first registers the LM list in its second argument, i.e. the
+<literal>LMIter</literal> object's LM list, as its own member
+<literal>currentLMlist</literal>. Then it asks the FO node to accept
+it as the <literal>FOTreeVisitor</literal>
+(<literal>acceptVisitor</literal>). The FO node then calls the
+appropriate method of this FO tree visitor, in this case
+(<literal>fo:flow</literal>) the method <literal>serveFlow</literal>
+(<literal>AddLMVisitor.serveFlow</literal>). This method creates a
+<literal>FlowLayoutManager</literal> object and adds it to the
+<literal>currentLMList</literal>. Thus <literal>LMIter</literal> has a
+layout manager for its next child. It returns this layout manager in
+the call to its <literal>next()</literal> method, when the current
+layout manager invokes its <literal>getChildLM</literal> method.</para>
+
+<para>Note that layout manager types may have their own subclass of
+<literal>LMIter</literal>,
+e.g. <literal>BlockLayoutManager$BlockLMiter</literal> and
+<literal>AbstractList$ListItr</literal>, which may implement a
+different method of creating child layout managers.</para>
+
+<para>The method <literal>acceptVisitor</literal> of the FO node calls the
+appropriate method of its visitor. This procedure effectively
+implements an indirect mapping from FO node type to layout
+manager. The indirection allows the <literal>AddLMVisitor</literal>
+object to return its own layout manager for each FO node type. Because
+the <literal>AddLMVisitor</literal> object is part of the layout
+strategy, this indirection allows the layout strategy to provide its
+own layout managers for the layout process. In this manner, a
+different layout strategy can be coupled to the other parts of the
+program.</para>
+
+<para>Note that <literal>AbstractLayoutManager.getChildLM</literal> itself
+does not behave as an iterator. The current child layout manager is
+returned until it is finished. One can safely make multiple calls to
+<literal>getChildLM</literal>. If the current child layout manager is
+unfinished and does nothing in between the calls, it remains
+unfinished, and is returned at every call. If the current child layout
+manager is finished, the next layout manager is loaded, and, because
+it is unfinished, returned at every call. If this is the last child
+layout manager and it is finished, then null is returned because in
+<literal>LMiter.preLoadNext</literal>
+<literal>baseIter.hasNext()</literal> returns false. The latter case
+is used in <literal>BlockLayoutManager.getNextBreakPoss</literal>.</para>
+
+<para>Stack trace: Creating a new layout manager for a child, in
+<literal>LMiter.preLoadNext</literal>, in
+<literal>AbstractLayoutManager.getChildLM</literal>:</para>
+
+<screen>
+ [1] org.apache.fop.layoutmgr.AbstractLayoutManager.&lt;init&gt; (AbstractLayoutManager.java:71)
+ [2] org.apache.fop.layoutmgr.BlockStackingLayoutManager.&lt;init&gt; (BlockStackingLayoutManager.java:70)
+ [3] org.apache.fop.layoutmgr.FlowLayoutManager.&lt;init&gt; (FlowLayoutManager.java:81)
+ [4] org.apache.fop.layoutmgr.AddLMVisitor.serveFlow (AddLMVisitor.java:894)
+ [5] org.apache.fop.fo.pagination.Flow.acceptVisitor (Flow.java:187)
+ [6] org.apache.fop.layoutmgr.AddLMVisitor.addLayoutManager (AddLMVisitor.java:198)
+ [7] org.apache.fop.layoutmgr.LMiter.preLoadNext (LMiter.java:88)
+ [8] org.apache.fop.layoutmgr.LMiter.hasNext (LMiter.java:77)
+ [9] org.apache.fop.layoutmgr.AbstractLayoutManager.getChildLM (AbstractLayoutManager.java:186)
+ [10] org.apache.fop.layoutmgr.PageLayoutManager.getNextBreakPoss (PageLayoutManager.java:253)
+ [11] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:228)
+</screen>
+
+ </section>
+
+ <section>
+ <title>Block layout managers and their child layout managers</title>
+
+<para>Block LMs are different in their treatment of their child LMs. For
+this purpose <literal>BlockLayoutManager</literal> defines a nested class <literal>BlockLMiter</literal>,
+which is a subclass of <literal>LMiter</literal>.</para>
+
+<para>A <literal>BlockLMiter</literal> object has a member called proxy,
+which is the basic <literal>LMiter</literal> over the children of the
+block. If the proxy produces a child LM that does not generate inline
+areas, the child LM is added to the list of child LMs as normal. But
+if the childLM generates an inline area, a new
+<literal>LineLayoutManager</literal> object is created
+(<literal>BlockLayoutManager.BlockLMiter.createLineManager</literal>). This
+LM asks the proxy to produce more child LMs. As long as these child
+LMs generate inline areas, they are collected by the
+<literal>LineLayoutManager</literal> object. Finally, the
+<literal>LineLayoutManager</literal> object creates its
+<literal>LMiter</literal> object as the
+<literal>ListIterator</literal> over the list of collected child LMs.</para>
+
+ </section>
+
+ <section>
+ <title>About <literal>getNextBreakPoss</literal> and the list of
+child layout managers</title>
+
+<para>Note that the breakpoint may come from a deeply nested child. Each
+layout manager keeps a reference to its current child layout
+manager. The whole list is descended again
+(<literal>getChildLM</literal>) at the next call to
+<literal>getNextBreakPoss</literal>.<warning>
+ <simpara>TO BE IMPROVED</simpara>
+ </warning>
+</para>
+
+<para>Stack of layout managers:
+ <variablelist>
+ <varlistentry>
+ <term><literal>PageSequence</literal></term>
+ <listitem>
+ <simpara><literal>PageLayoutManager</literal></simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>Flow</literal></term>
+ <listitem>
+ <simpara><literal>FlowLayoutManager</literal></simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>Block</literal></term>
+ <listitem>
+ <simpara><literal>BlockLayoutManager</literal></simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>Block</literal></term>
+ <listitem>
+ <simpara><literal>LineLayoutManager</literal></simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>FOText</literal></term>
+ <listitem>
+ <simpara><literal>TextLayoutManager</literal></simpara>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+For <literal>BlockLayoutManager</literal> and
+<literal>LineLayoutManager</literal> <literal>Block</literal> is the
+same, but their <literal>childLMIter</literal> are different:
+<literal>BlockLayoutManager$BlockLMiter</literal> vs
+<literal>AbstractList$ListItr</literal></para>
+
+<screen>
+ [1] org.apache.fop.layoutmgr.TextLayoutManager.getNextBreakPoss (TextLayoutManager.java:270)
+ [2] org.apache.fop.layoutmgr.LineLayoutManager.getNextBreakPoss (LineLayoutManager.java:212)
+ [3] org.apache.fop.layoutmgr.BlockLayoutManager.getNextBreakPoss (BlockLayoutManager.java:229)
+ [4] org.apache.fop.layoutmgr.FlowLayoutManager.getNextBreakPoss (FlowLayoutManager.java:111)
+ [5] org.apache.fop.layoutmgr.PageLayoutManager.getNextBreakPoss (PageLayoutManager.java:261)
+ [6] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:228)
+</screen>
+
+<para>A <literal>TextLayoutManager</literal>:
+<screen>
+ this = {
+ vecAreaInfo: instance of java.util.ArrayList(id=1062)
+ chars: instance of char[13] (id=1064)
+ textInfo: instance of org.apache.fop.fo.TextInfo(id=1065)
+ iAreaStart: 0
+ iNextStart: 0
+ ipdTotal: null
+ spaceCharIPD: 4448
+ hyphIPD: 5328
+ halfWS: instance of org.apache.fop.traits.SpaceVal(id=1066)
+ iNbSpacesPending: 0
+ org.apache.fop.layoutmgr.AbstractLayoutManager.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=1067)
+ org.apache.fop.layoutmgr.AbstractLayoutManager.parentLM: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1068)
+ org.apache.fop.layoutmgr.AbstractLayoutManager.fobj: instance of org.apache.fop.fo.FOText(id=1069)
+ org.apache.fop.layoutmgr.AbstractLayoutManager.foID: null
+ org.apache.fop.layoutmgr.AbstractLayoutManager.markers: null
+ org.apache.fop.layoutmgr.AbstractLayoutManager.bFinished: false
+ org.apache.fop.layoutmgr.AbstractLayoutManager.curChildLM: null
+ org.apache.fop.layoutmgr.AbstractLayoutManager.childLMiter: instance of org.apache.fop.layoutmgr.LMiter(id=1070)
+ org.apache.fop.layoutmgr.AbstractLayoutManager.bInited: true
+}
+</screen>
+</para>
+
+<para>Text in <literal>fo:text</literal> is handled by a
+<literal>TextLayoutManager</literal>. Two routines add the text and
+calculate the next possible break.</para>
+
+ </section>
+
+ <section>
+ <title><literal>LineLayoutManager.getNextBreakPoss</literal></title>
+
+ <section>
+ <title>Prepare for the main loop</title>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <simpara>Create a new empty list of possible line endings,
+<literal>vecPossEnd</literal>.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>Retrieve the <literal>ipd</literal>
+<literal>availIPD</literal> from the layout context.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>Create a new layout context (inline layout
+context) for the child layout managers, based on the layout context
+for this layout manager.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>Clear the map of previous
+ <literal>ipd</literal>s.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>Record the length of
+<literal>vecInlineBreaks</literal>, which we can use to find the last
+breakposs of the previous line.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>Set <literal>prevBP</literal> to
+<literal>null</literal>; <literal>prevBP</literal> contains the last
+confirmed breakposs of this line.</simpara>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>The main loop over the list of child layout managers</title>
+
+ <para>Loop until the list of child layout managers is
+exhausted: <itemizedlist spacing="compact">
+ <listitem>
+ <para>Get a child layout manager
+(<literal>AbstractLayoutManager.getChildLM</literal>). The current
+child layout manager is returned until it is finished. Then the layout
+manager for the next child is returned.</para>
+ </listitem>
+ <listitem>
+ <para>Record the last breakposs.</para>
+ </listitem>
+ <listitem>
+ <para>Record whether the breakposs we are going to
+find is the first breakposs of this line.</para>
+ </listitem>
+ <listitem>
+ <para>Record whether it is the first breakposs of
+this child layout manager.</para>
+ </listitem>
+ <listitem>
+ <para>Initialize the inline layout context (note that
+it is not a new layout context, the same inline layout context is used
+by all child layout managers) (method
+<literal>InlineStackingLayout.initChildLC</literal>): <itemizedlist spacing="compact">
+ <listitem>
+ <para>Record whether this is a new area; it is a
+new area if this is the start of a new line or of a new child
+LM.</para>
+ </listitem>
+ <listitem>
+ <para>If this is the start of a new
+line <itemizedlist spacing="compact">
+ <listitem>
+ <para>record whether this is the first area
+of this child LM,</para>
+ </listitem>
+ <listitem>
+ <para>set the leading space as passed by
+argument.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else if this starts a new child
+LM <itemizedlist spacing="compact">
+ <listitem>
+ <para>record that this is the first area,</para>
+ </listitem>
+ <listitem>
+ <para>set the leading space from the previous
+BP.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else set the leading space to
+ <literal>null</literal>.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Record on the inline layout context whether
+leading space is supppressed; it is suppressed if this is the start of
+a new line, but not the start of this child LM, and the previous line
+was not ended by a forced break.</para>
+ </listitem>
+ <listitem>
+ <para>Retrieve the next breakposs from the current child
+LM (<literal>getNextBreakPoss</literal> method of child LM). If it is
+not <literal>null</literal>:
+<itemizedlist spacing="compact">
+ <listitem>
+ <para>Calculate the <literal>ipd</literal> up to
+the previous BP (method
+<literal>InlineStackingLayout.updatePrevIPD</literal>): <itemizedlist spacing="compact">
+ <listitem>
+ <para>Take an empty <literal>ipd</literal>
+ size.</para>
+ </listitem>
+ <listitem>
+ <para>If this starts a new line: <itemizedlist spacing="compact">
+ <listitem>
+ <para>if it has a leading fence, add
+leading space (?),</para>
+ </listitem>
+ <listitem>
+ <para>list the <literal>ipd</literal>
+for the LM of this BP in the map of previous
+<literal>ipd</literal>s.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else <itemizedlist spacing="compact">
+ <listitem>
+ <para>retrieve the
+<literal>ipd</literal> for the LM of this BP in the map of previous
+<literal>ipd</literal>s,</para>
+ </listitem>
+ <listitem>
+ <para>if that is
+<literal>null</literal> (first BP of this child LM) <itemizedlist spacing="compact">
+ <listitem>
+ <para>retrieve the
+<literal>ipd</literal> for the LM of the previous BP in the map of
+previous <literal>ipd</literal>s,</para>
+ </listitem>
+ <listitem>
+ <para>add the leading space
+of this BP,</para>
+ </listitem>
+ <listitem>
+ <para>add the pending space-end
+(stacking size) of the previous BP,</para>
+ </listitem>
+ <listitem>
+ <para>list the
+<literal>ipd</literal> for the LM of this BP in the map of previous
+<literal>ipd</literal>s.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Add to the <literal>ipd</literal> the
+pending space-end (stacking size) of this BP.</para>
+ </listitem>
+ <listitem>
+ <para>Record whether this BP could end the
+line: <itemizedlist spacing="compact">
+ <listitem>
+ <para>if a break may occur after this BP,
+record true;</para>
+ </listitem>
+ <listitem>
+ <para>else if this BP is suppressible at a
+line break, return false;</para>
+ </listitem>
+ <listitem>
+ <para>else, return whether this is the last
+child LM and it is finished, or the next area could start a new
+line.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>If this BP could end the line, add trailing
+space.</para>
+ </listitem>
+ <listitem>
+ <para>If this BP exceeds the line length
+(<literal>bpDim.min > availIPD.max</literal>), <itemizedlist spacing="compact">
+ <listitem>
+ <para>if the text should be justified or if
+this is the first BP of this line, <itemizedlist spacing="compact">
+ <listitem>
+ <para>if we are in a hyphenation try,
+break the loop; we have exhausted our options and one of the previous
+BPs should end the line (<literal>_exit of loop_</literal>);</para>
+ </listitem>
+ <listitem>
+ <para>if this BP could not end the
+line, add it to the list of inline breaks, and continue with the next
+iteration;</para>
+ </listitem>
+ <listitem>
+ <para>prepare to hyphenate: get the
+hyphenation context for the text between the last and this BP (method
+<literal>getHyphenContext</literal>): <itemizedlist spacing="compact">
+ <listitem>
+ <para>add this BP to the list of
+inline breaks; even though this is not a good BP, we add it to the
+list, so that we can retrieve the text between the last and this
+BP;</para>
+ </listitem>
+ <listitem>
+ <para>iterate back to the
+previous BP in this list;</para>
+ </listitem>
+ <listitem>
+ <para>loop over the following
+BPs in this list: <itemizedlist spacing="compact">
+ <listitem>
+ <para>retrieve the text
+between the preceding and this BP.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>remove this BP again from
+the list of inline breaks.</para>
+ </listitem>
+ <listitem>
+ <para>create a hyphenation
+object for the retrieved text, taking the language, country and other
+hyphenation properties into account.</para>
+ </listitem>
+ <listitem>
+ <para>create a hyphenation
+context object from it, and return that.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>store the hyphenation context
+with the inline layout context.</para>
+ </listitem>
+ <listitem>
+ <para>Record on the inline layout
+context that we are in a hyphenation try.</para>
+ </listitem>
+ <listitem>
+ <para>reset the child LMs to the
+previous BP or to the start of the line.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else (if text should not be justified
+and if this is not the first BP of this line) break the loop; one of
+the previous BPs should end the line (<literal>_exit of
+loop_</literal>);</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else (if this BP does not exceed the line
+length): <itemizedlist spacing="compact">
+ <listitem>
+ <para>add this BP to the list of inline
+breaks,</para>
+ </listitem>
+ <listitem>
+ <para>if this BP could end the line,
+<itemizedlist spacing="compact">
+ <listitem>
+ <para>record it as the last confirmed
+BP: set prevBP to this BP.</para>
+ </listitem>
+ <listitem>
+ <para>if this BP is a forced line
+break, break the loop; this BP (or one of the previous BPs?) should
+end the line (<literal>_exit of loop_</literal>).</para>
+ </listitem>
+ <listitem>
+ <para>if this BP may fill the line
+length (<literal>bpDim.max >= availIPD.min</literal>), add it to the
+list of possible line endings, <literal>vecPossEnd</literal>, with a
+cost which is equal to the difference of the optimal values of the
+content length and the line length (<literal>Math.abs(availIPD.opt -
+bpDim.opt)</literal>).</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>If we are in a hypenation try, and the hyphenation
+context has no more hyphenation points, break the loop; this or one of
+the previous BPs should end the line (<literal>_exit of
+loop_</literal>).</para>
+ </listitem>
+ </itemizedlist></para>
+ </section>
+
+ <section>
+ <title>After the main loop</title>
+
+ <para>There are five exit points of the main loop: <orderedlist>
+ <listitem>
+ <simpara>The last BP in the hyphenation try has exceeded
+the line length.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>The last BP has exceeded the line length, and
+we cannot get a hyphenation context.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>The last BP has exceeded the line length, and
+we do not hyphenate.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>The last BP has not exceeded the line length
+but forces a line break.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>We have run out of hyphenation points (and the
+last BP has not exceeded the line length).</simpara>
+ </listitem>
+ <listitem>
+ <simpara>Natural end of the while loop: we are through
+the list of child layout managers.</simpara>
+ </listitem>
+ </orderedlist></para>
+
+<para>If the last BP has exceeded the line length, it is not in the
+list of inline breaks, and prevBP points to the last good break;
+otherwise it is in the list of inline breaks, and prevBP points to
+it.</para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>If we are through the list of child LMs, mark this
+ LM as finished.</para>
+ </listitem>
+ <listitem>
+ <para>If no BP was produced, return
+<literal>null</literal>. (This should concur with being
+finished?)</para>
+ </listitem>
+ <listitem>
+ <para>If prevBP is <literal>null</literal>, there is not
+last good break; set it to this BP, even though it fails some
+criteria: <itemizedlist spacing="compact">
+ <listitem>
+ <para>it has exceeded the line length in the
+hyphenation try or we cannot get a hyphenation context,</para>
+ </listitem>
+ <listitem>
+ <para>or it cannot end the line but it is the last
+BP of the last child layout manager.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>If this BP is not a forced break, and there are
+several possible line breaks, select the best one; make
+<literal>prevBP</literal> point to it. (Could this produce the wrong
+result if the BP has exceeded the line length and at the same time is
+a forced line break? Should <literal>prevBP</literal> be tested for
+being a forced break instead?)</para>
+ </listitem>
+ <listitem>
+ <para>If the last BP is not the actual breakpoint
+<literal>prevBP</literal> (<literal>bp != prevBP</literal>) and the
+material after <literal>prevBP</literal> is not suppressible at the
+end of a line, back up to <literal>prevBP</literal> for a proper start
+of the next line.</para>
+ </listitem>
+ <listitem>
+ <para>If the text should be justified and the breakpoint
+is a forced line break (here <literal>prevBP</literal> is tested) or
+this is the last line of the layout manager, set text alignment to
+left-aligned.</para>
+ </listitem>
+ <listitem>
+ <para>Make a line break and return the associated
+ breakposs.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section>
+ <title><literal>LineLayoutManager.makeLineBreak</literal></title>
+
+ <para>Arguments are: <itemizedlist spacing="compact">
+ <listitem>
+ <para>index in <literal>vecInlineBreaks</literal> of
+ line breaking BP of last line,</para>
+ </listitem>
+ <listitem>
+ <para>target line length,</para>
+ </listitem>
+ <listitem>
+ <para>type of text alignment.</para>
+ </listitem>
+ </itemizedlist></para>
+
+<para>Calculate line dimensions. The Line LayoutManager contains the
+parameters <literal>lineHeight</literal>, <literal>lead</literal> and
+<literal>follow</literal> as members, which it received from its Block
+LayoutManager parent at construction. The Blo ckLayoutManager contains
+these parameters as members as well, and has received them from a
+<literal>TextInfo</literal> object in the method set
+<literal>BlockTextInfo</literal>. The <literal>TextInfo</literal>
+object has a reference to the <literal>Font</literal>
+object. <literal>lead</literal> is the font ascender,
+<literal>follow</literal> is the font descender.</para>
+
+<para>The leading is the difference between
+<literal>lineHeight</literal> and font height = ascender +
+descender. The leading is split in two halves, one for above, the
+other for below the line. The variable <literal>lineLead</literal> is
+calculated as the distance from the baseline to the top of the line,
+the variable <literal>maxtb</literal> is calculated as the distance
+from the baseline to the bottom of the line. The variable
+<literal>middlefollow</literal> set equal to <literal>maxtb</literal>.
+These parameters correspond to the members <literal>lead</literal>,
+<literal>total</literal> and <literal>follow</literal> of the
+breakposs. <warning>
+ <simpara>Find out the exact meaning of these.</simpara>
+ </warning></para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>Loop over the breakposs in
+ <literal>vecInlineBreaks</literal>: <itemizedlist spacing="compact">
+ <listitem>
+ <para>adjust <literal>lineLead</literal>,
+<literal>maxtb</literal> and <literal>middlefollow</literal> if the
+corresponding dimension of the BP is larger;</para>
+ </listitem>
+ <listitem>
+ <para>add the <literal>ipd</literal>s; a BP does
+not just hold the <literal>ipd</literal> of the area since the
+previous BP, but the cumulative <literal>ipd</literal> for all the
+areas contributed by its layout manager; therefore care is taken to
+add only the <literal>ipd</literal> of the last BP of each LM; more
+precisely, the <literal>ipd</literal> of the last BP of the previous
+LM is added when the next LM is encountered;</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Add the <literal>ipd</literal> of the last BP.</para>
+ </listitem>
+ <listitem>
+ <para>Resolve the trailing space of the last BP.</para>
+ </listitem>
+ <listitem>
+ <para>Adjust <literal>middlefollow</literal> if it is
+smaller than <literal>maxtb - lineHeight</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>Calculate the stretch or shrink factor
+<literal>ipdAdjust</literal> for the stretch- and shrinkable elements
+in this line: <itemizedlist spacing="compact">
+ <listitem>
+ <para>if content optimum is larger than line
+ length optimum, <itemizedlist spacing="compact">
+ <listitem>
+ <para>if content minimum is smaller than
+ line length optimum, <itemizedlist spacing="compact">
+ <listitem>
+ <para>calculate
+<literal>ipdAdjust</literal> between 0 and -1, real line length = line
+length optimum,</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>else (content minimum is larger than
+ line length optimum) <itemizedlist spacing="compact">
+ <listitem>
+ <para><literal>ipdAdjust =
+-1</literal>, real line length = content minimum,</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>else (content optimum is smaller than line
+ length optimum), <itemizedlist spacing="compact">
+ <listitem>
+ <para>if content maximum is larger than line
+ length optimum, <itemizedlist spacing="compact">
+ <listitem>
+ <para>calculate
+<literal>ipdAdjust</literal> between 0 and 1, real line length = line
+length optimum,</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>else (content maximum is smaller than
+ line length optimum), <itemizedlist spacing="compact">
+ <listitem>
+ <para><literal>ipdAdjust =
+1</literal>, real line length = content maximum.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Calculate the stretch or shrink factor
+<literal>dAdjust</literal> for white space and the indent:
+<itemizedlist spacing="compact">
+ <listitem>
+ <para>justify: calculate
+<literal>dAdjust</literal>,</para>
+ </listitem>
+ <listitem>
+ <para>center or end: calculate the required
+ indent.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Create a new <literal>LineBreakPosition</literal>
+based on this LM, the last BP in <literal>vecInlineBreaks</literal>
+and the calculated dimensions; use <literal>lineLead</literal> for the
+baseline position and <literal>lineLead + middlefollow</literal> for
+the <literal>lineHeight</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>Create a <literal>BreakPoss</literal> from this
+ <literal>LineBreakPosition</literal> object.</para>
+ </listitem>
+ <listitem>
+ <para>Mark the BP as last if this LM is finished.</para>
+ </listitem>
+ <listitem>
+ <para>Set the stacking size of the BP
+(<literal>bpd</literal>) equal to <literal>lineLead +
+middlefollow</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Line LayoutManager, a sequence of breakposs</title>
+
+<para>The text is: "waterstaatsingenieur ministersportefeuille
+aandachtstrekker. Vernederlandste vakliteratuur" etc. It consists of a
+few long Dutch words, which can be found in the hyphenation exceptions
+in <filename>nl.xml</filename>. The column width is 8cm. This text and
+width have been chosen so that they force many hyphenations.</para>
+
+<para>This text is contained in a single <literal>FOText</literal>
+node, and is dealt with by a single Text LayoutManager, which is a
+child layout manager for the Line LayoutManager. The Text
+LayoutManager maintains a list of area information objects,
+<literal>vecAreaInfo</literal>, and the Line LayoutManager maintains a
+list of breakposs, <literal>vecInlineBreaks</literal>. Each breakposs
+refers to an area, in its <literal>position.iLeafPos</literal>
+member.</para>
+
+<para>During the process of finding suitable line breaks, breakposs
+are generated until one is found that exceeds the line length. Then
+the Line LayoutManager backs up to the previous BP, either to start a
+hyphenation try or to create the line break. When it creates a line
+break, the last breakposs, which exceeds the line length, is not added
+to the list of inline breaks. When it starts a hyphenation try, the
+breakposs is added to that list, and removed again after the text for
+hyphenation has been obtained. Each time, the corresponding area info
+is left in the list of area information objects. As a consequence the
+list <literal>vecAreaInfo</literal> is longer than the list
+<literal>vecInlineBreaks</literal>, and some areas have no
+corresponding breakposs.</para>
+
+<screen>
+wa-ter-staats-in-ge-nieur mi-nis-ters-por-te-feuil-le aandachtstrekker.
+0 2 5 1 1 1 2 2 2 2 3 3 3 4 4 6
+ 1 3 5 0 3 6 9 0 3 5 0 2 0
+
+text: waterstaatsingenieur wa ter staats in |
+AreaInfo: 0: 0-20 (removed) 0: 0-2 1: 2-5 2: 5-11 3: 11-13 |
+InlineBreaks: 0 (removed) 0 1 2 3 |
+ too long, hyphenate, |
+ back up V
+
+gen genieur _ministersportefeuille _mi nis |
+4: 13-15 5: 13-20 6: 20-42 7: 20-23 8: 23-26 |
+ 4 5 (removed) 5 6 |
+too long, too long, hyphenate |
+line break, back up |
+back up v
+
+ters tersportefeuille_ ter s por
+9: 26-30 10: 26-42 11: 26-29 12: 29-30 13: 30-33
+ 7 (removed) 7 8 9
+too long, too long, hyphenate, hyphenation
+line break, back up error
+back up
+
+te feuil | le | _aandachtstrekker.
+14: 33-35 15: 35-40 | 16: 40-42 | 17: 42-60
+10 11 | 12 | 13 (removed)
+ last hyphenpoint, | | too long,
+ line break v | hyphenation fails,
+ | line break,
+ v back up
+
+aandachtstrekker. | etc.
+18: 43-60 |
+13 |
+too long, |
+hyphenation fails, |
+first BP, |
+line break v
+</screen>
+
+<para>A few remarkable points: <orderedlist>
+
+<listitem>
+<simpara>The first AreaInfo object is removed from the list during backing
+ up. This is because the previous BP, which is
+ <literal>null</literal>, does not belong to this child layout
+ manager, and therefore the whole child LM is reset.</simpara>
+</listitem>
+
+<listitem>
+<simpara>The last BP, no. 18, exceeds the line length, but because it is the
+ first BP of this line, it is accepted for the line break.</simpara>
+</listitem>
+
+<listitem>
+<simpara>BP 7 at position 29 falls at a point that is not a good hyphenation
+ point. This is probably caused by the fact that for this line only
+ the partial word is subjected to hyphenation. On the previous line
+ the complete word was subjected to hyphenation, and there was no BP
+ at position 29.</simpara>
+</listitem>
+
+<listitem>
+<simpara>For the word "aandachtstrekker." hyphenation fails
+ (<literal>hyph == null</literal> is returned). This may be due to
+ the period not being separated from the word. When the period is
+ removed, the word is properly broken.</simpara>
+</listitem>
+ </orderedlist></para>
+ </section>
+
+ <section>
+ <title><literal>TextLayoutManager.getNextBreakPoss</literal></title>
+
+ <para> <itemizedlist spacing="compact">
+ <listitem>
+ <para>If this is the first call to this Text
+LayoutManager, initialize <literal>ipdTotal</literal> and record that
+this breakposs is the first in <literal>iFlags</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>If leading spaces must be suppressed, suppress all
+leading space characters <literal>U+20</literal>. Return if this
+finished the text.</para>
+ </listitem>
+ <listitem>
+ <para>For the remaining leading space characters,
+<itemizedlist spacing="compact">
+ <listitem>
+ <para>If this is a space <literal>U+20</literal>
+ or a non-breaking space <literal>U+A0</literal>,
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>count it;</para>
+ </listitem>
+ <listitem>
+ <para>if this is the first character and this
+ is the first breakposs, <itemizedlist spacing="compact">
+ <listitem>
+ <para>if the context has leading spaces,
+add it (or <literal>halfWS</literal>?);</para>
+ </listitem>
+ <listitem>
+ <para>else add it (or
+<literal>halfWS</literal>?) to the pending space, and add the pending
+space to the <literal>space</literal> ipd.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>add the space width to the word
+<literal>ipd</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>set the pending space to
+ <literal>halfWS</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>if this is a non-breaking space
+<literal>U+A0</literal>, register it in
+<literal>bSawNonSuppressible</literal>.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else (other space characters), <itemizedlist spacing="compact">
+ <listitem>
+ <para>register it in
+ <literal>bSawNonSuppressible</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>add the pending space to the space
+<literal>ipd</literal>, and clear the pending space.</para>
+ </listitem>
+ <listitem>
+ <para>add the character width to the word
+ <literal>ipd</literal>.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>If this finishes the text, <itemizedlist spacing="compact">
+ <listitem>
+ <para>register whether there were any
+nonsuppressible spaces (<literal>bSawNonSuppressible</literal>) in
+<literal>iFlags</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>pass all the info to
+ <literal>makeBreakPoss</literal> and
+ <literal>_return_</literal> its breakposs.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else, <itemizedlist spacing="compact">
+ <listitem>
+ <para>add pending space.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>If hypenation is on, get the size of the next
+ syllable: <itemizedlist spacing="compact">
+ <listitem>
+ <para>get the size of the next syllable,
+<itemizedlist spacing="compact">
+ <listitem>
+ <para>if successful, add the flags
+<literal>BreakPoss.CAN_BREAK_AFTER</literal> and
+<literal>BreakPoss.CAN_BREAK_AFTER</literal> in
+<literal>iFlags</literal>,</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>add the syllable length to the word
+ <literal>ipd</literal>.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else look for a legal line-break: breakable
+white-space and certain characters such as '-' which can serve as word
+breaks; don't look for hyphenation points here though, <itemizedlist spacing="compact">
+ <listitem>
+ <para>for all following characters: <itemizedlist spacing="compact">
+ <listitem>
+ <para>If this is a newline character
+<literal>U+0A</literal>, or if <literal>textInfo.bWrap</literal> and
+this is a breakable space, or if this is one of the linebreak
+characters ("-/") and it is the first character or the preceding
+character is a letter or a digit, <itemizedlist spacing="compact">
+ <listitem>
+ <para>add the flag
+<literal>BreakPoss.CAN_BREAK_AFTER</literal> to
+<literal>iFlags</literal>,</para>
+ </listitem>
+ <listitem>
+ <para>if this is not a space
+ <literal>U+20</literal>, <itemizedlist spacing="compact">
+ <listitem>
+ <para>move the counter to the next
+ character,</para>
+ </listitem>
+ <listitem>
+ <para>if this is a newline
+<literal>U+0A</literal>, add the flag
+<literal>BreakPoss.FORCE</literal> to
+<literal>iFlags</literal>,</para>
+ </listitem>
+ <listitem>
+ <para>else add the character width
+to the word <literal>ipd</literal>.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>if the rest of the text consists
+of spaces <literal>U+20</literal>, register that the rest is
+suppressible at a line break
+(<literal>BreakPoss.REST_ARE_SUPPRESS_AT_LB</literal>) in
+<literal>iFlags</literal>,</para>
+ </listitem>
+ <listitem>
+ <para>pass all the info to
+<literal>makeBreakPoss</literal> and <literal>_return_</literal> its
+breakposs.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Else add the character width to the word
+ <literal>ipd</literal>,</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>and continue with the cycle for the next
+ character.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>At the end of the text, pass all the info to
+<literal>makeBreakPoss</literal> and <literal>_return_</literal> its
+breakposs.</para>
+ </listitem>
+ </itemizedlist></para>
+ </section>
+
+ <section>
+ <title><literal>TextLayoutManager.makeBreakPoss</literal></title>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>Make word <literal>ipd</literal> into a
+ <literal>MinOptMax</literal> object.</para>
+ </listitem>
+ <listitem>
+ <para>Add space <literal>ipd</literal> to it.</para>
+ </listitem>
+ <listitem>
+ <para>Add total <literal>ipd</literal> from previous texts
+ to it.</para>
+ </listitem>
+ <listitem>
+ <para>Create an <literal>AreaInfo</literal> object for this
+text fragment and add it to the vector of <literal>AreaInfo</literal>
+objects.</para>
+ </listitem>
+ <listitem>
+ <para>Create a breakposs for this text fragment.</para>
+ </listitem>
+ <listitem>
+ <para>Set the total <literal>ipd</literal> to the current
+ <literal>ipd</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>If the flags contain
+<literal>BreakPoss.HYPHENATED</literal>, set the stacking size to the
+<literal>ipd</literal> plus the width of the hyphen character,</para>
+ </listitem>
+ <listitem>
+ <para>Else set the stacking size to the
+ <literal>ipd</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>Set the non-stacking size to the line height, from the
+ text info.</para>
+ </listitem>
+ <listitem>
+ <para>Register the descender and ascender with the breakposs
+object; this is currently commented out.</para>
+ </listitem>
+ <listitem>
+ <para>If this is the end of the text, <itemizedlist spacing="compact">
+ <listitem>
+ <para>add <literal>BreakPoss.ISLAST</literal> to the
+ flags,</para>
+ </listitem>
+ <listitem>
+ <para>declare the LM finished.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ <listitem>
+ <para>Register the flags with the breakposs object</para>
+ </listitem>
+ <listitem>
+ <para>Register the pending space or the absence thereof with
+the breakposs object.</para>
+ </listitem>
+ <listitem>
+ <para>Register the leading space or the absence thereof with
+the breakposs object.</para>
+ </listitem>
+ <listitem>
+ <para>Return the breakposs object.</para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
+ </chapter>
+
+<!-- Local Variables: -->
+<!-- current-language-environment: UTF-8 -->
+<!-- coding: utf-8 -->
+<!-- default-input-method: TeX -->
+<!-- End: -->