From: Simon Pepping Date: Fri, 30 Dec 2005 11:39:08 +0000 (+0000) Subject: Block Knuth sequences in inline content are properly joined, taking X-Git-Tag: fop-0_92-beta~244 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7dfb879efc02a9ee49c1f12778f46b5b9358656c;p=xmlgraphics-fop.git Block Knuth sequences in inline content are properly joined, taking keeps into account. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@360073 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java b/src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java index c3c837f1e..9ef3d61e3 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java @@ -57,109 +57,33 @@ public class BlockKnuthSequence extends KnuthSequence { 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 + /* (non-Javadoc) + * @see org.apache.fop.layoutmgr.KnuthList#appendSequence(org.apache.fop.layoutmgr.KnuthSequence,) */ - public static boolean mustKeepTogether(BlockKnuthSequence sequence1, - BlockKnuthSequence sequence2) { - ListElement element1 = (ListElement) sequence1.get(sequence1.size() - 1); - LayoutManager lm1 = (LayoutManager) element1.getLayoutManager(); - ListElement element2 = (ListElement) 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; - } - } - } + public boolean appendSequence(KnuthSequence sequence) { + // log.debug("Cannot append a sequence without a BreakElement"); 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) + * @see KnuthList#appendSequence(KnuthSequence, boolean, BreakElement) */ - /** - * 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) { + public boolean appendSequence(KnuthSequence sequence, boolean keepTogether, + BreakElement breakElement) { 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)); + if (keepTogether) { + breakElement.setPenaltyValue(KnuthElement.INFINITE); + add(breakElement); + } else if (!((ListElement) getLast()).isGlue()) { + breakElement.setPenaltyValue(0); + add(breakElement); } -*/ addAll(sequence); + 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() */ diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index e495b4062..631aacf32 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -27,6 +27,7 @@ import org.apache.fop.area.Block; import org.apache.fop.area.LineArea; import org.apache.fop.datatypes.Length; import org.apache.fop.fonts.Font; +import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; import org.apache.fop.layoutmgr.inline.LineLayoutManager; import org.apache.fop.traits.MinOptMax; @@ -198,13 +199,15 @@ public class BlockLayoutManager extends BlockStackingLayoutManager * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether() */ public boolean mustKeepTogether() { - //TODO Keeps will have to be more sophisticated sooner or later + // TODO Keeps will have to be more sophisticated sooner or later // 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(); + return (!getBlockFO().getKeepTogether().getWithinPage().isAuto() + || !getBlockFO().getKeepTogether().getWithinColumn().isAuto() + || (getParent() instanceof BlockLevelLayoutManager + && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) + || (getParent() instanceof InlineLayoutManager + && ((InlineLayoutManager) getParent()).mustKeepTogether())); } /** @@ -212,7 +215,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager */ public boolean mustKeepWithPrevious() { return !getBlockFO().getKeepWithPrevious().getWithinPage().isAuto() - || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto(); + || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 494d732d7..c09ae8ae5 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -29,6 +29,7 @@ import org.apache.fop.area.Block; import org.apache.fop.fo.FObj; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.layoutmgr.inline.LineLayoutManager; import org.apache.fop.traits.MinOptMax; @@ -309,9 +310,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (mustKeepTogether() || context.isKeepWithNextPending() || childLC.isKeepWithPreviousPending()) { - //Clear keep pending flag + // Clear keep pending flag context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); // add an infinite penalty to forbid a break between // blocks contentList.add(new BreakElement( @@ -368,11 +368,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager return returnList; }*/ } - if (childLC.isKeepWithNextPending()) { - //Clear and propagate - childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); - context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); - } + // propagate and clear + context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, childLC.isKeepWithNextPending()); + childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); + childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); prevLM = curLM; } @@ -617,6 +616,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } fromIndex = workListIterator.previousIndex(); + /* + * TODO: why are KnuthPenalties added here, + * while in getNextKE they were changed to BreakElements? + */ // there is another block after this one if (bSomethingAdded && (this.mustKeepTogether() @@ -732,8 +735,12 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether() */ + // default action: ask parentLM public boolean mustKeepTogether() { - return false; + return ((getParent() instanceof BlockLevelLayoutManager + && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) + || (getParent() instanceof InlineLayoutManager + && ((InlineLayoutManager) getParent()).mustKeepTogether())); } /** diff --git a/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java b/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java index efe3e28ce..0e48eb1ae 100644 --- a/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java @@ -26,7 +26,8 @@ import org.apache.fop.layoutmgr.inline.KnuthInlineBox; /** - * + * Represents a list of inline Knuth elements. + * If closed, it represents all elements of a Knuth paragraph. */ public class InlineKnuthSequence extends KnuthSequence { @@ -63,9 +64,9 @@ public class InlineKnuthSequence extends KnuthSequence { } /* (non-Javadoc) - * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequence(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager) + * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequence(org.apache.fop.layoutmgr.KnuthSequence) */ - public boolean appendSequence(KnuthSequence sequence, LayoutManager lm) { + public boolean appendSequence(KnuthSequence sequence) { if (!canAppendSequence(sequence)) { return false; } @@ -82,17 +83,14 @@ public class InlineKnuthSequence extends KnuthSequence { } /* (non-Javadoc) - * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequenceOrClose(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager) + * @see KnuthSequence#appendSequence(KnuthSequence, boolean, BreakElement) */ - public boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm) { - if (!appendSequence(sequence, lm)) { - endSequence(); - return false; - } else { - return true; - } + public boolean appendSequence(KnuthSequence sequence, boolean keepTogether, + BreakElement breakElement) { + return appendSequence(sequence); } + /* (non-Javadoc) * @see org.apache.fop.layoutmgr.KnuthSequence#endSequence() */ @@ -108,9 +106,9 @@ public class InlineKnuthSequence extends KnuthSequence { KnuthBox prevBox = (KnuthBox) getLast(); if (prevBox.isAuxiliary() && (size() < 4 - || !getElement(size()-2).isGlue() - || !getElement(size()-3).isPenalty() - || !getElement(size()-4).isBox() + || !getElement(size() - 2).isGlue() + || !getElement(size() - 3).isPenalty() + || !getElement(size() - 4).isBox() ) ) { // Not the sequence we are expecting diff --git a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java index 405af1157..c574c7396 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java @@ -65,22 +65,53 @@ public abstract class KnuthSequence extends ArrayList { /** * 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. + * @param keepTogether Whether the two sequences must be kept together. + * @param breakElement The BreakElement that may be inserted between the two sequences. * @return whether the sequence was succesfully appended to this sequence. */ - public abstract boolean appendSequence(KnuthSequence sequence, LayoutManager lm); + public abstract boolean appendSequence(KnuthSequence sequence, boolean keepTogether, + BreakElement breakElement); + + /** + * Append sequence to this sequence if it can be appended. + * @param sequence The sequence that is to be appended. + * @return whether the sequence was succesfully appended to this sequence. + */ + public abstract boolean appendSequence(KnuthSequence 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 abstract boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm); + public boolean appendSequenceOrClose(KnuthSequence sequence) { + if (!appendSequence(sequence)) { + endSequence(); + return false; + } else { + return true; + } + } + + /** + * Append sequence to this sequence if it can be appended. + * If that is not possible, close this sequence. + * @param sequence The sequence that is to be appended. + * @param keepTogether Whether the two sequences must be kept together. + * @param breakElement The BreakElement that may be inserted between the two sequences. + * @return whether the sequence was succesfully appended to this sequence. + */ + public boolean appendSequenceOrClose(KnuthSequence sequence, boolean keepTogether, + BreakElement breakElement) { + if (!appendSequence(sequence, keepTogether, breakElement)) { + endSequence(); + return false; + } else { + return true; + } + } /** * Wrap the Positions of the elements of this sequence in a Position for LayoutManager lm. diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 633dda77d..d287b59f8 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -35,6 +35,8 @@ 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.BlockLevelLayoutManager; +import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthSequence; @@ -196,6 +198,24 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } } + /** + * @return true if this element must be kept together + */ + // TODO Use the keep-together property on Inline as well + public boolean mustKeepTogether() { + return mustKeepTogether(this.getParent()); + } + + private boolean mustKeepTogether(LayoutManager lm) { + if (lm instanceof BlockLevelLayoutManager) { + return ((BlockLevelLayoutManager) lm).mustKeepTogether(); + } else if (lm instanceof InlineLayoutManager) { + return ((InlineLayoutManager) lm).mustKeepTogether(); + } else { + return mustKeepTogether(lm.getParent()); + } + } + /** @see org.apache.fop.layoutmgr.LayoutManager */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; @@ -267,6 +287,9 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } // get KnuthElements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); + if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) { + childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); + } if (returnedList == null) { // curLM returned null because it finished; // just iterate once more to see if there is another child @@ -276,6 +299,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { continue; } if (curLM instanceof InlineLevelLayoutManager) { + context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); // "wrap" the Position stored in each element of returnedList ListIterator seqIter = returnedList.listIterator(); while (seqIter.hasNext()) { @@ -283,7 +307,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { sequence.wrapPositions(this); } if (lastSequence != null && lastSequence.appendSequenceOrClose - ((KnuthSequence) returnedList.get(0), this)) { + ((KnuthSequence) returnedList.get(0))) { returnedList.remove(0); } // add border and padding to the first complete sequence of this LM @@ -293,13 +317,21 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } 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)) { + boolean appended = false; + if (lastSequence != null) { + if (lastSequence.canAppendSequence(sequence)) { + BreakElement bk = new BreakElement(new Position(this), 0, context); + boolean keepTogether = (mustKeepTogether() + || context.isKeepWithNextPending() + || childLC.isKeepWithPreviousPending()); + appended = lastSequence.appendSequenceOrClose(sequence, keepTogether, bk); + } else { + lastSequence.endSequence(); + } + } + if (!appended) { // add border and padding to the first complete sequence of this LM if (!borderAdded) { addKnuthElementsForBorderPaddingStart(sequence); @@ -307,6 +339,11 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } returnList.add(sequence); } + // propagate and clear + context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, + childLC.isKeepWithNextPending()); + childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false); + childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); } lastSequence = (KnuthSequence) returnList.getLast(); lastChildLM = curLM; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index aa6c4b862..e3ea55669 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -1312,7 +1312,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether */ public boolean mustKeepTogether() { - return false; + return ((BlockLevelLayoutManager) getParent()).mustKeepTogether(); } /** diff --git a/test/layoutengine/standard-testcases/inline_block_nested_6.xml b/test/layoutengine/standard-testcases/inline_block_nested_6.xml new file mode 100644 index 000000000..eeb0bdd40 --- /dev/null +++ b/test/layoutengine/standard-testcases/inline_block_nested_6.xml @@ -0,0 +1,66 @@ + + + + + +

+ This test checks the value of the penalties between + KnuthBlockBoxes in inline context, with and without keep conditions. +

+
+ + + + + + + + + + + Before + Before1 + A1=B1, + C1=D1.after1 + Before2 + A2=B2, + C2=D2.after2 + Before3 + A3=B3, + C3=D3.after3after + + + + + + + 5 + + + 6 + + + + 6 + + + + 5 + 3 + + +