You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2005/08/12 11:50:32 UTC

svn commit: r232250 [1/2] - in /xmlgraphics/fop/trunk: src/java/org/apache/fop/area/ src/java/org/apache/fop/area/inline/ src/java/org/apache/fop/fo/ src/java/org/apache/fop/fo/flow/ src/java/org/apache/fop/layoutmgr/ src/java/org/apache/fop/layoutmgr/...

Author: jeremias
Date: Fri Aug 12 02:50:01 2005
New Revision: 232250

URL: http://svn.apache.org/viewcvs?rev=232250&view=rev
Log:
Merged branch https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/inlineblock back into Trunk.
Revisions: 227462 to HEAD (231261)

This adds support for block-level content inside fo:inline.

The full set of changes on the branch can be extracted by:
svn log http://svn.apache.org/repos/asf/xmlgraphics/fop/branches/inlineblock -r 227462:231261

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/area/inline/InlineBlockParent.java
      - copied unchanged from r232242, xmlgraphics/fop/branches/inlineblock/src/java/org/apache/fop/area/inline/InlineBlockParent.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/NullCharIterator.java
      - copied unchanged from r232242, xmlgraphics/fop/branches/inlineblock/src/java/org/apache/fop/fo/NullCharIterator.java
    xmlgraphics/fop/trunk/test/layoutengine/testcases/inline-block1.xml
      - copied unchanged from r232242, xmlgraphics/fop/branches/inlineblock/test/layoutengine/testcases/inline-block1.xml
    xmlgraphics/fop/trunk/test/layoutengine/testcases/inline-block2.xml
      - copied unchanged from r232242, xmlgraphics/fop/branches/inlineblock/test/layoutengine/testcases/inline-block2.xml
Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/Block.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/KnuthSequence.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/LayoutContext.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractRenderer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/xml/XMLRenderer.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/logging/LoggingElementListObserver.java
    xmlgraphics/fop/trunk/test/layoutengine/disabled-testcases.txt
    xmlgraphics/fop/trunk/test/layoutengine/testcases/inline1.xml

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/area/LineArea.java Fri Aug 12 02:50:01 2005
@@ -91,5 +91,19 @@
     public int getStartIndent() {
         return startIndent;
     }
+
+    /**
+     * Updates the extents of the line area from its children.
+     */
+    public void updateExtentsFromChildren() {
+        int ipd = 0;
+        int bpd = 0;
+        for (int i = 0, len = inlineAreas.size(); i < len; i++) {
+            ipd = Math.max(ipd, ((InlineArea)inlineAreas.get(i)).getAllocIPD());
+            bpd += ((InlineArea)inlineAreas.get(i)).getAllocBPD();
+        }
+        setIPD(ipd);
+        setBPD(bpd);
+    }
 }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/Block.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/Block.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/Block.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/Block.java Fri Aug 12 02:50:01 2005
@@ -29,6 +29,7 @@
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.FOText;
 import org.apache.fop.fo.FObjMixed;
+import org.apache.fop.fo.NullCharIterator;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.PropertySets;
 import org.apache.fop.fo.RecursiveCharIterator;
@@ -507,6 +508,11 @@
         }
     }
      
+    /** @see org.apache.fop.fo.FONode#charIterator() */
+    public CharIterator charIterator() {
+        return NullCharIterator.getInstance();
+    }
+
     /**
      * @see org.apache.fop.fo.FONode#getName()
      */

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java Fri Aug 12 02:50:01 2005
@@ -187,6 +187,7 @@
             alignment = Constants.EN_START;
         }
         alignmentLast = Constants.EN_START;
+        childLC.setBPAlignment(alignment);
 
         BlockSequence blockList;
         blockLists = new java.util.ArrayList();

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java Fri Aug 12 02:50:01 2005
@@ -166,7 +166,10 @@
      */
     public boolean mustKeepTogether() {
         //TODO Keeps will have to be more sophisticated sooner or later
-        return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() 
+        // TODO This is a quick fix for the fact that the parent is not always a BlockLevelLM;
+        // eventually mustKeepTogether() must be moved up to the LM interface
+        return (getParent() instanceof BlockLevelLayoutManager
+                && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) 
                 || !getBlockFO().getKeepTogether().getWithinPage().isAuto()
                 || !getBlockFO().getKeepTogether().getWithinColumn().isAuto();
     }
@@ -303,7 +306,7 @@
                     splitLength += element.getW();
                     lastLM = element.getLayoutManager();
                 }
-                }
+            }
             //System.out.println("addAreas riferito a storedList da " +
                   // iFirst + " a " + iLast);
             //System.out.println("splitLength= " + splitLength

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/KnuthSequence.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/KnuthSequence.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/KnuthSequence.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/KnuthSequence.java Fri Aug 12 02:50:01 2005
@@ -28,6 +28,8 @@
     public int ignoreAtStart = 0;
     /** Number of elements to ignore at the end of the list. */
     public int ignoreAtEnd = 0;
+    // Is this an inline or a block sequence?
+    private boolean isInlineSequence = false;
 
     /**
      * Creates a new and empty list.
@@ -37,6 +39,14 @@
     }
 
     /**
+     * Creates a new and empty list, and sets isInlineSequence.
+     */
+    public KnuthSequence(boolean isInlineSequence) {
+        super();
+        this.isInlineSequence = isInlineSequence;
+    }
+
+    /**
      * Marks the start of the sequence.
      */
     public void startSequence() {
@@ -83,5 +93,13 @@
 
     public KnuthElement getElement(int index) {
         return (KnuthElement) get(index);
+    }
+
+    /**
+     * Is this an inline or a block sequence?
+     * @return true if this is an inline sequence
+     */
+    public boolean isInlineSequence() {
+        return isInlineSequence;
     }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/LayoutContext.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/LayoutContext.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/LayoutContext.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/LayoutContext.java Fri Aug 12 02:50:01 2005
@@ -91,6 +91,9 @@
     /** Current hyphenation context. May be null. */
     private HyphContext hyphContext = null;
 
+    /** Alignment in BP direction */
+    private int bpAlignment = Constants.EN_START;
+    
     /** Stretch or shrink value when making areas. */
     private double ipdAdjust = 0.0;
 
@@ -112,6 +115,7 @@
         this.leadingSpace = parentLC.leadingSpace; //???
         this.trailingSpace = parentLC.trailingSpace; //???
         this.hyphContext = parentLC.hyphContext;
+        this.bpAlignment = parentLC.bpAlignment;
         this.dSpaceAdjust = parentLC.dSpaceAdjust;
         this.ipdAdjust = parentLC.ipdAdjust;
         this.iLineHeight = parentLC.iLineHeight;
@@ -224,6 +228,19 @@
         return ((this.flags & TRY_HYPHENATE) != 0);
     }
 
+    /**
+     * Sets the currently applicable alignment in BP direction.
+     * @param alignment one of EN_START, EN_JUSTIFY etc.
+     */
+    public void setBPAlignment(int alignment) {
+        this.bpAlignment = alignment;
+    }
+    
+    /** @return the currently applicable alignment in BP direction (EN_START, EN_JUSTIFY...) */
+    public int getBPAlignment() {
+        return this.bpAlignment;
+    }
+    
     public void setSpaceAdjust(double adjust) {
         dSpaceAdjust = adjust;
     }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java Fri Aug 12 02:50:01 2005
@@ -20,6 +20,7 @@
 
 import org.apache.fop.fo.flow.BasicLink;
 import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineParent;
 import org.apache.fop.area.Trait;
 import org.apache.fop.area.LinkResolver;
@@ -41,14 +42,14 @@
         fobj = node;
     }
 
-    protected InlineParent createArea() {
-        InlineParent area = super.createArea();
+    protected InlineArea createArea(boolean bInlineParent) {
+        InlineArea area = super.createArea(bInlineParent);
         setupBasicLinkArea(parentLM, area);
         return area;
     }
     
     private void setupBasicLinkArea(LayoutManager parentLM,
-                                      InlineParent area) {
+                                      InlineArea area) {
          if (fobj.getExternalDestination() != null) {
              area.addTrait(Trait.EXTERNAL_LINK, fobj.getExternalDestination());
          } else {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java Fri Aug 12 02:50:01 2005
@@ -26,6 +26,7 @@
 import org.apache.fop.layoutmgr.AbstractLayoutManager;
 import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
 import org.apache.fop.layoutmgr.KnuthElement;
+import org.apache.fop.layoutmgr.KnuthSequence;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.Position;
 
@@ -45,7 +46,7 @@
         footnote = node;
 
         // create an InlineStackingLM handling the fo:inline child of fo:footnote
-        citationLM = new InlineStackingLayoutManager(footnote.getFootnoteCitation());
+        citationLM = new InlineLayoutManager(footnote.getFootnoteCitation());
 
         // create a FootnoteBodyLM handling the fo:footnote-body child of fo:footnote
         bodyLM = new FootnoteBodyLayoutManager(footnote.getFootnoteBody());
@@ -85,12 +86,24 @@
     private void addAnchor(LinkedList citationList) {
         // find the last box in the sequence, and add a reference
         // to the FootnoteBodyLM
-        ListIterator citationIterator = citationList.listIterator(citationList.size());
         KnuthInlineBox lastBox = null;
+        ListIterator citationIterator = citationList.listIterator(citationList.size());
         while (citationIterator.hasPrevious() && lastBox == null) {
-            KnuthElement element = (KnuthElement) citationIterator.previous();
-            if (element instanceof KnuthInlineBox) {
-                lastBox = (KnuthInlineBox) element;
+            Object obj = citationIterator.previous();
+            if (obj instanceof KnuthElement) {
+                KnuthElement element = (KnuthElement)obj;
+                if (element instanceof KnuthInlineBox) {
+                    lastBox = (KnuthInlineBox) element;
+                }
+            } else {
+                KnuthSequence seq = (KnuthSequence)obj;
+                ListIterator nestedIterator = seq.listIterator(seq.size());
+                while (nestedIterator.hasPrevious() && lastBox == null) {
+                    KnuthElement element = (KnuthElement)nestedIterator.previous();
+                    if (element instanceof KnuthInlineBox) {
+                        lastBox = (KnuthInlineBox) element;
+                    }
+                }
             }
         }
         if (lastBox != null) {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java Fri Aug 12 02:50:01 2005
@@ -21,6 +21,9 @@
 import java.util.ListIterator;
 import java.util.LinkedList;
 
+import org.apache.fop.area.Area;
+import org.apache.fop.area.inline.InlineArea;
+import org.apache.fop.area.inline.InlineBlockParent;
 import org.apache.fop.area.inline.InlineParent;
 import org.apache.fop.fo.flow.Inline;
 import org.apache.fop.fo.flow.InlineLevel;
@@ -28,10 +31,14 @@
 import org.apache.fop.fo.properties.CommonMarginInline;
 import org.apache.fop.fo.properties.SpaceProperty;
 import org.apache.fop.layoutmgr.KnuthElement;
+import org.apache.fop.layoutmgr.KnuthSequence;
+import org.apache.fop.layoutmgr.KnuthPenalty;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.layoutmgr.SpaceSpecifier;
 import org.apache.fop.layoutmgr.TraitSetter;
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.PositionIterator;
 import org.apache.fop.traits.MinOptMax;
 import org.apache.fop.traits.SpaceVal;
 
@@ -46,6 +53,9 @@
     private CommonMarginInline inlineProps = null;
     private CommonBorderPaddingBackground borderProps = null;
 
+    private boolean bAreaCreated = false;
+    private LayoutManager lastChildLM = null; // Set when return last breakposs;
+
     /**
      * Create an inline layout manager.
      * This is used for fo's that create areas that
@@ -109,8 +119,14 @@
     }
     
     /** @see org.apache.fop.layoutmgr.inline.InlineStackingLayoutManager#createArea() */
-    protected InlineParent createArea() {
-        InlineParent area = super.createArea(); 
+    protected InlineArea createArea(boolean bInlineParent) {
+        InlineArea area;
+        if (bInlineParent) {
+            area = new InlineParent();
+            area.setOffset(0);
+        } else {
+            area = new InlineBlockParent();
+        }
         TraitSetter.setProducerID(area, getInlineFO().getId());
         return area;
     }
@@ -132,7 +148,8 @@
 
     /** @see org.apache.fop.layoutmgr.LayoutManager */
     public LinkedList getNextKnuthElements(LayoutContext lc, int alignment) {
-        InlineLevelLayoutManager curLM;
+        InlineLevelLayoutManager curILM;
+        LayoutManager curLM, lastLM = null;
 
         // the list returned by child LM
         LinkedList returnedList;
@@ -140,6 +157,7 @@
 
         // the list which will be returned to the parent LM
         LinkedList returnList = new LinkedList();
+        KnuthSequence lastSequence = null;
 
         SpaceSpecifier leadingSpace = lc.getLeadingSpace();
 
@@ -160,27 +178,236 @@
             clearPrevIPD(); // Clear stored prev content dimensions
         }
 
-        while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
+        StringBuffer trace = new StringBuffer("InlineLM:");
+
+        while ((curLM = (LayoutManager) getChildLM()) != null) {
             // get KnuthElements from curLM
             returnedList = curLM.getNextKnuthElements(lc, alignment);
-            if (returnedList != null) {
+            if (returnedList == null) {
+                // curLM returned null because it finished;
+                // just iterate once more to see if there is another child
+                continue;
+            }
+            if (curLM instanceof InlineLevelLayoutManager) {
+                // close the last block sequence 
+                if (lastSequence != null && !lastSequence.isInlineSequence()) {
+                    lastSequence = null;
+                    if (log.isTraceEnabled()) {
+                        trace.append(" ]");
+                    }
+                }
                 // "wrap" the Position stored in each element of returnedList
-                ListIterator listIter = returnedList.listIterator();
-                while (listIter.hasNext()) {
-                    returnedElement = (KnuthElement) listIter.next();
-                    returnedElement.setPosition
+                ListIterator seqIter = returnedList.listIterator();
+                while (seqIter.hasNext()) {
+                    KnuthSequence sequence = (KnuthSequence) seqIter.next();
+                    ListIterator listIter = sequence.listIterator();
+                    while (listIter.hasNext()) {
+                        returnedElement = (KnuthElement) listIter.next();
+                        returnedElement.setPosition
                         (new NonLeafPosition(this,
-                                             returnedElement.getPosition()));
-                    returnList.add(returnedElement);
+                                returnedElement.getPosition()));
+                    }
+                    if (!sequence.isInlineSequence()) {
+                        if (lastSequence != null && lastSequence.isInlineSequence()) {
+                            // log.error("Last inline sequence should be closed before a block sequence");
+                            lastSequence.add(new KnuthPenalty(0, -KnuthElement.INFINITE,
+                                                   false, null, false));
+                            lastSequence = null;
+                            if (log.isTraceEnabled()) {
+                                trace.append(" ]");
+                            }
+                        }
+                        returnList.add(sequence);
+                        if (log.isTraceEnabled()) {
+                            trace.append(" B");
+                        }
+                    } else {
+                        if (lastSequence == null) {
+                            lastSequence = new KnuthSequence(true);
+                            returnList.add(lastSequence);
+                            if (log.isTraceEnabled()) {
+                                trace.append(" [");
+                            }
+                        } else {
+                            if (log.isTraceEnabled()) {
+                                trace.append(" +");
+                            }
+                        }
+                        lastSequence.addAll(sequence);
+                        if (log.isTraceEnabled()) {
+                            trace.append(" I");
+                        }
+                       // finish last paragraph if it was closed with a linefeed
+                        KnuthElement lastElement = (KnuthElement) sequence.getLast();
+                        if (lastElement.isPenalty()
+                                && ((KnuthPenalty) lastElement).getP()
+                                == -KnuthPenalty.INFINITE) {
+                            // a penalty item whose value is -inf
+                            // represents a preserved linefeed,
+                            // wich forces a line break
+                            lastSequence = null;
+                            if (log.isTraceEnabled()) {
+                                trace.append(" ]");
+                            }
+                        }
+                    }
+                }
+            } else { // A block LM
+                // close the last inline sequence 
+                if (lastSequence != null && lastSequence.isInlineSequence()) {
+                    lastSequence.add(new KnuthPenalty(0, -KnuthElement.INFINITE,
+                                           false, null, false));
+                    lastSequence = null;
+                    if (log.isTraceEnabled()) {
+                        trace.append(" ]");
+                    }
+                }
+                if (curLM != lastLM) {
+                    // close the last block sequence
+                    if (lastSequence != null && !lastSequence.isInlineSequence()) {
+                        lastSequence = null;
+                        if (log.isTraceEnabled()) {
+                            trace.append(" ]");
+                        }
+                    }
+                    lastLM = curLM;
+                }
+                if (lastSequence == null) {
+                    lastSequence = new KnuthSequence(false);
+                    returnList.add(lastSequence);
+                    if (log.isTraceEnabled()) {
+                        trace.append(" [");
+                    }
+                } else {
+                    if (log.isTraceEnabled()) {
+                        trace.append(" +");
+                    }
+                }
+                ListIterator iter = returnedList.listIterator();
+                while (iter.hasNext()) {
+                    KnuthElement element = (KnuthElement) iter.next();
+                    element.setPosition
+                    (new NonLeafPosition(this,
+                            element.getPosition()));
+                }
+                lastSequence.addAll(returnedList);
+                if (log.isTraceEnabled()) {
+                    trace.append(" L");
                 }
-                return returnList;
-            } else {
-                // curLM returned null because it finished;
-                // just iterate once more to see if there is another child
             }
         }
         setFinished(true);
-        return null;
+        log.trace(trace);
+        return returnList.size() == 0 ? null : returnList;
+    }
+
+    /**
+     * Generate and add areas to parent area.
+     * Set size of each area. This should only create and return one
+     * inline area for any inline parent area.
+     *
+     * @param parentIter Iterator over Position information returned
+     * by this LayoutManager.
+     * @param dSpaceAdjust Factor controlling how much extra space to add
+     * in order to justify the line.
+     */
+    public void addAreas(PositionIterator parentIter,
+                         LayoutContext context) {
+        addId();
+
+        setChildContext(new LayoutContext(context)); // Store current value
+
+        // If has fence, make a new leadingSS
+        /* How to know if first area created by this LM? Keep a count and
+         * reset it if getNextBreakPoss() is called again.
+         */
+        if (hasLeadingFence(bAreaCreated)) {
+            getContext().setLeadingSpace(new SpaceSpecifier(false));
+            getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE,
+                                  true);
+        } else {
+            getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE,
+                                  false);
+        }
+
+        if (getSpaceStart() != null) {
+            context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart()));
+        }
+
+        // "unwrap" the NonLeafPositions stored in parentIter
+        // and put them in a new list; 
+        // also set lastLM to be the LayoutManager which created
+        // the last Position: if the LAST_AREA flag is set in context,
+        // it must be also set in the LayoutContext given to lastLM,
+        // but unset in the LayoutContext given to the other LMs
+        LinkedList positionList = new LinkedList();
+        NonLeafPosition pos = null;
+        LayoutManager lastLM = null; // last child LM in this iterator
+        while (parentIter.hasNext()) {
+            pos = (NonLeafPosition) parentIter.next();
+            positionList.add(pos.getPosition());
+        }
+        if (pos != null) {
+            lastLM = pos.getPosition().getLM();
+        }
+
+        InlineArea parent = createArea(lastLM == null || lastLM instanceof InlineLevelLayoutManager);
+        parent.setBPD(context.getLineHeight());
+        setCurrentArea(parent);
+        
+        StackingIter childPosIter
+            = new StackingIter(positionList.listIterator());
+
+        LayoutManager prevLM = null;
+        LayoutManager childLM;
+        while ((childLM = childPosIter.getNextChildLM())
+               != null) {
+            getContext().setFlags(LayoutContext.LAST_AREA,
+                                  context.isLastArea() && childLM == lastLM);
+            childLM.addAreas(childPosIter, getContext());
+            getContext().setLeadingSpace(getContext().getTrailingSpace());
+            getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
+            prevLM = childLM;
+        }
+
+        /* If has trailing fence,
+         * resolve trailing space specs from descendants.
+         * Otherwise, propagate any trailing space specs to parent LM via
+         * the context object.
+         * If the last child LM called return ISLAST in the context object
+         * and it is the last child LM for this LM, then this must be
+         * the last area for the current LM also.
+         */
+        boolean bIsLast =
+          (getContext().isLastArea() && prevLM == lastChildLM);
+        if (hasTrailingFence(bIsLast)) {
+            addSpace(getCurrentArea(),
+                     getContext().getTrailingSpace().resolve(false),
+                     getContext().getSpaceAdjust());
+            context.setTrailingSpace(new SpaceSpecifier(false));
+        } else {
+            // Propagate trailing space-spec sequence to parent LM in context
+            context.setTrailingSpace(getContext().getTrailingSpace());
+        }
+        // Add own trailing space to parent context (or set on area?)
+        if (context.getTrailingSpace() != null  && getSpaceEnd() != null) {
+            context.getTrailingSpace().addSpace(new SpaceVal(getSpaceEnd()));
+        }
+        setTraits(bAreaCreated, !bIsLast);
+        
+        parentLM.addChildArea(getCurrentArea());
+        context.setFlags(LayoutContext.LAST_AREA, bIsLast);
+        bAreaCreated = true;
+    }
+
+    public void addChildArea(Area childArea) {
+        Area parent = getCurrentArea();
+        if (getContext().resolveLeadingSpace()) {
+            addSpace(parent,
+                    getContext().getLeadingSpace().resolve(false),
+                    getContext().getSpaceAdjust());
+        }
+        parent.addChildArea(childArea);
     }
 
     /*

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java Fri Aug 12 02:50:01 2005
@@ -33,11 +33,7 @@
 import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.layoutmgr.Position;
 import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.SpaceSpecifier;
-import org.apache.fop.traits.SpaceVal;
 import org.apache.fop.area.Area;
-import org.apache.fop.area.inline.InlineArea;
-import org.apache.fop.area.inline.InlineParent;
 import org.apache.fop.area.inline.Space;
 import org.apache.fop.traits.MinOptMax;
 
@@ -50,7 +46,7 @@
                                          implements InlineLevelLayoutManager {
 
 
-    private static class StackingIter extends PositionIterator {
+    protected static class StackingIter extends PositionIterator {
 
         StackingIter(Iterator parentIter) {
             super(parentIter);
@@ -81,7 +77,6 @@
     //private BreakPoss prevBP;
     protected LayoutContext childLC;
 
-    private LayoutManager lastChildLM = null; // Set when return last breakposs
     private boolean bAreaCreated = false;
 
     //private LayoutManager currentLM = null;
@@ -177,10 +172,6 @@
         hmPrevIPD.clear();
     }
 
-    protected InlineParent createArea() {
-        return new InlineParent();
-    }
-
     /**
      * This method is called by addAreas() so IDs can be added to a page for FOs that 
      * support the 'id' property.
@@ -189,103 +180,6 @@
         // Do nothing here, overriden in subclasses that have an 'id' property.
     }
     
-    /**
-     * Generate and add areas to parent area.
-     * Set size of each area. This should only create and return one
-     * inline area for any inline parent area.
-     *
-     * @param parentIter Iterator over Position information returned
-     * by this LayoutManager.
-     * @param dSpaceAdjust Factor controlling how much extra space to add
-     * in order to justify the line.
-     */
-    public void addAreas(PositionIterator parentIter,
-                         LayoutContext context) {
-        addId();
-        InlineParent parent = createArea();
-        parent.setBPD(context.getLineHeight());
-        parent.setOffset(0);
-        setCurrentArea(parent);
-
-        setChildContext(new LayoutContext(context)); // Store current value
-
-        // If has fence, make a new leadingSS
-        /* How to know if first area created by this LM? Keep a count and
-         * reset it if getNextBreakPoss() is called again.
-         */
-        if (hasLeadingFence(bAreaCreated)) {
-            getContext().setLeadingSpace(new SpaceSpecifier(false));
-            getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE,
-                                  true);
-        } else {
-            getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE,
-                                  false);
-        }
-
-        if (getSpaceStart() != null) {
-            context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart()));
-        }
-
-        // "unwrap" the NonLeafPositions stored in parentIter
-        // and put them in a new list; 
-        // also set lastLM to be the LayoutManager which created
-        // the last Position: if the LAST_AREA flag is set in context,
-        // it must be also set in the LayoutContext given to lastLM,
-        // but unset in the LayoutContext given to the other LMs
-        LinkedList positionList = new LinkedList();
-        NonLeafPosition pos;
-        LayoutManager lastLM = null; // last child LM in this iterator
-        while (parentIter.hasNext()) {
-            pos = (NonLeafPosition) parentIter.next();
-            lastLM = pos.getPosition().getLM();
-            positionList.add(pos.getPosition());
-        }
-
-        StackingIter childPosIter
-            = new StackingIter(positionList.listIterator());
-
-        LayoutManager prevLM = null;
-        InlineLevelLayoutManager childLM;
-        while ((childLM = (InlineLevelLayoutManager) childPosIter.getNextChildLM())
-               != null) {
-            getContext().setFlags(LayoutContext.LAST_AREA,
-                                  context.isLastArea() && childLM == lastLM);
-            childLM.addAreas(childPosIter, getContext());
-            getContext().setLeadingSpace(getContext().getTrailingSpace());
-            getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
-            prevLM = childLM;
-        }
-
-        /* If has trailing fence,
-         * resolve trailing space specs from descendants.
-         * Otherwise, propagate any trailing space specs to parent LM via
-         * the context object.
-         * If the last child LM called return ISLAST in the context object
-         * and it is the last child LM for this LM, then this must be
-         * the last area for the current LM also.
-         */
-        boolean bIsLast =
-          (getContext().isLastArea() && prevLM == lastChildLM);
-        if (hasTrailingFence(bIsLast)) {
-            addSpace(getCurrentArea(),
-                     getContext().getTrailingSpace().resolve(false),
-                     getContext().getSpaceAdjust());
-            context.setTrailingSpace(new SpaceSpecifier(false));
-        } else {
-            // Propagate trailing space-spec sequence to parent LM in context
-            context.setTrailingSpace(getContext().getTrailingSpace());
-        }
-        // Add own trailing space to parent context (or set on area?)
-        if (context.getTrailingSpace() != null  && getSpaceEnd() != null) {
-            context.getTrailingSpace().addSpace(new SpaceVal(getSpaceEnd()));
-        }
-        setTraits(bAreaCreated, !bIsLast);
-        
-        parentLM.addChildArea(getCurrentArea());
-        context.setFlags(LayoutContext.LAST_AREA, bIsLast);
-        bAreaCreated = true;
-    }
-
     protected Area getCurrentArea() {
         return currentArea;
     }
@@ -298,19 +192,6 @@
         
     }
 
-    public void addChildArea(Area childArea) {
-        // Make sure childArea is inline area
-        if (childArea instanceof InlineArea) {
-            Area parent = getCurrentArea();
-            if (getContext().resolveLeadingSpace()) {
-                addSpace(parent,
-                         getContext().getLeadingSpace().resolve(false),
-                         getContext().getSpaceAdjust());
-            }
-            parent.addChildArea(childArea);
-        }
-    }
-
     protected void setChildContext(LayoutContext lc) {
         childLC = lc;
     }
@@ -342,57 +223,6 @@
         }
     }
 
-    public LinkedList getNextKnuthElements(LayoutContext lc, int alignment) {
-        InlineLevelLayoutManager curLM;
-
-        // the list returned by child LM
-        LinkedList returnedList;
-        KnuthElement returnedElement;
-
-        // the list which will be returned to the parent LM
-        LinkedList returnList = new LinkedList();
-
-        SpaceSpecifier leadingSpace = lc.getLeadingSpace();
-
-        if (lc.startsNewArea()) {
-            // First call to this LM in new parent "area", but this may
-            // not be the first area created by this inline
-            childLC = new LayoutContext(lc);
-            lc.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart()));
-
-            // Check for "fence"
-            if (hasLeadingFence(!lc.isFirstArea())) {
-                // Reset leading space sequence for child areas
-                leadingSpace = new SpaceSpecifier(false);
-            }
-            // Reset state variables
-            clearPrevIPD(); // Clear stored prev content dimensions
-        }
-
-        while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
-            // get KnuthElements from curLM
-            returnedList = curLM.getNextKnuthElements(lc, alignment);
-            if (returnedList != null) {
-                // "wrap" the Position stored in each element of returnedList
-                ListIterator listIter = returnedList.listIterator();
-                while (listIter.hasNext()) {
-                    returnedElement = (KnuthElement) listIter.next();
-                    returnedElement.setPosition
-                        (new NonLeafPosition(this,
-                                             returnedElement.getPosition()));
-                    returnList.add(returnedElement);
-                }
-                setFinished(curLM.isFinished() && (getChildLM() == null));
-                return returnList;
-            } else {
-                // curLM returned null because it finished;
-                // just iterate once more to see if there is another child
-            }
-        }
-        setFinished(true);
-        return null;
-    }
-
     public List addALetterSpaceTo(List oldList) {
         // old list contains only a box, or the sequence: box penalty glue box
 
@@ -407,7 +237,7 @@
         oldList = ((InlineLevelLayoutManager)
                    element.getLayoutManager()).addALetterSpaceTo(oldList);
 
-        // "wrap" againg the Position stored in each element of oldList
+        // "wrap" again the Position stored in each element of oldList
         oldListIterator = oldList.listIterator();
         while (oldListIterator.hasNext()) {
             element = (KnuthElement) oldListIterator.next();

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java Fri Aug 12 02:50:01 2005
@@ -37,10 +37,13 @@
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.LayoutManager;
 import org.apache.fop.layoutmgr.LeafPosition;
+import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.layoutmgr.Position;
 import org.apache.fop.layoutmgr.PositionIterator;
 import org.apache.fop.layoutmgr.SpaceSpecifier;
+import org.apache.fop.area.Area;
 import org.apache.fop.area.LineArea;
+import org.apache.fop.area.inline.InlineArea;
 
 import java.util.ListIterator;
 import java.util.List;
@@ -184,7 +187,7 @@
 
         public Paragraph(LineLayoutManager llm, int alignment, int alignmentLast,
                          int indent) {
-            super();
+            super(true);
             layoutManager = llm;
             textAlignment = alignment;
             textAlignmentLast = alignmentLast;
@@ -268,6 +271,40 @@
             }
         }
 
+        private void addALetterSpace() {
+            KnuthBox prevBox = (KnuthBox) removeLast();
+            LinkedList oldList = new LinkedList();
+            // if there are two consecutive KnuthBoxes the
+            // first one does not represent a whole word,
+            // so it must be given one more letter space
+            if (!prevBox.isAuxiliary()) {
+                // if letter spacing is constant,
+                // only prevBox needs to be replaced;
+                oldList.add(prevBox);
+            } else {
+                // prevBox is the last element
+                // in the sub-sequence
+                //   <box> <aux penalty> <aux glue> <aux box>
+                // the letter space is added to <aux glue>,
+                // while the other elements are not changed
+                oldList.add(prevBox);
+                oldList.addFirst((KnuthGlue) removeLast());
+                oldList.addFirst((KnuthPenalty) removeLast());
+                oldList.addFirst((KnuthBox) removeLast());
+            }
+            // adding a letter space could involve, according to the text
+            // represented by oldList, replacing a glue element or adding
+            // new elements
+            addAll(((InlineLevelLayoutManager)
+                         prevBox.getLayoutManager())
+                        .addALetterSpaceTo(oldList));
+            if (((KnuthInlineBox) prevBox).isAnchor()) {
+                // prevBox represents a footnote citation: copy footnote info
+                // from prevBox to the new box
+                KnuthInlineBox newBox = (KnuthInlineBox) getLast();
+                newBox.setFootnoteBodyLM(((KnuthInlineBox) prevBox).getFootnoteBodyLM());
+            }
+        }
     }
 
     private class LineBreakingAlgorithm extends BreakingAlgorithm {
@@ -510,6 +547,7 @@
         initialize(); // Normally done when started by parent!
     }
 
+    /** @see org.apache.fop.layoutmgr.LayoutManager */
     public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
         // Get a break from currently active child LM
         // Set up constraints for inline level managers
@@ -546,7 +584,7 @@
         }
 
         //PHASE 2: Create line breaks
-        return findOptimalLineBreakingPoints(alignment);
+        return createLineBreaks(context.getBPAlignment());
         /*
         LineBreakPosition lbp = null;
         if (breakpoints == null) {
@@ -586,19 +624,17 @@
         LayoutContext inlineLC = new LayoutContext(context);
 
         InlineLevelLayoutManager curLM;
-        KnuthElement thisElement = null;
         LinkedList returnedList = null;
         iLineWidth = context.getStackLimit().opt;
 
         // convert all the text in a sequence of paragraphs made
         // of KnuthBox, KnuthGlue and KnuthPenalty objects
         boolean bPrevWasKnuthBox = false;
-        KnuthBox prevBox = null;
 
-        Paragraph knuthPar = new Paragraph(this, 
-                                           bTextAlignment, bTextAlignmentLast, 
-                                           textIndent.getValue());
-        knuthPar.startParagraph(availIPD.opt);
+        StringBuffer trace = new StringBuffer("LineLM:");
+
+        Paragraph lastPar = null;
+
         while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
             if ((returnedList
                  = curLM.getNextKnuthElements(inlineLC,
@@ -607,78 +643,119 @@
                 if (returnedList.size() == 0) {
                     continue;
                 }
-                // look at the first element
-                thisElement = (KnuthElement) returnedList.getFirst();
-                if (thisElement.isBox() && !thisElement.isAuxiliary()
-                    && bPrevWasKnuthBox) {
-                    prevBox = (KnuthBox) knuthPar.removeLast();
-                    LinkedList oldList = new LinkedList();
-                    // if there are two consecutive KnuthBoxes the
-                    // first one does not represent a whole word,
-                    // so it must be given one more letter space
-                    if (!prevBox.isAuxiliary()) {
-                        // if letter spacing is constant,
-                        // only prevBox needs to be replaced;
-                        oldList.add(prevBox);
+                // does the first element of the first paragraph add to an existing word?
+                if (lastPar != null) {
+                    Object obj = returnedList.getFirst();
+                    KnuthElement thisElement;
+                    if (obj instanceof KnuthElement) {
+                        thisElement = (KnuthElement)obj;
                     } else {
-                        // prevBox is the last element
-                        // in the sub-sequence
-                        //   <box> <aux penalty> <aux glue> <aux box>
-                        // the letter space is added to <aux glue>,
-                        // while the other elements are not changed
-                        oldList.add(prevBox);
-                        oldList.addFirst((KnuthGlue) knuthPar.removeLast());
-                        oldList.addFirst((KnuthPenalty) knuthPar.removeLast());
-                        oldList.addFirst((KnuthBox) knuthPar.removeLast());
+                        KnuthSequence firstSeq = (KnuthSequence) obj;
+                        if (!firstSeq.isInlineSequence()) {
+                            log.error("Expect inline sequence as first sequence when last paragraph is not null");
+                        }
+                        thisElement = (KnuthElement) firstSeq.get(0);
                     }
-                    // adding a letter space could involve, according to the text
-                    // represented by oldList, replacing a glue element or adding
-                    // new elements
-                    knuthPar.addAll(((InlineLevelLayoutManager)
-                                     prevBox.getLayoutManager())
-                                    .addALetterSpaceTo(oldList));
-                    if (((KnuthInlineBox) prevBox).isAnchor()) {
-                        // prevBox represents a footnote citation: copy footnote info
-                        // from prevBox to the new box
-                        KnuthInlineBox newBox = (KnuthInlineBox) knuthPar.getLast();
-                        newBox.setFootnoteBodyLM(((KnuthInlineBox) prevBox).getFootnoteBodyLM());
+                    if (thisElement.isBox() && !thisElement.isAuxiliary()
+                            && bPrevWasKnuthBox) {
+                        lastPar.addALetterSpace();
                     }
                 }
 
-                // look at the last element
-                KnuthElement lastElement = (KnuthElement) returnedList.getLast();
-                boolean bForceLinefeed = false;
-                if (lastElement.isBox()) {
-                    bPrevWasKnuthBox = true;
-                } else {
-                    bPrevWasKnuthBox = false;
-                    if (lastElement.isPenalty()
-                        && ((KnuthPenalty) lastElement).getP()
-                            == -KnuthPenalty.INFINITE) {
-                        // a penalty item whose value is -inf
-                        // represents a preserved linefeed,
-                        // wich forces a line break
-                        bForceLinefeed = true;
-                        returnedList.removeLast();
+                // loop over the KnuthSequences (and single KnuthElements) in returnedList
+                // (LeafNodeLM descendants may also skip wrapping elements in KnuthSequences
+                // to cause fewer container structures)
+                // TODO the mixture here adds a little to the complexity. Decide whether:
+                // - to leave as is and save some container instances
+                // - to use KnuthSequences exclusively (adjustments on leaf-type LMs necessary)
+                // See also FootnoteLM.addAnchor() as well as right above this comment
+                // for similar code. Or see http://svn.apache.org/viewcvs?rev=230779&view=rev 
+                ListIterator iter = returnedList.listIterator();
+                while (iter.hasNext()) {
+                    Object obj = iter.next();
+                    KnuthElement singleElement = null;
+                    KnuthSequence sequence = null;
+                    if (obj instanceof KnuthElement) {
+                        singleElement = (KnuthElement)obj;
+                    } else {
+                        sequence = (KnuthSequence)obj;
                     }
-                }
+                    // the sequence contains inline Knuth elements
+                    if (singleElement != null || sequence.isInlineSequence()) {
+                        // look at the last element 
+                        KnuthElement lastElement;
+                        if (singleElement != null) {
+                            lastElement = singleElement;
+                        } else {
+                            lastElement = (KnuthElement) sequence.getLast();
+                            if (lastElement == null) {
+                                throw new NullPointerException(
+                                        "Sequence was empty! lastElement is null");
+                            }
+                        }
+                        bPrevWasKnuthBox = lastElement.isBox();
 
-                // add the new elements to the paragraph
-                knuthPar.addAll(returnedList);
-                if (bForceLinefeed) {
-                    if (knuthPar.size() == 0) {
-                        //only a forced linefeed on this line 
-                        //-> compensate with a zero width box
-                        knuthPar.add(new KnuthInlineBox(0, 0, 0, 0,
-                                null, false));
+                        // if last paragraph is open, add the new elements to the paragraph
+                        // else this is the last paragraph
+                        if (lastPar == null) { 
+                            lastPar = new Paragraph(this, 
+                                                    bTextAlignment, bTextAlignmentLast, 
+                                                    textIndent.getValue());
+                            lastPar.startParagraph(availIPD.opt);
+                            if (log.isTraceEnabled()) {
+                                trace.append(" [");
+                            }
+                        } else {
+                            if (log.isTraceEnabled()) {
+                                trace.append(" +");
+                            }
+                        }
+                        if (singleElement != null) {
+                            lastPar.add(singleElement);
+                        } else {
+                            lastPar.addAll(sequence);
+                        }
+                        if (log.isTraceEnabled()) {
+                            trace.append(" I");
+                        }
+
+                        // finish last paragraph if it was closed with a linefeed
+                        if (lastElement.isPenalty()
+                                && ((KnuthPenalty) lastElement).getP()
+                                    == -KnuthPenalty.INFINITE) {
+                            // a penalty item whose value is -inf
+                            // represents a preserved linefeed,
+                            // wich forces a line break
+                            lastPar.removeLast();
+                            if (lastPar.size() == 0) {
+                                //only a forced linefeed on this line 
+                                //-> compensate with a zero width box
+                                lastPar.add(new KnuthInlineBox(0, 0, 0, 0,
+                                        null, false));
+                            }
+                            lastPar.endParagraph();
+                            ElementListObserver.observe(lastPar, "line", null);
+                            lastPar = null;
+                            if (log.isTraceEnabled()) {
+                                trace.append(" ]");
+                            }
+                            bPrevWasKnuthBox = false;
+                        }
+                    } else { // the sequence is a block sequence
+/*                        // "wrap" the Position stored in each element of returnedList
+                        ListIterator listIter = sequence.listIterator();
+                        while (listIter.hasNext()) {
+                            KnuthElement returnedElement = (KnuthElement) listIter.next();
+                            returnedElement.setPosition
+                                (new NonLeafPosition(this,
+                                                     returnedElement.getPosition()));
+                        }
+*/                        knuthParagraphs.add(sequence);
+                        if (log.isTraceEnabled()) {
+                            trace.append(" B");
+                        }
                     }
-                    knuthPar.endParagraph();
-                    knuthPar = new Paragraph(this, 
-                                             bTextAlignment, bTextAlignmentLast, 
-                                             textIndent.getValue());
-                    knuthPar.startParagraph(availIPD.opt);
-                    bPrevWasKnuthBox = false;
-                }
+                } // end of loop over returnedList
             } else {
                 // curLM returned null; this can happen
                 // if it has nothing more to layout,
@@ -686,8 +763,14 @@
                 // if there are other children
             }
         }
-        knuthPar.endParagraph();
-        ElementListObserver.observe(knuthPar, "line", null);
+        if (lastPar != null) {
+            lastPar.endParagraph();
+            ElementListObserver.observe(lastPar, "line", null);
+            if (log.isTraceEnabled()) {
+                trace.append(" ]");
+            }
+        }
+        log.trace(trace);
     }
 
     /**
@@ -822,121 +905,167 @@
     
     /**
      * Phase 2 of Knuth algorithm: find optimal break points.
-     * @param alignment alignmenr of the paragraph
+     * @param alignment alignment in BP direction of the paragraph
      * @return a list of Knuth elements representing broken lines
      */
-    private LinkedList findOptimalLineBreakingPoints(int alignment) {
+    private LinkedList createLineBreaks(int alignment) {
 
         // find the optimal line breaking points for each paragraph
         ListIterator paragraphsIterator
             = knuthParagraphs.listIterator(knuthParagraphs.size());
-        Paragraph currPar = null;
-        LineBreakingAlgorithm alg;
         lineLayoutsList = new ArrayList(knuthParagraphs.size());
         while (paragraphsIterator.hasPrevious()) {
-            lineLayouts = new LineLayoutPossibilities();
-            currPar = (Paragraph) paragraphsIterator.previous();
-            double maxAdjustment = 1;
-            int iBPcount = 0;
-            alg = new LineBreakingAlgorithm(alignment,
-                                            bTextAlignment, bTextAlignmentLast,
-                                            textIndent.getValue(), currPar.lineFiller.opt,
-                                            lineHeight, lead, follow, middleShift,
-                                            (knuthParagraphs.indexOf(currPar) == 0),
-                                            this);
-    
-            if (hyphProps.hyphenate == EN_TRUE) {
-                findHyphenationPoints(currPar);
-            }
-    
-            // first try
-            boolean bHyphenationAllowed = false;
-            alg.setConstantLineWidth(iLineWidth);
-            iBPcount = alg.findBreakingPoints(currPar,
-                                              maxAdjustment, false, bHyphenationAllowed);
-            if (iBPcount == 0 || alignment == EN_JUSTIFY) {
-                // if the first try found a set of breaking points, save them
-                if (iBPcount > 0) {
-                    alg.resetAlgorithm();
-                    lineLayouts.savePossibilities(false);
-                } else {
-                    // the first try failed
-                    log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment);
-                }
-    
-                // now try something different
-                log.debug("Hyphenation possible? " + (hyphProps.hyphenate == EN_TRUE));
-                if (hyphProps.hyphenate == EN_TRUE) {
-                    // consider every hyphenation point as a legal break
-                    bHyphenationAllowed = true;
-                } else {
-                    // try with a higher threshold
-                    maxAdjustment = 5;
-                }
-    
-                if ((iBPcount
-                     = alg.findBreakingPoints(currPar,
-                                              maxAdjustment, false, bHyphenationAllowed)) == 0) {
-                    // the second try failed too, try with a huge threshold
-                    // and force the algorithm to find
-                    // a set of breaking points
-                    log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment
-                                     + (hyphProps.hyphenate == EN_TRUE ? " and hyphenation" : ""));
-                    maxAdjustment = 20;
-                    iBPcount
-                        = alg.findBreakingPoints(currPar,
-                                                 maxAdjustment, true, bHyphenationAllowed);
-                }
-    
-                // use non-hyphenated breaks, when possible
-                lineLayouts.restorePossibilities();
-    
-                /* extension (not in the XSL FO recommendation): if vertical alignment
-                   is justify and the paragraph has only one layout, try using 
-                   shorter or longer lines */
-                //TODO This code snippet is disabled. Reenable?
-                if (false && alignment == EN_JUSTIFY && bTextAlignment == EN_JUSTIFY) {
-                    //System.out.println("LLM.getNextKnuthElements> layouts with more lines? " + lineLayouts.canUseMoreLines());
-                    //System.out.println("                          layouts with fewer lines? " + lineLayouts.canUseLessLines());
-                    if (!lineLayouts.canUseMoreLines()) {
-                        alg.resetAlgorithm();
-                        lineLayouts.savePossibilities(true);
-                        // try with shorter lines
-                        int savedLineWidth = iLineWidth;
-                        iLineWidth = (int) (iLineWidth * 0.95);
-                        iBPcount = alg.findBreakingPoints(currPar,
-                                 maxAdjustment, true, bHyphenationAllowed);
-                        // use normal lines, when possible
-                        lineLayouts.restorePossibilities();
-                        iLineWidth = savedLineWidth;
-                    }
-                    if (!lineLayouts.canUseLessLines()) {
-                        alg.resetAlgorithm();
-                        lineLayouts.savePossibilities(true);
-                        // try with longer lines
-                        int savedLineWidth = iLineWidth;
-                        iLineWidth = (int) (iLineWidth * 1.05);
-                        alg.setConstantLineWidth(iLineWidth);
-                        iBPcount = alg.findBreakingPoints(currPar,
-                                maxAdjustment, true, bHyphenationAllowed);
-                        // use normal lines, when possible
-                        lineLayouts.restorePossibilities();
-                        iLineWidth = savedLineWidth;
-                    }
-                    //System.out.println("LLM.getNextKnuthElements> now, layouts with more lines? " + lineLayouts.canUseMoreLines());
-                    //System.out.println("                          now, layouts with fewer lines? " + lineLayouts.canUseLessLines());
-                }
+            KnuthSequence seq = (KnuthSequence) paragraphsIterator.previous();
+            if (!seq.isInlineSequence()) {
+                lineLayouts = createBlockLineBreak(seq);
+            } else {
+                lineLayouts = findOptimalBreakingPoints(alignment, (Paragraph) seq);
             }
             lineLayoutsList.add(0, lineLayouts);
         }
         
-        
         setFinished(true);
     
         //Post-process the line breaks found
         return postProcessLineBreaks(alignment);
     }
 
+    /**
+     * create a single line layout possibility with a single linebreak
+     * for a block sequence
+     * @param seq the Knuth sequence for which the linebreak is created
+     * @return the line layout possibilities for the paragraph
+     */
+    private LineLayoutPossibilities createBlockLineBreak(KnuthSequence seq) {
+        //TODO Should this really create only a single LineBreakPosition???
+        //This creates an implicit keep-together on the nested block-level FOs.
+        lineLayouts = new LineLayoutPossibilities();
+        lineLayouts.addPossibility(1,0);
+        int lineHeight = 0, lineStretch = 0, lineShrink = 0;
+        ListIterator seqIterator = seq.listIterator();
+        while (seqIterator.hasNext()) {
+            KnuthElement element = (KnuthElement) seqIterator.next();
+            lineHeight += element.getW();
+            if (element.isGlue()) {
+                lineStretch += element.getY();
+                lineShrink += element.getZ();
+            }
+        }
+        LineBreakPosition lbp = new LineBreakPosition(this,
+                knuthParagraphs.indexOf(seq), seq.size() - 1,
+                lineShrink, lineStretch, 0, 0, 0, 0, lineHeight,
+                iLineWidth, 0, 0, 0);
+        lineLayouts.addBreakPosition(lbp, 0);
+        return lineLayouts;
+    }
+
+    /**
+     * Fint the optimal linebreaks for a paragraph
+     * @param alignment alignment of the paragraph
+     * @param currPar the Paragraph for which the linebreaks are found
+     * @return the line layout possibilities for the paragraph
+     */
+    private LineLayoutPossibilities findOptimalBreakingPoints(int alignment, Paragraph currPar) {
+        lineLayouts = new LineLayoutPossibilities();
+        double maxAdjustment = 1;
+        int iBPcount = 0;
+        LineBreakingAlgorithm alg = new LineBreakingAlgorithm(alignment,
+                bTextAlignment, bTextAlignmentLast,
+                                        textIndent.getValue(), currPar.lineFiller.opt,
+                                        lineHeight, lead, follow, middleShift,
+                                        (knuthParagraphs.indexOf(currPar) == 0),
+                                        this);
+   
+        if (hyphProps.hyphenate == EN_TRUE) {
+            findHyphenationPoints(currPar);
+        }
+   
+        // first try
+        boolean bHyphenationAllowed = false;
+        alg.setConstantLineWidth(iLineWidth);
+        iBPcount = alg.findBreakingPoints(currPar,
+                                          maxAdjustment, false, bHyphenationAllowed);
+        if (iBPcount == 0 || alignment == EN_JUSTIFY) {
+            // if the first try found a set of breaking points, save them
+            if (iBPcount > 0) {
+                alg.resetAlgorithm();
+                lineLayouts.savePossibilities(false);
+            } else {
+                // the first try failed
+                log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment);
+            }
+   
+            // now try something different
+            log.debug("Hyphenation possible? " + (hyphProps.hyphenate == EN_TRUE));
+            if (hyphProps.hyphenate == EN_TRUE) {
+                // consider every hyphenation point as a legal break
+                bHyphenationAllowed = true;
+            } else {
+                // try with a higher threshold
+                maxAdjustment = 5;
+            }
+   
+            if ((iBPcount
+                 = alg.findBreakingPoints(currPar,
+                                          maxAdjustment, false, bHyphenationAllowed)) == 0) {
+                // the second try failed too, try with a huge threshold
+                // and force the algorithm to find
+                // a set of breaking points
+                log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment
+                                 + (hyphProps.hyphenate == EN_TRUE ? " and hyphenation" : ""));
+                maxAdjustment = 20;
+                iBPcount
+                    = alg.findBreakingPoints(currPar,
+                                             maxAdjustment, true, bHyphenationAllowed);
+            }
+   
+            // use non-hyphenated breaks, when possible
+            lineLayouts.restorePossibilities();
+   
+            /* extension (not in the XSL FO recommendation): if vertical alignment
+               is justify and the paragraph has only one layout, try using 
+               shorter or longer lines */
+            //TODO This code snippet is disabled. Reenable?
+            if (false && alignment == EN_JUSTIFY && bTextAlignment == EN_JUSTIFY) {
+                //System.out.println("LLM.getNextKnuthElements> layouts with more lines? " + lineLayouts.canUseMoreLines());
+                //System.out.println("                          layouts with fewer lines? " + lineLayouts.canUseLessLines());
+                if (!lineLayouts.canUseMoreLines()) {
+                    alg.resetAlgorithm();
+                    lineLayouts.savePossibilities(true);
+                    // try with shorter lines
+                    int savedLineWidth = iLineWidth;
+                    iLineWidth = (int) (iLineWidth * 0.95);
+                    iBPcount = alg.findBreakingPoints(currPar,
+                             maxAdjustment, true, bHyphenationAllowed);
+                    // use normal lines, when possible
+                    lineLayouts.restorePossibilities();
+                    iLineWidth = savedLineWidth;
+                }
+                if (!lineLayouts.canUseLessLines()) {
+                    alg.resetAlgorithm();
+                    lineLayouts.savePossibilities(true);
+                    // try with longer lines
+                    int savedLineWidth = iLineWidth;
+                    iLineWidth = (int) (iLineWidth * 1.05);
+                    alg.setConstantLineWidth(iLineWidth);
+                    iBPcount = alg.findBreakingPoints(currPar,
+                            maxAdjustment, true, bHyphenationAllowed);
+                    // use normal lines, when possible
+                    lineLayouts.restorePossibilities();
+                    iLineWidth = savedLineWidth;
+                }
+                //System.out.println("LLM.getNextKnuthElements> now, layouts with more lines? " + lineLayouts.canUseMoreLines());
+                //System.out.println("                          now, layouts with fewer lines? " + lineLayouts.canUseLessLines());
+            }
+        }
+        return lineLayouts;
+    }
+
+    /**
+     * Creates the element list in BP direction for the broken lines.
+     * @param alignment the currently applicable vertical alignment
+     * @return the newly built element list
+     */
     private LinkedList postProcessLineBreaks(int alignment) {
     
         LinkedList returnList = new LinkedList();
@@ -949,8 +1078,22 @@
             }
         
             lineLayouts = (LineLayoutPossibilities)lineLayoutsList.get(p);
-        
-            if (alignment == EN_JUSTIFY) {
+            KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(p);
+
+            if (!seq.isInlineSequence()) {
+                LinkedList targetList = new LinkedList();
+                ListIterator listIter = seq.listIterator();
+                while (listIter.hasNext()) {
+                    KnuthElement tempElement;
+                    tempElement = (KnuthElement) listIter.next();
+                    if (tempElement.getLayoutManager() != this) {
+                        tempElement.setPosition(new NonLeafPosition(this,
+                                tempElement.getPosition()));
+                    }
+                    targetList.add(tempElement);
+                }
+                returnList.addAll(targetList); 
+            } else if (seq.isInlineSequence() && alignment == EN_JUSTIFY) {
                 /* justified vertical alignment (not in the XSL FO recommendation):
                    create a multi-layout sequence whose elements will contain 
                    a conventional Position */
@@ -975,17 +1118,28 @@
                     // create a list of the FootnoteBodyLM handling footnotes 
                     // whose citations are in this line
                     LinkedList footnoteList = new LinkedList();
-                    ListIterator elementIterator = ((Paragraph) knuthParagraphs.get(p)).listIterator(startIndex);
+                    ListIterator elementIterator = seq.listIterator(startIndex);
                     while (elementIterator.nextIndex() <= endIndex) {
                         KnuthElement element = (KnuthElement) elementIterator.next();
                         if (element instanceof KnuthInlineBox
                             && ((KnuthInlineBox) element).isAnchor()) {
                             footnoteList.add(((KnuthInlineBox) element).getFootnoteBodyLM());
+                        } else if (element instanceof KnuthBlockBox) {
+                            footnoteList.addAll(((KnuthBlockBox) element).getFootnoteBodyLMs());
                         }
                     }
                     startIndex = endIndex + 1;
-                    returnList.add(new KnuthBlockBox(((LineBreakPosition) lineLayouts.getChosenPosition(i)).lineHeight,
-                                                     footnoteList, lineLayouts.getChosenPosition(i), false));
+                    LineBreakPosition lbp = (LineBreakPosition) lineLayouts.getChosenPosition(i);
+                    returnList.add(new KnuthBlockBox(lbp.lineHeight, footnoteList, lbp, false));
+                    /* // add stretch and shrink to the returnlist
+                    if (!seq.isInlineSequence()
+                            && lbp.availableStretch != 0 || lbp.availableShrink != 0) {
+                        returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE,
+                                false, new Position(this), false));
+                        returnList.add(new KnuthGlue(0, lbp.availableStretch, lbp.availableShrink,
+                                new Position(this), false));
+                    }
+                    */
                 }
             }
         }
@@ -1403,7 +1557,7 @@
         while (parentIter.hasNext()) {
             Position pos = (Position) parentIter.next();
             if (pos instanceof LineBreakPosition) {
-                ListIterator paragraphIterator = null;
+                ListIterator seqIterator = null;
                 KnuthElement tempElement = null;
                 // the TLM which created the last KnuthElement in this line
                 LayoutManager lastLM = null;
@@ -1412,6 +1566,7 @@
                 LineArea lineArea = new LineArea();
                 lineArea.setStartIndent(lbp.startIndent);
                 lineArea.setBPD(lbp.lineHeight);
+                lineArea.setIPD(lbp.lineWidth);
                 lc.setBaseline(lbp.baseline);
                 lc.setLineHeight(lbp.lineHeight);
                 lc.setMiddleShift(middleShift);
@@ -1419,43 +1574,46 @@
                 lc.setBottomShift(lbp.bottomShift);
 
                 iCurrParIndex = lbp.iParIndex;
-                Paragraph currPar = (Paragraph) knuthParagraphs.get(iCurrParIndex);
+                KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(iCurrParIndex); 
                 iEndElement = lbp.getLeafPos();
     
-                // ignore the first elements added by the LineLayoutManager
-                iStartElement += (iStartElement == 0) ? currPar.ignoreAtStart : 0;
-    
-                // ignore the last elements added by the LineLayoutManager
-                iEndElement -= (iEndElement == (currPar.size() - 1))
+                if (seq instanceof Paragraph) {
+                    Paragraph currPar = (Paragraph) seq;
+                    // ignore the first elements added by the LineLayoutManager
+                    iStartElement += (iStartElement == 0) ? currPar.ignoreAtStart : 0;
+                    
+                    // ignore the last elements added by the LineLayoutManager
+                    iEndElement -= (iEndElement == (currPar.size() - 1))
                     ? currPar.ignoreAtEnd : 0;
-    
+                }
+                
                 // ignore the last element in the line if it is a KnuthGlue object
-                paragraphIterator = currPar.listIterator(iEndElement);
-                tempElement = (KnuthElement) paragraphIterator.next();
+                seqIterator = seq.listIterator(iEndElement);
+                tempElement = (KnuthElement) seqIterator.next();
                 if (tempElement.isGlue()) {
                     iEndElement --;
                     // this returns the same KnuthElement
-                    paragraphIterator.previous();
-                    tempElement = (KnuthElement) paragraphIterator.previous();
+                    seqIterator.previous();
+                    tempElement = (KnuthElement) seqIterator.previous();
                 }
                 lastLM = tempElement.getLayoutManager();
     
                 // ignore KnuthGlue and KnuthPenalty objects
                 // at the beginning of the line
-                paragraphIterator = currPar.listIterator(iStartElement);
-                tempElement = (KnuthElement) paragraphIterator.next();
-                while (!tempElement.isBox() && paragraphIterator.hasNext()) {
-                    tempElement = (KnuthElement) paragraphIterator.next();
+                seqIterator = seq.listIterator(iStartElement);
+                tempElement = (KnuthElement) seqIterator.next();
+                while (!tempElement.isBox() && seqIterator.hasNext()) {
+                    tempElement = (KnuthElement) seqIterator.next();
                     iStartElement ++;
                 }
     
                 // Add the inline areas to lineArea
                 PositionIterator inlinePosIter
-                    = new KnuthPossPosIter(currPar, iStartElement,
+                    = new KnuthPossPosIter(seq, iStartElement,
                                            iEndElement + 1);
     
                 iStartElement = lbp.getLeafPos() + 1;
-                if (iStartElement == currPar.size()) {
+                if (iStartElement == seq.size()) {
                     // advance to next paragraph
                     iStartElement = 0;
                 }
@@ -1507,11 +1665,73 @@
                     lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter());
                 }
                 parentLM.addChildArea(lineArea);
+            } else if (pos instanceof NonLeafPosition) {
+                // Nested block-level content;
+                // go down the LM stack again;
+                // collect all consecutive NonLeafPosition objects,
+                // "unwrap" them and put the child positions in a new list.
+                LinkedList positionList = new LinkedList();
+                Position innerPosition;
+                innerPosition = ((NonLeafPosition) pos).getPosition();
+                positionList.add(innerPosition);
+                while (parentIter.hasNext()) {
+                    pos = (Position)parentIter.peekNext();
+                    if (!(pos instanceof NonLeafPosition)) {
+                        break;
+                    }
+                    pos = (Position) parentIter.next();
+                    innerPosition = ((NonLeafPosition) pos).getPosition();
+                    positionList.add(innerPosition);
+                }
+                
+                // do we have the last LM?
+                LayoutManager lastLM = null;
+                if (!parentIter.hasNext()) {
+                    lastLM = innerPosition.getLM();
+                }
+
+                // this may be wrong; not all areas belong inside a single line area
+                // see InlineStackingLM.addChildArea
+                LineArea lineArea = new LineArea();
+                setCurrentArea(lineArea);
+                setChildContext(lc);
+
+                PositionIterator childPosIter = new StackingIter(positionList.listIterator());
+                LayoutContext blocklc = new LayoutContext(0);
+                blocklc.setLeadingSpace(new SpaceSpecifier(true));
+                blocklc.setTrailingSpace(new SpaceSpecifier(false));
+                blocklc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
+                while ((childLM = childPosIter.getNextChildLM()) != null) {
+                    // set last area flag
+                    blocklc.setFlags(LayoutContext.LAST_AREA,
+                            (context.isLastArea() && childLM == lastLM));
+                    blocklc.setStackLimit(context.getStackLimit());
+                    // Add the line areas to Area
+                    childLM.addAreas(childPosIter, blocklc);
+                    blocklc.setLeadingSpace(blocklc.getTrailingSpace());
+                    blocklc.setTrailingSpace(new SpaceSpecifier(false));
+                }
+                lineArea.updateExtentsFromChildren();
+                parentLM.addChildArea(lineArea);
             } else {
                 // pos was the Position inside a penalty item, nothing to do
             }
         }
         setCurrentArea(null); // ?? necessary
     }
+
+    public void addChildArea(Area childArea) {
+        // Make sure childArea is inline area
+        if (childArea instanceof InlineArea) {
+            Area parent = getCurrentArea();
+            if (getContext().resolveLeadingSpace()) {
+                addSpace(parent,
+                         getContext().getLeadingSpace().resolve(false),
+                         getContext().getSpaceAdjust());
+            }
+            parent.addChildArea(childArea);
+        }
+    }
+
 }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java?rev=232250&r1=232249&r2=232250&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java Fri Aug 12 02:50:01 2005
@@ -26,6 +26,7 @@
 import org.apache.fop.fo.FOText;
 import org.apache.fop.fo.flow.Inline;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.layoutmgr.KnuthSequence;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthGlue;
@@ -418,6 +419,8 @@
     public LinkedList getNextKnuthElements(LayoutContext context,
                                            int alignment) {
         LinkedList returnList = new LinkedList();
+        KnuthSequence sequence = new KnuthSequence(true);
+        returnList.add(sequence);
 
         while (iNextStart < textArray.length) {
             if (textArray[iNextStart] == SPACE
@@ -425,7 +428,7 @@
                 // normal, breaking space
                 // or non-breaking space
                 if (textArray[iNextStart] == NBSPACE) {
-                    returnList.add
+                    sequence.add
                         (new KnuthPenalty(0, KnuthElement.INFINITE, false,
                                           new LeafPosition(this, vecAreaInfo.size() - 1),
                                           false));
@@ -436,23 +439,23 @@
                         (new AreaInfo(iNextStart, (short) (iNextStart + 1),
                                       (short) 1, (short) 0,
                                       wordSpaceIPD, false));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                        new LeafPosition(this, vecAreaInfo.size() - 1), false));
-                    returnList.add
+                    sequence.add
                         (new KnuthPenalty(0, 0, false,
                                           new LeafPosition(this, -1), true));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(wordSpaceIPD.opt,
                                        - 6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                        new LeafPosition(this, -1), true));
-                    returnList.add
+                    sequence.add
                         (new KnuthInlineBox(0, 0, 0, 0,
                                       new LeafPosition(this, -1), true));
-                    returnList.add
+                    sequence.add
                         (new KnuthPenalty(0, KnuthElement.INFINITE, false,
                                           new LeafPosition(this, -1), true));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0,
                                        new LeafPosition(this, -1), true));
                     iNextStart ++;
@@ -464,13 +467,13 @@
                         (new AreaInfo(iNextStart, (short) (iNextStart + 1),
                                       (short) 1, (short) 0,
                                       wordSpaceIPD, false));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(0, 3 * wordSpaceIPD.opt, 0,
                                        new LeafPosition(this, vecAreaInfo.size() - 1), false));
-                    returnList.add
+                    sequence.add
                         (new KnuthPenalty(0, 0, false,
                                           new LeafPosition(this, -1), true));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(wordSpaceIPD.opt,
                                        - 3 * wordSpaceIPD.opt, 0,
                                        new LeafPosition(this, -1), true));
@@ -482,7 +485,7 @@
                         (new AreaInfo(iNextStart, (short) (iNextStart + 1),
                                       (short) 1, (short) 0,
                                       wordSpaceIPD, false));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(wordSpaceIPD.opt,
                                        wordSpaceIPD.max - wordSpaceIPD.opt,
                                        wordSpaceIPD.opt - wordSpaceIPD.min,
@@ -495,7 +498,7 @@
                         (new AreaInfo(iNextStart, (short) (iNextStart + 1),
                                       (short) 1, (short) 0,
                                       wordSpaceIPD, false));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(wordSpaceIPD.opt,
                                        wordSpaceIPD.max - wordSpaceIPD.opt, 0,
                                        new LeafPosition(this, vecAreaInfo.size() - 1), false));
@@ -507,10 +510,10 @@
                     (new AreaInfo(iNextStart, (short) (iNextStart + 1),
                                   (short) 1, (short) 0,
                                   wordSpaceIPD, false));
-                returnList.add
+                sequence.add
                     (new KnuthPenalty(0, KnuthElement.INFINITE, false,
                                       new LeafPosition(this, vecAreaInfo.size() - 1), false));
-                returnList.add
+                sequence.add
                     (new KnuthGlue(wordSpaceIPD.opt,
                                    wordSpaceIPD.max - wordSpaceIPD.opt,
                                    wordSpaceIPD.opt - wordSpaceIPD.min,
@@ -518,12 +521,13 @@
                 iNextStart ++;
             } else if (textArray[iNextStart] == NEWLINE) {
                 // linefeed; this can happen when linefeed-treatment="preserve"
-                // add a penalty item to the list and return
-                returnList.add
+                // add a penalty item to the list and start a new sequence
+                sequence.add
                     (new KnuthPenalty(0, -KnuthElement.INFINITE,
                                       false, null, false));
+                sequence = new KnuthSequence(true);
+                returnList.add(sequence);
                 iNextStart ++;
-                return returnList;
             } else {
                 // the beginning of a word
                 iThisStart = iNextStart;
@@ -548,25 +552,25 @@
                 if (letterSpaceIPD.min == letterSpaceIPD.max) {
                     // constant letter space; simply return a box
                     // whose width includes letter spaces
-                    returnList.add
+                    sequence.add
                         (new KnuthInlineBox(wordIPD.opt, lead, total, middle,
                                       new LeafPosition(this, vecAreaInfo.size() - 1), false));
                 } else {
                     // adjustable letter space;
                     // some other KnuthElements are needed
-                    returnList.add
+                    sequence.add
                         (new KnuthInlineBox(wordIPD.opt - iLetterSpaces * letterSpaceIPD.opt,
                                       lead, total, middle,
                                       new LeafPosition(this, vecAreaInfo.size() - 1), false));
-                    returnList.add
+                    sequence.add
                         (new KnuthPenalty(0, KnuthElement.INFINITE, false,
                                           new LeafPosition(this, -1), true));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(iLetterSpaces * letterSpaceIPD.opt,
                                        iLetterSpaces * (letterSpaceIPD.max - letterSpaceIPD.opt),
                                        iLetterSpaces * (letterSpaceIPD.opt - letterSpaceIPD.min),
                                        new LeafPosition(this, -1), true));
-                    returnList.add
+                    sequence.add
                         (new KnuthInlineBox(0, lead, total, middle,
                                             new LeafPosition(this, -1), true));
                 }
@@ -577,10 +581,10 @@
                     && iTempStart < textArray.length
                     && textArray[iTempStart] != SPACE
                     && textArray[iTempStart] != NBSPACE) {
-                    returnList.add
+                    sequence.add
                         (new KnuthPenalty(0, KnuthPenalty.FLAGGED_PENALTY, true,
                                           new LeafPosition(this, -1), false));
-                    returnList.add
+                    sequence.add
                         (new KnuthGlue(letterSpaceIPD.opt,
                                        letterSpaceIPD.max - letterSpaceIPD.opt,
                                        letterSpaceIPD.opt - letterSpaceIPD.min,
@@ -592,6 +596,10 @@
                 iNextStart = iTempStart;
             }
         } // end of while
+        if (((List)returnList.getLast()).size() == 0) {
+            //Remove an empty sequence because of a trailing newline
+            returnList.removeLast();
+        }
         setFinished(true);
         if (returnList.size() > 0) {
             return returnList;
@@ -605,7 +613,8 @@
         // look at the Position stored in the first element in oldList
         // which is always a box
         ListIterator oldListIterator = oldList.listIterator();
-        LeafPosition pos = (LeafPosition) ((KnuthBox) oldListIterator.next()).getPosition();
+        KnuthElement el = (KnuthElement)oldListIterator.next();
+        LeafPosition pos = (LeafPosition) ((KnuthBox) el).getPosition();
         AreaInfo ai = (AreaInfo) vecAreaInfo.get(pos.getLeafPos());
         ai.iLScount ++;
         ai.ipdArea.add(letterSpaceIPD);



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org