From e47a618945b52de9da35fc5eb0a5a4ef1c1749e7 Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Thu, 22 Dec 2005 08:48:51 +0000 Subject: [PATCH] Modified the KnuthSequence system. Transferred logic from the layout managers to the KnuthSequences. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@358534 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/layoutmgr/AbstractBreaker.java | 42 ++- .../fop/layoutmgr/AbstractLayoutManager.java | 2 +- .../fop/layoutmgr/BlockKnuthSequence.java | 171 ++++++++++++ .../fop/layoutmgr/InlineKnuthSequence.java | 95 +++++++ .../apache/fop/layoutmgr/KnuthSequence.java | 99 ++++--- .../apache/fop/layoutmgr/LayoutManager.java | 7 + .../inline/CharacterLayoutManager.java | 3 +- .../inline/ContentLayoutManager.java | 7 + .../inline/FootnoteLayoutManager.java | 3 +- .../layoutmgr/inline/InlineLayoutManager.java | 136 ++-------- .../layoutmgr/inline/LeaderLayoutManager.java | 3 +- .../inline/LeafNodeLayoutManager.java | 3 +- .../layoutmgr/inline/LineLayoutManager.java | 246 ++++++++---------- .../layoutmgr/inline/TextLayoutManager.java | 9 +- 14 files changed, 531 insertions(+), 295 deletions(-) create mode 100644 src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java create mode 100644 src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 2258441f1..54cf80ebd 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -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); diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 085fe9a69..5fc39972a 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -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 index 000000000..1093fee74 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java @@ -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 index 000000000..7872193f3 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java @@ -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; + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java index 15a61a182..a063ee9f0 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java @@ -19,18 +19,16 @@ 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(); + } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManager.java b/src/java/org/apache/fop/layoutmgr/LayoutManager.java index 5ea5bb50b..35d28a715 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManager.java @@ -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); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index c337548fd..d51b2fa15 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -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); diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 85d9f0e35..a1f6950c9 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -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; + } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java index a78aa3a86..caca90596 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java @@ -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); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index c24245f79..8b0f54256 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -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)); } } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index cad328e82..5ee42bac8 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -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); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index f4062a79a..43db78b7f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -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); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index fa266b6ba..c96adde02 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -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(); diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index fedb3d10e..b9730b583 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -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 -- 2.39.5