From 829cd8e6757340bbdcb53d59e0f0ed5948b9e2c4 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Mon, 24 Oct 2005 09:21:26 +0000 Subject: [PATCH] Merged work on Temp_SpaceResolution branch into trunk (-r 320826:327988). Source: http://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_SpaceResolution/ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@328010 13f79535-47bb-0310-9956-ffa450edef68 --- .../datatypes/SimplePercentBaseContext.java | 3 +- .../ValidationPercentBaseContext.java | 59 ++ src/java/org/apache/fop/fo/FONode.java | 4 +- src/java/org/apache/fop/fo/flow/Table.java | 25 +- .../org/apache/fop/fo/flow/TableFObj.java | 16 +- .../apache/fop/layoutmgr/AbstractBreaker.java | 33 +- .../fop/layoutmgr/AreaAdditionUtil.java | 20 +- .../BlockContainerLayoutManager.java | 154 ++-- .../fop/layoutmgr/BlockLayoutManager.java | 122 +-- .../layoutmgr/BlockStackingLayoutManager.java | 351 ++++++--- .../apache/fop/layoutmgr/BorderElement.java | 65 ++ .../fop/layoutmgr/BorderOrPaddingElement.java | 50 ++ .../apache/fop/layoutmgr/BreakElement.java | 149 ++++ .../layoutmgr/ConditionalElementListener.java | 52 ++ .../fop/layoutmgr/ElementListUtils.java | 25 +- .../fop/layoutmgr/FlowLayoutManager.java | 25 +- .../layoutmgr/FootnoteBodyLayoutManager.java | 15 +- .../apache/fop/layoutmgr/KnuthElement.java | 67 +- .../fop/layoutmgr/KnuthPossPosIter.java | 8 +- .../apache/fop/layoutmgr/KnuthSequence.java | 12 +- .../apache/fop/layoutmgr/LayoutContext.java | 89 ++- .../org/apache/fop/layoutmgr/ListElement.java | 90 +++ .../apache/fop/layoutmgr/PaddingElement.java | 65 ++ .../fop/layoutmgr/PageBreakingAlgorithm.java | 5 + .../layoutmgr/PageSequenceLayoutManager.java | 15 +- .../fop/layoutmgr/PositionIterator.java | 2 +- .../org/apache/fop/layoutmgr/RelSide.java | 53 ++ .../apache/fop/layoutmgr/SpaceElement.java | 93 +++ .../apache/fop/layoutmgr/SpaceResolver.java | 737 ++++++++++++++++++ .../layoutmgr/StaticContentLayoutManager.java | 14 +- .../org/apache/fop/layoutmgr/TraitSetter.java | 116 ++- .../fop/layoutmgr/UnresolvedListElement.java | 46 ++ .../UnresolvedListElementWithLength.java | 112 +++ .../layoutmgr/inline/LineLayoutManager.java | 28 +- .../list/ListBlockLayoutManager.java | 96 ++- .../layoutmgr/list/ListItemLayoutManager.java | 191 +++-- .../table/TableCellLayoutManager.java | 89 ++- .../table/TableContentLayoutManager.java | 58 +- .../layoutmgr/table/TableLayoutManager.java | 187 +++-- .../fop/layoutmgr/table/TableStepper.java | 16 +- .../apache/fop/render/AbstractRenderer.java | 6 +- src/java/org/apache/fop/traits/MinOptMax.java | 5 + test/fotree/testcases/shorthand-prop-mix.fo | 43 + .../testcases/table_border-separation.fo | 79 ++ .../fop/fotreetest/ext/AssertElement.java | 21 +- .../logging/LoggingElementListObserver.java | 6 +- test/layoutengine/disabled-testcases.txt | 7 +- ...k-container_display-align_space-before.xml | 106 +-- ...k-container_space-before_space-after_1.xml | 160 ++++ ...k-container_space-before_space-after_2.xml | 93 +++ ...k-container_space-before_space-after_3.xml | 126 +++ .../testcases/block_border_padding.xml | 168 ++-- test/layoutengine/testcases/block_margin.xml | 50 +- .../testcases/block_margin_inherit.xml | 49 +- .../testcases/block_margin_percentages.xml | 49 +- .../testcases/block_margin_shorthands.xml | 60 +- .../testcases/block_padding_2.xml | 46 +- .../block_space-before_space-after_1.xml | 36 +- .../block_space-before_space-after_2.xml | 93 ++- .../block_space-before_space-after_3.xml | 2 +- .../block_space-before_space-after_4.xml | 83 ++ .../block_space-before_space-after_5.xml | 96 +++ .../block_space-before_space-after_6.xml | 92 +++ .../block_space-before_space-after_7.xml | 56 ++ .../block_space-before_space-after_8.xml | 49 ++ .../block_space-before_space-after_9.xml | 69 ++ .../block_space-before_space-after_9a.xml | 90 +++ .../testcases/character_border_padding.xml | 84 +- .../testcases/character_vertical-align.xml | 8 +- .../testcases/footnote_space-resolution.xml | 58 ++ .../testcases/inline_alignment-adjust_1.xml | 30 +- .../testcases/inline_alignment-adjust_2.xml | 62 +- .../testcases/inline_alignment-baseline_1.xml | 30 +- .../testcases/inline_alignment-baseline_2.xml | 66 +- .../testcases/inline_alignment-baseline_3.xml | 32 +- .../testcases/inline_alignment-baseline_4.xml | 150 ++-- .../testcases/inline_background-color.xml | 74 +- .../testcases/inline_baseline-shift_1.xml | 96 +-- .../testcases/inline_baseline-shift_2.xml | 91 +-- .../testcases/inline_baseline-shift_3.xml | 104 +-- .../testcases/inline_baseline-shift_4.xml | 104 +-- .../testcases/inline_border_padding.xml | 144 ++-- .../inline_border_padding_block_nested_1.xml | 104 +-- .../inline_border_padding_block_nested_2.xml | 336 ++++---- ...inline_border_padding_conditionality_1.xml | 326 ++++---- ...inline_border_padding_conditionality_2.xml | 250 +++--- .../inline_border_padding_hyphenate.xml | 342 ++++---- .../inline_border_padding_hyphenate_de.xml | 346 ++++---- .../testcases/inline_dominant-baseline_1.xml | 84 +- .../testcases/inline_dominant-baseline_2.xml | 88 +-- .../testcases/inline_dominant-baseline_3.xml | 46 +- .../testcases/inline_vertical-align_1.xml | 110 +-- .../testcases/inline_vertical-align_2.xml | 68 +- .../testcases/leader_border_padding.xml | 204 ++--- .../testcases/list-block_border_padding.xml | 196 ++--- .../list-block_space-before_space-after_1.xml | 221 ++++++ .../list-block_space-before_space-after_2.xml | 114 +++ .../list-item_space-before_space-after_1.xml | 13 + .../list-item_space-before_space-after_2.xml | 26 +- .../list-item_space-before_space-after_3.xml | 73 ++ .../testcases/page-breaking_2.xml | 5 +- .../page-number-citation_border_padding.xml | 84 +- .../page-number-citation_vertical-align.xml | 8 +- .../testcases/page-number_border_padding.xml | 84 +- .../testcases/page-number_vertical-align.xml | 8 +- .../region_side_space-resolution.xml | 63 ++ .../table-cell_block_margin_percentage.xml | 14 +- ...ble-cell_border_padding_conditionality.xml | 128 +++ .../testcases/table_border_padding_2.xml | 203 +++++ .../table_margin_space-before_space-after.xml | 182 ++--- .../table_space-before_space-after_1.xml | 203 +++++ .../table_space-before_space-after_2.xml | 104 +++ .../testcases/table_table-layout_fixed_1.xml | 18 +- 113 files changed, 7471 insertions(+), 2810 deletions(-) create mode 100644 src/java/org/apache/fop/datatypes/ValidationPercentBaseContext.java create mode 100644 src/java/org/apache/fop/layoutmgr/BorderElement.java create mode 100644 src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java create mode 100644 src/java/org/apache/fop/layoutmgr/BreakElement.java create mode 100644 src/java/org/apache/fop/layoutmgr/ConditionalElementListener.java create mode 100644 src/java/org/apache/fop/layoutmgr/ListElement.java create mode 100644 src/java/org/apache/fop/layoutmgr/PaddingElement.java create mode 100644 src/java/org/apache/fop/layoutmgr/RelSide.java create mode 100644 src/java/org/apache/fop/layoutmgr/SpaceElement.java create mode 100644 src/java/org/apache/fop/layoutmgr/SpaceResolver.java create mode 100644 src/java/org/apache/fop/layoutmgr/UnresolvedListElement.java create mode 100644 src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java create mode 100644 test/fotree/testcases/shorthand-prop-mix.fo create mode 100644 test/fotree/testcases/table_border-separation.fo create mode 100644 test/layoutengine/testcases/block-container_space-before_space-after_1.xml create mode 100644 test/layoutengine/testcases/block-container_space-before_space-after_2.xml create mode 100644 test/layoutengine/testcases/block-container_space-before_space-after_3.xml create mode 100644 test/layoutengine/testcases/block_space-before_space-after_4.xml create mode 100644 test/layoutengine/testcases/block_space-before_space-after_5.xml create mode 100644 test/layoutengine/testcases/block_space-before_space-after_6.xml create mode 100644 test/layoutengine/testcases/block_space-before_space-after_7.xml create mode 100644 test/layoutengine/testcases/block_space-before_space-after_8.xml create mode 100644 test/layoutengine/testcases/block_space-before_space-after_9.xml create mode 100644 test/layoutengine/testcases/block_space-before_space-after_9a.xml create mode 100644 test/layoutengine/testcases/footnote_space-resolution.xml create mode 100644 test/layoutengine/testcases/list-block_space-before_space-after_1.xml create mode 100644 test/layoutengine/testcases/list-block_space-before_space-after_2.xml create mode 100644 test/layoutengine/testcases/list-item_space-before_space-after_3.xml create mode 100644 test/layoutengine/testcases/region_side_space-resolution.xml create mode 100644 test/layoutengine/testcases/table-cell_border_padding_conditionality.xml create mode 100644 test/layoutengine/testcases/table_border_padding_2.xml create mode 100644 test/layoutengine/testcases/table_space-before_space-after_1.xml create mode 100644 test/layoutengine/testcases/table_space-before_space-after_2.xml diff --git a/src/java/org/apache/fop/datatypes/SimplePercentBaseContext.java b/src/java/org/apache/fop/datatypes/SimplePercentBaseContext.java index 8b0688fe1..4a3f26227 100644 --- a/src/java/org/apache/fop/datatypes/SimplePercentBaseContext.java +++ b/src/java/org/apache/fop/datatypes/SimplePercentBaseContext.java @@ -31,7 +31,8 @@ public class SimplePercentBaseContext implements PercentBaseContext { /** * @param parentContext the context to be used for all percentages other than lengthBase - * @param lengthBase the particular percentage length base for which this context provides a value + * @param lengthBase the particular percentage length base for which this context provides + * a value * @param lengthBaseValue the value to be returned for requests to the given lengthBase */ public SimplePercentBaseContext(PercentBaseContext parentContext, diff --git a/src/java/org/apache/fop/datatypes/ValidationPercentBaseContext.java b/src/java/org/apache/fop/datatypes/ValidationPercentBaseContext.java new file mode 100644 index 000000000..6d3e8fa36 --- /dev/null +++ b/src/java/org/apache/fop/datatypes/ValidationPercentBaseContext.java @@ -0,0 +1,59 @@ +/* + * 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: SimplePercentBaseContext.java 279656 2005-09-08 22:06:48Z pietsch $ */ + +package org.apache.fop.datatypes; + +import org.apache.fop.fo.FObj; + +/** + * This base context is used during validation when the actual base values are still unknown + * but should still already be checked. The actual value returned is not so important in this + * case. But it's important that zero and non-zero values can be distinguished. + *

+ * Example: A table with collapsing border model has no padding. The Table FO should be able + * to check if non-zero values (even percentages) have been specified. + */ +public final class ValidationPercentBaseContext implements PercentBaseContext { + + /** + * Main constructor. + */ + private ValidationPercentBaseContext() { + } + + /** + * Returns the value for the given lengthBase. + * @see org.apache.fop.datatypes.PercentBaseContext#getBaseLength(int, FObj) + */ + public int getBaseLength(int lengthBase, FObj fobj) { + //Simply return a dummy value which produces a non-zero value when a non-zero percentage + //was specified. + return 100000; + } + + private static PercentBaseContext pseudoContextForValidation = null; + + /** @return a base context for validation purposes. See class description. */ + public static PercentBaseContext getPseudoContextForValidationPurposes() { + if (pseudoContextForValidation == null) { + pseudoContextForValidation = new ValidationPercentBaseContext(); + } + return pseudoContextForValidation; + } + +} diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 86011004e..a142b9e3e 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -311,7 +311,7 @@ public abstract class FONode implements Cloneable { * @param problem text to display that indicates the problem */ protected void attributeWarning(String problem) { - log.warn(errorText(locator) + getName() + ", " + problem); + log.warn(warningText(locator) + getName() + ", " + problem); } /** @@ -437,7 +437,7 @@ public abstract class FONode implements Cloneable { * @param loc org.xml.sax.Locator object * @return String the formatted text */ - protected static String getLocatorString(Locator loc) { + public static String getLocatorString(Locator loc) { if (loc == null) { return "Unknown location"; } else { diff --git a/src/java/org/apache/fop/fo/flow/Table.java b/src/java/org/apache/fop/fo/flow/Table.java index 47047d41f..e08456127 100644 --- a/src/java/org/apache/fop/fo/flow/Table.java +++ b/src/java/org/apache/fop/fo/flow/Table.java @@ -24,9 +24,8 @@ import java.util.List; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.datatypes.Numeric; +import org.apache.fop.datatypes.ValidationPercentBaseContext; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.StaticPropertyList; import org.apache.fop.fo.ValidationException; @@ -129,17 +128,19 @@ public class Table extends TableFObj { colPList.setWritingMode(); defaultColumn.bind(colPList); - /*if (borderCollapse != EN_SEPARATE && commonBorderPaddingBackground.hasPadding()) { - //See "17.6.2 The collapsing border model" in CSS2 - getLogger().warn("Table may not have padding when using the collapsing " - + "border model. Padding will be ignored."); - }*/ if (borderCollapse != EN_SEPARATE) { - getLogger().warn("The collapsing border model on an fo:table " + attributeWarning("The collapsing border model on an fo:table " + "is currently not supported by FOP"); } if (tableLayout == EN_AUTO) { - getLogger().warn("table-layout=\"auto\" is currently not supported by FOP"); + attributeWarning("table-layout=\"auto\" is currently not supported by FOP"); + } + if (!isSeparateBorderModel() && getCommonBorderPaddingBackground().hasPadding( + ValidationPercentBaseContext.getPseudoContextForValidationPurposes())) { + //See "17.6.2 The collapsing border model" in CSS2 + attributeWarning("In collapsing border model a table does not have padding" + + " (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders)" + + ", but a non-zero value for padding was found. The padding will be ignored."); } } @@ -217,11 +218,11 @@ public class Table extends TableFObj { * @see org.apache.fop.fo.FONode#addChildNode(FONode) */ protected void addChildNode(FONode child) throws FOPException { - if (child.getName().equals("fo:table-column")) { + if ("fo:table-column".equals(child.getName())) { addColumnNode((TableColumn) child); - } else if (child.getName().equals("fo:table-footer")) { + } else if ("fo:table-footer".equals(child.getName())) { tableFooter = (TableBody)child; - } else if (child.getName().equals("fo:table-header")) { + } else if ("fo:table-header".equals(child.getName())) { tableHeader = (TableBody)child; } else { // add bodies diff --git a/src/java/org/apache/fop/fo/flow/TableFObj.java b/src/java/org/apache/fop/fo/flow/TableFObj.java index 11f4c3295..db95871e5 100644 --- a/src/java/org/apache/fop/fo/flow/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/TableFObj.java @@ -20,6 +20,7 @@ package org.apache.fop.fo.flow; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Numeric; +import org.apache.fop.datatypes.ValidationPercentBaseContext; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; @@ -27,9 +28,7 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; /** * Superclass for table-related FOs - * */ - public abstract class TableFObj extends FObj { private Numeric borderAfterPrecedence; @@ -82,8 +81,17 @@ public abstract class TableFObj extends FObj { if (getNameId() != FO_TABLE && getNameId() != FO_TABLE_CELL && getTable().isSeparateBorderModel() && getCommonBorderPaddingBackground().hasBorderInfo()) { - getLogger().warn("Borders on " + getName() - + " non-applicable for table with border-collapse=\"separate\""); + attributeWarning("In the separate border model (border-collapse=\"separate\")" + + ", borders cannot be specified on a " + getName() + + ", but a non-zero value for border was found. The border will be ignored. "); + } + if (getNameId() != FO_TABLE //Separate check for fo:table in Table.java + && getNameId() != FO_TABLE_CELL + && getCommonBorderPaddingBackground().hasPadding( + ValidationPercentBaseContext.getPseudoContextForValidationPurposes())) { + attributeWarning(getName() + " does not have padding" + + " (see the property list for " + getName() + " in XSL 1.0)" + + ", but a non-zero value for padding was found. The padding will be ignored."); } } diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 74df8e188..743d30574 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -76,8 +76,8 @@ public abstract class AbstractBreaker { return this.startOn; } - public BlockSequence endBlockSequence() { - KnuthSequence temp = super.endSequence(); + public BlockSequence endBlockSequence(Position breakPosition) { + KnuthSequence temp = super.endSequence(breakPosition); if (temp != null) { BlockSequence returnSequence = new BlockSequence(startOn); returnSequence.addAll(temp); @@ -273,6 +273,7 @@ public abstract class AbstractBreaker { ListIterator effectiveListIterator = effectiveList.listIterator(); int startElementIndex = 0; int endElementIndex = 0; + int lastBreak = -1; for (int p = 0; p < partCount; p++) { PageBreakPosition pbp = (PageBreakPosition) alg.getPageBreaks().get(p); @@ -307,6 +308,10 @@ public abstract class AbstractBreaker { int displayAlign = getCurrentDisplayAlign(); + //The following is needed by SpaceResolver.performConditionalsNotification() + //further down as there may be important Position elements in the element list trailer + int notificationEndElementIndex = endElementIndex; + // ignore the last elements added by the // PageSequenceLayoutManager endElementIndex -= (endElementIndex == (originalList.size() - 1)) @@ -328,12 +333,13 @@ public abstract class AbstractBreaker { while (effectiveListIterator.hasNext() && !(firstElement = (KnuthElement) effectiveListIterator.next()) .isBox()) { - if (firstElement.isGlue()) { + /* + if (firstElement.isGlue() && firstElement.getLayoutManager() != null) { // discard the space representd by the glue element ((BlockLevelLayoutManager) firstElement .getLayoutManager()) .discardSpace((KnuthGlue) firstElement); - } + }*/ startElementIndex++; } @@ -377,6 +383,11 @@ public abstract class AbstractBreaker { } /* *** *** non-standard extension *** *** */ + // Handle SpaceHandling(Break)Positions, see SpaceResolver! + SpaceResolver.performConditionalsNotification(effectiveList, + startElementIndex, notificationEndElementIndex, lastBreak); + + // Add areas now! addAreas(new KnuthPossPosIter(effectiveList, startElementIndex, endElementIndex + 1), childLC); } else { @@ -386,10 +397,18 @@ public abstract class AbstractBreaker { finishPart(alg, pbp); + lastBreak = endElementIndex; startElementIndex = pbp.getLeafPos() + 1; } } - + /** + * Notifies the layout managers about the space and conditional length situation based on + * the break decisions. + * @param effectiveList Element list to be painted + * @param startElementIndex start index of the part + * @param endElementIndex end index of the part + * @param lastBreak index of the last break element + */ /** * Handles span changes reported through the LayoutContext. * Only used by the PSLM and called by getNextBlockList(). @@ -425,10 +444,12 @@ public abstract class AbstractBreaker { //Only implemented by the PSLM nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn); + Position breakPosition = null; if (((KnuthElement) returnedList.getLast()).isPenalty() && ((KnuthPenalty) returnedList.getLast()).getP() == -KnuthElement.INFINITE) { KnuthPenalty breakPenalty = (KnuthPenalty) returnedList .removeLast(); + breakPosition = breakPenalty.getPosition(); switch (breakPenalty.getBreakClass()) { case Constants.EN_PAGE: log.debug("PLM> break - PAGE"); @@ -454,7 +475,7 @@ public abstract class AbstractBreaker { } blockList.addAll(returnedList); BlockSequence seq = null; - seq = blockList.endBlockSequence(); + seq = blockList.endBlockSequence(breakPosition); if (seq != null) { blockLists.add(seq); } diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java index 44ad1496b..a210754af 100644 --- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java +++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java @@ -21,6 +21,11 @@ package org.apache.fop.layoutmgr; import java.util.Iterator; import java.util.LinkedList; +import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition; + +/** + * Utility class which provides common code for the addAreas stage. + */ public class AreaAdditionUtil { private static class StackingIter extends PositionIterator { @@ -37,6 +42,12 @@ public class AreaAdditionUtil { } } + /** + * Creates the child areas for the given layout manager. + * @param bslm the BlockStackingLayoutManager instance for which "addAreas" is performed. + * @param parentIter the position iterator + * @param layoutContext the layout context + */ public static void addAreas(BlockStackingLayoutManager bslm, PositionIterator parentIter, LayoutContext layoutContext) { LayoutManager childLM = null; @@ -52,6 +63,9 @@ public class AreaAdditionUtil { Position pos; while (parentIter.hasNext()) { pos = (Position)parentIter.next(); + if (pos == null) { + continue; + } if (pos.getIndex() >= 0) { if (firstPos == null) { firstPos = pos; @@ -65,12 +79,14 @@ public class AreaAdditionUtil { if (firstLM == null) { firstLM = lastLM; } + } else if (pos instanceof SpaceHandlingBreakPosition) { + positionList.add(pos); } else { // pos was created by this LM, so it must be ignored } } - if (bslm.markers != null) { + if (bslm != null && bslm.markers != null) { bslm.getCurrentPV().addMarkers(bslm.markers, true, bslm.isFirst(firstPos), bslm.isLast(lastPos)); } @@ -91,7 +107,7 @@ public class AreaAdditionUtil { lc.setStackLimit(layoutContext.getStackLimit()); childLM.addAreas(childPosIter, lc); } - if (bslm.markers != null) { + if (bslm != null && bslm.markers != null) { bslm.getCurrentPV().addMarkers(bslm.markers, false, bslm.isFirst(firstPos), bslm.isLast(lastPos)); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 55dd12dde..50281ef44 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -39,7 +39,8 @@ import org.apache.fop.traits.SpaceVal; /** * LayoutManager for a block-container FO. */ -public class BlockContainerLayoutManager extends BlockStackingLayoutManager { +public class BlockContainerLayoutManager extends BlockStackingLayoutManager + implements ConditionalElementListener { private BlockViewport viewportBlockArea; private Block referenceArea; @@ -68,6 +69,14 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { private MinOptMax foBlockSpaceBefore; private MinOptMax foBlockSpaceAfter; + private boolean discardBorderBefore; + private boolean discardBorderAfter; + private boolean discardPaddingBefore; + private boolean discardPaddingAfter; + private MinOptMax effSpaceBefore; + private MinOptMax effSpaceAfter; + + /** * Create a new block container layout manager. * @param node block-container node to create the layout manager for. @@ -76,6 +85,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { super(node); } + /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */ public void initialize() { abProps = getBlockContainerFO().getCommonAbsolutePosition(); foBlockSpaceBefore = new SpaceVal(getBlockContainerFO().getCommonMarginBlock() @@ -111,6 +121,15 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { .spaceAfter.getSpace().getMinimum(this).getLength().getValue(this); } } + + private void resetSpaces() { + this.discardBorderBefore = false; + this.discardBorderAfter = false; + this.discardPaddingBefore = false; + this.discardPaddingAfter = false; + this.effSpaceBefore = foSpaceBefore; + this.effSpaceAfter = foSpaceAfter; + } /** @return the content IPD */ protected int getRotatedIPD() { @@ -151,6 +170,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { /** @see org.apache.fop.layoutmgr.LayoutManager */ public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + resetSpaces(); if (isAbsoluteOrFixed()) { return getNextKnuthElementsAbsolute(context, alignment); } @@ -201,7 +221,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { if (!bBreakBeforeServed) { try { - if (addKnuthElementsForBreakBefore(returnList)) { + if (addKnuthElementsForBreakBefore(returnList, context)) { return returnList; } } finally { @@ -209,18 +229,20 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { } } - if (!bSpaceBeforeServed) { - addKnuthElementsForSpaceBefore(returnList, alignment); - bSpaceBeforeServed = true; - } + addKnuthElementsForSpaceBefore(returnList, alignment); - addKnuthElementsForBorderPaddingBefore(returnList); + addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); + firstVisibleMarkServed = true; if (autoHeight) { + //Spaces, border and padding to be repeated at each break + addPendingMarks(context); + BlockLevelLayoutManager curLM; // currently active LM BlockLevelLayoutManager prevLM = null; // previously active LM while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); + childLC.copyPendingMarksFrom(context); // curLM is a ? childLC.setStackLimit(MinOptMax.subtract(context .getStackLimit(), stackLimit)); @@ -230,10 +252,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { // get elements from curLM returnedList = curLM.getNextKnuthElements(childLC, alignment); if (returnedList.size() == 1 - && ((KnuthElement)returnedList.getFirst()).isPenalty() - && ((KnuthPenalty)returnedList.getFirst()).getP() - == -KnuthElement.INFINITE) { + && ((KnuthElement)returnedList.getFirst()).isForcedBreak()) { // a descendant of this block has break-before + /* if (returnList.size() == 0) { // the first child (or its first child ...) has // break-before; @@ -241,7 +262,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { // the // following page bSpaceBeforeServed = false; - } + }*/ contentList.addAll(returnedList); // "wrap" the Position inside each element @@ -259,13 +280,17 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { || curLM.mustKeepWithPrevious()) { // add an infinite penalty to forbid a break between // blocks - contentList.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, - new Position(this), false)); + contentList.add(new BreakElement( + new Position(this), KnuthElement.INFINITE, context)); + //contentList.add(new KnuthPenalty(0, + // KnuthElement.INFINITE, false, + // new Position(this), false)); } else if (!((KnuthElement) contentList.getLast()).isGlue()) { // add a null penalty to allow a break between blocks - contentList.add(new KnuthPenalty(0, 0, false, - new Position(this), false)); + contentList.add(new BreakElement( + new Position(this), 0, context)); + //contentList.add(new KnuthPenalty(0, 0, false, + // new Position(this), false)); } else { // the last element in contentList is a glue; // it is a feasible breakpoint, there is no need to add @@ -277,9 +302,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { //Avoid NoSuchElementException below (happens with empty blocks) continue; } - if (((KnuthElement) returnedList.getLast()).isPenalty() - && ((KnuthPenalty) returnedList.getLast()).getP() - == -KnuthElement.INFINITE) { + if (((ListElement)returnedList.getLast()).isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished()) { // there is no other content in this block; @@ -328,9 +351,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { } } } - addKnuthElementsForBorderPaddingAfter(returnList); + addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); - addKnuthElementsForBreakAfter(returnList); + addKnuthElementsForBreakAfter(returnList, context); setFinished(true); return returnList; @@ -422,7 +445,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { contentRectOffsetX += getBlockContainerFO() .getCommonMarginBlock().startIndent.getValue(this); double contentRectOffsetY = offset.getY(); - contentRectOffsetY += getSpaceBefore(); + contentRectOffsetY += getSpaceBefore(); //TODO Uhm, is that necessary? contentRectOffsetY += getBlockContainerFO() .getCommonBorderPaddingBackground().getBorderBeforeWidth(false); contentRectOffsetY += getBlockContainerFO() @@ -544,9 +567,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { } if (returnedList != null) { bclm.wrapPositionElements(returnedList, returnList); - //returnList.addAll(returnedList); } } + SpaceResolver.resolveElementList(returnList); setFinished(true); return returnList; } @@ -605,9 +628,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { return new Point(x, y); } - /** - * @see org.apache.fop.layoutmgr.LayoutManager#addAreas(org.apache.fop.layoutmgr.PositionIterator, org.apache.fop.layoutmgr.LayoutContext) - */ + /** @see org.apache.fop.layoutmgr.LayoutManager */ public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); @@ -766,11 +787,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { //} } - // if adjusted space before - if (bSpaceBefore) { - addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); - } - while ((childLM = childPosIter.getNextChildLM()) != null) { // set last area flag lc.setFlags(LayoutContext.LAST_AREA, @@ -780,30 +796,21 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { childLM.addAreas(childPosIter, lc); } } else { - // if adjusted space before - if (bSpaceBefore) { - addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); - } //Add child areas inside the reference area bcpos.getBreaker().addContainedAreas(); } - //int bIndents = getBlockContainerFO().getCommonBorderPaddingBackground() - // .getBPPaddingAndBorder(false); - if (markers != null) { getCurrentPV().addMarkers(markers, false, isFirst(firstPos), isLast(lastPos)); } + TraitSetter.addSpaceBeforeAfter(viewportBlockArea, layoutContext.getSpaceAdjust(), + effSpaceBefore, effSpaceAfter); flush(); - // if adjusted space after - if (bSpaceAfter) { - addBlockSpacing(0, new MinOptMax(adjustedSpaceAfter)); - } - viewportBlockArea = null; referenceArea = null; + resetSpaces(); } /** @@ -826,7 +833,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { TraitSetter.setProducerID(viewportBlockArea, getBlockContainerFO().getId()); TraitSetter.addBorders(viewportBlockArea, - getBlockContainerFO().getCommonBorderPaddingBackground(), this); + getBlockContainerFO().getCommonBorderPaddingBackground(), + discardBorderBefore, discardBorderAfter, false, false, this); + TraitSetter.addPadding(viewportBlockArea, + getBlockContainerFO().getCommonBorderPaddingBackground(), + discardPaddingBefore, discardPaddingAfter, false, false, this); // TraitSetter.addBackground(viewportBlockArea, // getBlockContainerFO().getCommonBorderPaddingBackground(), // this); @@ -918,17 +929,13 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { } } - /** - * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#negotiateBPDAdjustment(int, org.apache.fop.layoutmgr.KnuthElement) - */ + /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager */ public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { // TODO Auto-generated method stub return 0; } - /** - * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#discardSpace(org.apache.fop.layoutmgr.KnuthGlue) - */ + /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager */ public void discardSpace(KnuthGlue spaceGlue) { // TODO Auto-generated method stub @@ -982,6 +989,51 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { public boolean getGeneratesBlockArea() { return true; } - + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifySpace(RelSide side, MinOptMax effectiveLength) { + if (RelSide.BEFORE == side) { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceBefore + "-> " + effectiveLength); + } + this.effSpaceBefore = effectiveLength; + } else { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceAfter + "-> " + effectiveLength); + } + this.effSpaceAfter = effectiveLength; + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyBorder(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardBorderBefore = true; + } else { + this.discardBorderAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Border " + side + " -> " + effectiveLength); + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyPadding(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardPaddingBefore = true; + } else { + this.discardPaddingAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Padding " + side + " -> " + effectiveLength); + } + } + } diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index d353727e4..838e23cfb 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -35,7 +35,8 @@ import org.apache.fop.traits.SpaceVal; /** * LayoutManager for a block FO. */ -public class BlockLayoutManager extends BlockStackingLayoutManager { +public class BlockLayoutManager extends BlockStackingLayoutManager + implements ConditionalElementListener { private Block curBlockArea; @@ -46,6 +47,13 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { private Length lineHeight; private int follow = 2000; private int middleShift = 0; + + private boolean discardBorderBefore; + private boolean discardBorderAfter; + private boolean discardPaddingBefore; + private boolean discardPaddingAfter; + private MinOptMax effSpaceBefore; + private MinOptMax effSpaceAfter; /** The list of child BreakPoss instances. */ protected List childBreaks = new java.util.ArrayList(); @@ -87,6 +95,21 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { } } + /** @see org.apache.fop.layoutmgr.BlockStackingLayoutManager */ + public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + resetSpaces(); + return super.getNextKnuthElements(context, alignment); + } + + private void resetSpaces() { + this.discardBorderBefore = false; + this.discardBorderAfter = false; + this.discardPaddingBefore = false; + this.discardPaddingAfter = false; + this.effSpaceBefore = foSpaceBefore; + this.effSpaceAfter = foSpaceAfter; + } + /** * Proxy iterator for Block LM. * This iterator creates and holds the complete list @@ -277,12 +300,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { } getPSLM().addIDToPage(getBlockFO().getId()); - /* TODO remove when markers are really ok - log.debug("Checking on " + this); - log.debug("Checking first=" + firstPos); - log.debug("Checking last=" + lastPos); - log.debug("->" + isFirst(firstPos) + "/" + isLast(lastPos)); - */ if (markers != null) { getCurrentPV().addMarkers(markers, true, isFirst(firstPos), isLast(lastPos)); } @@ -361,14 +378,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { //} } - // if adjusted space before - double adjust = layoutContext.getSpaceAdjust(); - addBlockSpacing(adjust, foSpaceBefore); - foSpaceBefore = null; - //if (bSpaceBefore) { - // addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); - //} - while ((childLM = childPosIter.getNextChildLM()) != null) { // set last area flag lc.setFlags(LayoutContext.LAST_AREA, @@ -378,22 +387,16 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { childLM.addAreas(childPosIter, lc); } - //int bIndents = getBlockFO().getCommonBorderPaddingBackground() - // .getBPPaddingAndBorder(false); - if (markers != null) { getCurrentPV().addMarkers(markers, false, isFirst(firstPos), isLast(lastPos)); } + TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), + effSpaceBefore, effSpaceAfter); flush(); - // if adjusted space after - addBlockSpacing(adjust, foSpaceAfter); - //if (bSpaceAfter) { - // addBlockSpacing(0, new MinOptMax(adjustedSpaceAfter)); - //} - curBlockArea = null; + resetSpaces(); } /** @@ -426,30 +429,16 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { // set traits TraitSetter.setProducerID(curBlockArea, getBlockFO().getId()); TraitSetter.addBorders(curBlockArea, - getBlockFO().getCommonBorderPaddingBackground(), this); + getBlockFO().getCommonBorderPaddingBackground(), + discardBorderBefore, discardBorderAfter, false, false, this); + TraitSetter.addPadding(curBlockArea, + getBlockFO().getCommonBorderPaddingBackground(), + discardPaddingBefore, discardPaddingAfter, false, false, this); TraitSetter.addMargins(curBlockArea, getBlockFO().getCommonBorderPaddingBackground(), getBlockFO().getCommonMarginBlock(), this); - // Set up dimensions - // Get reference IPD from parentArea - //int referenceIPD = parentArea.getIPD(); - //curBlockArea.setIPD(referenceIPD); - - // Set the width of the block based on the parent block - // Need to be careful though, if parent is BC then width may not be set - /* TODO remove if really not used anymore - int parentwidth = 0; - if (parentArea instanceof BlockParent) { - parentwidth = ((BlockParent) parentArea).getIPD(); - } - if (parentwidth == 0) { - parentwidth = referenceIPD; - } - parentwidth -= getIPIndents(); - */ - setCurrentArea(curBlockArea); // ??? for generic operations } return curBlockArea; @@ -533,6 +522,51 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { public boolean getGeneratesBlockArea() { return true; } - + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifySpace(RelSide side, MinOptMax effectiveLength) { + if (RelSide.BEFORE == side) { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceBefore + "-> " + effectiveLength); + } + this.effSpaceBefore = effectiveLength; + } else { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceAfter + "-> " + effectiveLength); + } + this.effSpaceAfter = effectiveLength; + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyBorder(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardBorderBefore = true; + } else { + this.discardBorderAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Border " + side + " -> " + effectiveLength); + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyPadding(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardPaddingBefore = true; + } else { + this.discardPaddingAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Padding " + side + " -> " + effectiveLength); + } + } + } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 084101ce4..b3ad7225b 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -53,12 +53,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager protected int adjustedSpaceAfter = 0; /** Only used to store the original list when createUnitElements is called */ protected LinkedList storedList = null; - /** FO node */ - protected FObj fobj; /** Indicates whether break before has been served or not */ protected boolean bBreakBeforeServed = false; - /** Indicates whether space before has been served or not */ - protected boolean bSpaceBeforeServed = false; + /** Indicates whether the first visible mark has been returned by this LM, yet */ + protected boolean firstVisibleMarkServed = false; /** Reference IPD available */ protected int referenceIPD = 0; /** @@ -84,7 +82,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager public BlockStackingLayoutManager(FObj node) { super(node); setGeneratesBlockArea(true); - fobj = node; } /** @@ -103,16 +100,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager this.parentArea = parentArea; } - protected MinOptMax resolveSpaceSpecifier(Area nextArea) { - SpaceSpecifier spaceSpec = new SpaceSpecifier(false); - // Area prevArea = getCurrentArea().getLast(); - // if (prevArea != null) { - // spaceSpec.addSpace(prevArea.getSpaceAfter()); - // } - // spaceSpec.addSpace(nextArea.getSpaceBefore()); - return spaceSpec.resolve(false); - } - /** * Add a block spacer for space before and space after a block. * This adds an empty Block area that acts as a block space. @@ -121,15 +108,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param minoptmax the min/opt/max value of the spacing */ public void addBlockSpacing(double adjust, MinOptMax minoptmax) { - if (minoptmax == null) { - return; - } - int sp = minoptmax.opt; - if (adjust > 0) { - sp = sp + (int)(adjust * (minoptmax.max - minoptmax.opt)); - } else { - sp = sp + (int)(adjust * (minoptmax.opt - minoptmax.min)); - } + int sp = TraitSetter.getEffectiveSpace(adjust, minoptmax); if (sp != 0) { Block spacer = new Block(); spacer.setBPD(sp); @@ -153,7 +132,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager //log.error("Child not a Block in BlockStackingLM!"); } - MinOptMax spaceBefore = resolveSpaceSpecifier(childArea); parentArea.addBlock((Block) childArea); flush(); // hand off current area to parent } @@ -232,7 +210,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (!bBreakBeforeServed) { try { - if (addKnuthElementsForBreakBefore(returnList)) { + if (addKnuthElementsForBreakBefore(returnList, context)) { return returnList; } } finally { @@ -240,15 +218,17 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } } - if (!bSpaceBeforeServed) { - addKnuthElementsForSpaceBefore(returnList, alignment); - bSpaceBeforeServed = true; - } + addKnuthElementsForSpaceBefore(returnList, alignment); - addKnuthElementsForBorderPaddingBefore(returnList); + addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); + firstVisibleMarkServed = true; + + //Spaces, border and padding to be repeated at each break + addPendingMarks(context); while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); + childLC.copyPendingMarksFrom(context); if (curLM instanceof LineLayoutManager) { // curLM is a LineLayoutManager // set stackLimit for lines @@ -273,9 +253,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } if (returnedList != null && returnedList.size() == 1 - && ((KnuthElement) returnedList.getFirst()).isPenalty() - && ((KnuthPenalty) returnedList.getFirst()).getP() == -KnuthElement.INFINITE) { + && ((ListElement) returnedList.getFirst()).isForcedBreak()) { // a descendant of this block has break-before + /* if (returnList.size() == 0) { // the first child (or its first child ...) has // break-before; @@ -283,7 +263,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // the // following page bSpaceBeforeServed = false; - } + }*/ contentList.addAll(returnedList); /* extension: conversione di tutta la sequenza fin'ora ottenuta */ @@ -311,17 +291,27 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); // add an infinite penalty to forbid a break between // blocks + contentList.add(new BreakElement( + new Position(this), KnuthElement.INFINITE, context)); + /* contentList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new Position(this), false)); - } else if (!((KnuthElement) contentList.getLast()).isGlue()) { + */ + } else if (!((ListElement) contentList.getLast()).isGlue()) { // add a null penalty to allow a break between blocks + contentList.add(new BreakElement( + new Position(this), 0, context)); + /* contentList.add(new KnuthPenalty(0, 0, false, - new Position(this), false)); + new Position(this), false));*/ } else { // the last element in contentList is a glue; // it is a feasible breakpoint, there is no need to add // a penalty + log.warn("glue-type break possibility not handled properly, yet"); + //TODO Does this happen? If yes, need to deal with border and padding + //at the break possibility } } if (returnedList == null || returnedList.size() == 0) { @@ -329,9 +319,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager continue; } contentList.addAll(returnedList); - if (((KnuthElement) returnedList.getLast()).isPenalty() - && ((KnuthPenalty) returnedList.getLast()).getP() - == -KnuthElement.INFINITE) { + if (((ListElement) returnedList.getLast()).isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished()) { // there is no other content in this block; @@ -380,9 +368,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager returnList.add(new KnuthBox(0, notifyPos(new Position(this)), true)); } - addKnuthElementsForBorderPaddingAfter(returnList); + addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); - addKnuthElementsForBreakAfter(returnList); + addKnuthElementsForBreakAfter(returnList, context); if (mustKeepWithNext()) { context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); @@ -741,27 +729,159 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** - * Creates Knuth elements for before border padding and adds them to the return list. - * @param returnList return list to add the additional elements to + * Adds the unresolved elements for border and padding to a layout context so break + * possibilities can be properly constructed. + * @param context the layout context */ - protected void addKnuthElementsForBorderPaddingBefore(LinkedList returnList/*, - Position returnPosition*/) { - //Border and Padding (before) - CommonBorderPaddingBackground borderAndPadding = null; + protected void addPendingMarks(LayoutContext context) { + SpaceProperty spaceBefore = getSpaceBeforeProperty(); + if (spaceBefore != null + && !(spaceBefore.getMinimum(this).getLength().getValue(this) == 0 + && spaceBefore.getMaximum(this).getLength().getValue(this) == 0)) { + context.addPendingBeforeMark(new SpaceElement(getAuxiliaryPosition(), spaceBefore, + RelSide.BEFORE, + true, false, this)); + } + SpaceProperty spaceAfter = getSpaceAfterProperty(); + if (spaceAfter != null + && !(spaceAfter.getMinimum(this).getLength().getValue(this) == 0 + && spaceAfter.getMaximum(this).getLength().getValue(this) == 0)) { + context.addPendingAfterMark(new SpaceElement(getAuxiliaryPosition(), spaceAfter, + RelSide.AFTER, + false, true, this)); + } + CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground(); + if (borderAndPadding != null) { + if (borderAndPadding.getBorderBeforeWidth(false) > 0) { + context.addPendingBeforeMark(new BorderElement( + getAuxiliaryPosition(), + borderAndPadding.getBorderInfo( + CommonBorderPaddingBackground.BEFORE).getWidth(), + RelSide.BEFORE, + false, false, this)); + } + if (borderAndPadding.getPaddingBefore(false, this) > 0) { + context.addPendingBeforeMark(new PaddingElement( + getAuxiliaryPosition(), + borderAndPadding.getPaddingLengthProperty( + CommonBorderPaddingBackground.BEFORE), + RelSide.BEFORE, + false, false, this)); + } + if (borderAndPadding.getBorderAfterWidth(false) > 0) { + context.addPendingAfterMark(new BorderElement( + getAuxiliaryPosition(), + borderAndPadding.getBorderInfo( + CommonBorderPaddingBackground.AFTER).getWidth(), + RelSide.AFTER, + false, false, this)); + } + if (borderAndPadding.getPaddingAfter(false, this) > 0) { + context.addPendingAfterMark(new PaddingElement( + getAuxiliaryPosition(), + borderAndPadding.getPaddingLengthProperty( + CommonBorderPaddingBackground.AFTER), + RelSide.AFTER, + false, false, this)); + } + } + } + + /** @return the border, padding and background info structure */ + private CommonBorderPaddingBackground getBorderPaddingBackground() { if (fobj instanceof org.apache.fop.fo.flow.Block) { - borderAndPadding = ((org.apache.fop.fo.flow.Block)fobj) + return ((org.apache.fop.fo.flow.Block)fobj) .getCommonBorderPaddingBackground(); } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) { - borderAndPadding = ((org.apache.fop.fo.flow.BlockContainer)fobj) + return ((org.apache.fop.fo.flow.BlockContainer)fobj) + .getCommonBorderPaddingBackground(); + } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) { + return ((org.apache.fop.fo.flow.ListBlock)fobj) .getCommonBorderPaddingBackground(); + } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) { + return ((org.apache.fop.fo.flow.ListItem)fobj) + .getCommonBorderPaddingBackground(); + } else if (fobj instanceof org.apache.fop.fo.flow.Table) { + return ((org.apache.fop.fo.flow.Table)fobj) + .getCommonBorderPaddingBackground(); + } else { + return null; + } + } + + /** @return the space-before property */ + private SpaceProperty getSpaceBeforeProperty() { + if (fobj instanceof org.apache.fop.fo.flow.Block) { + return ((org.apache.fop.fo.flow.Block)fobj) + .getCommonMarginBlock().spaceBefore; + } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) { + return ((org.apache.fop.fo.flow.BlockContainer)fobj) + .getCommonMarginBlock().spaceBefore; + } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) { + return ((org.apache.fop.fo.flow.ListBlock)fobj) + .getCommonMarginBlock().spaceBefore; + } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) { + return ((org.apache.fop.fo.flow.ListItem)fobj) + .getCommonMarginBlock().spaceBefore; + } else if (fobj instanceof org.apache.fop.fo.flow.Table) { + return ((org.apache.fop.fo.flow.Table)fobj) + .getCommonMarginBlock().spaceBefore; + } else { + return null; + } + } + + /** @return the space-after property */ + private SpaceProperty getSpaceAfterProperty() { + if (fobj instanceof org.apache.fop.fo.flow.Block) { + return ((org.apache.fop.fo.flow.Block)fobj) + .getCommonMarginBlock().spaceAfter; + } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) { + return ((org.apache.fop.fo.flow.BlockContainer)fobj) + .getCommonMarginBlock().spaceAfter; + } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) { + return ((org.apache.fop.fo.flow.ListBlock)fobj) + .getCommonMarginBlock().spaceAfter; + } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) { + return ((org.apache.fop.fo.flow.ListItem)fobj) + .getCommonMarginBlock().spaceAfter; + } else if (fobj instanceof org.apache.fop.fo.flow.Table) { + return ((org.apache.fop.fo.flow.Table)fobj) + .getCommonMarginBlock().spaceAfter; + } else { + return null; } + } + + /** + * Creates Knuth elements for before border padding and adds them to the return list. + * @param returnList return list to add the additional elements to + */ + protected void addKnuthElementsForBorderPaddingBefore(LinkedList returnList, boolean isFirst) { + //Border and Padding (before) + CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground(); if (borderAndPadding != null) { + if (borderAndPadding.getBorderBeforeWidth(false) > 0) { + returnList.add(new BorderElement( + getAuxiliaryPosition(), + borderAndPadding.getBorderInfo(CommonBorderPaddingBackground.BEFORE) + .getWidth(), + RelSide.BEFORE, isFirst, false, this)); + } + if (borderAndPadding.getPaddingBefore(false, this) > 0) { + returnList.add(new PaddingElement( + getAuxiliaryPosition(), + borderAndPadding.getPaddingLengthProperty( + CommonBorderPaddingBackground.BEFORE), + RelSide.BEFORE, isFirst, false, this)); + } //TODO Handle conditionality + /* int bpBefore = borderAndPadding.getBorderBeforeWidth(false) + borderAndPadding.getPaddingBefore(false, this); if (bpBefore > 0) { returnList.add(new KnuthBox(bpBefore, getAuxiliaryPosition(), true)); - } + }*/ } } @@ -769,24 +889,31 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * Creates Knuth elements for after border padding and adds them to the return list. * @param returnList return list to add the additional elements to */ - protected void addKnuthElementsForBorderPaddingAfter(LinkedList returnList/*, - Position returnPosition*/) { + protected void addKnuthElementsForBorderPaddingAfter(LinkedList returnList, boolean isLast) { //Border and Padding (after) - CommonBorderPaddingBackground borderAndPadding = null; - if (fobj instanceof org.apache.fop.fo.flow.Block) { - borderAndPadding = ((org.apache.fop.fo.flow.Block)fobj) - .getCommonBorderPaddingBackground(); - } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) { - borderAndPadding = ((org.apache.fop.fo.flow.BlockContainer)fobj) - .getCommonBorderPaddingBackground(); - } + CommonBorderPaddingBackground borderAndPadding = getBorderPaddingBackground(); if (borderAndPadding != null) { + if (borderAndPadding.getPaddingAfter(false, this) > 0) { + returnList.add(new PaddingElement( + getAuxiliaryPosition(), + borderAndPadding.getPaddingLengthProperty( + CommonBorderPaddingBackground.AFTER), + RelSide.AFTER, false, isLast, this)); + } + if (borderAndPadding.getBorderAfterWidth(false) > 0) { + returnList.add(new BorderElement( + getAuxiliaryPosition(), + borderAndPadding.getBorderInfo(CommonBorderPaddingBackground.AFTER) + .getWidth(), + RelSide.AFTER, false, isLast, this)); + } //TODO Handle conditionality + /* int bpAfter = borderAndPadding.getBorderAfterWidth(false) + borderAndPadding.getPaddingAfter(false, this); if (bpAfter > 0) { returnList.add(new KnuthBox(bpAfter, getAuxiliaryPosition(), true)); - } + }*/ } } @@ -795,8 +922,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param returnList return list to add the additional elements to * @return true if an element has been added due to a break-before. */ - protected boolean addKnuthElementsForBreakBefore(LinkedList returnList/*, - Position returnPosition*/) { + protected boolean addKnuthElementsForBreakBefore(LinkedList returnList, + LayoutContext context) { int breakBefore = -1; if (fobj instanceof org.apache.fop.fo.flow.Block) { breakBefore = ((org.apache.fop.fo.flow.Block) fobj).getBreakBefore(); @@ -810,8 +937,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager || breakBefore == EN_EVEN_PAGE || breakBefore == EN_ODD_PAGE) { // return a penalty element, representing a forced page break - returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, - breakBefore, getAuxiliaryPosition(), false)); + returnList.add(new BreakElement(getAuxiliaryPosition(), + 0, -KnuthElement.INFINITE, breakBefore, context)); + //returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, + // breakBefore, getAuxiliaryPosition(), false)); return true; } else { return false; @@ -823,8 +952,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @param returnList return list to add the additional elements to * @return true if an element has been added due to a break-after. */ - protected boolean addKnuthElementsForBreakAfter(LinkedList returnList/*, - Position returnPosition*/) { + protected boolean addKnuthElementsForBreakAfter(LinkedList returnList, + LayoutContext context) { int breakAfter = -1; if (fobj instanceof org.apache.fop.fo.flow.Block) { breakAfter = ((org.apache.fop.fo.flow.Block) fobj).getBreakAfter(); @@ -838,8 +967,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager || breakAfter == EN_EVEN_PAGE || breakAfter == EN_ODD_PAGE) { // add a penalty element, representing a forced page break - returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, - breakAfter, getAuxiliaryPosition(), false)); + returnList.add(new BreakElement(getAuxiliaryPosition(), + 0, -KnuthElement.INFINITE, breakAfter, context)); + //returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, + // breakAfter, getAuxiliaryPosition(), false)); return true; } else { return false; @@ -853,21 +984,16 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager */ protected void addKnuthElementsForSpaceBefore(LinkedList returnList/*, Position returnPosition*/, int alignment) { - SpaceProperty spaceBefore = null; - if (fobj instanceof org.apache.fop.fo.flow.Block) { - spaceBefore = ((org.apache.fop.fo.flow.Block)fobj) - .getCommonMarginBlock().spaceBefore; - } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) { - spaceBefore = ((org.apache.fop.fo.flow.BlockContainer)fobj) - .getCommonMarginBlock().spaceBefore; - } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) { - spaceBefore = ((org.apache.fop.fo.flow.ListBlock)fobj) - .getCommonMarginBlock().spaceBefore; - } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) { - spaceBefore = ((org.apache.fop.fo.flow.ListItem)fobj) - .getCommonMarginBlock().spaceBefore; - } + SpaceProperty spaceBefore = getSpaceBeforeProperty(); // append elements representing space-before + if (spaceBefore != null + && !(spaceBefore.getMinimum(this).getLength().getValue(this) == 0 + && spaceBefore.getMaximum(this).getLength().getValue(this) == 0)) { + returnList.add(new SpaceElement(getAuxiliaryPosition(), spaceBefore, + RelSide.BEFORE, + true, false, this)); + } + /* if (bpUnit > 0 || spaceBefore != null && !(spaceBefore.getMinimum(this).getLength().getValue(this) == 0 @@ -882,7 +1008,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager returnList.add(new KnuthGlue(0, 0, 0, BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT, getAuxiliaryPosition(), true)); - } else /*if (alignment == EN_JUSTIFY)*/ { + } else { //if (alignment == EN_JUSTIFY) { returnList.add(new KnuthGlue( spaceBefore.getOptimum(this).getLength().getValue(this), spaceBefore.getMaximum(this).getLength().getValue(this) @@ -891,13 +1017,13 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager - spaceBefore.getMinimum(this).getLength().getValue(this), BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT, getAuxiliaryPosition(), true)); - } /*else { - returnList.add(new KnuthGlue( - spaceBefore.getOptimum().getLength().getValue(this), - 0, 0, BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT, - returnPosition, true)); - }*/ - } +// } else { +// returnList.add(new KnuthGlue( +// spaceBefore.getOptimum().getLength().getValue(this), +// 0, 0, BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT, +// returnPosition, true)); + } + }*/ } /** @@ -907,21 +1033,16 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager */ protected void addKnuthElementsForSpaceAfter(LinkedList returnList/*, Position returnPosition*/, int alignment) { - SpaceProperty spaceAfter = null; - if (fobj instanceof org.apache.fop.fo.flow.Block) { - spaceAfter = ((org.apache.fop.fo.flow.Block)fobj) - .getCommonMarginBlock().spaceAfter; - } else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) { - spaceAfter = ((org.apache.fop.fo.flow.BlockContainer)fobj) - .getCommonMarginBlock().spaceAfter; - } else if (fobj instanceof org.apache.fop.fo.flow.ListBlock) { - spaceAfter = ((org.apache.fop.fo.flow.ListBlock)fobj) - .getCommonMarginBlock().spaceAfter; - } else if (fobj instanceof org.apache.fop.fo.flow.ListItem) { - spaceAfter = ((org.apache.fop.fo.flow.ListItem)fobj) - .getCommonMarginBlock().spaceAfter; - } + SpaceProperty spaceAfter = getSpaceAfterProperty(); // append elements representing space-after + if (spaceAfter != null + && !(spaceAfter.getMinimum(this).getLength().getValue(this) == 0 + && spaceAfter.getMaximum(this).getLength().getValue(this) == 0)) { + returnList.add(new SpaceElement(getAuxiliaryPosition(), spaceAfter, + RelSide.AFTER, + false, true, this)); + } + /* if (bpUnit > 0 || spaceAfter != null && !(spaceAfter.getMinimum(this).getLength().getValue(this) == 0 @@ -934,7 +1055,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager returnList.add(new KnuthGlue(0, 0, 0, BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT, getAuxiliaryPosition(), true)); - } else /*if (alignment == EN_JUSTIFY)*/ { + } else { //if (alignment == EN_JUSTIFY) { returnList.add(new KnuthGlue( spaceAfter.getOptimum(this).getLength().getValue(this), spaceAfter.getMaximum(this).getLength().getValue(this) @@ -943,16 +1064,16 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager - spaceAfter.getMinimum(this).getLength().getValue(this), BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT, getAuxiliaryPosition(), (!spaceAfter.getSpace().isDiscard()) ? false : true)); - } /*else { - returnList.add(new KnuthGlue( - spaceAfter.getOptimum().getLength().getValue(this), 0, 0, - BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT, returnPosition, - (!spaceAfter.getSpace().isDiscard()) ? false : true)); - }*/ +// } else { +// returnList.add(new KnuthGlue( +// spaceAfter.getOptimum().getLength().getValue(this), 0, 0, +// BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT, returnPosition, +// (!spaceAfter.getSpace().isDiscard()) ? false : true)); + } if (spaceAfter != null && !spaceAfter.getSpace().isDiscard()) { returnList.add(new KnuthBox(0, getAuxiliaryPosition(), true)); } - } + }*/ } protected LinkedList createUnitElements(LinkedList oldList) { @@ -1330,8 +1451,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager ListIterator listIter = sourceList.listIterator(); while (listIter.hasNext()) { - KnuthElement tempElement; - tempElement = (KnuthElement) listIter.next(); + ListElement tempElement; + tempElement = (ListElement) listIter.next(); if (force || tempElement.getLayoutManager() != this) { tempElement.setPosition(notifyPos(new NonLeafPosition(this, tempElement.getPosition()))); diff --git a/src/java/org/apache/fop/layoutmgr/BorderElement.java b/src/java/org/apache/fop/layoutmgr/BorderElement.java new file mode 100644 index 000000000..691fcab90 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BorderElement.java @@ -0,0 +1,65 @@ +/* + * 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 org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.properties.CondLengthProperty; +import org.apache.fop.traits.MinOptMax; + +/** + * This represents an unresolved border element. + */ +public class BorderElement extends BorderOrPaddingElement { + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + * @param side the side to which this space element applies. + * @param condLength the length-conditional property for a border or padding specification + * @param isFirst true if this is a padding- or border-before of the first area generated. + * @param isLast true if this is a padding- or border-after of the last area generated. + * @param context the property evaluation context + */ + public BorderElement(Position position, CondLengthProperty condLength, + RelSide side, + boolean isFirst, boolean isLast, PercentBaseContext context) { + super(position, condLength, side, isFirst, isLast, context); + } + + /** @see org.apache.fop.layoutmgr.UnresolvedListElementWithLength */ + public void notifyLayoutManager(MinOptMax effectiveLength) { + LayoutManager lm = getOriginatingLayoutManager(); + if (lm instanceof ConditionalElementListener) { + ((ConditionalElementListener)lm).notifyBorder( + getSide(), effectiveLength); + } else { + log.warn("Cannot notify LM. It does not implement ConditionalElementListener: " + + lm.getClass().getName()); + } + } + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer("Border["); + sb.append(super.toString()); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java b/src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java new file mode 100644 index 000000000..2e4dc315e --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java @@ -0,0 +1,50 @@ +/* + * 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 org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.properties.CondLengthProperty; +import org.apache.fop.traits.MinOptMax; + +/** + * This class represents an unresolved border or padding element. + */ +public abstract class BorderOrPaddingElement extends UnresolvedListElementWithLength { + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + * @param side the side to which this space element applies. + * @param condLength the length-conditional property for a border or padding specification + * @param isFirst true if this is a padding- or border-before of the first area generated. + * @param isLast true if this is a padding- or border-after of the last area generated. + * @param context the property evaluation context + */ + public BorderOrPaddingElement(Position position, CondLengthProperty condLength, + RelSide side, + boolean isFirst, boolean isLast, PercentBaseContext context) { + super(position, + new MinOptMax(condLength.getLength().getValue(context)), side, + condLength.isDiscard(), isFirst, isLast); + } + + /** @see org.apache.fop.layoutmgr.UnresolvedListElementWithLength */ + public abstract void notifyLayoutManager(MinOptMax effectiveLength); + +} diff --git a/src/java/org/apache/fop/layoutmgr/BreakElement.java b/src/java/org/apache/fop/layoutmgr/BreakElement.java new file mode 100644 index 000000000..db9246fbf --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BreakElement.java @@ -0,0 +1,149 @@ +/* + * 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; + +import org.apache.fop.fo.Constants; + +/** + * This class represents an unresolved break possibility. + */ +public class BreakElement extends UnresolvedListElement { + + private int penaltyWidth; + private int penaltyValue; + private int breakClass = -1; + private List pendingBeforeMarks; + private List pendingAfterMarks; + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + * @param penaltyValue the penalty value for the penalty element to be constructed + * @param context the layout context which contains the pending conditional elements + */ + public BreakElement(Position position, int penaltyValue, LayoutContext context) { + this(position, 0, penaltyValue, -1, context); + } + + /** + * Constructor for hard breaks. + * @param position the Position instance needed by the addAreas stage of the LMs. + * @param penaltyWidth the penalty width + * @param penaltyValue the penalty value for the penalty element to be constructed + * @param breakClass the break class of this penalty (one of the break-* constants) + * @param context the layout context which contains the pending conditional elements + */ + public BreakElement(Position position, int penaltyWidth, int penaltyValue, + int breakClass, LayoutContext context) { + super(position); + this.penaltyWidth = penaltyWidth; + this.penaltyValue = penaltyValue; + this.breakClass = breakClass; + this.pendingBeforeMarks = context.getPendingBeforeMarks(); + this.pendingAfterMarks = context.getPendingAfterMarks(); + } + + /** @see org.apache.fop.layoutmgr.UnresolvedListElement#isConditional() */ + public boolean isConditional() { + return false; //Does not really apply here + } + + /** @see org.apache.fop.layoutmgr.ListElement#isPenalty() */ + /* + public boolean isPenalty() { + return true; //not entirely true but a BreakElement will generate a penalty later + }*/ + + /** @return the penalty width */ + public int getPenaltyWidth() { + return this.penaltyWidth; + } + + /** @return the penalty value */ + public int getPenaltyValue() { + return this.penaltyValue; + } + + /** + * Sets the penalty value. + * @param p the new penalty value + */ + public void setPenaltyValue(int p) { + this.penaltyValue = p; + } + + /** @see org.apache.fop.layoutmgr.ListElement#isForcedBreak() */ + public boolean isForcedBreak() { + return penaltyValue == -KnuthElement.INFINITE; + } + + /** @return the break class of this penalty (one of the break-* constants) */ + public int getBreakClass() { + return breakClass; + } + + /** + * Sets the break class. + * @param breakClass the new break class + */ + public void setBreakClass(int breakClass) { + this.breakClass = breakClass; + } + + /** @return the pending border and padding elements at the before edge */ + public List getPendingBeforeMarks() { + return this.pendingBeforeMarks; + } + + /** @return the pending border and padding elements at the after edge */ + public List getPendingAfterMarks() { + return this.pendingAfterMarks; + } + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("BreakPossibility[p:"); + sb.append(this.penaltyValue); + if (isForcedBreak()) { + sb.append(" (forced break"); + switch (getBreakClass()) { + case Constants.EN_PAGE: + sb.append(", page"); + break; + case Constants.EN_COLUMN: + sb.append(", column"); + break; + case Constants.EN_EVEN_PAGE: + sb.append(", even page"); + break; + case Constants.EN_ODD_PAGE: + sb.append(", odd page"); + break; + default: + } + sb.append(")"); + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/ConditionalElementListener.java b/src/java/org/apache/fop/layoutmgr/ConditionalElementListener.java new file mode 100644 index 000000000..3cc4be678 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/ConditionalElementListener.java @@ -0,0 +1,52 @@ +/* + * 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 org.apache.fop.traits.MinOptMax; + +/** + * This interface is used to notify layout managers about the situation around spaces, borders + * and padding just before the addArea() method is called when a part is being painted. + */ +public interface ConditionalElementListener { + + /** + * Notifies the layout manager about the effective length of its space. + * @param side the side to which the space applies + * @param effectiveLength the effective length after space-resolution (null means zero length) + */ + void notifySpace(RelSide side, MinOptMax effectiveLength); + + /** + * Notifies the layout manager about the effective length/width of its border. + * @param side the side to which the border applies + * @param effectiveLength the effective length in the current break situation + * (null means zero length) + */ + void notifyBorder(RelSide side, MinOptMax effectiveLength); + + /** + * Notifies the layout manager about the effective length/width of its padding. + * @param side the side to which the padding applies + * @param effectiveLength the effective length in the current break situation + * (null means zero length) + */ + void notifyPadding(RelSide side, MinOptMax effectiveLength); + +} diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java index c1100d00f..c4fd42a35 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -36,13 +36,16 @@ public class ElementListUtils { public static void removeLegalBreaks(LinkedList elements) { ListIterator i = elements.listIterator(); while (i.hasNext()) { - KnuthElement el = (KnuthElement)i.next(); + ListElement el = (ListElement)i.next(); if (el.isPenalty()) { - KnuthPenalty penalty = (KnuthPenalty)el; + BreakElement breakPoss = (BreakElement)el; //Convert all penalties no break inhibitors - if (penalty.getP() < KnuthPenalty.INFINITE) { + if (breakPoss.getPenaltyValue() < KnuthPenalty.INFINITE) { + breakPoss.setPenaltyValue(KnuthPenalty.INFINITE); + /* i.set(new KnuthPenalty(penalty.getW(), KnuthPenalty.INFINITE, penalty.isFlagged(), penalty.getPosition(), penalty.isAuxiliary())); + */ } } else if (el.isGlue()) { i.previous(); @@ -106,11 +109,11 @@ public class ElementListUtils { int count = end - start + 1; int len = 0; while (iter.hasNext()) { - KnuthElement el = (KnuthElement)iter.next(); + ListElement el = (ListElement)iter.next(); if (el.isBox()) { - len += el.getW(); + len += ((KnuthElement)el).getW(); } else if (el.isGlue()) { - len += el.getW(); + len += ((KnuthElement)el).getW(); } else { //log.debug("Ignoring penalty: " + el); //ignore penalties @@ -133,4 +136,14 @@ public class ElementListUtils { return calcContentLength(elems, 0, elems.size() - 1); } + /** + * Indicates whether the given element list ends with a forced break. + * @param elems the element list + * @return true if the list ends with a forced break + */ + public static boolean endsWithForcedBreak(LinkedList elems) { + ListElement last = (ListElement)elems.getLast(); + return last.isForcedBreak(); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 37e852cb6..3ec814bd2 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -36,7 +36,6 @@ import java.util.ListIterator; */ public class FlowLayoutManager extends BlockStackingLayoutManager implements BlockLevelLayoutManager { - private Flow fobj; /** Array of areas currently being filled stored by area class */ private BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX]; @@ -51,7 +50,6 @@ public class FlowLayoutManager extends BlockStackingLayoutManager */ public FlowLayoutManager(PageSequenceLayoutManager pslm, Flow node) { super(node); - fobj = node; setParent(pslm); } @@ -84,6 +82,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager log.debug("span change from " + currentSpan + " to " + span); context.signalSpanChange(span); currentSpan = span; + SpaceResolver.resolveElementList(returnList); return returnList; } @@ -109,10 +108,10 @@ public class FlowLayoutManager extends BlockStackingLayoutManager wrapPositionElements(tempList, returnedList); if (returnedList.size() == 1 - && ((KnuthElement)returnedList.getFirst()).isPenalty() - && ((KnuthPenalty)returnedList.getFirst()).getP() == -KnuthElement.INFINITE) { + && ElementListUtils.endsWithForcedBreak(returnedList)) { // a descendant of this flow has break-before returnList.addAll(returnedList); + SpaceResolver.resolveElementList(returnList); return returnList; } else { if (returnList.size() > 0) { @@ -123,20 +122,19 @@ public class FlowLayoutManager extends BlockStackingLayoutManager 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 - returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, - new Position(this), false)); - } else if (!((KnuthElement) returnList.getLast()).isGlue()) { + returnList.add(new BreakElement( + new Position(this), KnuthElement.INFINITE, context)); + } else if (!((ListElement) returnList.getLast()).isGlue()) { // add a null penalty to allow a break between blocks - returnList.add(new KnuthPenalty(0, 0, false, - new Position(this), false)); + returnList.add(new BreakElement( + new Position(this), 0, context)); } } - if (returnedList.size() > 0) { // controllare! + if (returnedList.size() > 0) { returnList.addAll(returnedList); - if (((KnuthElement)returnedList.getLast()).isPenalty() - && ((KnuthPenalty)returnedList.getLast()).getP() - == -KnuthElement.INFINITE) { + if (ElementListUtils.endsWithForcedBreak(returnList)) { // a descendant of this flow has break-after + SpaceResolver.resolveElementList(returnList); return returnList; } } @@ -148,6 +146,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } } + SpaceResolver.resolveElementList(returnList); setFinished(true); if (returnList.size() > 0) { diff --git a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java index 9ba98048e..51868f4e9 100644 --- a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java @@ -23,12 +23,20 @@ import org.apache.fop.fo.flow.FootnoteBody; import java.util.LinkedList; +/** + * Layout manager for footnote bodies. + */ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { + /** + * Creates a new FootnoteBodyLayoutManager. + * @param body the footnote-body element + */ public FootnoteBodyLayoutManager(FootnoteBody body) { super(body); } + /** @see org.apache.fop.layoutmgr.LayoutManager */ public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { LayoutManager childLM = null; LayoutManager lastLM = null; @@ -38,8 +46,6 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { // and put them in a new list; LinkedList positionList = new LinkedList(); Position pos; - boolean bSpaceBefore = false; - boolean bSpaceAfter = false; while (parentIter.hasNext()) { pos = (Position) parentIter.next(); //log.trace("pos = " + pos.getClass().getName() + "; " + pos); @@ -73,14 +79,13 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { } } + /** @see org.apache.fop.layoutmgr.LayoutManager#addChildArea(org.apache.fop.area.Area) */ public void addChildArea(Area childArea) { childArea.setAreaClass(Area.CLASS_FOOTNOTE); parentLM.addChildArea(childArea); } - /** - * convenience method that returns the FootnoteBody node - */ + /** @return the FootnoteBody node */ protected FootnoteBody getFootnodeBodyFO() { return (FootnoteBody) fobj; } diff --git a/src/java/org/apache/fop/layoutmgr/KnuthElement.java b/src/java/org/apache/fop/layoutmgr/KnuthElement.java index cef81aaab..97d0bbd56 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthElement.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthElement.java @@ -26,12 +26,12 @@ package org.apache.fop.layoutmgr; * special feature (for example, the additional elements used to represent * a space when text alignment is right, left or center). */ -public abstract class KnuthElement { +public abstract class KnuthElement extends ListElement { + /** The value used as an infinite indicator. */ public static final int INFINITE = 1000; private int width; - private Position position; private boolean bIsAuxiliary; /** @@ -43,84 +43,39 @@ public abstract class KnuthElement { * @param bAux is this an auxiliary element? */ protected KnuthElement(int w, Position pos, boolean bAux) { + super(pos); width = w; - position = pos; bIsAuxiliary = bAux; } - /** - * Return true if this element is a KnuthBox. - */ - public boolean isBox() { - return false; - } - - /** - * Return true if this element is a KnuthGlue. - */ - public boolean isGlue() { - return false; - } - - /** - * Return true if this element is a KnuthPenalty. - */ - public boolean isPenalty() { - return false; - } - - /** - * Return true if this element is an auxiliary one. - */ + /** @return true if this element is an auxiliary one. */ public boolean isAuxiliary() { return bIsAuxiliary; } - /** - * Return the width of this element. - */ + /** @return the width of this element. */ public int getW() { return width; } + /** @return the penalty value of this element, if applicable. */ public int getP() { throw new RuntimeException("Element is not a penalty"); } + /** @return the stretch value of this element, if applicable. */ public int getY() { throw new RuntimeException("Element is not a glue"); } + /** @return the shrink value of this element, if applicable. */ public int getZ() { throw new RuntimeException("Element is not a glue"); } - - public boolean isForcedBreak() { + + /** @see org.apache.fop.layoutmgr.ListElement#isUnresolvedElement() */ + public boolean isUnresolvedElement() { return false; } - /** - * Return the Position stored in this element. - */ - public Position getPosition() { - return position; - } - - /** - * Change the Position stored in this element. - */ - public void setPosition(Position pos) { - position = pos; - } - - /** - * Return the LayoutManager responsible for this element. - */ - public LayoutManager getLayoutManager() { - if (position != null) { - return position.getLM(); - } else { - return null; - } - } } diff --git a/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java b/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java index 0b157c050..3cd2c9e69 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthPossPosIter.java @@ -65,15 +65,15 @@ public class KnuthPossPosIter extends PositionIterator { return super.next(); } - public KnuthElement getKE() { - return (KnuthElement) peekNext(); + public ListElement getKE() { + return (ListElement) peekNext(); } protected LayoutManager getLM(Object nextObj) { - return ((KnuthElement) nextObj).getLayoutManager(); + return ((ListElement) nextObj).getLayoutManager(); } protected Position getPos(Object nextObj) { - return ((KnuthElement) nextObj).getPosition(); + return ((ListElement) nextObj).getPosition(); } } diff --git a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java index 77f30f1c5..15a61a182 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java @@ -53,9 +53,19 @@ public class KnuthSequence extends ArrayList { } /** + * 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()) { @@ -66,7 +76,7 @@ public class KnuthSequence extends ArrayList { // 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, null, false)); + this.add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, breakPosition, false)); ignoreAtEnd = 3; return this; } else { diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 45ce1889b..e4710b1a1 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2004 The Apache Software Foundation. + * Copyright 1999-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. @@ -18,6 +18,9 @@ package org.apache.fop.layoutmgr; +import java.util.Collections; +import java.util.List; + import org.apache.fop.fo.Constants; import org.apache.fop.layoutmgr.inline.HyphContext; import org.apache.fop.traits.MinOptMax; @@ -25,7 +28,7 @@ import org.apache.fop.layoutmgr.inline.AlignmentContext; /** - * This class is used to pass information to the getNextBreakPoss() + * This class is used to pass information to the getNextKnuthElements() * method. It is set up by higher level LM and used by lower level LM. */ public class LayoutContext { @@ -91,6 +94,18 @@ public class LayoutContext { /** Current pending space-before or space-start from ancestor areas */ SpaceSpecifier leadingSpace; + + /** + * A list of pending marks (border and padding) on the after edge when a page break occurs. + * May be null. + */ + private List pendingAfterMarks; + + /** + * A list of pending marks (border and padding) on the before edge when a page break occurs. + * May be null. + */ + private List pendingBeforeMarks; /** Current hyphenation context. May be null. */ private HyphContext hyphContext = null; @@ -117,6 +132,10 @@ public class LayoutContext { /** Amount of space to reserve at the end of each line */ private int lineEndBorderAndPaddingWidth = 0; + /** + * Copy constructor for creating child layout contexts. + * @param parentLC the parent layout context to copy from + */ public LayoutContext(LayoutContext parentLC) { this.flags = parentLC.flags; this.refIPD = parentLC.refIPD; @@ -131,9 +150,14 @@ public class LayoutContext { this.alignmentContext = parentLC.alignmentContext; this.lineStartBorderAndPaddingWidth = parentLC.lineStartBorderAndPaddingWidth; this.lineEndBorderAndPaddingWidth = parentLC.lineEndBorderAndPaddingWidth; - // Copy other fields as necessary. Use clone??? + copyPendingMarksFrom(parentLC); + // Copy other fields as necessary. } + /** + * Main constructor. + * @param flags the initial flags + */ public LayoutContext(int flags) { this.flags = flags; this.refIPD = 0; @@ -142,6 +166,15 @@ public class LayoutContext { trailingSpace = null; } + public void copyPendingMarksFrom(LayoutContext source) { + if (source.pendingAfterMarks != null) { + this.pendingAfterMarks = new java.util.ArrayList(source.pendingAfterMarks); + } + if (source.pendingBeforeMarks != null) { + this.pendingBeforeMarks = new java.util.ArrayList(source.pendingBeforeMarks); + } + } + public void setFlags(int flags) { setFlags(flags, true); } @@ -206,6 +239,56 @@ public class LayoutContext { return trailingSpace; } + /** + * Adds a border or padding element to the pending list which will be used to generate + * the right element list for break possibilities. Conditionality resolution will be done + * elsewhere. + * @param element the border, padding or space element + */ + public void addPendingAfterMark(UnresolvedListElementWithLength element) { + if (this.pendingAfterMarks == null) { + this.pendingAfterMarks = new java.util.ArrayList(); + } + this.pendingAfterMarks.add(element); + } + + /** + * @return the pending border and padding elements at the after edge + * @see addPendingAfterMark(BorderOrPaddingElement) + */ + public List getPendingAfterMarks() { + if (this.pendingAfterMarks != null) { + return Collections.unmodifiableList(this.pendingAfterMarks); + } else { + return null; + } + } + + /** + * Adds a border or padding element to the pending list which will be used to generate + * the right element list for break possibilities. Conditionality resolution will be done + * elsewhere. + * @param element the border, padding or space element + */ + public void addPendingBeforeMark(UnresolvedListElementWithLength element) { + if (this.pendingBeforeMarks == null) { + this.pendingBeforeMarks = new java.util.ArrayList(); + } + this.pendingBeforeMarks.add(element); + } + + /** + * @return the pending border and padding elements at the before edge + * @see addPendingBeforeMark(BorderOrPaddingElement) + */ + public List getPendingBeforeMarks() { + if (this.pendingBeforeMarks != null) { + return Collections.unmodifiableList(this.pendingBeforeMarks); + } else { + return null; + } + } + public void setStackLimit(MinOptMax limit) { stackLimit = limit; } diff --git a/src/java/org/apache/fop/layoutmgr/ListElement.java b/src/java/org/apache/fop/layoutmgr/ListElement.java new file mode 100644 index 000000000..6707c66fe --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/ListElement.java @@ -0,0 +1,90 @@ +/* + * 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; + +/** + * This class is the base class for all kinds of elements that are added to element lists. There + * are basically two kinds of list elements: Knuth elements and unresolved elements like spaces, + * border and padding elements which are converted to Knuth elements prior to the breaking + * process. + */ +public abstract class ListElement { + + private Position position; + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + */ + public ListElement(Position position) { + this.position = position; + } + + /** + * @return the Position instance for this element. + */ + public Position getPosition() { + return this.position; + } + + /** + * Change the Position stored in this element. + * @param position the Position instance + */ + public void setPosition(Position position) { + this.position = position; + } + + /** + * @return the LayoutManager responsible for this element. + */ + public LayoutManager getLayoutManager() { + if (position != null) { + return position.getLM(); + } else { + return null; + } + } + + /** @return true if this element is a KnuthBox. */ + public boolean isBox() { + return false; + } + + /** @return true if this element is a KnuthGlue. */ + public boolean isGlue() { + return false; + } + + /** @return true if this element is a KnuthPenalty. */ + public boolean isPenalty() { + return false; + } + + /** @return true if the element is a penalty and represents a forced break. */ + public boolean isForcedBreak() { + return false; + } + + /** @return true if the element is an unresolved element such as a space or a border. */ + public boolean isUnresolvedElement() { + return true; + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/PaddingElement.java b/src/java/org/apache/fop/layoutmgr/PaddingElement.java new file mode 100644 index 000000000..3928b7abe --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/PaddingElement.java @@ -0,0 +1,65 @@ +/* + * 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 org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.properties.CondLengthProperty; +import org.apache.fop.traits.MinOptMax; + +/** + * This represents an unresolved padding element. + */ +public class PaddingElement extends BorderOrPaddingElement { + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + * @param side the side to which this space element applies. + * @param condLength the length-conditional property for a border or padding specification + * @param isFirst true if this is a padding- or border-before of the first area generated. + * @param isLast true if this is a padding- or border-after of the last area generated. + * @param context the property evaluation context + */ + public PaddingElement(Position position, CondLengthProperty condLength, + RelSide side, + boolean isFirst, boolean isLast, PercentBaseContext context) { + super(position, condLength, side, isFirst, isLast, context); + } + + /** @see org.apache.fop.layoutmgr.UnresolvedListElementWithLength */ + public void notifyLayoutManager(MinOptMax effectiveLength) { + LayoutManager lm = getOriginatingLayoutManager(); + if (lm instanceof ConditionalElementListener) { + ((ConditionalElementListener)lm).notifyPadding( + getSide(), effectiveLength); + } else { + log.warn("Cannot notify LM. It does not implement ConditionalElementListene: " + + lm.getClass().getName()); + } + } + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer("Padding["); + sb.append(super.toString()); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 507e2a384..a6d912904 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -201,6 +201,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { ListIterator elementListsIterator = elementLists.listIterator(); while (elementListsIterator.hasNext()) { LinkedList noteList = (LinkedList) elementListsIterator.next(); + + //Space resolution (Note: this does not respect possible stacking constraints + //between footnotes!) + SpaceResolver.resolveElementList(noteList); + int noteLength = 0; footnotesList.add(noteList); ListIterator noteListIterator = noteList.listIterator(); diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index ed557b5a8..6dbc997b3 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -227,7 +227,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { if (contentList != null) { ListIterator contentListIterator = contentList.listIterator(); while (contentListIterator.hasNext()) { - KnuthElement element = (KnuthElement) contentListIterator.next(); + ListElement element = (ListElement) contentListIterator.next(); if (element instanceof KnuthBlockBox && ((KnuthBlockBox) element).hasAnchors()) { // element represents a line with footnote citations @@ -402,10 +402,11 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { int lastIndex = (i == pbp.footnoteLastListIndex ? pbp.footnoteLastElementIndex : elementList.size() - 1); - FootnoteBodyLayoutManager fblm = (FootnoteBodyLayoutManager) - ((KnuthElement) elementList.getFirst()).getLayoutManager(); + SpaceResolver.performConditionalsNotification(elementList, + firstIndex, lastIndex, -1); LayoutContext childLC = new LayoutContext(0); - fblm.addAreas(new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1), + AreaAdditionUtil.addAreas(null, + new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1), childLC); } // set the offset from the top margin @@ -424,6 +425,12 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { return childFLM; } + /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */ + protected void observeElementList(List elementList) { + ElementListObserver.observe(elementList, "breaker", + ((PageSequence)pslm.getFObj()).getId()); + } + } /** diff --git a/src/java/org/apache/fop/layoutmgr/PositionIterator.java b/src/java/org/apache/fop/layoutmgr/PositionIterator.java index ae38b96d5..cc0c73c89 100644 --- a/src/java/org/apache/fop/layoutmgr/PositionIterator.java +++ b/src/java/org/apache/fop/layoutmgr/PositionIterator.java @@ -60,7 +60,7 @@ public abstract class PositionIterator implements Iterator { LayoutManager lm = getLM(nextObj); if (childLM == null) { childLM = lm; - } else if (childLM != lm) { + } else if (childLM != lm && lm != null) { // End of this sub-sequence with same child LM bHasNext = false; childLM = null; diff --git a/src/java/org/apache/fop/layoutmgr/RelSide.java b/src/java/org/apache/fop/layoutmgr/RelSide.java new file mode 100644 index 000000000..6371cff39 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/RelSide.java @@ -0,0 +1,53 @@ +/* + * 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; + +/** Enum class for relative sides. */ +public final class RelSide { + + /** the before side */ + public static final RelSide BEFORE = new RelSide("before"); + /** the after side */ + public static final RelSide AFTER = new RelSide("after"); + /** the start side */ + public static final RelSide START = new RelSide("start"); + /** the end side */ + public static final RelSide END = new RelSide("end"); + + private String name; + + /** + * Constructor to add a new named item. + * @param name Name of the item. + */ + private RelSide(String name) { + this.name = name; + } + + /** @return the name of the enum */ + public String getName() { + return this.name; + } + + /** @see java.lang.Object#toString() */ + public String toString() { + return "RelSide:" + name; + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/SpaceElement.java b/src/java/org/apache/fop/layoutmgr/SpaceElement.java new file mode 100644 index 000000000..ef365b78e --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/SpaceElement.java @@ -0,0 +1,93 @@ +/* + * 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 org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.traits.MinOptMax; + +/** + * This class represents an unresolved space element. + */ +public class SpaceElement extends UnresolvedListElementWithLength { + + private int precedence; + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + * @param space the space property + * @param side the side to which this space element applies. + * @param isFirst true if this is a space-before of the first area generated. + * @param isLast true if this is a space-after of the last area generated. + * @param context the property evaluation context + */ + public SpaceElement(Position position, SpaceProperty space, RelSide side, + boolean isFirst, boolean isLast, + PercentBaseContext context) { + super(position, + MinOptMaxUtil.toMinOptMax( + space.getSpace().getLengthRange(), + context), side, space.isDiscard(), isFirst, isLast); + int en = space.getSpace().getPrecedence().getEnum(); + if (en == Constants.EN_FORCE) { + this.precedence = Integer.MAX_VALUE; + } else { + this.precedence = space.getSpace().getPrecedence().getNumber().intValue(); + } + } + + /** @return true if the space is forcing. */ + public boolean isForcing() { + return this.precedence == Integer.MAX_VALUE; + } + + /** @return the precedence of the space */ + public int getPrecedence() { + return this.precedence; + } + + /** @see org.apache.fop.layoutmgr.UnresolvedListElementWithLength */ + public void notifyLayoutManager(MinOptMax effectiveLength) { + LayoutManager lm = getOriginatingLayoutManager(); + if (lm instanceof ConditionalElementListener) { + ((ConditionalElementListener)lm).notifySpace( + getSide(), effectiveLength); + } else { + log.warn("Cannot notify LM. It does not implement ConditionalElementListener:" + + lm.getClass().getName()); + } + } + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer("Space["); + sb.append(super.toString()); + sb.append(", precedence="); + if (isForcing()) { + sb.append("forcing"); + } else { + sb.append(getPrecedence()); + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java new file mode 100644 index 000000000..45e9990ea --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java @@ -0,0 +1,737 @@ +/* + * 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.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.traits.MinOptMax; + +/** + * This class resolves spaces and conditional borders and paddings by replacing the + * UnresolvedListElements descendants by the right combination of KnuthElements on an element + * list. + */ +public class SpaceResolver { + + /** Logger instance */ + protected static Log log = LogFactory.getLog(SpaceResolver.class); + + private UnresolvedListElementWithLength[] firstPart; + private BreakElement breakPoss; + private UnresolvedListElementWithLength[] secondPart; + private UnresolvedListElementWithLength[] noBreak; + + private MinOptMax[] firstPartLengths; + private MinOptMax[] secondPartLengths; + private MinOptMax[] noBreakLengths; + + private boolean isFirst; + private boolean isLast; + + /** + * Main constructor. + * @param first Element list before a break (optional) + * @param breakPoss Break possibility (optional) + * @param second Element list after a break (or if no break possibility in vicinity) + * @param isFirst Resolution at the beginning of a (full) element list + * @param isLast Resolution at the end of a (full) element list + */ + public SpaceResolver(List first, BreakElement breakPoss, List second, + boolean isFirst, boolean isLast) { + this.isFirst = isFirst; + this.isLast = isLast; + //Create combined no-break list + int c = 0; + if (first != null) { + c += first.size(); + } + if (second != null) { + c += second.size(); + } + noBreak = new UnresolvedListElementWithLength[c]; + noBreakLengths = new MinOptMax[c]; + int i = 0; + ListIterator iter; + if (first != null) { + iter = first.listIterator(); + while (iter.hasNext()) { + noBreak[i] = (UnresolvedListElementWithLength)iter.next(); + noBreakLengths[i] = noBreak[i].getLength(); + i++; + } + } + if (second != null) { + iter = second.listIterator(); + while (iter.hasNext()) { + noBreak[i] = (UnresolvedListElementWithLength)iter.next(); + noBreakLengths[i] = noBreak[i].getLength(); + i++; + } + } + + //Add pending elements from higher level FOs + if (breakPoss != null) { + if (breakPoss.getPendingAfterMarks() != null) { + if (log.isTraceEnabled()) { + log.trace(" adding pending before break: " + + breakPoss.getPendingAfterMarks()); + } + first.addAll(0, breakPoss.getPendingAfterMarks()); + } + if (breakPoss.getPendingBeforeMarks() != null) { + if (log.isTraceEnabled()) { + log.trace(" adding pending after break: " + + breakPoss.getPendingBeforeMarks()); + } + second.addAll(0, breakPoss.getPendingBeforeMarks()); + } + } + if (log.isTraceEnabled()) { + log.trace("before: " + first); + log.trace(" break: " + breakPoss); + log.trace("after: " + second); + log.trace("NO-BREAK: " + toString(noBreak, noBreakLengths)); + } + + if (first != null) { + firstPart = new UnresolvedListElementWithLength[first.size()]; + firstPartLengths = new MinOptMax[firstPart.length]; + first.toArray(firstPart); + for (i = 0; i < firstPart.length; i++) { + firstPartLengths[i] = firstPart[i].getLength(); + } + } + this.breakPoss = breakPoss; + if (second != null) { + secondPart = new UnresolvedListElementWithLength[second.size()]; + secondPartLengths = new MinOptMax[secondPart.length]; + second.toArray(secondPart); + for (i = 0; i < secondPart.length; i++) { + secondPartLengths[i] = secondPart[i].getLength(); + } + } + resolve(); + } + + private String toString(Object[] arr1, Object[] arr2) { + if (arr1.length != arr2.length) { + new IllegalArgumentException("The length of both arrays must be equal"); + } + StringBuffer sb = new StringBuffer("["); + for (int i = 0; i < arr1.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(String.valueOf(arr1[i])); + sb.append("/"); + sb.append(String.valueOf(arr2[i])); + } + sb.append("]"); + return sb.toString(); + } + + private void removeConditionalBorderAndPadding( + UnresolvedListElement[] elems, MinOptMax[] lengths, boolean reverse) { + for (int i = 0; i < elems.length; i++) { + int effIndex; + if (reverse) { + effIndex = elems.length - 1 - i; + } else { + effIndex = i; + } + if (elems[effIndex] instanceof BorderOrPaddingElement) { + BorderOrPaddingElement bop = (BorderOrPaddingElement)elems[effIndex]; + if (bop.isConditional() && !(bop.isFirst() || bop.isLast())) { + if (log.isDebugEnabled()) { + log.debug("Nulling conditional element: " + bop); + } + lengths[effIndex] = null; + } + } + } + if (log.isTraceEnabled() && elems.length > 0) { + log.trace("-->Resulting list: " + toString(elems, lengths)); + } + } + + private void performSpaceResolutionRule1(UnresolvedListElement[] elems, MinOptMax[] lengths, + boolean reverse) { + for (int i = 0; i < elems.length; i++) { + int effIndex; + if (reverse) { + effIndex = elems.length - 1 - i; + } else { + effIndex = i; + } + if (lengths[effIndex] == null) { + //Zeroed border or padding doesn't create a fence + continue; + } else if (elems[effIndex] instanceof BorderOrPaddingElement) { + //Border or padding form fences! + break; + } else if (!elems[effIndex].isConditional()) { + break; + } + if (log.isDebugEnabled()) { + log.debug("Nulling conditional element using 4.3.1, rule 1: " + elems[effIndex]); + } + lengths[effIndex] = null; + } + if (log.isTraceEnabled() && elems.length > 0) { + log.trace("-->Resulting list: " + toString(elems, lengths)); + } + } + + private void performSpaceResolutionRules2to3(UnresolvedListElement[] elems, + MinOptMax[] lengths, int start, int end) { + if (log.isTraceEnabled()) { + log.trace("rule 2-3: " + start + "-" + end); + } + SpaceElement space; + int remaining; + + //Rule 2 (4.3.1, XSL 1.0) + boolean hasForcing = false; + remaining = 0; + for (int i = start; i <= end; i++) { + if (lengths[i] == null) { + continue; + } + remaining++; + space = (SpaceElement)elems[i]; + if (space.isForcing()) { + hasForcing = true; + break; + } + } + if (remaining == 0) { + return; //shortcut + } + if (hasForcing) { + for (int i = start; i <= end; i++) { + if (lengths[i] == null) { + continue; + } + space = (SpaceElement)elems[i]; + if (!space.isForcing()) { + if (log.isDebugEnabled()) { + log.debug("Nulling non-forcing space-specifier using 4.3.1, rule 2: " + + elems[i]); + } + lengths[i] = null; + } + } + return; //If rule is triggered skip rule 3 + } + + //Rule 3 (4.3.1, XSL 1.0) + //Determine highes precedence + int highestPrecedence = Integer.MIN_VALUE; + for (int i = start; i <= end; i++) { + if (lengths[i] == null) { + continue; + } + space = (SpaceElement)elems[i]; + highestPrecedence = Math.max(highestPrecedence, space.getPrecedence()); + } + if (highestPrecedence != 0 && log.isDebugEnabled()) { + log.debug("Highest precedence is " + highestPrecedence); + } + //Suppress space-specifiers with lower precedence + remaining = 0; + int greatestOptimum = Integer.MIN_VALUE; + for (int i = start; i <= end; i++) { + if (lengths[i] == null) { + continue; + } + space = (SpaceElement)elems[i]; + if (space.getPrecedence() != highestPrecedence) { + if (log.isDebugEnabled()) { + log.debug("Nulling space-specifier with precedence " + + space.getPrecedence() + " using 4.3.1, rule 3: " + + elems[i]); + } + lengths[i] = null; + } else { + greatestOptimum = Math.max(greatestOptimum, space.getLength().opt); + remaining++; + } + } + if (log.isDebugEnabled()) { + log.debug("Greatest optimum: " + greatestOptimum); + } + if (remaining <= 1) { + return; + } + //Suppress space-specifiers with smaller optimum length + remaining = 0; + for (int i = start; i <= end; i++) { + if (lengths[i] == null) { + continue; + } + space = (SpaceElement)elems[i]; + if (space.getLength().opt < greatestOptimum) { + if (log.isDebugEnabled()) { + log.debug("Nulling space-specifier with smaller optimum length " + + "using 4.3.1, rule 3: " + + elems[i]); + } + lengths[i] = null; + } else { + remaining++; + } + } + if (remaining <= 1) { + return; + } + //Construct resolved space-specifier from the remaining spaces + int min = Integer.MIN_VALUE; + int max = Integer.MAX_VALUE; + for (int i = start; i <= end; i++) { + if (lengths[i] == null) { + continue; + } + space = (SpaceElement)elems[i]; + min = Math.max(min, space.getLength().min); + max = Math.min(max, space.getLength().max); + if (remaining > 1) { + if (log.isDebugEnabled()) { + log.debug("Nulling non-last space-specifier using 4.3.1, rule 3, second part: " + + elems[i]); + } + lengths[i] = null; + remaining--; + } else { + lengths[i].min = min; + lengths[i].max = max; + } + } + + if (log.isTraceEnabled() && elems.length > 0) { + log.trace("Remaining spaces: " + remaining); + log.trace("-->Resulting list: " + toString(elems, lengths)); + } + } + + private void performSpaceResolutionRules2to3(UnresolvedListElement[] elems, + MinOptMax[] lengths) { + int start = 0; + int i = start; + while (i < elems.length) { + if (elems[i] instanceof SpaceElement) { + while (i < elems.length) { + if (elems[i] == null || elems[i] instanceof SpaceElement) { + i++; + } else { + break; + } + } + performSpaceResolutionRules2to3(elems, lengths, start, i - 1); + } + i++; + start = i; + } + } + + private boolean hasFirstPart() { + return firstPart != null && firstPart.length > 0; + } + + private boolean hasSecondPart() { + return secondPart != null && secondPart.length > 0; + } + + private void resolve() { + if (breakPoss != null) { + if (hasFirstPart()) { + removeConditionalBorderAndPadding(firstPart, firstPartLengths, true); + performSpaceResolutionRule1(firstPart, firstPartLengths, true); + performSpaceResolutionRules2to3(firstPart, firstPartLengths); + } + if (hasSecondPart()) { + removeConditionalBorderAndPadding(secondPart, secondPartLengths, false); + performSpaceResolutionRule1(secondPart, secondPartLengths, false); + performSpaceResolutionRules2to3(secondPart, secondPartLengths); + } + if (noBreak != null) { + performSpaceResolutionRules2to3(noBreak, noBreakLengths); + } + } else { + if (isFirst) { + removeConditionalBorderAndPadding(secondPart, secondPartLengths, false); + performSpaceResolutionRule1(secondPart, secondPartLengths, false); + } + if (isLast) { + removeConditionalBorderAndPadding(firstPart, firstPartLengths, true); + performSpaceResolutionRule1(firstPart, firstPartLengths, true); + } + + if (hasFirstPart()) { + //Now that we've handled isFirst/isLast conditions, we need to look at the + //active part in its normal order so swap it back. + log.trace("Swapping first and second parts."); + UnresolvedListElementWithLength[] tempList; + MinOptMax[] tempLengths; + tempList = secondPart; + tempLengths = secondPartLengths; + secondPart = firstPart; + secondPartLengths = firstPartLengths; + firstPart = tempList; + firstPartLengths = tempLengths; + if (hasFirstPart()) { + throw new IllegalStateException("Didn't expect more than one parts in a" + + "no-break condition."); + } + } + performSpaceResolutionRules2to3(secondPart, secondPartLengths); + } + } + + private MinOptMax sum(MinOptMax[] lengths) { + MinOptMax sum = new MinOptMax(); + for (int i = 0; i < lengths.length; i++) { + if (lengths[i] != null) { + sum.add(lengths[i]); + } + } + return sum; + } + + private void generate(ListIterator iter) { + MinOptMax noBreakLength = new MinOptMax(); + MinOptMax glue1; //space before break possibility if break occurs + //MinOptMax glue2; //difference between glue 1 and 3 when no break occurs + MinOptMax glue3; //space after break possibility if break occurs + glue1 = sum(firstPartLengths); + glue3 = sum(secondPartLengths); + noBreakLength = sum(noBreakLengths); + + //This doesn't produce the right glue2 + //glue2 = new MinOptMax(noBreakLength); + //glue2.subtract(glue1); + //glue2.subtract(glue3); + + int glue2w = noBreakLength.opt - glue1.opt - glue3.opt; + int glue2stretch = (noBreakLength.max - noBreakLength.opt); + int glue2shrink = (noBreakLength.opt - noBreakLength.min); + glue2stretch -= glue1.max - glue1.opt; + glue2stretch -= glue3.max - glue3.opt; + glue2shrink -= glue1.opt - glue1.min; + glue2shrink -= glue3.opt - glue3.min; + + boolean hasPrecedingNonBlock = false; + if (log.isDebugEnabled()) { + log.debug("noBreakLength=" + noBreakLength + + ", glue1=" + glue1 + + ", glue2=" + glue2w + "+" + glue2stretch + "-" + glue2shrink + + ", glue3=" + glue3); + } + if (breakPoss != null) { + if (glue1.isNonZero()) { + iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, + false, (Position)null, true)); + iter.add(new KnuthGlue(glue1.opt, glue1.max - glue1.opt, glue1.opt - glue1.min, + (Position)null, true)); + } + iter.add(new KnuthPenalty(breakPoss.getPenaltyWidth(), breakPoss.getPenaltyValue(), + false, breakPoss.getBreakClass(), + new SpaceHandlingBreakPosition(this, breakPoss), false)); + //if (glue2.isNonZero()) { + if (glue2w != 0 || glue2stretch != 0 || glue2shrink != 0) { + /* + iter.add(new KnuthGlue(glue2.opt, glue2.max - glue2.opt, glue2.opt - glue2.min, + (Position)null, true)); + */ + iter.add(new KnuthGlue(glue2w, glue2stretch, glue2shrink, + (Position)null, true)); + } + } else { + if (glue1.isNonZero()) { + throw new IllegalStateException("glue1 should be 0 in this case"); + } + } + Position pos = null; + if (breakPoss == null) { + pos = new SpaceHandlingPosition(this); + } + if (glue3.isNonZero() || pos != null) { + iter.add(new KnuthBox(0, pos, true)); + } + if (glue3.isNonZero()) { + iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, + false, (Position)null, true)); + iter.add(new KnuthGlue(glue3.opt, glue3.max - glue3.opt, glue3.opt - glue3.min, + (Position)null, true)); + hasPrecedingNonBlock = true; + } + if (isLast && hasPrecedingNonBlock) { + //Otherwise, the preceding penalty and glue will be cut off + iter.add(new KnuthBox(0, (Position)null, true)); + } + } + + /** + * Position class for break possibilities. It is used to notify layout manager about the + * effective spaces and conditional lengths. + */ + public class SpaceHandlingBreakPosition extends Position { + + private SpaceResolver resolver; + private Position originalPosition; + + /** + * Main constructor. + * @param resolver the space resolver that provides the info about the actual situation + */ + public SpaceHandlingBreakPosition(SpaceResolver resolver, BreakElement breakPoss) { + super(null); + this.resolver = resolver; + this.originalPosition = breakPoss.getPosition(); + //Unpack since the SpaceHandlingBreakPosition is a non-wrapped Position, too + while (this.originalPosition instanceof NonLeafPosition) { + this.originalPosition = this.originalPosition.getPosition(); + } + } + + /** @return the space resolver */ + public SpaceResolver getSpaceResolver() { + return this.resolver; + } + + /** + * Notifies all affected layout managers about the current situation in the part to be + * handled for area generation. + * @param isBreakSituation true if this is a break situation. + * @param side defines to notify about the situation whether before or after the break. + * May be null if isBreakSituation is null. + */ + public void notifyBreakSituation(boolean isBreakSituation, RelSide side) { + if (isBreakSituation) { + if (RelSide.BEFORE == side) { + for (int i = 0; i < resolver.secondPart.length; i++) { + resolver.secondPart[i].notifyLayoutManager(resolver.secondPartLengths[i]); + } + } else { + for (int i = 0; i < resolver.firstPart.length; i++) { + resolver.firstPart[i].notifyLayoutManager(resolver.firstPartLengths[i]); + } + } + } else { + for (int i = 0; i < resolver.noBreak.length; i++) { + resolver.noBreak[i].notifyLayoutManager(resolver.noBreakLengths[i]); + } + } + } + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("SpaceHandlingBreakPosition("); + sb.append(this.originalPosition); + sb.append(")"); + return sb.toString(); + } + + /** + * @return the original Position instance set at the BreakElement that this Position was + * created for. + */ + public Position getOriginalBreakPosition() { + return this.originalPosition; + } + } + + /** + * Position class for no-break situations. It is used to notify layout manager about the + * effective spaces and conditional lengths. + */ + public class SpaceHandlingPosition extends Position { + + private SpaceResolver resolver; + + /** + * Main constructor. + * @param resolver the space resolver that provides the info about the actual situation + */ + public SpaceHandlingPosition(SpaceResolver resolver) { + super(null); + this.resolver = resolver; + } + + /** @return the space resolver */ + public SpaceResolver getSpaceResolver() { + return this.resolver; + } + + /** + * Notifies all affected layout managers about the current situation in the part to be + * handled for area generation. + */ + public void notifySpaceSituation() { + if (resolver.breakPoss != null) { + throw new IllegalStateException("Only applicable to no-break situations"); + } + for (int i = 0; i < resolver.secondPart.length; i++) { + resolver.secondPart[i].notifyLayoutManager(resolver.secondPartLengths[i]); + } + } + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("SpaceHandlingPosition"); + return sb.toString(); + } + } + + /** + * Resolves unresolved elements applying the space resolution rules defined in 4.3.1. + * @param elems the element list + */ + public static void resolveElementList(LinkedList elems) { + if (log.isTraceEnabled()) { + log.trace(elems); + } + boolean first = true; + boolean last = false; + boolean skipNextElement = false; + List unresolvedFirst = new java.util.ArrayList(); + List unresolvedSecond = new java.util.ArrayList(); + List currentGroup; + ListIterator iter = elems.listIterator(); + while (iter.hasNext()) { + ListElement el = (ListElement)iter.next(); + if (el.isUnresolvedElement()) { + if (log.isTraceEnabled()) { + log.trace("unresolved found: " + el + " " + first + "/" + last); + } + BreakElement breakPoss = null; + //Clear temp lists + unresolvedFirst.clear(); + unresolvedSecond.clear(); + //Collect groups + if (el instanceof BreakElement) { + breakPoss = (BreakElement)el; + currentGroup = unresolvedSecond; + } else { + currentGroup = unresolvedFirst; + currentGroup.add(el); + } + iter.remove(); + last = true; + skipNextElement = true; + while (iter.hasNext()) { + el = (ListElement)iter.next(); + if (el instanceof BreakElement && breakPoss != null) { + skipNextElement = false; + last = false; + break; + } else if (currentGroup == unresolvedFirst && (el instanceof BreakElement)) { + breakPoss = (BreakElement)el; + iter.remove(); + currentGroup = unresolvedSecond; + } else if (el.isUnresolvedElement()) { + currentGroup.add(el); + iter.remove(); + } else { + last = false; + break; + } + } + //last = !iter.hasNext(); + if (breakPoss == null && unresolvedSecond.size() == 0 && !last) { + log.trace("Swap first and second parts in no-break condition," + + " second part is empty."); + //The first list is reversed, so swap if this shouldn't happen + List swapList = unresolvedSecond; + unresolvedSecond = unresolvedFirst; + unresolvedFirst = swapList; + } + + log.debug("----start space resolution (first=" + first + ", last=" + last + ")..."); + SpaceResolver resolver = new SpaceResolver( + unresolvedFirst, breakPoss, unresolvedSecond, first, last); + if (!last) { + iter.previous(); + } + resolver.generate(iter); + if (!last && skipNextElement) { + iter.next(); + } + log.debug("----end space resolution."); + } + first = false; + } + } + + /** + * Inspects an effective element list and notifies all layout managers about the state of + * the spaces and conditional lengths. + * @param effectiveList the effective element list + * @param startElementIndex index of the first element in the part to be processed + * @param endElementIndex index of the last element in the part to be processed + * @param lastBreak index of the the break possibility just before this part (used to + * identify a break condition, lastBreak <= 0 represents a no-break condition) + */ + public static void performConditionalsNotification(List effectiveList, + int startElementIndex, int endElementIndex, int lastBreak) { + KnuthElement el = null; + if (lastBreak > 0) { + el = (KnuthElement)effectiveList.get(lastBreak); + } + SpaceResolver.SpaceHandlingBreakPosition beforeBreak = null; + SpaceResolver.SpaceHandlingBreakPosition afterBreak = null; + if (el != null && el.isPenalty()) { + Position pos = el.getPosition(); + if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) { + beforeBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos; + beforeBreak.notifyBreakSituation(true, RelSide.BEFORE); + } + } + el = (KnuthElement)effectiveList.get(endElementIndex); + if (el != null && el.isPenalty()) { + Position pos = el.getPosition(); + if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) { + afterBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos; + afterBreak.notifyBreakSituation(true, RelSide.AFTER); + } + } + for (int i = startElementIndex; i <= endElementIndex; i++) { + Position pos = ((KnuthElement)effectiveList.get(i)).getPosition(); + if (pos instanceof SpaceResolver.SpaceHandlingPosition) { + ((SpaceResolver.SpaceHandlingPosition)pos).notifySpaceSituation(); + } else if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) { + SpaceResolver.SpaceHandlingBreakPosition noBreak; + noBreak = (SpaceResolver.SpaceHandlingBreakPosition)pos; + if (noBreak != beforeBreak && noBreak != afterBreak) { + noBreak.notifyBreakSituation(false, null); + } + } + } + } + + + +} diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 949594beb..34da18505 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -19,11 +19,13 @@ package org.apache.fop.layoutmgr; import java.util.LinkedList; +import java.util.List; import java.util.ListIterator; import org.apache.fop.area.RegionReference; import org.apache.fop.area.Area; import org.apache.fop.area.Block; +import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.SideRegion; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; @@ -251,6 +253,16 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { this.displayAlign = displayAlign; } + /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */ + protected void observeElementList(List elementList) { + String elementListID = getStaticContentFO().getFlowName(); + String pageSequenceID = ((PageSequence)lm.getParent().getFObj()).getId(); + if (pageSequenceID != null && pageSequenceID.length() > 0) { + elementListID += "-" + pageSequenceID; + } + ElementListObserver.observe(elementList, "static-content", elementListID); + } + /** @see org.apache.fop.layoutmgr.AbstractBreaker#isPartOverflowRecoveryActivated() */ protected boolean isPartOverflowRecoveryActivated() { //For side regions, this must be disabled because of wanted overflow. @@ -287,9 +299,9 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } if (returnedList != null) { lm.wrapPositionElements(returnedList, returnList); - //returnList.addAll(returnedList); } } + SpaceResolver.resolveElementList(returnList); setFinished(true); return returnList; } diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index 1dcf52b62..89d03fff9 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.MinOptMax; import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.LengthBase; @@ -105,12 +106,13 @@ public class TraitSetter { } /** - * Add borders to an area. + * Add borders to an area. Note: this method also adds unconditional padding. Don't use! * Layout managers that create areas with borders can use this to * add the borders to the area. * @param area the area to set the traits on. * @param bordProps border properties * @param context Property evaluation context + * @deprecated Call the other addBorders() method and addPadding separately. */ public static void addBorders(Area area, CommonBorderPaddingBackground bordProps, PercentBaseContext context) { @@ -134,6 +136,40 @@ public class TraitSetter { addPadding(area, bordProps, context); } + /** + * Add borders to an area. + * Layout managers that create areas with borders can use this to + * add the borders to the area. + * @param area the area to set the traits on. + * @param bordProps border properties + * @param discardBefore true if the before border should be discarded + * @param discardAfter true if the after border should be discarded + * @param discardStart true if the start border should be discarded + * @param discardEnd true if the end border should be discarded + * @param context Property evaluation context + */ + public static void addBorders(Area area, CommonBorderPaddingBackground bordProps, + boolean discardBefore, boolean discardAfter, + boolean discardStart, boolean discardEnd, + PercentBaseContext context) { + BorderProps bps = getBorderProps(bordProps, CommonBorderPaddingBackground.BEFORE); + if (bps != null && !discardBefore) { + area.addTrait(Trait.BORDER_BEFORE, bps); + } + bps = getBorderProps(bordProps, CommonBorderPaddingBackground.AFTER); + if (bps != null && !discardAfter) { + area.addTrait(Trait.BORDER_AFTER, bps); + } + bps = getBorderProps(bordProps, CommonBorderPaddingBackground.START); + if (bps != null && !discardStart) { + area.addTrait(Trait.BORDER_START, bps); + } + bps = getBorderProps(bordProps, CommonBorderPaddingBackground.END); + if (bps != null && !discardEnd) { + area.addTrait(Trait.BORDER_END, bps); + } + } + /** * Add borders to an area for the collapsing border model in tables. * Layout managers that create areas with borders can use this to @@ -174,25 +210,49 @@ public class TraitSetter { private static void addPadding(Area area, CommonBorderPaddingBackground bordProps, PercentBaseContext context) { - int padding = bordProps.getPadding(CommonBorderPaddingBackground.START, false, context); + addPadding(area, bordProps, false, false, false, false, context); + } + + /** + * Add padding to an area. + * Layout managers that create areas with padding can use this to + * add the borders to the area. + * @param area the area to set the traits on. + * @param bordProps border and padding properties + * @param discardBefore true if the before padding should be discarded + * @param discardAfter true if the after padding should be discarded + * @param discardStart true if the start padding should be discarded + * @param discardEnd true if the end padding should be discarded + * @param context Property evaluation context + */ + public static void addPadding(Area area, CommonBorderPaddingBackground bordProps, + boolean discardBefore, boolean discardAfter, + boolean discardStart, boolean discardEnd, + PercentBaseContext context) { + int padding = bordProps.getPadding(CommonBorderPaddingBackground.BEFORE, + discardBefore, context); if (padding != 0) { - area.addTrait(Trait.PADDING_START, new java.lang.Integer(padding)); + area.addTrait(Trait.PADDING_BEFORE, new java.lang.Integer(padding)); } - padding = bordProps.getPadding(CommonBorderPaddingBackground.END, false, context); + padding = bordProps.getPadding(CommonBorderPaddingBackground.AFTER, + discardAfter, context); if (padding != 0) { - area.addTrait(Trait.PADDING_END, new java.lang.Integer(padding)); + area.addTrait(Trait.PADDING_AFTER, new java.lang.Integer(padding)); } - padding = bordProps.getPadding(CommonBorderPaddingBackground.BEFORE, false, context); + padding = bordProps.getPadding(CommonBorderPaddingBackground.START, + discardStart, context); if (padding != 0) { - area.addTrait(Trait.PADDING_BEFORE, new java.lang.Integer(padding)); + area.addTrait(Trait.PADDING_START, new java.lang.Integer(padding)); } - padding = bordProps.getPadding(CommonBorderPaddingBackground.AFTER, false, context); + padding = bordProps.getPadding(CommonBorderPaddingBackground.END, + discardEnd, context); if (padding != 0) { - area.addTrait(Trait.PADDING_AFTER, new java.lang.Integer(padding)); + area.addTrait(Trait.PADDING_END, new java.lang.Integer(padding)); } + } private static BorderProps getBorderProps(CommonBorderPaddingBackground bordProps, int side) { @@ -254,9 +314,9 @@ public class TraitSetter { width += backProps.getPaddingEnd(false, context); back.setHoriz(backProps.backgroundPositionHorizontal.getValue( new SimplePercentBaseContext(context, - LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, - (width - back.getFopImage().getIntrinsicWidth()) - ) + LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, + (width - back.getFopImage().getIntrinsicWidth()) + ) )); } else { //TODO Area IPD has to be set for this to work @@ -275,9 +335,9 @@ public class TraitSetter { height += backProps.getPaddingAfter(false, context); back.setVertical(backProps.backgroundPositionVertical.getValue( new SimplePercentBaseContext(context, - LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL, - (height - back.getFopImage().getIntrinsicHeight()) - ) + LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL, + (height - back.getFopImage().getIntrinsicHeight()) + ) )); } else { //TODO Area BPD has to be set for this to work @@ -329,6 +389,32 @@ public class TraitSetter { } } + public static int getEffectiveSpace(double adjust, MinOptMax space) { + if (space == null) { + return 0; + } + int sp = space.opt; + if (adjust > 0) { + sp = sp + (int)(adjust * (space.max - space.opt)); + } else { + sp = sp + (int)(adjust * (space.opt - space.min)); + } + return sp; + } + + public static void addSpaceBeforeAfter(Area area, double adjust, + MinOptMax spaceBefore, MinOptMax spaceAfter) { + int space; + space = getEffectiveSpace(adjust, spaceBefore); + if (space != 0) { + area.addTrait(Trait.SPACE_BEFORE, new Integer(space)); + } + space = getEffectiveSpace(adjust, spaceAfter); + if (space != 0) { + area.addTrait(Trait.SPACE_AFTER, new Integer(space)); + } + } + /** * Sets the traits for breaks on an area. * @param area the area to set the traits on. diff --git a/src/java/org/apache/fop/layoutmgr/UnresolvedListElement.java b/src/java/org/apache/fop/layoutmgr/UnresolvedListElement.java new file mode 100644 index 000000000..5f17db283 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/UnresolvedListElement.java @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * This class represents an unresolved list element. + */ +public abstract class UnresolvedListElement extends ListElement { + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + */ + public UnresolvedListElement(Position position) { + super(position); + } + + /** @return true if the element is conditional (conditionality="discard") */ + public abstract boolean isConditional(); + + /** @return the layout manager that created this ListElement */ + protected LayoutManager getOriginatingLayoutManager() { + Position pos = getPosition(); + while (pos instanceof NonLeafPosition && pos.getPosition() != null) { + pos = pos.getPosition(); + } + return pos.getLM(); + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java b/src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java new file mode 100644 index 000000000..57637bbf5 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java @@ -0,0 +1,112 @@ +/* + * 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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.traits.MinOptMax; + +/** + * This class represents an unresolved list element element with a (conditional) length. This + * is the base class for spaces, borders and paddings. + */ +public abstract class UnresolvedListElementWithLength extends UnresolvedListElement { + + /** Logger instance */ + protected static Log log = LogFactory.getLog(UnresolvedListElementWithLength.class); + + private MinOptMax length; + private boolean conditional; + private RelSide side; + private boolean isFirst; + private boolean isLast; + + /** + * Main constructor + * @param position the Position instance needed by the addAreas stage of the LMs. + * @param length the length of the element + * @param side the side to which this element applies + * @param conditional true if it's a conditional element (conditionality=discard) + * @param isFirst true if this is a space-before of the first area generated. + * @param isLast true if this is a space-after of the last area generated. + */ + public UnresolvedListElementWithLength(Position position, MinOptMax length, + RelSide side, + boolean conditional, boolean isFirst, boolean isLast) { + super(position); + this.length = length; + this.side = side; + this.conditional = conditional; + this.isFirst = isFirst; + this.isLast = isLast; + } + + /** @see org.apache.fop.layoutmgr.UnresolvedListElement#isConditional() */ + public boolean isConditional() { + return this.conditional; + } + + /** @return the space as resolved MinOptMax instance */ + public MinOptMax getLength() { + return this.length; + } + + /** @return the side this element was generated for */ + public RelSide getSide() { + return this.side; + } + + /** @return true if this is a space-before of the first area generated. */ + public boolean isFirst() { + return this.isFirst; + } + + /** @return true if this is a space-after of the last area generated. */ + public boolean isLast() { + return this.isLast; + } + + /** + * Called to notify the affected layout manager about the effective length after resolution. + * This method is called once before each call to the layout manager's addAreas() method. + * @param effectiveLength the effective length after resolution (may be null which equals to + * zero effective length) + */ + public abstract void notifyLayoutManager(MinOptMax effectiveLength); + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(getSide().getName()).append(", "); + sb.append(this.length.toString()); + if (isConditional()) { + sb.append("[discard]"); + } else { + sb.append("[RETAIN]"); + } + if (isFirst()) { + sb.append("[first]"); + } + if (isLast()) { + sb.append("[last]"); + } + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index e2aec76bd..396851b67 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -25,6 +25,7 @@ import org.apache.fop.fo.properties.CommonHyphenation; import org.apache.fop.hyphenation.Hyphenation; import org.apache.fop.hyphenation.Hyphenator; 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.KnuthBlockBox; @@ -642,7 +643,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } //PHASE 2: Create line breaks - return createLineBreaks(context.getBPAlignment()); + return createLineBreaks(context.getBPAlignment(), context); /* LineBreakPosition lbp = null; if (breakpoints == null) { @@ -979,9 +980,10 @@ public class LineLayoutManager extends InlineStackingLayoutManager /** * Phase 2 of Knuth algorithm: find optimal break points. * @param alignment alignment in BP direction of the paragraph + * @param context the layout context * @return a list of Knuth elements representing broken lines */ - private LinkedList createLineBreaks(int alignment) { + private LinkedList createLineBreaks(int alignment, LayoutContext context) { // find the optimal line breaking points for each paragraph ListIterator paragraphsIterator @@ -1000,7 +1002,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager setFinished(true); //Post-process the line breaks found - return postProcessLineBreaks(alignment); + return postProcessLineBreaks(alignment, context); } /** @@ -1143,17 +1145,19 @@ public class LineLayoutManager extends InlineStackingLayoutManager /** * Creates the element list in BP direction for the broken lines. * @param alignment the currently applicable vertical alignment + * @param context the layout context * @return the newly built element list */ - private LinkedList postProcessLineBreaks(int alignment) { + private LinkedList postProcessLineBreaks(int alignment, LayoutContext context) { LinkedList returnList = new LinkedList(); for (int p = 0; p < knuthParagraphs.size(); p++) { // null penalty between paragraphs - if (p > 0 - && !((BlockLevelLayoutManager) parentLM).mustKeepTogether()) { - returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); + if (p > 0 && !((BlockLevelLayoutManager) parentLM).mustKeepTogether()) { + returnList.add(new BreakElement( + new Position(this), 0, context)); + //returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } lineLayouts = (LineLayoutPossibilities)lineLayoutsList.get(p); @@ -1187,11 +1191,13 @@ public class LineLayoutManager extends InlineStackingLayoutManager i < lineLayouts.getChosenLineCount(); i++) { if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether() - && i >= fobj.getOrphans() - && i <= lineLayouts.getChosenLineCount() - fobj.getWidows() - && returnList.size() > 0) { + && i >= fobj.getOrphans() + && i <= lineLayouts.getChosenLineCount() - fobj.getWidows() + && returnList.size() > 0) { // null penalty allowing a page break between lines - returnList.add(new KnuthPenalty(0, 0, false, returnPosition, false)); + returnList.add(new BreakElement( + returnPosition, 0, context)); + //returnList.add(new KnuthPenalty(0, 0, false, returnPosition, false)); } int endIndex = ((LineBreakPosition) lineLayouts.getChosenPosition(i)).getLeafPos(); // create a list of the FootnoteBodyLM handling footnotes diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index db157f4cf..d1f88c717 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -21,11 +21,13 @@ package org.apache.fop.layoutmgr.list; import org.apache.fop.fo.flow.ListBlock; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.RelSide; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -41,11 +43,17 @@ import java.util.List; * A list block contains list items which are stacked within * the list block area.. */ -public class ListBlockLayoutManager extends BlockStackingLayoutManager { +public class ListBlockLayoutManager extends BlockStackingLayoutManager + implements ConditionalElementListener { private Block curBlockArea; - //TODO space-before|after: handle space-resolution rules + private boolean discardBorderBefore; + private boolean discardBorderAfter; + private boolean discardPaddingBefore; + private boolean discardPaddingAfter; + private MinOptMax effSpaceBefore; + private MinOptMax effSpaceAfter; private static class StackingIter extends PositionIterator { StackingIter(Iterator parentIter) { @@ -86,11 +94,23 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager { return (ListBlock)fobj; } + /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */ public void initialize() { - foSpaceBefore = new SpaceVal(getListBlockFO().getCommonMarginBlock().spaceBefore, this).getSpace(); - foSpaceAfter = new SpaceVal(getListBlockFO().getCommonMarginBlock().spaceAfter, this).getSpace(); + foSpaceBefore = new SpaceVal( + getListBlockFO().getCommonMarginBlock().spaceBefore, this).getSpace(); + foSpaceAfter = new SpaceVal( + getListBlockFO().getCommonMarginBlock().spaceAfter, this).getSpace(); } + private void resetSpaces() { + this.discardBorderBefore = false; + this.discardBorderAfter = false; + this.discardPaddingBefore = false; + this.discardPaddingAfter = false; + this.effSpaceBefore = foSpaceBefore; + this.effSpaceAfter = foSpaceAfter; + } + private int getIPIndents() { int iIndents = 0; iIndents += getListBlockFO().getCommonMarginBlock().startIndent.getValue(this); @@ -98,6 +118,12 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager { return iIndents; } + /** @see org.apache.fop.layoutmgr.BlockStackingLayoutManager */ + public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { + resetSpaces(); + return super.getNextKnuthElements(context, alignment); + } + /** @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int) */ public LinkedList getChangedKnuthElements(List oldList, int alignment) { //log.debug("LBLM.getChangedKnuthElements>"); @@ -121,11 +147,6 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager { addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); } - // if adjusted space before - double adjust = layoutContext.getSpaceAdjust(); - addBlockSpacing(adjust, foSpaceBefore); - foSpaceBefore = null; - getPSLM().addIDToPage(getListBlockFO().getId()); // the list block contains areas stacked from each list item @@ -184,13 +205,13 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager { TraitSetter.addBackground(curBlockArea, getListBlockFO().getCommonBorderPaddingBackground(), this); + TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), + effSpaceBefore, effSpaceAfter); flush(); - // if adjusted space after - addBlockSpacing(adjust, foSpaceAfter); - curBlockArea = null; + resetSpaces(); } /** @@ -217,7 +238,11 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager { // set traits TraitSetter.setProducerID(curBlockArea, getListBlockFO().getId()); TraitSetter.addBorders(curBlockArea, - getListBlockFO().getCommonBorderPaddingBackground(), this); + getListBlockFO().getCommonBorderPaddingBackground(), + discardBorderBefore, discardBorderAfter, false, false, this); + TraitSetter.addPadding(curBlockArea, + getListBlockFO().getCommonBorderPaddingBackground(), + discardPaddingBefore, discardPaddingAfter, false, false, this); TraitSetter.addMargins(curBlockArea, getListBlockFO().getCommonBorderPaddingBackground(), getListBlockFO().getCommonMarginBlock(), @@ -278,5 +303,50 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager { || !getListBlockFO().getKeepWithNext().getWithinColumn().isAuto(); } + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifySpace(RelSide side, MinOptMax effectiveLength) { + if (RelSide.BEFORE == side) { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceBefore + "-> " + effectiveLength); + } + this.effSpaceBefore = effectiveLength; + } else { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceAfter + "-> " + effectiveLength); + } + this.effSpaceAfter = effectiveLength; + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyBorder(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardBorderBefore = true; + } else { + this.discardBorderAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Border " + side + " -> " + effectiveLength); + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyPadding(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardPaddingBefore = true; + } else { + this.discardPaddingAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Padding " + side + " -> " + effectiveLength); + } + } + } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 3ebc4bda7..c8cedb0bb 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -23,11 +23,17 @@ import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.BreakElement; +import org.apache.fop.layoutmgr.ConditionalElementListener; +import org.apache.fop.layoutmgr.ElementListObserver; +import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.NonLeafPosition; +import org.apache.fop.layoutmgr.RelSide; +import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthBox; @@ -35,6 +41,7 @@ import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.area.Area; import org.apache.fop.area.Block; +import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; import java.util.ArrayList; @@ -46,7 +53,8 @@ import java.util.ListIterator; * LayoutManager for a list-item FO. * The list item contains a list item label and a list item body. */ -public class ListItemLayoutManager extends BlockStackingLayoutManager { +public class ListItemLayoutManager extends BlockStackingLayoutManager + implements ConditionalElementListener { private ListItemContentLayoutManager label; private ListItemContentLayoutManager body; @@ -57,20 +65,16 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { private int listItemHeight; - //TODO space-before|after: handle space-resolution rules + private boolean discardBorderBefore; + private boolean discardBorderAfter; + private boolean discardPaddingBefore; + private boolean discardPaddingAfter; + private MinOptMax effSpaceBefore; + private MinOptMax effSpaceAfter; private boolean keepWithNextPendingOnLabel; private boolean keepWithNextPendingOnBody; - - /* - private class ItemPosition extends LeafPosition { - protected List cellBreaks; - protected ItemPosition(LayoutManager lm, int pos, List l) { - super(lm, pos); - cellBreaks = l; - } - }*/ - + private class ListItemPosition extends Position { private int iLabelFirstIndex; private int iLabelLastIndex; @@ -149,11 +153,23 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { body.setParent(this); } + /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */ public void initialize() { - foSpaceBefore = new SpaceVal(getListItemFO().getCommonMarginBlock().spaceBefore, this).getSpace(); - foSpaceAfter = new SpaceVal(getListItemFO().getCommonMarginBlock().spaceAfter, this).getSpace(); + foSpaceBefore = new SpaceVal( + getListItemFO().getCommonMarginBlock().spaceBefore, this).getSpace(); + foSpaceAfter = new SpaceVal( + getListItemFO().getCommonMarginBlock().spaceAfter, this).getSpace(); } + private void resetSpaces() { + this.discardBorderBefore = false; + this.discardBorderAfter = false; + this.discardPaddingBefore = false; + this.discardPaddingAfter = false; + this.effSpaceBefore = foSpaceBefore; + this.effSpaceAfter = foSpaceAfter; + } + private int getIPIndents() { int iIndents = 0; iIndents += getListItemFO().getCommonMarginBlock().startIndent.getValue(this); @@ -168,16 +184,22 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { LinkedList returnList = new LinkedList(); - if (!bSpaceBeforeServed) { - addKnuthElementsForSpaceBefore(returnList, alignment); - bSpaceBeforeServed = true; - } + addKnuthElementsForSpaceBefore(returnList, alignment); + //Spaces, border and padding to be repeated at each break + addPendingMarks(context); + // label childLC = new LayoutContext(0); childLC.setRefIPD(context.getRefIPD()); label.initialize(); labelList = label.getNextKnuthElements(childLC, alignment); + + //Space resolution as if the contents were placed in a new reference area + //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph) + SpaceResolver.resolveElementList(labelList); + ElementListObserver.observe(labelList, "list-item-label", label.getPartFO().getId()); + if (childLC.isKeepWithPreviousPending()) { context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); } @@ -188,13 +210,19 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { childLC.setRefIPD(context.getRefIPD()); body.initialize(); bodyList = body.getNextKnuthElements(childLC, alignment); + + //Space resolution as if the contents were placed in a new reference area + //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph) + SpaceResolver.resolveElementList(bodyList); + ElementListObserver.observe(bodyList, "list-item-body", body.getPartFO().getId()); + if (childLC.isKeepWithPreviousPending()) { context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); } this.keepWithNextPendingOnBody = childLC.isKeepWithNextPending(); // create a combined list - LinkedList returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList); + LinkedList returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context); // "wrap" the Position inside each element wrapPositionElements(returnedList, returnList, true); @@ -209,16 +237,18 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { } setFinished(true); + resetSpaces(); return returnList; } private LinkedList getCombinedKnuthElementsForListItem(LinkedList labelElements, - LinkedList bodyElements) { + LinkedList bodyElements, + LayoutContext context) { //Copy elements to array lists to improve element access performance List[] elementLists = {new ArrayList(labelElements), new ArrayList(bodyElements)}; - int[] fullHeights = {calcItemHeightFromContents(elementLists[0]), - calcItemHeightFromContents(elementLists[1])}; + int[] fullHeights = {ElementListUtils.calcContentLength(elementLists[0]), + ElementListUtils.calcContentLength(elementLists[1])}; int[] partialHeights = {0, 0}; int[] start = {-1, -1}; int[] end = {-1, -1}; @@ -259,39 +289,14 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { if (keepWithNextActive || mustKeepTogether()) { p = KnuthPenalty.INFINITE; } - returnList.add(new KnuthPenalty(penaltyHeight, p, false, stepPosition, false)); + //returnList.add(new KnuthPenalty(penaltyHeight, p, false, stepPosition, false)); + returnList.add(new BreakElement(stepPosition, penaltyHeight, p, 0, context)); } } return returnList; } - private int calcItemHeightFromContents(List elements, int start, int end) { - ListIterator iter = elements.listIterator(start); - int count = end - start + 1; - int len = 0; - while (iter.hasNext()) { - KnuthElement el = (KnuthElement)iter.next(); - if (el.isBox()) { - len += el.getW(); - } else if (el.isGlue()) { - len += el.getW(); - } else { - log.debug("Ignoring penalty: " + el); - //ignore penalties - } - count--; - if (count == 0) { - break; - } - } - return len; - } - - private int calcItemHeightFromContents(List elements) { - return calcItemHeightFromContents(elements, 0, elements.size() - 1); - } - private int getNextStep(List[] elementLists, int[] start, int[] end, int[] partialHeights) { // backup of partial heights int[] backupHeights = {partialHeights[0], partialHeights[1]}; @@ -422,11 +427,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { LayoutContext layoutContext) { getParentArea(null); - // if adjusted space before - double adjust = layoutContext.getSpaceAdjust(); - addBlockSpacing(adjust, foSpaceBefore); - foSpaceBefore = null; - getPSLM().addIDToPage(getListItemFO().getId()); LayoutContext lc = new LayoutContext(0); @@ -461,6 +461,31 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { int bodyFirstIndex = ((ListItemPosition) positionList.getFirst()).getBodyFirstIndex(); int bodyLastIndex = ((ListItemPosition) positionList.getLast()).getBodyLastIndex(); + int lastBreak; + //Determine last break if any + lastBreak = labelFirstIndex - 1; + while (lastBreak >= 0) { + KnuthElement el = (KnuthElement)labelList.get(lastBreak); + if (el.isPenalty() && el.getP() < KnuthElement.INFINITE) { + break; + } + lastBreak--; + } + SpaceResolver.performConditionalsNotification(labelList, + labelFirstIndex, labelLastIndex, lastBreak); + + //Determine last break if any + lastBreak = bodyFirstIndex - 1; + while (lastBreak >= 0) { + KnuthElement el = (KnuthElement)bodyList.get(lastBreak); + if (el.isPenalty() && el.getP() < KnuthElement.INFINITE) { + break; + } + lastBreak--; + } + SpaceResolver.performConditionalsNotification(bodyList, + bodyFirstIndex, bodyLastIndex, lastBreak); + // add label areas if (labelFirstIndex <= labelLastIndex) { KnuthPossPosIter labelIter = new KnuthPossPosIter(labelList, @@ -508,13 +533,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { TraitSetter.addBackground(curBlockArea, getListItemFO().getCommonBorderPaddingBackground(), this); + TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), + effSpaceBefore, effSpaceAfter); flush(); - // if adjusted space after - addBlockSpacing(adjust, foSpaceAfter); - curBlockArea = null; + resetSpaces(); } /** @@ -550,7 +575,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { // set traits TraitSetter.setProducerID(curBlockArea, getListItemFO().getId()); TraitSetter.addBorders(curBlockArea, - getListItemFO().getCommonBorderPaddingBackground(), this); + getListItemFO().getCommonBorderPaddingBackground(), + discardBorderBefore, discardBorderAfter, false, false, this); + TraitSetter.addPadding(curBlockArea, + getListItemFO().getCommonBorderPaddingBackground(), + discardPaddingBefore, discardPaddingAfter, false, false, this); TraitSetter.addMargins(curBlockArea, getListItemFO().getCommonBorderPaddingBackground(), getListItemFO().getCommonMarginBlock(), this); @@ -610,5 +639,51 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { || !getListItemFO().getKeepWithNext().getWithinColumn().isAuto(); } + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifySpace(RelSide side, MinOptMax effectiveLength) { + if (RelSide.BEFORE == side) { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceBefore + "-> " + effectiveLength); + } + this.effSpaceBefore = effectiveLength; + } else { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceAfter + "-> " + effectiveLength); + } + this.effSpaceAfter = effectiveLength; + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyBorder(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardBorderBefore = true; + } else { + this.discardBorderAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Border " + side + " -> " + effectiveLength); + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyPadding(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardPaddingBefore = true; + } else { + this.discardPaddingAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Padding " + side + " -> " + effectiveLength); + } + } + + } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index c4175f95b..407088522 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -27,12 +27,14 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.layoutmgr.AreaAdditionUtil; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; -import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -43,9 +45,9 @@ import org.apache.fop.traits.MinOptMax; * LayoutManager for a table-cell FO. * A cell contains blocks. These blocks fill the cell. */ -public class TableCellLayoutManager extends BlockStackingLayoutManager implements BlockLevelLayoutManager { +public class TableCellLayoutManager extends BlockStackingLayoutManager + implements BlockLevelLayoutManager { - private TableCell fobj; private PrimaryGridUnit gridUnit; private Block curBlockArea; @@ -75,22 +77,27 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement /** @return the table-cell FO */ public TableCell getTableCell() { - return this.fobj; + return (TableCell)this.fobj; } private boolean isSeparateBorderModel() { - return fobj.isSeparateBorderModel(); + return getTableCell().isSeparateBorderModel(); } + /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */ public void initialize() { borderAndPaddingBPD = 0; - borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground().getBorderBeforeWidth(false); - borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground().getBorderAfterWidth(false); + borderAndPaddingBPD += getTableCell() + .getCommonBorderPaddingBackground().getBorderBeforeWidth(false); + borderAndPaddingBPD += getTableCell() + .getCommonBorderPaddingBackground().getBorderAfterWidth(false); if (!isSeparateBorderModel()) { borderAndPaddingBPD /= 2; } - borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground().getPaddingBefore(false, this); - borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground().getPaddingAfter(false, this); + borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground() + .getPaddingBefore(false, this); + borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground() + .getPaddingAfter(false, this); } /** @@ -115,8 +122,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement if (!isSeparateBorderModel()) { iIndents /= 2; } - iIndents += fobj.getCommonBorderPaddingBackground().getPaddingStart(false, this); - iIndents += fobj.getCommonBorderPaddingBackground().getPaddingEnd(false, this); + iIndents += getTableCell().getCommonBorderPaddingBackground().getPaddingStart(false, this); + iIndents += getTableCell().getCommonBorderPaddingBackground().getPaddingEnd(false, this); return iIndents; } @@ -130,7 +137,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement cellIPD = referenceIPD; cellIPD -= getIPIndents(); if (isSeparateBorderModel()) { - int borderSep = fobj.getBorderSeparation().getLengthPair() + int borderSep = getTableCell().getBorderSeparation().getLengthPair() .getIPD().getLength().getValue(this); cellIPD -= borderSep; } @@ -159,8 +166,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement } if (returnedList.size() == 1 - && ((KnuthElement) returnedList.getFirst()).isPenalty() - && ((KnuthPenalty) returnedList.getFirst()).getP() == -KnuthElement.INFINITE) { + && ((ListElement)returnedList.getFirst()).isForcedBreak()) { // a descendant of this block has break-before if (returnList.size() == 0) { // the first child (or its first child ...) has @@ -176,6 +182,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement returnedList = new LinkedList(); wrapPositionElements(contentList, returnList); + //Space resolution + SpaceResolver.resolveElementList(returnList); + return returnList; } else { if (prevLM != null) { @@ -189,13 +198,17 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false); // add an infinite penalty to forbid a break between // blocks - contentList.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, - new Position(this), false)); + contentList.add(new BreakElement( + new Position(this), KnuthElement.INFINITE, context)); + //contentList.add(new KnuthPenalty(0, + // KnuthElement.INFINITE, false, + // new Position(this), false)); } else if (!((KnuthElement) contentList.getLast()).isGlue()) { // add a null penalty to allow a break between blocks - contentList.add(new KnuthPenalty(0, 0, false, - new Position(this), false)); + contentList.add(new BreakElement( + new Position(this), 0, context)); + //contentList.add(new KnuthPenalty(0, 0, false, + // new Position(this), false)); } else { // the last element in contentList is a glue; // it is a feasible breakpoint, there is no need to add @@ -207,9 +220,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement //Avoid NoSuchElementException below (happens with empty blocks) continue; } - if (((KnuthElement) returnedList.getLast()).isPenalty() - && ((KnuthPenalty) returnedList.getLast()).getP() - == -KnuthElement.INFINITE) { + if (((ListElement)returnedList.getLast()).isForcedBreak()) { // a descendant of this block has break-after if (curLM.isFinished()) { // there is no other content in this block; @@ -220,6 +231,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement returnedList = new LinkedList(); wrapPositionElements(contentList, returnList); + //Space resolution + SpaceResolver.resolveElementList(returnList); + return returnList; } } @@ -234,6 +248,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement returnedList = new LinkedList(); wrapPositionElements(contentList, returnList); + //Space resolution + SpaceResolver.resolveElementList(returnList); + setFinished(true); return returnList; } @@ -314,11 +331,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(fobj.getId()); + getPSLM().addIDToPage(getTableCell().getId()); if (isSeparateBorderModel()) { - if (!emptyCell || fobj.showEmptyCells()) { - TraitSetter.addBorders(curBlockArea, fobj.getCommonBorderPaddingBackground(), this); + if (!emptyCell || getTableCell().showEmptyCells()) { + TraitSetter.addBorders(curBlockArea, + getTableCell().getCommonBorderPaddingBackground(), this); } } else { boolean[] outer = new boolean[] { @@ -384,11 +402,11 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement //Handle display-align int contentBPD = getContentHeight(rowHeight, gridUnit); if (usedBPD < contentBPD) { - if (fobj.getDisplayAlign() == EN_CENTER) { + if (getTableCell().getDisplayAlign() == EN_CENTER) { Block space = new Block(); space.setBPD((contentBPD - usedBPD) / 2); curBlockArea.addBlock(space); - } else if (fobj.getDisplayAlign() == EN_AFTER) { + } else if (getTableCell().getDisplayAlign() == EN_AFTER) { Block space = new Block(); space.setBPD((contentBPD - usedBPD)); curBlockArea.addBlock(space); @@ -401,15 +419,15 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement // Add background after we know the BPD if (isSeparateBorderModel()) { - if (!emptyCell || fobj.showEmptyCells()) { + if (!emptyCell || getTableCell().showEmptyCells()) { TraitSetter.addBackground(curBlockArea, - fobj.getCommonBorderPaddingBackground(), - this); + getTableCell().getCommonBorderPaddingBackground(), + this); } } else { TraitSetter.addBackground(curBlockArea, - fobj.getCommonBorderPaddingBackground(), - this); + getTableCell().getCommonBorderPaddingBackground(), + this); } flush(); @@ -434,18 +452,19 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement if (curBlockArea == null) { curBlockArea = new Block(); curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); - TraitSetter.setProducerID(curBlockArea, fobj.getId()); + TraitSetter.setProducerID(curBlockArea, getTableCell().getId()); curBlockArea.setPositioning(Block.ABSOLUTE); int indent = 0; indent += startBorderWidth; if (!isSeparateBorderModel()) { indent /= 2; } - indent += fobj.getCommonBorderPaddingBackground().getPaddingStart(false, this); + indent += getTableCell() + .getCommonBorderPaddingBackground().getPaddingStart(false, this); // set position int halfBorderSep = 0; if (isSeparateBorderModel()) { - halfBorderSep = fobj.getBorderSeparation().getLengthPair() + halfBorderSep = getTableCell().getBorderSeparation().getLengthPair() .getIPD().getLength().getValue(this) / 2; } int borderAdjust = 0; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index fd4a81b58..6c8b9e05b 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -36,6 +36,7 @@ import org.apache.fop.fo.flow.TableBody; import org.apache.fop.fo.flow.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; +import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthBox; @@ -44,10 +45,12 @@ import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.MinOptMaxUtil; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; +import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition; import org.apache.fop.traits.MinOptMax; /** @@ -199,16 +202,22 @@ public class TableContentLayoutManager implements PercentBaseContext { if (rowFO != null && rowFO.getBreakBefore() != Constants.EN_AUTO) { log.info("break-before found"); if (returnList.size() > 0) { - KnuthElement last = (KnuthElement)returnList.getLast(); + ListElement last = (ListElement)returnList.getLast(); if (last.isPenalty()) { KnuthPenalty pen = (KnuthPenalty)last; pen.setP(-KnuthPenalty.INFINITE); pen.setBreakClass(rowFO.getBreakBefore()); + } else if (last instanceof BreakElement) { + BreakElement breakPoss = (BreakElement)last; + breakPoss.setPenaltyValue(-KnuthPenalty.INFINITE); + breakPoss.setBreakClass(rowFO.getBreakBefore()); } } else { if (!firstBreakBeforeServed) { - returnList.add(new KnuthPenalty(0, -KnuthPenalty.INFINITE, - false, rowFO.getBreakBefore(), new Position(getTableLM()), true)); + //returnList.add(new KnuthPenalty(0, -KnuthPenalty.INFINITE, + // false, rowFO.getBreakBefore(), new Position(getTableLM()), true)); + returnList.add(new BreakElement(new Position(getTableLM()), + 0, -KnuthPenalty.INFINITE, rowFO.getBreakBefore(), context)); iter.backToPreviousRow(); firstBreakBeforeServed = true; break; @@ -234,12 +243,12 @@ public class TableContentLayoutManager implements PercentBaseContext { log.debug("child LM (row group) signals pending keep-with-previous"); if (returnList.size() > 0) { //Modify last penalty - KnuthElement last = (KnuthElement)returnList.getLast(); + ListElement last = (ListElement)returnList.getLast(); if (last.isPenalty()) { - KnuthPenalty pen = (KnuthPenalty)last; + BreakElement breakPoss = (BreakElement)last; //Only honor keep if there's no forced break - if (!pen.isForcedBreak()) { - pen.setP(KnuthPenalty.INFINITE); + if (!breakPoss.isForcedBreak()) { + breakPoss.setPenaltyValue(KnuthPenalty.INFINITE); } } } @@ -250,11 +259,15 @@ public class TableContentLayoutManager implements PercentBaseContext { if (rowFO != null && rowFO.getBreakAfter() != Constants.EN_AUTO) { log.info("break-after found"); if (returnList.size() > 0) { - KnuthElement last = (KnuthElement)returnList.getLast(); - if (last.isPenalty()) { + ListElement last = (ListElement)returnList.getLast(); + if (last instanceof KnuthPenalty) { KnuthPenalty pen = (KnuthPenalty)last; pen.setP(-KnuthPenalty.INFINITE); pen.setBreakClass(rowFO.getBreakAfter()); + } else if (last instanceof BreakElement) { + BreakElement breakPoss = (BreakElement)last; + breakPoss.setPenaltyValue(-KnuthPenalty.INFINITE); + breakPoss.setBreakClass(rowFO.getBreakAfter()); } } } @@ -262,10 +275,9 @@ public class TableContentLayoutManager implements PercentBaseContext { if (returnList.size() > 0) { //Remove last penalty - KnuthElement last = (KnuthElement)returnList.getLast(); - if (last.isPenalty()) { - KnuthPenalty pen = (KnuthPenalty)last; - if (!pen.isForcedBreak()) { + ListElement last = (ListElement)returnList.getLast(); + if (last.isPenalty() || last instanceof BreakElement) { + if (!last.isForcedBreak()) { //Only remove if we don't signal a forced break returnList.removeLast(); } @@ -461,9 +473,7 @@ public class TableContentLayoutManager implements PercentBaseContext { ElementListObserver.observe(elems, "table-cell", primary.getCell().getId()); if ((elems.size() > 0) - && ((KnuthElement)elems.getLast()).isPenalty() - && ((KnuthPenalty)elems.getLast()).getP() - == -KnuthElement.INFINITE) { + && ((KnuthElement)elems.getLast()).isForcedBreak()) { // a descendant of this block has break-after log.warn("Descendant of table-cell signals break: " + primary.getCellLM().isFinished()); @@ -587,12 +597,24 @@ public class TableContentLayoutManager implements PercentBaseContext { List footerElements = null; Position firstPos = null; Position lastPos = null; + Position lastCheckPos = null; while (parentIter.hasNext()) { Position pos = (Position)parentIter.next(); + if (pos instanceof SpaceHandlingBreakPosition) { + //This position has only been needed before addAreas was called, now we need the + //original one created by the layout manager. + pos = ((SpaceHandlingBreakPosition)pos).getOriginalBreakPosition(); + } + if (pos == null) { + continue; + } if (firstPos == null) { firstPos = pos; } lastPos = pos; + if (pos.getIndex() >= 0) { + lastCheckPos = pos; + } if (pos instanceof TableHeaderFooterPosition) { TableHeaderFooterPosition thfpos = (TableHeaderFooterPosition)pos; //these positions need to be unpacked @@ -627,7 +649,7 @@ public class TableContentLayoutManager implements PercentBaseContext { Map markers = getTableLM().getTable().getMarkers(); if (markers != null) { getTableLM().getCurrentPV().addMarkers(markers, - true, getTableLM().isFirst(firstPos), getTableLM().isLast(lastPos)); + true, getTableLM().isFirst(firstPos), getTableLM().isLast(lastCheckPos)); } if (headerElements != null) { @@ -655,7 +677,7 @@ public class TableContentLayoutManager implements PercentBaseContext { if (markers != null) { getTableLM().getCurrentPV().addMarkers(markers, - false, getTableLM().isFirst(firstPos), getTableLM().isLast(lastPos)); + false, getTableLM().isFirst(firstPos), getTableLM().isLast(lastCheckPos)); } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index cda906c9e..f805fe9c7 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -24,12 +24,14 @@ import org.apache.fop.fo.flow.TableColumn; import org.apache.fop.fo.properties.TableColLength; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; -import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.Position; +import org.apache.fop.layoutmgr.RelSide; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -50,8 +52,7 @@ import org.apache.fop.fo.FObj; * the render background. */ public class TableLayoutManager extends BlockStackingLayoutManager - implements BlockLevelLayoutManager { - private Table fobj; + implements ConditionalElementListener { private TableContentLayoutManager contentLM; private ColumnSetup columns = null; @@ -63,9 +64,12 @@ public class TableLayoutManager extends BlockStackingLayoutManager private double tableUnits; private boolean autoLayout = true; - //TODO space-before|after: handle space-resolution rules - private MinOptMax spaceBefore; - private MinOptMax spaceAfter; + private boolean discardBorderBefore; + private boolean discardBorderAfter; + private boolean discardPaddingBefore; + private boolean discardPaddingAfter; + private MinOptMax effSpaceBefore; + private MinOptMax effSpaceAfter; /** * Create a new table layout manager. @@ -73,13 +77,12 @@ public class TableLayoutManager extends BlockStackingLayoutManager */ public TableLayoutManager(Table node) { super(node); - fobj = node; this.columns = new ColumnSetup(node); } /** @return the table FO */ public Table getTable() { - return this.fobj; + return (Table)this.fobj; } /** @@ -91,19 +94,31 @@ public class TableLayoutManager extends BlockStackingLayoutManager /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */ public void initialize() { - spaceBefore = new SpaceVal(fobj.getCommonMarginBlock().spaceBefore, this).getSpace(); - spaceAfter = new SpaceVal(fobj.getCommonMarginBlock().spaceAfter, this).getSpace(); + foSpaceBefore = new SpaceVal( + getTable().getCommonMarginBlock().spaceBefore, this).getSpace(); + foSpaceAfter = new SpaceVal( + getTable().getCommonMarginBlock().spaceAfter, this).getSpace(); - if (!fobj.isAutoLayout() - && fobj.getInlineProgressionDimension().getOptimum(this).getEnum() != EN_AUTO) { + if (!getTable().isAutoLayout() + && getTable().getInlineProgressionDimension().getOptimum(this).getEnum() + != EN_AUTO) { autoLayout = false; } } + private void resetSpaces() { + this.discardBorderBefore = false; + this.discardBorderAfter = false; + this.discardPaddingBefore = false; + this.discardPaddingAfter = false; + this.effSpaceBefore = foSpaceBefore; + this.effSpaceAfter = foSpaceAfter; + } + private int getIPIndents() { int iIndents = 0; - iIndents += fobj.getCommonMarginBlock().startIndent.getValue(this); - iIndents += fobj.getCommonMarginBlock().endIndent.getValue(this); + iIndents += getTable().getCommonMarginBlock().startIndent.getValue(this); + iIndents += getTable().getCommonMarginBlock().endIndent.getValue(this); return iIndents; } @@ -114,7 +129,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager if (!bBreakBeforeServed) { try { - if (addKnuthElementsForBreakBefore(returnList)) { + if (addKnuthElementsForBreakBefore(returnList, context)) { return returnList; } } finally { @@ -125,12 +140,12 @@ public class TableLayoutManager extends BlockStackingLayoutManager referenceBPD = context.getStackLimit().opt; referenceIPD = context.getRefIPD(); - if (fobj.getInlineProgressionDimension().getOptimum(this).getEnum() != EN_AUTO) { - referenceIPD = fobj.getInlineProgressionDimension().getOptimum(this) + if (getTable().getInlineProgressionDimension().getOptimum(this).getEnum() != EN_AUTO) { + referenceIPD = getTable().getInlineProgressionDimension().getOptimum(this) .getLength().getValue(this); contentIPD = referenceIPD; } else { - if (!fobj.isAutoLayout()) { + if (!getTable().isAutoLayout()) { log.info("table-layout=\"fixed\" and width=\"auto\", " + "but auto-layout not supported " + "=> assuming width=\"100%\""); @@ -141,15 +156,6 @@ public class TableLayoutManager extends BlockStackingLayoutManager log.warn("Allocated IPD exceeds available reference IPD"); } - MinOptMax stackSize = new MinOptMax(); - //Add spacing - if (spaceAfter != null) { - stackSize.add(spaceAfter); - } - if (spaceBefore != null) { - stackSize.add(spaceBefore); - } - // either works out table of column widths or if proportional-column-width function // is used works out total factor, so that value of single unit can be computed. int sumCols = 0; @@ -172,16 +178,28 @@ public class TableLayoutManager extends BlockStackingLayoutManager } } + addKnuthElementsForSpaceBefore(returnList, alignment); + + if (getTable().isSeparateBorderModel()) { + addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); + firstVisibleMarkServed = true; + } + + //Spaces, border and padding to be repeated at each break + addPendingMarks(context); + LinkedList returnedList = null; LinkedList contentList = new LinkedList(); //Position returnPosition = new NonLeafPosition(this, null); //Body prevLM = null; LayoutContext childLC = new LayoutContext(0); + /* childLC.setStackLimit( MinOptMax.subtract(context.getStackLimit(), - stackSize)); + stackSize));*/ childLC.setRefIPD(context.getRefIPD()); + childLC.copyPendingMarksFrom(context); if (contentLM == null) { contentLM = new TableContentLayoutManager(this); @@ -199,14 +217,13 @@ public class TableLayoutManager extends BlockStackingLayoutManager //Set index values on elements coming from the content LM Iterator iter = returnedList.iterator(); while (iter.hasNext()) { - KnuthElement el = (KnuthElement)iter.next(); + ListElement el = (ListElement)iter.next(); notifyPos(el.getPosition()); } log.debug(returnedList); if (returnedList.size() == 1 - && ((KnuthElement) returnedList.getFirst()).isPenalty() - && ((KnuthPenalty) returnedList.getFirst()).getP() == -KnuthElement.INFINITE) { + && ((ListElement)returnedList.getFirst()).isForcedBreak()) { // a descendant of this block has break-before if (returnList.size() == 0) { // the first child (or its first child ...) has @@ -250,8 +267,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager }*/ contentList.addAll(returnedList); if (returnedList.size() > 0) { - if (((KnuthElement) returnedList.getLast()).isPenalty() - && ((KnuthPenalty) returnedList.getLast()).getP() == -KnuthElement.INFINITE) { + if (((ListElement)returnedList.getLast()).isForcedBreak()) { // a descendant of this block has break-after if (false /*curLM.isFinished()*/) { // there is no other content in this block; @@ -267,8 +283,13 @@ public class TableLayoutManager extends BlockStackingLayoutManager } } wrapPositionElements(contentList, returnList); - addKnuthElementsForBreakAfter(returnList); + if (getTable().isSeparateBorderModel()) { + addKnuthElementsForBorderPaddingAfter(returnList, true); + } + addKnuthElementsForSpaceAfter(returnList, alignment); + addKnuthElementsForBreakAfter(returnList, context); setFinished(true); + resetSpaces(); return returnList; } @@ -282,14 +303,9 @@ public class TableLayoutManager extends BlockStackingLayoutManager public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { getParentArea(null); - getPSLM().addIDToPage(fobj.getId()); + getPSLM().addIDToPage(getTable().getId()); - // if adjusted space before - double adjust = layoutContext.getSpaceAdjust(); - addBlockSpacing(adjust, spaceBefore); - spaceBefore = null; - - int startXOffset = fobj.getCommonMarginBlock().startIndent.getValue(this); + int startXOffset = getTable().getCommonMarginBlock().startIndent.getValue(this); // add column, body then row areas @@ -305,25 +321,29 @@ public class TableLayoutManager extends BlockStackingLayoutManager curBlockArea.setBPD(tableHeight); - if (fobj.isSeparateBorderModel()) { - TraitSetter.addBorders(curBlockArea, fobj.getCommonBorderPaddingBackground(), this); + if (getTable().isSeparateBorderModel()) { + TraitSetter.addBorders(curBlockArea, + getTable().getCommonBorderPaddingBackground(), + discardBorderBefore, discardBorderAfter, false, false, this); + TraitSetter.addPadding(curBlockArea, + getTable().getCommonBorderPaddingBackground(), + discardPaddingBefore, discardPaddingAfter, false, false, this); } TraitSetter.addBackground(curBlockArea, - fobj.getCommonBorderPaddingBackground(), + getTable().getCommonBorderPaddingBackground(), this); TraitSetter.addMargins(curBlockArea, - fobj.getCommonBorderPaddingBackground(), - fobj.getCommonMarginBlock(), + getTable().getCommonBorderPaddingBackground(), + getTable().getCommonMarginBlock(), this); TraitSetter.addBreaks(curBlockArea, - fobj.getBreakBefore(), fobj.getBreakAfter()); + getTable().getBreakBefore(), getTable().getBreakAfter()); + TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), + effSpaceBefore, effSpaceAfter); flush(); - // if adjusted space after - addBlockSpacing(adjust, spaceAfter); - - //bodyBreaks.clear(); + resetSpaces(); curBlockArea = null; } @@ -378,17 +398,13 @@ public class TableLayoutManager extends BlockStackingLayoutManager } } - /** - * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#negotiateBPDAdjustment(int, org.apache.fop.layoutmgr.KnuthElement) - */ + /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager */ public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { // TODO Auto-generated method stub return 0; } - /** - * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#discardSpace(org.apache.fop.layoutmgr.KnuthGlue) - */ + /** @see org.apache.fop.layoutmgr.BlockLevelLayoutManager */ public void discardSpace(KnuthGlue spaceGlue) { // TODO Auto-generated method stub @@ -400,24 +416,24 @@ public class TableLayoutManager extends BlockStackingLayoutManager public boolean mustKeepTogether() { //TODO Keeps will have to be more sophisticated sooner or later return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() - || !fobj.getKeepTogether().getWithinPage().isAuto() - || !fobj.getKeepTogether().getWithinColumn().isAuto(); + || !getTable().getKeepTogether().getWithinPage().isAuto() + || !getTable().getKeepTogether().getWithinColumn().isAuto(); } /** * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithPrevious() */ public boolean mustKeepWithPrevious() { - return !fobj.getKeepWithPrevious().getWithinPage().isAuto() - || !fobj.getKeepWithPrevious().getWithinColumn().isAuto(); + return !getTable().getKeepWithPrevious().getWithinPage().isAuto() + || !getTable().getKeepWithPrevious().getWithinColumn().isAuto(); } /** * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithNext() */ public boolean mustKeepWithNext() { - return !fobj.getKeepWithNext().getWithinPage().isAuto() - || !fobj.getKeepWithNext().getWithinColumn().isAuto(); + return !getTable().getKeepWithNext().getWithinPage().isAuto() + || !getTable().getKeepWithNext().getWithinColumn().isAuto(); } // --------- Property Resolution related functions --------- // @@ -461,4 +477,49 @@ public class TableLayoutManager extends BlockStackingLayoutManager return referenceBPD; } + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifySpace(RelSide side, MinOptMax effectiveLength) { + if (RelSide.BEFORE == side) { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceBefore + "-> " + effectiveLength); + } + this.effSpaceBefore = effectiveLength; + } else { + if (log.isDebugEnabled()) { + log.debug(this + ": Space " + side + ", " + + this.effSpaceAfter + "-> " + effectiveLength); + } + this.effSpaceAfter = effectiveLength; + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyBorder(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardBorderBefore = true; + } else { + this.discardBorderAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Border " + side + " -> " + effectiveLength); + } + } + + /** @see org.apache.fop.layoutmgr.ConditionalElementListener */ + public void notifyPadding(RelSide side, MinOptMax effectiveLength) { + if (effectiveLength == null) { + if (RelSide.BEFORE == side) { + this.discardPaddingBefore = true; + } else { + this.discardPaddingAfter = true; + } + } + if (log.isDebugEnabled()) { + log.debug(this + ": Padding " + side + " -> " + effectiveLength); + } + } + } \ No newline at end of file diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index f7a381a3e..00eeae4ba 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListUtils; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -162,7 +163,7 @@ public class TableStepper { private void setupElementList(int column) { GridUnit gu = getActiveGridUnit(column); EffRow row = getActiveRow(); - if (gu.isEmpty()){ + if (gu.isEmpty()) { elementLists[column] = null; start[column] = 0; end[column] = -1; @@ -296,14 +297,6 @@ public class TableStepper { //Create elements for step int effPenaltyLen = penaltyLen; - if (isSeparateBorderModel()) { - CommonBorderPaddingBackground borders - = getTableLM().getTable().getCommonBorderPaddingBackground(); - effPenaltyLen += borders.getBorderBeforeWidth(false); - effPenaltyLen += borders.getBorderAfterWidth(false); - effPenaltyLen += borders.getPaddingBefore(false, getTableLM()); - effPenaltyLen += borders.getPaddingAfter(false, getTableLM()); - } TableContentPosition tcpos = new TableContentPosition(getTableLM(), gridUnitParts, getActiveRow()); if (returnList.size() == 0) { @@ -345,7 +338,8 @@ public class TableStepper { p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0) clearBreakCondition(); } - returnList.add(new KnuthPenalty(effPenaltyLen, p, false, penaltyPos, false)); + //returnList.add(new KnuthPenalty(effPenaltyLen, p, false, penaltyPos, false)); + returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, 0, context)); log.debug("step=" + step + " (+" + increase + ")" + " box=" + boxLen @@ -364,7 +358,7 @@ public class TableStepper { context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); } if (isBreakCondition()) { - ((KnuthPenalty)returnList.getLast()).setP(-KnuthPenalty.INFINITE); + ((BreakElement)returnList.getLast()).setPenaltyValue(-KnuthPenalty.INFINITE); } lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true); return returnList; diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index aceac1a87..ab2fc8588 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -530,8 +530,9 @@ public abstract class AbstractRenderer int saveBP = currentBPPosition; if (block.getPositioning() == Block.ABSOLUTE) { - currentIPPosition = containingIPPosition + block.getXOffset(); - currentBPPosition = containingBPPosition + block.getYOffset(); + currentIPPosition += block.getXOffset(); + currentBPPosition += block.getYOffset(); + currentBPPosition += block.getSpaceBefore(); handleBlockTraits(block); @@ -545,6 +546,7 @@ public abstract class AbstractRenderer // relative blocks are offset currentIPPosition += block.getXOffset(); currentBPPosition += block.getYOffset(); + currentBPPosition += block.getSpaceBefore(); handleBlockTraits(block); diff --git a/src/java/org/apache/fop/traits/MinOptMax.java b/src/java/org/apache/fop/traits/MinOptMax.java index 47469d161..143e93ae0 100644 --- a/src/java/org/apache/fop/traits/MinOptMax.java +++ b/src/java/org/apache/fop/traits/MinOptMax.java @@ -162,6 +162,11 @@ public class MinOptMax implements java.io.Serializable, Cloneable { opt -= op.opt; max -= op.min; } + + /** @return true if this instance represents a zero-width length (min=opt=max=0) */ + public boolean isNonZero() { + return (min != 0 || max != 0); + } /** @see java.lang.Object#toString() */ public String toString() { diff --git a/test/fotree/testcases/shorthand-prop-mix.fo b/test/fotree/testcases/shorthand-prop-mix.fo new file mode 100644 index 000000000..822d5c740 --- /dev/null +++ b/test/fotree/testcases/shorthand-prop-mix.fo @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + Hello World! + Hello World! + Hello World! + Hello World! + + + + diff --git a/test/fotree/testcases/table_border-separation.fo b/test/fotree/testcases/table_border-separation.fo new file mode 100644 index 000000000..5819255f2 --- /dev/null +++ b/test/fotree/testcases/table_border-separation.fo @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + cell1 + + + cell2 + + + + + cell3 + + + cell4 + + + + + + + + + + + + + cell1 + + + cell2 + + + + + cell3 + + + cell4 + + + + + + + diff --git a/test/java/org/apache/fop/fotreetest/ext/AssertElement.java b/test/java/org/apache/fop/fotreetest/ext/AssertElement.java index ebd8335c1..f773c76a6 100644 --- a/test/java/org/apache/fop/fotreetest/ext/AssertElement.java +++ b/test/java/org/apache/fop/fotreetest/ext/AssertElement.java @@ -23,6 +23,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOPropertyMapping; import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.properties.LengthPairProperty; import org.apache.fop.fo.properties.Property; import org.apache.fop.fotreetest.ResultCollector; @@ -51,13 +52,29 @@ public class AssertElement extends TestObj { //super.processNode(elementName, locator, attlist, propertyList); ResultCollector collector = ResultCollector.getInstance(); - String propName = attlist.getValue("property"); + String propName = attlist.getValue("property"); + String component = null; + int dotIndex = propName.indexOf('.'); + if (dotIndex >= 0) { + component = propName.substring(dotIndex + 1); + propName = propName.substring(0, dotIndex); + } int propID = FOPropertyMapping.getPropertyId(propName); if (propID < 0) { collector.notifyException(new IllegalArgumentException( "Property not found: " + propName)); } else { - Property prop = propertyList.getParentPropertyList().get(propID); + Property prop; + prop = propertyList.getParentPropertyList().get(propID); + if (component != null) { + //Access subcomponent + Property mainProp = prop; + prop = null; + LengthPairProperty lpp = mainProp.getLengthPair(); + if (lpp != null) { + prop = lpp.getComponent(FOPropertyMapping.getSubPropertyId(component)); + } + } String s = String.valueOf(prop); String expected = attlist.getValue("expected"); if (!expected.equals(s)) { diff --git a/test/java/org/apache/fop/logging/LoggingElementListObserver.java b/test/java/org/apache/fop/logging/LoggingElementListObserver.java index 255cff900..881a8c3ee 100644 --- a/test/java/org/apache/fop/logging/LoggingElementListObserver.java +++ b/test/java/org/apache/fop/logging/LoggingElementListObserver.java @@ -23,7 +23,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.layoutmgr.KnuthElement; +import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.ElementListObserver.Observer; /** @@ -49,9 +49,9 @@ public class LoggingElementListObserver implements Observer { return; } ListIterator tempIter = elementList.listIterator(); - KnuthElement temp; + ListElement temp; while (tempIter.hasNext()) { - temp = (KnuthElement) tempIter.next(); + temp = (ListElement) tempIter.next(); if (temp.isBox()) { log.debug(tempIter.previousIndex() + ") " + temp); diff --git a/test/layoutengine/disabled-testcases.txt b/test/layoutengine/disabled-testcases.txt index 91db41057..6159cda4b 100644 --- a/test/layoutengine/disabled-testcases.txt +++ b/test/layoutengine/disabled-testcases.txt @@ -1,11 +1,12 @@ block-container_reference-orientation_bug36391.xml +block-container_space-before_space-after_3.xml block_font-stretch.xml block_padding_2.xml -block_space-before_space-after_2.xml -block_space-before_space-after_3.xml +block_space-before_space-after_8.xml block_word-spacing.xml block_word-spacing_text-align_justify.xml external-graphic_oversized.xml +footnote_space-resolution.xml inline-block_keep-together.xml inline_block_nested_3.xml inline-container_block_nested.xml @@ -16,7 +17,6 @@ inline_word-spacing_text-align_justify.xml leader-alignment.xml list-block_keep-with-previous.xml list-item_block_keep-with-previous.xml -list-item_space-before_space-after_2.xml page-breaking_4.xml page-breaking_6.xml page-height_indefinite_simple.xml @@ -31,6 +31,7 @@ table_border-collapse_collapse_1.xml table_border-collapse_collapse_2.xml table_border_padding.xml table-cell_block_keep-with-previous.xml +table-cell_border_padding_conditionality.xml table-column_first-row-width.xml table-header_background-image.xml table-row_keep-with-previous.xml diff --git a/test/layoutengine/testcases/block-container_display-align_space-before.xml b/test/layoutengine/testcases/block-container_display-align_space-before.xml index be7035e9e..b483edbd3 100644 --- a/test/layoutengine/testcases/block-container_display-align_space-before.xml +++ b/test/layoutengine/testcases/block-container_display-align_space-before.xml @@ -52,77 +52,77 @@ - - - - - - + + + + + + - - - - - + + + + + - + - - - - - - + + + + + + - - - - - + + + + + - + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - + - - - - - - + + + + + + - - - - - + + + + + - - - + + + diff --git a/test/layoutengine/testcases/block-container_space-before_space-after_1.xml b/test/layoutengine/testcases/block-container_space-before_space-after_1.xml new file mode 100644 index 000000000..37b7b87c2 --- /dev/null +++ b/test/layoutengine/testcases/block-container_space-before_space-after_1.xml @@ -0,0 +1,160 @@ + + + + + +

+ This test checks space properties on block-container. +

+ + + + + + + + + + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + +Two blocks, testing conditionality="retain". + + + + + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + +Two blocks, testing conditionality="discard". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + 8 + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + diff --git a/test/layoutengine/testcases/block-container_space-before_space-after_2.xml b/test/layoutengine/testcases/block-container_space-before_space-after_2.xml new file mode 100644 index 000000000..d742b3e85 --- /dev/null +++ b/test/layoutengine/testcases/block-container_space-before_space-after_2.xml @@ -0,0 +1,93 @@ + + + + + +

+ This test checks block-level space properties. Demonstrates that spaces are repeated on every generated area. +

+
+ + + + + + + + + + + line 1 + line 2 + line 3 + line 4 + line 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/block-container_space-before_space-after_3.xml b/test/layoutengine/testcases/block-container_space-before_space-after_3.xml new file mode 100644 index 000000000..6e9d607d7 --- /dev/null +++ b/test/layoutengine/testcases/block-container_space-before_space-after_3.xml @@ -0,0 +1,126 @@ + + + + + +

+ This test checks space properties on block-containers. The focus is on space properties on content inside the block-containers. +

+
+ + + + + + + + + + + line 1 + line 2 + + A block between block-containers. + + + line 1 + line 2 + + + + + + + line 1 + line 2 + + A block between block-containers. + + line 1 + line 2 + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + + + + + 3 + + + + + + + + 3 + + + + + + + + 3 + + +
diff --git a/test/layoutengine/testcases/block_border_padding.xml b/test/layoutengine/testcases/block_border_padding.xml index dd3278917..caf283542 100644 --- a/test/layoutengine/testcases/block_border_padding.xml +++ b/test/layoutengine/testcases/block_border_padding.xml @@ -48,107 +48,107 @@ - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - + diff --git a/test/layoutengine/testcases/block_margin.xml b/test/layoutengine/testcases/block_margin.xml index 8259c0a0a..3723e5da0 100644 --- a/test/layoutengine/testcases/block_margin.xml +++ b/test/layoutengine/testcases/block_margin.xml @@ -40,33 +40,35 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - - - - + + + + + - - - + + + + - + diff --git a/test/layoutengine/testcases/block_margin_inherit.xml b/test/layoutengine/testcases/block_margin_inherit.xml index da022fb3b..ea43a11cd 100644 --- a/test/layoutengine/testcases/block_margin_inherit.xml +++ b/test/layoutengine/testcases/block_margin_inherit.xml @@ -41,23 +41,36 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/block_margin_percentages.xml b/test/layoutengine/testcases/block_margin_percentages.xml index f3f9b531c..c84a816c5 100644 --- a/test/layoutengine/testcases/block_margin_percentages.xml +++ b/test/layoutengine/testcases/block_margin_percentages.xml @@ -41,23 +41,36 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/block_margin_shorthands.xml b/test/layoutengine/testcases/block_margin_shorthands.xml index 8dc53fd90..25ac7d553 100644 --- a/test/layoutengine/testcases/block_margin_shorthands.xml +++ b/test/layoutengine/testcases/block_margin_shorthands.xml @@ -30,10 +30,15 @@ + all + left/right + top/bottom + three values + EOF @@ -42,45 +47,48 @@ - + - - - - - + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + + - + - + - - - - - + + + + + + - + diff --git a/test/layoutengine/testcases/block_padding_2.xml b/test/layoutengine/testcases/block_padding_2.xml index 73b430aa6..e64750785 100644 --- a/test/layoutengine/testcases/block_padding_2.xml +++ b/test/layoutengine/testcases/block_padding_2.xml @@ -44,39 +44,61 @@ - + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + + + - + + + + + 3 diff --git a/test/layoutengine/testcases/block_space-before_space-after_1.xml b/test/layoutengine/testcases/block_space-before_space-after_1.xml index 746cf15c9..9c462b29c 100644 --- a/test/layoutengine/testcases/block_space-before_space-after_1.xml +++ b/test/layoutengine/testcases/block_space-before_space-after_1.xml @@ -42,30 +42,34 @@ - - + + + - + - - + + - + - - + + + - - + + + - + - - + + - + - - + + + diff --git a/test/layoutengine/testcases/block_space-before_space-after_2.xml b/test/layoutengine/testcases/block_space-before_space-after_2.xml index 58b5a3e6f..0676277f9 100644 --- a/test/layoutengine/testcases/block_space-before_space-after_2.xml +++ b/test/layoutengine/testcases/block_space-before_space-after_2.xml @@ -28,7 +28,7 @@ - + In olden times when wishing still helped one, there lived a king whose daughters @@ -44,7 +44,7 @@ Two blocks, testing conditionality="retain". - + In olden times when wishing still helped one, there lived a king whose daughters @@ -63,5 +63,94 @@ Two blocks, testing conditionality="discard". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + 8 + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + diff --git a/test/layoutengine/testcases/block_space-before_space-after_3.xml b/test/layoutengine/testcases/block_space-before_space-after_3.xml index a58c831a3..0c59ec68f 100644 --- a/test/layoutengine/testcases/block_space-before_space-after_3.xml +++ b/test/layoutengine/testcases/block_space-before_space-after_3.xml @@ -46,7 +46,7 @@ - + 3 diff --git a/test/layoutengine/testcases/block_space-before_space-after_4.xml b/test/layoutengine/testcases/block_space-before_space-after_4.xml new file mode 100644 index 000000000..3d4fb9f58 --- /dev/null +++ b/test/layoutengine/testcases/block_space-before_space-after_4.xml @@ -0,0 +1,83 @@ + + + + + +

+ This test checks block-level space properties. Demonstrates that spaces are repeated on every generated area. +

+
+ + + + + + + + + + + line 1 + line 2 + line 3 + line 4 + line 5 + + + + + + + + + + + + + + + + + + + + + + + 6 + 6 + + + + + + + 3 + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/block_space-before_space-after_5.xml b/test/layoutengine/testcases/block_space-before_space-after_5.xml new file mode 100644 index 000000000..5a7beac8e --- /dev/null +++ b/test/layoutengine/testcases/block_space-before_space-after_5.xml @@ -0,0 +1,96 @@ + + + + + +

+ This test checks block-level space properties. These here are the + examples 3 to 5 on the Wiki. +

+
+ + + + + + + + + + block 1: space-after conditional + block 2: space-before conditional + + + + + block 1: space-after retained + block 2: space-before: conditional + + + + + block 1: space-after retained + block 2: space-before: conditional + + + + + block 1: space-after retained + block 2: space-before retained + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + 3 + + + + + + + + + + + + 3 + + +
diff --git a/test/layoutengine/testcases/block_space-before_space-after_6.xml b/test/layoutengine/testcases/block_space-before_space-after_6.xml new file mode 100644 index 000000000..7b6737252 --- /dev/null +++ b/test/layoutengine/testcases/block_space-before_space-after_6.xml @@ -0,0 +1,92 @@ + + + + + +

+ This test checks block-level space properties. These here are the + examples 1 and 2 on the Wiki. +

+
+ + + + + + + + + + first line + + before break + after break + + + + + + first line + + before break + after break + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + 3 + + +
diff --git a/test/layoutengine/testcases/block_space-before_space-after_7.xml b/test/layoutengine/testcases/block_space-before_space-after_7.xml new file mode 100644 index 000000000..4387626f2 --- /dev/null +++ b/test/layoutengine/testcases/block_space-before_space-after_7.xml @@ -0,0 +1,56 @@ + + + + + +

+ This test checks block-level space properties. These here are the + examples 1 and 2 on the Wiki. +

+
+ + + + + + + + + + + first line + second line + + + + + + + + + + + + + + + + + 3 + + +
diff --git a/test/layoutengine/testcases/block_space-before_space-after_8.xml b/test/layoutengine/testcases/block_space-before_space-after_8.xml new file mode 100644 index 000000000..6a960077f --- /dev/null +++ b/test/layoutengine/testcases/block_space-before_space-after_8.xml @@ -0,0 +1,49 @@ + + + + + +

+ This test checks if the special case is properly handled when an empty block is between two + space-specifiers which should form a stacking constraint. +

+
+ + + + + + + + + + + first line + + + + second line + + + + + + + + + +
diff --git a/test/layoutengine/testcases/block_space-before_space-after_9.xml b/test/layoutengine/testcases/block_space-before_space-after_9.xml new file mode 100644 index 000000000..4df459117 --- /dev/null +++ b/test/layoutengine/testcases/block_space-before_space-after_9.xml @@ -0,0 +1,69 @@ + + + + + +

+ This test checks if the isLast case is properly handled. In this case the part list has to be + reversed to do the conditionals removal, but then has to be reversed again to its natural order + so space resolution rules 2 and 3 are properly performed. +

+
+ + + + + + + + + + + + + Apache FOP! + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + +
diff --git a/test/layoutengine/testcases/block_space-before_space-after_9a.xml b/test/layoutengine/testcases/block_space-before_space-after_9a.xml new file mode 100644 index 000000000..07f378368 --- /dev/null +++ b/test/layoutengine/testcases/block_space-before_space-after_9a.xml @@ -0,0 +1,90 @@ + + + + + +

+ This test checks if the isLast case is properly handled. In this case the part list has to be + reversed to do the conditionals removal, but then has to be reversed again to its natural order + so space resolution rules 2 and 3 are properly performed. +

+
+ + + + + + + + + + + + + Apache FOP! + + Apache FOP!!! + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/character_border_padding.xml b/test/layoutengine/testcases/character_border_padding.xml index a5c6f6f7a..02c72b118 100755 --- a/test/layoutengine/testcases/character_border_padding.xml +++ b/test/layoutengine/testcases/character_border_padding.xml @@ -47,52 +47,52 @@ + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/character_vertical-align.xml b/test/layoutengine/testcases/character_vertical-align.xml index 60f15505e..125d56fb0 100755 --- a/test/layoutengine/testcases/character_vertical-align.xml +++ b/test/layoutengine/testcases/character_vertical-align.xml @@ -50,10 +50,10 @@ + - - - - + + + diff --git a/test/layoutengine/testcases/footnote_space-resolution.xml b/test/layoutengine/testcases/footnote_space-resolution.xml new file mode 100644 index 000000000..151e276b9 --- /dev/null +++ b/test/layoutengine/testcases/footnote_space-resolution.xml @@ -0,0 +1,58 @@ + + + + + +

+ This test checks space-resolution inside the footnotes area. +

+
+ + + + + + + + + + region-body + 1 + + + 1I'm a footnote! + + + blah + 2 + + + 2I'm a footnote! + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/inline_alignment-adjust_1.xml b/test/layoutengine/testcases/inline_alignment-adjust_1.xml index ac6a6233f..1ad390a53 100755 --- a/test/layoutengine/testcases/inline_alignment-adjust_1.xml +++ b/test/layoutengine/testcases/inline_alignment-adjust_1.xml @@ -86,22 +86,22 @@ + - - - + + + + + + + + + + + - - - - - - - - - - - - + + + diff --git a/test/layoutengine/testcases/inline_alignment-adjust_2.xml b/test/layoutengine/testcases/inline_alignment-adjust_2.xml index fd21545b2..d8d766e50 100755 --- a/test/layoutengine/testcases/inline_alignment-adjust_2.xml +++ b/test/layoutengine/testcases/inline_alignment-adjust_2.xml @@ -53,6 +53,13 @@ + + + + + + + @@ -60,39 +67,32 @@ - - - - - - - - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/test/layoutengine/testcases/inline_alignment-baseline_1.xml b/test/layoutengine/testcases/inline_alignment-baseline_1.xml index 128fd6b00..9b514c7f4 100755 --- a/test/layoutengine/testcases/inline_alignment-baseline_1.xml +++ b/test/layoutengine/testcases/inline_alignment-baseline_1.xml @@ -86,22 +86,22 @@ + - - - + + + + + + + + + + + - - - - - - - - - - - - + + + diff --git a/test/layoutengine/testcases/inline_alignment-baseline_2.xml b/test/layoutengine/testcases/inline_alignment-baseline_2.xml index f5559f435..591ee2c9b 100755 --- a/test/layoutengine/testcases/inline_alignment-baseline_2.xml +++ b/test/layoutengine/testcases/inline_alignment-baseline_2.xml @@ -86,55 +86,55 @@ + + + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/test/layoutengine/testcases/inline_alignment-baseline_3.xml b/test/layoutengine/testcases/inline_alignment-baseline_3.xml index 77cc07167..3d32b3595 100755 --- a/test/layoutengine/testcases/inline_alignment-baseline_3.xml +++ b/test/layoutengine/testcases/inline_alignment-baseline_3.xml @@ -86,22 +86,22 @@ + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/inline_alignment-baseline_4.xml b/test/layoutengine/testcases/inline_alignment-baseline_4.xml index 794c81e5a..4268c1239 100755 --- a/test/layoutengine/testcases/inline_alignment-baseline_4.xml +++ b/test/layoutengine/testcases/inline_alignment-baseline_4.xml @@ -132,6 +132,15 @@ + + + + + + + + + @@ -141,91 +150,82 @@ + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - + + + + + + + + diff --git a/test/layoutengine/testcases/inline_background-color.xml b/test/layoutengine/testcases/inline_background-color.xml index 7b5fcdb03..ee56f58ed 100755 --- a/test/layoutengine/testcases/inline_background-color.xml +++ b/test/layoutengine/testcases/inline_background-color.xml @@ -82,51 +82,51 @@ + + + - - - - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/test/layoutengine/testcases/inline_baseline-shift_1.xml b/test/layoutengine/testcases/inline_baseline-shift_1.xml index 723abfc9d..591e33756 100755 --- a/test/layoutengine/testcases/inline_baseline-shift_1.xml +++ b/test/layoutengine/testcases/inline_baseline-shift_1.xml @@ -98,67 +98,67 @@ - + + + + + + + + - + - + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - + + + + + + diff --git a/test/layoutengine/testcases/inline_baseline-shift_2.xml b/test/layoutengine/testcases/inline_baseline-shift_2.xml index 6bc6d60bc..5e7b276b7 100755 --- a/test/layoutengine/testcases/inline_baseline-shift_2.xml +++ b/test/layoutengine/testcases/inline_baseline-shift_2.xml @@ -111,61 +111,62 @@ - + + + + + + + + + + - + - - - + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/inline_baseline-shift_3.xml b/test/layoutengine/testcases/inline_baseline-shift_3.xml index eee8906b7..10f745a18 100755 --- a/test/layoutengine/testcases/inline_baseline-shift_3.xml +++ b/test/layoutengine/testcases/inline_baseline-shift_3.xml @@ -135,76 +135,76 @@ - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/layoutengine/testcases/inline_baseline-shift_4.xml b/test/layoutengine/testcases/inline_baseline-shift_4.xml index 87055ac0e..c0ade7fbe 100755 --- a/test/layoutengine/testcases/inline_baseline-shift_4.xml +++ b/test/layoutengine/testcases/inline_baseline-shift_4.xml @@ -121,64 +121,64 @@ + + + + + + + + - - + + - + - - - - - - - - - + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + diff --git a/test/layoutengine/testcases/inline_border_padding.xml b/test/layoutengine/testcases/inline_border_padding.xml index 08cabc67c..609a09625 100644 --- a/test/layoutengine/testcases/inline_border_padding.xml +++ b/test/layoutengine/testcases/inline_border_padding.xml @@ -59,82 +59,82 @@ - - - - - - - + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/inline_border_padding_block_nested_1.xml b/test/layoutengine/testcases/inline_border_padding_block_nested_1.xml index a3d9e9e4e..fc26c2b8f 100755 --- a/test/layoutengine/testcases/inline_border_padding_block_nested_1.xml +++ b/test/layoutengine/testcases/inline_border_padding_block_nested_1.xml @@ -62,65 +62,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/inline_border_padding_block_nested_2.xml b/test/layoutengine/testcases/inline_border_padding_block_nested_2.xml index c7e9210f0..345a2c4c3 100755 --- a/test/layoutengine/testcases/inline_border_padding_block_nested_2.xml +++ b/test/layoutengine/testcases/inline_border_padding_block_nested_2.xml @@ -1,168 +1,168 @@ - - - - - -

- This test checks fo:inlines with border and padding properties and nested inner blocks. -

-
- - - - - - - - - - - Before inline - starting with a block - after block - After inline with conditionality="retain" - - - Before inline - before block - having a block at the end of an inline - After inline with conditionality="retain" - - - Before inline - before block - As far as the laws of mathematics refer to reality, they are not certain, - and as far as they are certain, they do not refer to reality - Albert Einstein - after block - After inline with conditionality="retain" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ + + + + +

+ This test checks fo:inlines with border and padding properties and nested inner blocks. +

+
+ + + + + + + + + + + Before inline + starting with a block + after block + After inline with conditionality="retain" + + + Before inline + before block + having a block at the end of an inline + After inline with conditionality="retain" + + + Before inline + before block + As far as the laws of mathematics refer to reality, they are not certain, + and as far as they are certain, they do not refer to reality - Albert Einstein + after block + After inline with conditionality="retain" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/inline_border_padding_conditionality_1.xml b/test/layoutengine/testcases/inline_border_padding_conditionality_1.xml index 744b6b33f..86284f868 100755 --- a/test/layoutengine/testcases/inline_border_padding_conditionality_1.xml +++ b/test/layoutengine/testcases/inline_border_padding_conditionality_1.xml @@ -155,6 +155,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -189,210 +223,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + - - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/layoutengine/testcases/inline_border_padding_conditionality_2.xml b/test/layoutengine/testcases/inline_border_padding_conditionality_2.xml index bb9b50ab5..3e2d4a9b9 100755 --- a/test/layoutengine/testcases/inline_border_padding_conditionality_2.xml +++ b/test/layoutengine/testcases/inline_border_padding_conditionality_2.xml @@ -128,6 +128,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -158,154 +188,124 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/inline_border_padding_hyphenate.xml b/test/layoutengine/testcases/inline_border_padding_hyphenate.xml index b2a0444ad..d55fdc934 100755 --- a/test/layoutengine/testcases/inline_border_padding_hyphenate.xml +++ b/test/layoutengine/testcases/inline_border_padding_hyphenate.xml @@ -156,6 +156,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -182,218 +208,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + - - + + + + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/test/layoutengine/testcases/inline_border_padding_hyphenate_de.xml b/test/layoutengine/testcases/inline_border_padding_hyphenate_de.xml index 06bfae0ea..48750c06e 100755 --- a/test/layoutengine/testcases/inline_border_padding_hyphenate_de.xml +++ b/test/layoutengine/testcases/inline_border_padding_hyphenate_de.xml @@ -156,6 +156,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -182,218 +208,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + - - + + + + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/test/layoutengine/testcases/inline_dominant-baseline_1.xml b/test/layoutengine/testcases/inline_dominant-baseline_1.xml index 550bca8cb..e812bc387 100755 --- a/test/layoutengine/testcases/inline_dominant-baseline_1.xml +++ b/test/layoutengine/testcases/inline_dominant-baseline_1.xml @@ -65,64 +65,64 @@ + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + + + + + - - - - - + + + + + diff --git a/test/layoutengine/testcases/inline_dominant-baseline_2.xml b/test/layoutengine/testcases/inline_dominant-baseline_2.xml index 1d863bfc1..f382e8aa3 100755 --- a/test/layoutengine/testcases/inline_dominant-baseline_2.xml +++ b/test/layoutengine/testcases/inline_dominant-baseline_2.xml @@ -65,64 +65,64 @@ + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + + + + + - - - - - + + + + + diff --git a/test/layoutengine/testcases/inline_dominant-baseline_3.xml b/test/layoutengine/testcases/inline_dominant-baseline_3.xml index 8b1056f62..4d09ad57b 100755 --- a/test/layoutengine/testcases/inline_dominant-baseline_3.xml +++ b/test/layoutengine/testcases/inline_dominant-baseline_3.xml @@ -80,36 +80,36 @@ + + + + + + + + - + - - - - - - - - - - - - - - - + + + + + + + - - - - - - - + + + + + + + diff --git a/test/layoutengine/testcases/inline_vertical-align_1.xml b/test/layoutengine/testcases/inline_vertical-align_1.xml index 1ff5ca2f1..457b4a898 100755 --- a/test/layoutengine/testcases/inline_vertical-align_1.xml +++ b/test/layoutengine/testcases/inline_vertical-align_1.xml @@ -68,6 +68,13 @@ + + + + + + + @@ -75,74 +82,67 @@ + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/layoutengine/testcases/inline_vertical-align_2.xml b/test/layoutengine/testcases/inline_vertical-align_2.xml index 53749b355..64d401957 100755 --- a/test/layoutengine/testcases/inline_vertical-align_2.xml +++ b/test/layoutengine/testcases/inline_vertical-align_2.xml @@ -70,52 +70,52 @@ - + + + + + + + + + + + + + - + - - - - - + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/layoutengine/testcases/leader_border_padding.xml b/test/layoutengine/testcases/leader_border_padding.xml index 6c0c99a75..aa89bcbfa 100755 --- a/test/layoutengine/testcases/leader_border_padding.xml +++ b/test/layoutengine/testcases/leader_border_padding.xml @@ -141,116 +141,116 @@ + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/list-block_border_padding.xml b/test/layoutengine/testcases/list-block_border_padding.xml index 88bd983b1..c26d2a2bc 100644 --- a/test/layoutengine/testcases/list-block_border_padding.xml +++ b/test/layoutengine/testcases/list-block_border_padding.xml @@ -66,124 +66,124 @@ - + - - - - - - - - - - + + + + + + + + + + - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - + - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - + diff --git a/test/layoutengine/testcases/list-block_space-before_space-after_1.xml b/test/layoutengine/testcases/list-block_space-before_space-after_1.xml new file mode 100644 index 000000000..82af9d20d --- /dev/null +++ b/test/layoutengine/testcases/list-block_space-before_space-after_1.xml @@ -0,0 +1,221 @@ + + + + + +

+ This test checks spaces on tables. +

+
+ + + + + + + + + + + + + • + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + • + + + here is text in the list item body + + + + +Two blocks, testing conditionality="retain". + + + + + + + + + • + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + • + + + here is text in the list item body + + + + +Two blocks, testing conditionality="discard". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + 8 + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/list-block_space-before_space-after_2.xml b/test/layoutengine/testcases/list-block_space-before_space-after_2.xml new file mode 100644 index 000000000..293faebd8 --- /dev/null +++ b/test/layoutengine/testcases/list-block_space-before_space-after_2.xml @@ -0,0 +1,114 @@ + + + + + +

+ This test checks lists. Checks space-before and space-after on list-block. +

+
+ + + + + + + + + + test + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + • + + + here is text in the list item body + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + +
diff --git a/test/layoutengine/testcases/list-item_space-before_space-after_1.xml b/test/layoutengine/testcases/list-item_space-before_space-after_1.xml index 31aea6ecc..6e55cf008 100644 --- a/test/layoutengine/testcases/list-item_space-before_space-after_1.xml +++ b/test/layoutengine/testcases/list-item_space-before_space-after_1.xml @@ -82,19 +82,32 @@ + + + + + + + + + + + + + 3 diff --git a/test/layoutengine/testcases/list-item_space-before_space-after_2.xml b/test/layoutengine/testcases/list-item_space-before_space-after_2.xml index 855046352..15e501324 100644 --- a/test/layoutengine/testcases/list-item_space-before_space-after_2.xml +++ b/test/layoutengine/testcases/list-item_space-before_space-after_2.xml @@ -89,21 +89,37 @@ instead of optimum and the addAreas stage doesn't create smaller space-before/after spacers. --> + + + + - + + + - + + + - + + - + + + + - + + + + + 3 diff --git a/test/layoutengine/testcases/list-item_space-before_space-after_3.xml b/test/layoutengine/testcases/list-item_space-before_space-after_3.xml new file mode 100644 index 000000000..6b8a81a65 --- /dev/null +++ b/test/layoutengine/testcases/list-item_space-before_space-after_3.xml @@ -0,0 +1,73 @@ + + + + + +

+ This test checks lists. Checks spaces inside list-item content. +

+

+ Some additional code is notify the LMs about the effective spaces, otherwise discardable spaces don't get discarded. +

+
+ + + + + + + + + + + + + • + + + here is text in the list item body + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + +
diff --git a/test/layoutengine/testcases/page-breaking_2.xml b/test/layoutengine/testcases/page-breaking_2.xml index 3fa18cd28..cc1797f84 100644 --- a/test/layoutengine/testcases/page-breaking_2.xml +++ b/test/layoutengine/testcases/page-breaking_2.xml @@ -31,7 +31,10 @@ - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/page-number-citation_vertical-align.xml b/test/layoutengine/testcases/page-number-citation_vertical-align.xml index be9bbb707..b8f5315a1 100755 --- a/test/layoutengine/testcases/page-number-citation_vertical-align.xml +++ b/test/layoutengine/testcases/page-number-citation_vertical-align.xml @@ -50,10 +50,10 @@ + - - - - + + + diff --git a/test/layoutengine/testcases/page-number_border_padding.xml b/test/layoutengine/testcases/page-number_border_padding.xml index c099d1c1e..cffa2eda1 100755 --- a/test/layoutengine/testcases/page-number_border_padding.xml +++ b/test/layoutengine/testcases/page-number_border_padding.xml @@ -47,52 +47,52 @@ + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/test/layoutengine/testcases/page-number_vertical-align.xml b/test/layoutengine/testcases/page-number_vertical-align.xml index f436bbd30..a4605027a 100755 --- a/test/layoutengine/testcases/page-number_vertical-align.xml +++ b/test/layoutengine/testcases/page-number_vertical-align.xml @@ -50,10 +50,10 @@ + - - - - + + + diff --git a/test/layoutengine/testcases/region_side_space-resolution.xml b/test/layoutengine/testcases/region_side_space-resolution.xml new file mode 100644 index 000000000..912fa6e16 --- /dev/null +++ b/test/layoutengine/testcases/region_side_space-resolution.xml @@ -0,0 +1,63 @@ + + + + + +

+ This test checks if space resolution works in side regions. +

+
+ + + + + + + + + + + line 1 + line 2 + + + region-body + + + + + + + + + + + + + + + + + 3 + + + + + + + +
diff --git a/test/layoutengine/testcases/table-cell_block_margin_percentage.xml b/test/layoutengine/testcases/table-cell_block_margin_percentage.xml index d791e965f..18a041c20 100644 --- a/test/layoutengine/testcases/table-cell_block_margin_percentage.xml +++ b/test/layoutengine/testcases/table-cell_block_margin_percentage.xml @@ -57,12 +57,14 @@ - - - - - - + + + + + + + + diff --git a/test/layoutengine/testcases/table-cell_border_padding_conditionality.xml b/test/layoutengine/testcases/table-cell_border_padding_conditionality.xml new file mode 100644 index 000000000..f3a189219 --- /dev/null +++ b/test/layoutengine/testcases/table-cell_border_padding_conditionality.xml @@ -0,0 +1,128 @@ + + + + + +

+ This test checks border and padding conditionality on table. +

+
+ + + + + + + + + + + + + + + + cell1 + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + + + + + + + + + + + cell1 + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/table_border_padding_2.xml b/test/layoutengine/testcases/table_border_padding_2.xml new file mode 100644 index 000000000..cea526998 --- /dev/null +++ b/test/layoutengine/testcases/table_border_padding_2.xml @@ -0,0 +1,203 @@ + + + + + +

+ This test checks border and padding conditionality on table. +

+
+ + + + + + + + + + + + + + + + cell1 + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + + + + + + + + + + + cell1 + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + 8 + 8 + 8 + 8 + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/table_margin_space-before_space-after.xml b/test/layoutengine/testcases/table_margin_space-before_space-after.xml index c1b37fafb..ddf51a9f2 100644 --- a/test/layoutengine/testcases/table_margin_space-before_space-after.xml +++ b/test/layoutengine/testcases/table_margin_space-before_space-after.xml @@ -16,99 +16,99 @@ --> - -

+ +

This test checks basic tables. Tests table spaces and margins.

-
- - - - - - - - - - before table - - - - - - - cell1 - - - cell2 - - - - - cell3 - - - cell4 - - - - - after table - - + + + + + + + + + + + before table + + + + + + + cell1 + + + cell2 + + + + + cell3 + + + cell4 + + + + + after table + + reference block - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/table_space-before_space-after_1.xml b/test/layoutengine/testcases/table_space-before_space-after_1.xml new file mode 100644 index 000000000..430d8689a --- /dev/null +++ b/test/layoutengine/testcases/table_space-before_space-after_1.xml @@ -0,0 +1,203 @@ + + + + + +

+ This test checks space properties on table. +

+
+ + + + + + + + + + + + + + + + cell1 + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + +Two blocks, testing conditionality="retain". + + + + + + + + + + + + cell1 + + + +In olden times when wishing still helped one, there lived a king whose daughters +were all beautiful; and the youngest was so beautiful that the sun itself, which +has seen so much, was astonished whenever it shone in her face. Close by the king's +castle lay a great dark forest, and under an old lime-tree in the forest was a well, +and when the day was very warm, the king's child went out into the forest and sat +down by the side of the cool fountain; and when she was bored she took a golden ball, +and threw it up on high and caught it; and this ball was her favorite plaything. + + + + + + +Two blocks, testing conditionality="discard". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + 8 + 8 + 8 + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/table_space-before_space-after_2.xml b/test/layoutengine/testcases/table_space-before_space-after_2.xml new file mode 100644 index 000000000..310c1135a --- /dev/null +++ b/test/layoutengine/testcases/table_space-before_space-after_2.xml @@ -0,0 +1,104 @@ + + + + + +

+ This test checks space properties on table. Demonstrates that spaces are repeated on every generated area. +

+
+ + + + + + + + + + + + + + + + cell1 + + + line 1 + line 2 + line 3 + line 4 + line 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + +
diff --git a/test/layoutengine/testcases/table_table-layout_fixed_1.xml b/test/layoutengine/testcases/table_table-layout_fixed_1.xml index 50c2ab834..7d1ebbaad 100644 --- a/test/layoutengine/testcases/table_table-layout_fixed_1.xml +++ b/test/layoutengine/testcases/table_table-layout_fixed_1.xml @@ -94,16 +94,16 @@ - + - - - - - - - - + + + + + + + + -- 2.39.5