]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Modified the KnuthSequence system. Transferred logic from the layout
authorSimon Pepping <spepping@apache.org>
Thu, 22 Dec 2005 08:48:51 +0000 (08:48 +0000)
committerSimon Pepping <spepping@apache.org>
Thu, 22 Dec 2005 08:48:51 +0000 (08:48 +0000)
managers to the KnuthSequences.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@358534 13f79535-47bb-0310-9956-ffa450edef68

14 files changed:
src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/KnuthSequence.java
src/java/org/apache/fop/layoutmgr/LayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java

index 2258441f12b45d788c2a98f73448228c70100a85..54cf80ebd6bb9110c7263454261c88c4bdfa65fd 100644 (file)
@@ -56,7 +56,12 @@ public abstract class AbstractBreaker {
         }
     }
 
-    public class BlockSequence extends KnuthSequence {
+    public class BlockSequence extends BlockKnuthSequence {
+
+        /** Number of elements to ignore at the beginning of the list. */ 
+        public int ignoreAtStart = 0;
+        /** Number of elements to ignore at the end of the list. */
+        public int ignoreAtEnd = 0;
 
         /**
          * startOn represents where on the page/which page layout
@@ -76,8 +81,41 @@ public abstract class AbstractBreaker {
             return this.startOn;
         }
 
+        /**
+         * Finalizes a Knuth sequence.
+         * @return a finalized sequence.
+         */
+        public KnuthSequence endSequence() {
+            return endSequence(null);
+        }
+        
+        /**
+         * Finalizes a Knuth sequence.
+         * @param breakPosition a Position instance for the last penalty (may be null)
+         * @return a finalized sequence.
+         */
+        public KnuthSequence endSequence(Position breakPosition) {
+            // remove glue and penalty item at the end of the paragraph
+            while (this.size() > ignoreAtStart
+                   && !((KnuthElement)this.get(this.size() - 1)).isBox()) {
+                this.remove(this.size() - 1);
+            }
+            if (this.size() > ignoreAtStart) {
+                // add the elements representing the space at the end of the last line
+                // and the forced break
+                this.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, null, false));
+                this.add(new KnuthGlue(0, 10000000, 0, null, false));
+                this.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, breakPosition, false));
+                ignoreAtEnd = 3;
+                return this;
+            } else {
+                this.clear();
+                return null;
+            }
+        }
+
         public BlockSequence endBlockSequence(Position breakPosition) {
-            KnuthSequence temp = super.endSequence(breakPosition);
+            KnuthSequence temp = endSequence(breakPosition);
             if (temp != null) {
                 BlockSequence returnSequence = new BlockSequence(startOn);
                 returnSequence.addAll(temp);
index 085fe9a69e4ddc4bd79d8db21529fb39437d40e0..5fc39972ab888dfe82bf654960ce515bca698bc2 100644 (file)
@@ -330,7 +330,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
      * @param pos the Position
      * @return the same Position but with a position index
      */
-    protected Position notifyPos(Position pos) {
+    public Position notifyPos(Position pos) {
         if (pos.getIndex() >= 0) {
             throw new IllegalStateException("Position already got its index");
         }
diff --git a/src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java b/src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java
new file mode 100644 (file)
index 0000000..1093fee
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2005 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$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.List;
+
+
+/**
+ * Represents a list of block level Knuth elements.
+ */
+public class BlockKnuthSequence extends KnuthSequence {
+    
+    private boolean isClosed = false;
+    
+    /**
+     * Creates a new and empty list.
+     */
+    public BlockKnuthSequence() {
+        super();
+    }
+    
+    /**
+     * Creates a new list from an existing list.
+     * @param list The list from which to create the new list.
+     */
+    public BlockKnuthSequence(List list) {
+        super(list);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthList#isInlineSequence()
+     */
+    public boolean isInlineSequence() {
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthList#canAppendSequence(org.apache.fop.layoutmgr.KnuthSequence)
+     */
+    public boolean canAppendSequence(KnuthSequence sequence) {
+        return !sequence.isInlineSequence() && !isClosed;
+    }
+
+    /**
+     * this and sequence are supposed to belong to the same LayoutManager,
+     * which is stored in the positions of the elements in the sequences
+     * @param sequence The sequence following this
+     * @return whether this and the following sequence must be kept together
+     */
+    private boolean mustKeepWithNext(BlockKnuthSequence sequence) {
+/*        // TODO read keep together correctly
+        // for now, return false
+        return BlockKnuthSequence.mustKeepTogether(this, sequence);
+*/        return false;
+    }
+
+    /**
+     * the two sequences are supposed to belong to the same LayoutManager,
+     * which is stored in the positions of the elements in the sequences
+     * @param sequence1 The leading sequence
+     * @param sequence2 The following sequence
+     * @return whether the two sequences must be kept together
+     */
+    public static boolean mustKeepTogether(BlockKnuthSequence sequence1,
+                                           BlockKnuthSequence sequence2) {
+        KnuthElement element1 = (KnuthElement) sequence1.get(sequence1.size() - 1);
+        LayoutManager lm1 = (LayoutManager) element1.getLayoutManager();
+        KnuthElement element2 = (KnuthElement) sequence2.get(0);
+        LayoutManager lm2 = (LayoutManager) element2.getLayoutManager();
+        if (!lm1.equals(lm2)) {
+            throw new IllegalStateException
+              ("The two sequences must belong to the same LayoutManager");
+        }
+        if (lm1 instanceof BlockLevelLayoutManager
+                && ((BlockLevelLayoutManager) lm1).mustKeepTogether()) {
+            return true;
+        }
+        Position pos1 = element1.getPosition();
+        if (pos1 != null) {
+            pos1 = pos1.getPosition();
+            if (pos1 != null) {
+                lm1 = pos1.getLM();
+                if (lm1 instanceof BlockLevelLayoutManager
+                    && ((BlockLevelLayoutManager) lm1).mustKeepWithNext()) {
+                        return true;
+                } 
+            }
+        }
+        Position pos2 = element1.getPosition();
+        if (pos2 != null) {
+            pos2 = pos2.getPosition();
+            if (pos2 != null) {
+                lm2 = pos2.getLM();
+                if (lm2 instanceof BlockLevelLayoutManager
+                    && ((BlockLevelLayoutManager) lm2).mustKeepWithPrevious()) {
+                        return true;
+                } 
+            }
+        }
+        return false;
+/*      From BlockStackingLM.getChangedKnuthElements
+        // there is another block after this one
+        if (bSomethingAdded
+            && (this.mustKeepTogether()
+                || prevLM.mustKeepWithNext()
+                || currLM.mustKeepWithPrevious())) {
+            // add an infinite penalty to forbid a break between blocks
+            returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, 
+                    new Position(this), false));
+        } else if (bSomethingAdded && !((KnuthElement) returnedList.getLast()).isGlue()) {
+            // add a null penalty to allow a break between blocks
+            returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
+        }
+*/    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthList#appendSequence(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
+     */
+    /**
+     * this and sequence are supposed to belong to the same LayoutManager,
+     * which is stored in the positions of the elements in the sequences
+     */
+    public boolean appendSequence(KnuthSequence sequence, LayoutManager lm) {
+        if (!canAppendSequence(sequence)) {
+            return false;
+        }
+/*        // TODO disable because InlineLM.addAreas expects only NonLeafPostions; why?
+        if (!mustKeepWithNext((BlockKnuthSequence) sequence)) {
+            add(new KnuthPenalty(0, 0, false, new Position(lm), false));
+        }
+*/        addAll(sequence);
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthList#appendSequenceOrClose(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
+     */
+    public boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm) {
+        if (!appendSequence(sequence, lm)) {
+            endSequence();
+            return false;
+        } else {
+            return true;
+        }
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthSequence#endSequence()
+     */
+    public KnuthSequence endSequence() {
+        isClosed = true;
+        return this;
+    }
+
+}
diff --git a/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java b/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java
new file mode 100644 (file)
index 0000000..7872193
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2005 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$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.List;
+
+
+/**
+ * 
+ */
+public class InlineKnuthSequence extends KnuthSequence  {
+
+    private boolean isClosed = false;
+
+    /**
+     * Creates a new and empty list. 
+     */
+    public InlineKnuthSequence() {
+        super();
+    }
+    
+    /**
+     * Creates a new list from an existing list.
+     * @param list The list from which to create the new list.
+     */
+    public InlineKnuthSequence(List list) {
+        super(list);
+    }
+
+    /**
+     * Is this an inline or a block sequence?
+     * @return false
+     */
+    public boolean isInlineSequence() {
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthSequence#canAppendSequence(org.apache.fop.layoutmgr.KnuthSequence)
+     */
+    public boolean canAppendSequence(KnuthSequence sequence) {
+        return sequence.isInlineSequence() && !isClosed;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequence(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
+     */
+    public boolean appendSequence(KnuthSequence sequence, LayoutManager lm) {
+        if (!canAppendSequence(sequence)) {
+            return false;
+        }
+        addAll(sequence);
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequenceOrClose(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
+     */
+    public boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm) {
+        if (!appendSequence(sequence, lm)) {
+            endSequence();
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthSequence#endSequence()
+     */
+    public KnuthSequence endSequence() {
+        if (!isClosed) {
+            add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, null, false));
+            isClosed = true;
+        }
+        return this;
+    }
+
+}
index 15a61a182ec645d9c609d8e903746a9686c95583..a063ee9f07730ff3c0259e1294ba7f356d665473 100644 (file)
 package org.apache.fop.layoutmgr;
 
 import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
 
 /**
  * Represents a list of Knuth elements.
  */
-public class KnuthSequence extends ArrayList {
-    /** Number of elements to ignore at the beginning of the list. */ 
-    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;
-
+/**
+ * 
+ */
+public abstract class KnuthSequence extends ArrayList {
     /**
      * Creates a new and empty list.
      */
@@ -39,11 +37,11 @@ public class KnuthSequence extends ArrayList {
     }
 
     /**
-     * Creates a new and empty list, and sets isInlineSequence.
+     * Creates a new list from an existing list.
+     * @param list The list from which to create the new list.
      */
-    public KnuthSequence(boolean isInlineSequence) {
-        super();
-        this.isInlineSequence = isInlineSequence;
+    public KnuthSequence(List list) {
+        super(list);
     }
 
     /**
@@ -56,35 +54,51 @@ public class KnuthSequence extends ArrayList {
      * Finalizes a Knuth sequence.
      * @return a finalized sequence.
      */
-    public KnuthSequence endSequence() {
-        return endSequence(null);
-    }
+    public abstract KnuthSequence endSequence();
+
+    /**
+     * Can sequence be appended to this sequence?
+     * @param sequence The sequence that may be appended.
+     * @return whether the sequence can be appended to this sequence.
+     */
+    public abstract boolean canAppendSequence(KnuthSequence sequence);
+
+    /**
+     * Append sequence to this sequence if it can be appended.
+     * TODO In principle the LayoutManager can also be retrieved from the elements in the sequence.
+     * @param sequence The sequence that is to be appended.
+     * @param lm The LayoutManager for the Position that may have to be created. 
+     * @return whether the sequence was succesfully appended to this sequence.
+     */
+    public abstract boolean appendSequence(KnuthSequence sequence, LayoutManager lm);
     
     /**
-     * Finalizes a Knuth sequence.
-     * @param breakPosition a Position instance for the last penalty (may be null)
-     * @return a finalized sequence.
+     * Append sequence to this sequence if it can be appended.
+     * If that is not possible, close this sequence.
+     * TODO In principle the LayoutManager can also be retrieved from the elements in the sequence.
+     * @param sequence The sequence that is to be appended.
+     * @param lm The LayoutManager for the Position that may have to be created. 
+     * @return whether the sequence was succesfully appended to this sequence.
      */
-    public KnuthSequence endSequence(Position breakPosition) {
-        // remove glue and penalty item at the end of the paragraph
-        while (this.size() > ignoreAtStart
-               && !((KnuthElement)this.get(this.size() - 1)).isBox()) {
-            this.remove(this.size() - 1);
-        }
-        if (this.size() > ignoreAtStart) {
-            // add the elements representing the space at the end of the last line
-            // and the forced break
-            this.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, null, false));
-            this.add(new KnuthGlue(0, 10000000, 0, null, false));
-            this.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, breakPosition, false));
-            ignoreAtEnd = 3;
-            return this;
-        } else {
-            this.clear();
-            return null;
+    public abstract boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm);
+    
+    /**
+     * Wrap the Positions of the elements of this sequence in a Position for LayoutManager lm.
+     * @param lm The LayoutManager for the Positions that will be created.
+     */
+    public void wrapPositions(LayoutManager lm) {
+        ListIterator listIter = listIterator();
+        KnuthElement element;
+        while (listIter.hasNext()) {
+            element = (KnuthElement) listIter.next();
+            element.setPosition
+            (lm.notifyPos(new NonLeafPosition(lm, element.getPosition())));
         }
     }
-
+    
+    /**
+     * @return the last element of this sequence.
+     */
     public KnuthElement getLast() {
         int idx = size();
         if (idx == 0) {
@@ -93,6 +107,10 @@ public class KnuthSequence extends ArrayList {
         return (KnuthElement) get(idx - 1);
     }
 
+    /**
+     * Remove the last element of this sequence.
+     * @return the removed element.
+     */
     public KnuthElement removeLast() {
         int idx = size();
         if (idx == 0) {
@@ -101,6 +119,10 @@ public class KnuthSequence extends ArrayList {
         return (KnuthElement) remove(idx - 1);
     }
 
+    /**
+     * @param index The index of the element to be returned
+     * @return the element at index index.
+     */
     public KnuthElement getElement(int index) {
         return (KnuthElement) get(index);
     }
@@ -109,7 +131,6 @@ public class KnuthSequence extends ArrayList {
      * Is this an inline or a block sequence?
      * @return true if this is an inline sequence
      */
-    public boolean isInlineSequence() {
-        return isInlineSequence;
-    }
+    public abstract boolean isInlineSequence();
+
 }
index 5ea5bb50b0f15255ea7d20b7f27117d44772b4e9..35d28a71588edf90b71b664ebf2ce01792b9fe0e 100644 (file)
@@ -219,4 +219,11 @@ public interface LayoutManager extends PercentBaseContext {
      */
     FObj getFObj();
     
+    /**
+     * Adds a Position to the Position participating in the first|last determination by assigning
+     * it a unique position index.
+     * @param pos the Position
+     * @return the same Position but with a position index
+     */
+    Position notifyPos(Position pos);
 }
index c337548fd61330e2f241b5edfdb16bb61fffcd4e..d51b2fa158ec7e17310e53d1fdb2cf7244b0700c 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr.inline;
 
 import org.apache.fop.fo.flow.Character;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthGlue;
 import org.apache.fop.layoutmgr.KnuthPenalty;
@@ -84,7 +85,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
     public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
         MinOptMax ipd;
         curArea = get(context);
-        KnuthSequence seq = new KnuthSequence(true);
+        KnuthSequence seq = new InlineKnuthSequence();
 
         if (curArea == null) {
             setFinished(true);
index 85d9f0e35fb0c41792a60dd4d767b9c3b482635b..a1f6950c98810edf643249a21fe8aeda5326a1b5 100644 (file)
@@ -350,6 +350,13 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager
     public boolean getGeneratesLineArea() {
         return holder instanceof LineArea;
     }
+
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.LayoutManager#notifyPos(org.apache.fop.layoutmgr.Position)
+     */
+    public Position notifyPos(Position pos) {
+        return pos;
+    }
    
 }
 
index a78aa3a86d79753cf42a2fb7bbe8277f9916a178..caca9059694f916e8d53f503f978dd813c2f87d4 100644 (file)
@@ -25,6 +25,7 @@ import java.util.ListIterator;
 import org.apache.fop.fo.flow.Footnote;
 import org.apache.fop.layoutmgr.AbstractLayoutManager;
 import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
+import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthSequence;
 import org.apache.fop.layoutmgr.LayoutContext;
@@ -84,7 +85,7 @@ public class FootnoteLayoutManager extends AbstractLayoutManager
         if (returnedList.size() == 0) {
             //Inline part of the footnote is empty. Need to send back an auxiliary
             //zero-width, zero-height inline box so the footnote gets painted.
-            KnuthSequence seq = new KnuthSequence(true);
+            KnuthSequence seq = new InlineKnuthSequence();
             //Need to use an aux. box, otherwise, the line height can't be forced to zero height.
             forcedAnchor = new KnuthInlineBox(0, null, null, true);
             seq.add(forcedAnchor);
index c24245f79b83fc0218e6db12fddd6feca769dd57..8b0f54256a4c3a54f10a68942ffda414ce8e2a22 100755 (executable)
@@ -34,6 +34,7 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.CommonMarginInline;
 import org.apache.fop.fo.properties.SpaceProperty;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.layoutmgr.BlockKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthSequence;
@@ -197,12 +198,10 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
 
     /** @see org.apache.fop.layoutmgr.LayoutManager */
     public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
-        InlineLevelLayoutManager curILM;
-        LayoutManager curLM, lastLM = null;
+        LayoutManager 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();
@@ -273,125 +272,46 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
                 // just iterate once more to see if there is another child
                 continue;
             }
+            if (returnedList.size() == 0) {
+                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 seqIter = returnedList.listIterator();
                 while (seqIter.hasNext()) {
                     KnuthSequence sequence = (KnuthSequence) seqIter.next();
-                    ListIterator listIter = sequence.listIterator();
-                    while (listIter.hasNext()) {
-                        returnedElement = (KnuthElement) listIter.next();
-                        returnedElement.setPosition
-                        (notifyPos(new NonLeafPosition(this,
-                                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 (!borderAdded) {
-                                addKnuthElementsForBorderPaddingStart(lastSequence);
-                                borderAdded = true;
-                            }
-                            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(" ]");
-                            }
-                        }
-                    }
+                    sequence.wrapPositions(this);
                 }
-            } 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 (lastSequence != null && lastSequence.appendSequenceOrClose
+                        ((KnuthSequence) returnedList.get(0), this)) {
+                    returnedList.remove(0);
                 }
-                if (curLM != lastLM) {
-                    // close the last block sequence
-                    if (lastSequence != null && !lastSequence.isInlineSequence()) {
-                        lastSequence = null;
-                        if (log.isTraceEnabled()) {
-                            trace.append(" ]");
-                        }
-                    }
-                    lastLM = curLM;
+                // add border and padding to the first complete sequence of this LM
+                if (!borderAdded && returnedList.size() != 0) {
+                    addKnuthElementsForBorderPaddingStart((KnuthSequence) returnedList.get(0));
+                    borderAdded = true;
                 }
-                if (lastSequence == null) {
-                    lastSequence = new KnuthSequence(false);
-                    returnList.add(lastSequence);
-                    if (log.isTraceEnabled()) {
-                        trace.append(" [");
-                    }
+                returnList.addAll(returnedList);
+            } else { // A block LM
+                // TODO For now avoid having two different block LMs in a single sequence
+                if (curLM != lastChildLM && lastSequence != null) {
+                    lastSequence.endSequence();
+                }
+                BlockKnuthSequence sequence = new BlockKnuthSequence(returnedList);
+                sequence.wrapPositions(this);
+                if (lastSequence == null || !lastSequence.appendSequenceOrClose(sequence, this)) {
+                    // add border and padding to the first complete sequence of this LM
                     if (!borderAdded) {
-                        addKnuthElementsForBorderPaddingStart(lastSequence);
+                        addKnuthElementsForBorderPaddingStart(sequence);
                         borderAdded = true;
                     }
-                } else {
-                    if (log.isTraceEnabled()) {
-                        trace.append(" +");
-                    }
-                }
-                ListIterator iter = returnedList.listIterator();
-                while (iter.hasNext()) {
-                    KnuthElement element = (KnuthElement) iter.next();
-                    element.setPosition
-                        (notifyPos(new NonLeafPosition(this,
-                                element.getPosition())));
-                }
-                lastSequence.addAll(returnedList);
-                if (log.isTraceEnabled()) {
-                    trace.append(" L");
+                    returnList.add(sequence);
                 }
             }
+            lastSequence = (KnuthSequence) returnList.getLast();
             lastChildLM = curLM;
         }
-
+        
         if (lastSequence != null) {
             addKnuthElementsForBorderPaddingEnd(lastSequence);
         }
@@ -541,7 +461,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
             int ipStart = borderAndPadding.getBorderStartWidth(false)
                          + borderAndPadding.getPaddingStart(false, this);
             if (ipStart > 0) {
-                returnList.add(new KnuthBox(ipStart, getAuxiliaryPosition(), true));
+                returnList.add(0,new KnuthBox(ipStart, getAuxiliaryPosition(), true));
             }
         }
     }
index cad328e82cb6d6052f3773f30e2e98422c59397f..5ee42bac8e2cc0a43fe0b1f48d1fe1bbfbd2bb04 100644 (file)
@@ -25,6 +25,7 @@ import org.apache.fop.area.inline.Space;
 import org.apache.fop.area.inline.TextArea;
 import org.apache.fop.fo.flow.Leader;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthGlue;
 import org.apache.fop.layoutmgr.KnuthPenalty;
@@ -227,7 +228,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager {
                                            int alignment) {
         MinOptMax ipd;
         curArea = get(context);
-        KnuthSequence seq = new KnuthSequence(true);
+        KnuthSequence seq = new InlineKnuthSequence();
 
         if (curArea == null) {
             setFinished(true);
index f4062a79a52d3114929bbbee961b400dd1be619f..43db78b7f34e8d446f49c18193c48c51b9243733 100644 (file)
@@ -26,6 +26,7 @@ import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.layoutmgr.AbstractLayoutManager;
+import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthGlue;
 import org.apache.fop.layoutmgr.KnuthPenalty;
 import org.apache.fop.layoutmgr.KnuthSequence;
@@ -265,7 +266,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager
 
         // node is a fo:ExternalGraphic, fo:InstreamForeignObject,
         // fo:PageNumber or fo:PageNumberCitation
-        KnuthSequence seq = new KnuthSequence(true);
+        KnuthSequence seq = new InlineKnuthSequence();
 
         addKnuthElementsForBorderPaddingStart(seq);
         
index fa266b6bab122603e5aa2df426966ac1803b9f2d..c96adde0262102d8f6e80d37751a953282d22f0b 100644 (file)
@@ -30,6 +30,7 @@ import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
 import org.apache.fop.layoutmgr.BreakElement;
 import org.apache.fop.layoutmgr.BreakingAlgorithm;
 import org.apache.fop.layoutmgr.ElementListObserver;
+import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthBlockBox;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
@@ -187,7 +188,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager
     }
 
     // this class represents a paragraph
-    private class Paragraph extends KnuthSequence {
+    private class Paragraph extends InlineKnuthSequence {
+        /** Number of elements to ignore at the beginning of the list. */ 
+        private int ignoreAtStart = 0;
+        /** Number of elements to ignore at the end of the list. */
+        private int ignoreAtEnd = 0;
+
         // space at the end of the last line (in millipoints)
         private MinOptMax lineFiller;
         private int textAlignment;
@@ -200,7 +206,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager
 
         public Paragraph(LineLayoutManager llm, int alignment, int alignmentLast,
                          int indent, int endIndent) {
-            super(true);
+            super();
             layoutManager = llm;
             textAlignment = alignment;
             textAlignmentLast = alignmentLast;
@@ -691,38 +697,106 @@ public class LineLayoutManager extends InlineStackingLayoutManager
      */
     private void collectInlineKnuthElements(LayoutContext context, MinOptMax availIPD) {
         LayoutContext inlineLC = new LayoutContext(context);
-
+        
         InlineLevelLayoutManager curLM;
         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;
-
+        
         StringBuffer trace = new StringBuffer("LineLM:");
-
+        
         Paragraph lastPar = null;
-
+        
         while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
-            if ((returnedList
-                 = curLM.getNextKnuthElements(inlineLC,
-                                              effectiveAlignment))
-                != null) {
-                if (returnedList.size() == 0) {
-                    continue;
+            returnedList = curLM.getNextKnuthElements(inlineLC, effectiveAlignment);
+            if (returnedList == null) {
+                // curLM returned null; this can happen
+                // if it has nothing more to layout,
+                // so just iterate once more to see
+                // if there are other children
+                continue;
+            }
+            if (returnedList.size() == 0) {
+                continue;
+            }
+            
+            if (lastPar != null) {
+                KnuthSequence firstSeq = (KnuthSequence) returnedList.getFirst();
+                
+                // finish last paragraph before a new block sequence
+                if (!firstSeq.isInlineSequence()) {
+                    lastPar.endParagraph();
+                    ElementListObserver.observe(lastPar, "line", null);
+                    lastPar = null;
+                    if (log.isTraceEnabled()) {
+                        trace.append(" ]");
+                    }
+                    bPrevWasKnuthBox = false;
                 }
-
+                
+                // does the first element of the first paragraph add to an existing word?
                 if (lastPar != null) {
-                    Object firstObj;
-                    KnuthSequence firstSeq = null;
-                    firstObj = returnedList.getFirst();
-                    if (firstObj instanceof KnuthSequence) {
-                        firstSeq = (KnuthSequence) firstObj;
+                    KnuthElement thisElement;
+                    thisElement = (KnuthElement) firstSeq.get(0);
+                    if (thisElement.isBox() && !thisElement.isAuxiliary()
+                            && bPrevWasKnuthBox) {
+                        lastPar.addALetterSpace();
                     }
+                }
+            }
+            
+            // loop over the KnuthSequences (and single KnuthElements) in returnedList
+            ListIterator iter = returnedList.listIterator();
+            while (iter.hasNext()) {
+                KnuthSequence sequence = (KnuthSequence) iter.next();
+                // the sequence contains inline Knuth elements
+                if (sequence.isInlineSequence()) {
+                    // look at the last element 
+                    KnuthElement lastElement;
+                    lastElement = (KnuthElement) sequence.getLast();
+                    if (lastElement == null) {
+                        throw new NullPointerException(
+                        "Sequence was empty! lastElement is null");
+                    }
+                    bPrevWasKnuthBox = lastElement.isBox() && lastElement.getW() != 0;
                     
-                    // finish last paragraph before a new block sequence
-                    if (firstSeq != null && !firstSeq.isInlineSequence()) {
+                    // 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, 
+                                                textAlignment, textAlignmentLast, 
+                                                textIndent.getValue(this),
+                                                lastLineEndIndent.getValue(this));
+                        lastPar.startParagraph(availIPD.opt);
+                        if (log.isTraceEnabled()) {
+                            trace.append(" [");
+                        }
+                    } else {
+                        if (log.isTraceEnabled()) {
+                            trace.append(" +");
+                        }
+                    }
+                    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, null, null, false));
+                        }
                         lastPar.endParagraph();
                         ElementListObserver.observe(lastPar, "line", null);
                         lastPar = null;
@@ -731,123 +805,23 @@ public class LineLayoutManager extends InlineStackingLayoutManager
                         }
                         bPrevWasKnuthBox = false;
                     }
-                
-                    // does the first element of the first paragraph add to an existing word?
-                    if (lastPar != null) {
-                        KnuthElement thisElement;
-                        if (firstObj instanceof KnuthElement) {
-                            thisElement = (KnuthElement) firstObj;
-                        } else {
-                            thisElement = (KnuthElement) firstSeq.get(0);
-                        }
-                        if (thisElement.isBox() && !thisElement.isAuxiliary()
-                                && bPrevWasKnuthBox) {
-                            lastPar.addALetterSpace();
-                        }
+                } 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");
                     }
-
                 }
-
-                
-                // 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() && lastElement.getW() != 0;
-
-                        // 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, 
-                                                    textAlignment, textAlignmentLast, 
-                                                    textIndent.getValue(this), lastLineEndIndent.getValue(this));
-                            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, null, 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");
-                        }
-                    }
-                } // end of loop over returnedList
-            } else {
-                // curLM returned null; this can happen
-                // if it has nothing more to layout,
-                // so just iterate once more to see
-                // if there are other children
-            }
+            } // end of loop over returnedList
         }
         if (lastPar != null) {
             lastPar.endParagraph();
index fedb3d10ec45952cab14908d61559afaa00020b4..b9730b583b8f564cb384ec7343d18702d60432ac 100644 (file)
@@ -28,6 +28,7 @@ import org.apache.fop.area.inline.TextArea;
 import org.apache.fop.fo.FOText;
 import org.apache.fop.fo.flow.Inline;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.layoutmgr.InlineKnuthSequence;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthGlue;
@@ -459,7 +460,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
         alignmentContext = context.getAlignmentContext();
 
         LinkedList returnList = new LinkedList();
-        KnuthSequence sequence = new KnuthSequence(true);
+        KnuthSequence sequence = new InlineKnuthSequence();
         AreaInfo ai = null;
         returnList.add(sequence);
 
@@ -487,10 +488,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
                         (new KnuthGlue(lineEndBAP, 0, 0,
                                        new LeafPosition(this, -1), true));
                 }
-                sequence.add
-                    (new KnuthPenalty(0, -KnuthElement.INFINITE,
-                                      false, null, false));
-                sequence = new KnuthSequence(true);
+                sequence.endSequence();
+                sequence = new InlineKnuthSequence();
                 returnList.add(sequence);
 
                 // advance to the next character