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()
*/
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;
* @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()));
}
/**
*/
public boolean mustKeepWithPrevious() {
return !getBlockFO().getKeepWithPrevious().getWithinPage().isAuto()
- || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto();
+ || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto();
}
/**
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;
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(
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;
}
}
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()
/**
* @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()));
}
/**
/**
- *
+ * Represents a list of inline Knuth elements.
+ * If closed, it represents all elements of a Knuth paragraph.
*/
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;
}
}
/* (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()
*/
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
/**
* 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.
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;
}
}
+ /**
+ * @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;
}
// 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
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()) {
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
}
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);
}
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;
* @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether
*/
public boolean mustKeepTogether() {
- return false;
+ return ((BlockLevelLayoutManager) getParent()).mustKeepTogether();
}
/**
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>
+ This test checks the value of the penalties between
+ KnuthBlockBoxes in inline context, with and without keep conditions.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+
+ <fo:page-sequence master-reference="normal" white-space-collapse="true">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block><fo:inline>Before
+ <fo:block id="b1" background-color="silver"><fo:inline>Before1
+ <fo:block id="b11" background-color="grey">A1=B1,</fo:block>
+ <fo:block id="b12">C1=D1.</fo:block>after1</fo:inline></fo:block>
+ <fo:block id="b2" background-color="lightgrey" keep-together.within-page="always"><fo:inline>Before2
+ <fo:block id="b21" background-color="grey">A2=B2,</fo:block>
+ <fo:block id="b22">C2=D2.</fo:block>after2</fo:inline></fo:block>
+ <fo:block id="b3" background-color="silver"><fo:inline>Before3
+ <fo:block id="b31" keep-with-next.within-page="always" background-color="grey">A3=B3,</fo:block>
+ <fo:block id="b32">C3=D3.</fo:block>after3</fo:inline></fo:block>after</fo:inline></fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <element-list category="breaker">
+ <skip>5</skip>
+ <!-- penalty between blocks b11 and b12, set by InlineLM in b1 -->
+ <penalty w="0" p="0"/>
+ <skip>6</skip>
+ <!-- penalty between blocks b21 and b22, set by InlineLM in b2 -->
+ <!-- keep-together.within-page="always" -->
+ <penalty w="0" p="1000"/>
+ <skip>6</skip>
+ <!-- penalty between blocks b31 and b32, set by InlineLM in b3 -->
+ <!-- keep-with-next.within-page="always" -->
+ <penalty w="0" p="1000"/>
+ <skip>5</skip>
+ <skip>3</skip>
+ </element-list>
+ </checks>
+</testcase>