From: Jeremias Maerki Date: Thu, 13 Oct 2005 18:04:49 +0000 (+0000) Subject: My space resolution work so far. Current issues: X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=873b55852897443ed83d42166cfabe7270bf945c;p=xmlgraphics-fop.git My space resolution work so far. Current issues: - no space resolution for tables, yet. - spaces inside list-item-labels and list-item-body to properly set up for addAreas stage. - conditional lengths on lists not checked, yet. - block w=0 causes a fence right now although it shouldn't. - no space resolution due to space-before and space-after caused by the line-height property (I've totally skipped that for now) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_SpaceResolution@320837 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 74df8e188..991b363f8 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -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); @@ -328,7 +329,7 @@ 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()) @@ -377,6 +378,11 @@ public abstract class AbstractBreaker { } /* *** *** non-standard extension *** *** */ + // Handle SpaceHandling(Break)Positions, see SpaceResolver! + performConditionalsNotification(effectiveList, + startElementIndex, endElementIndex, lastBreak); + + // Add areas now! addAreas(new KnuthPossPosIter(effectiveList, startElementIndex, endElementIndex + 1), childLC); } else { @@ -386,9 +392,54 @@ 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 + */ + private void performConditionalsNotification(BlockSequence effectiveList, + int startElementIndex, int endElementIndex, int lastBreak) { + KnuthElement el = null; + if (lastBreak > 0) { + el = effectiveList.getElement(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 = effectiveList.getElement(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 = effectiveList.getElement(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); + } + } + } + } /** * Handles span changes reported through the LayoutContext. diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java index 44ad1496b..8093ee071 100644 --- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java +++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java @@ -21,6 +21,8 @@ package org.apache.fop.layoutmgr; import java.util.Iterator; import java.util.LinkedList; +import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition; + public class AreaAdditionUtil { private static class StackingIter extends PositionIterator { @@ -52,6 +54,10 @@ public class AreaAdditionUtil { Position pos; while (parentIter.hasNext()) { pos = (Position)parentIter.next(); + if (pos == null) { + //positionList.add(new IgnorePosition(null)); + continue; + } if (pos.getIndex() >= 0) { if (firstPos == null) { firstPos = pos; @@ -65,6 +71,8 @@ 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 } diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 55dd12dde..a215ed6ed 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. @@ -111,6 +120,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 +169,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 +220,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { if (!bBreakBeforeServed) { try { - if (addKnuthElementsForBreakBefore(returnList)) { + if (addKnuthElementsForBreakBefore(returnList, context)) { return returnList; } } finally { @@ -217,10 +236,14 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { addKnuthElementsForBorderPaddingBefore(returnList); 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,9 +253,7 @@ 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 @@ -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; @@ -330,7 +353,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { } addKnuthElementsForBorderPaddingAfter(returnList); addKnuthElementsForSpaceAfter(returnList, alignment); - addKnuthElementsForBreakAfter(returnList); + addKnuthElementsForBreakAfter(returnList, context); setFinished(true); return returnList; @@ -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; } @@ -767,9 +790,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { } // if adjusted space before - if (bSpaceBefore) { - addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); - } +// if (bSpaceBefore) { +// addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); +// } + //addBlockSpacing(0, effSpaceBefore); while ((childLM = childPosIter.getNextChildLM()) != null) { // set last area flag @@ -781,9 +805,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { } } else { // if adjusted space before - if (bSpaceBefore) { - addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); - } +// if (bSpaceBefore) { +// addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); +// } + //addBlockSpacing(0, effSpaceBefore); //Add child areas inside the reference area bcpos.getBreaker().addContainedAreas(); } @@ -795,15 +820,19 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager { 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)); - } +// if (bSpaceAfter) { +// addBlockSpacing(0, new MinOptMax(adjustedSpaceAfter)); +// } + //addBlockSpacing(0, effSpaceAfter); viewportBlockArea = null; referenceArea = null; + resetSpaces(); } /** @@ -826,7 +855,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); @@ -982,6 +1015,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..11ca67d03 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 @@ -362,8 +385,9 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { } // if adjusted space before - double adjust = layoutContext.getSpaceAdjust(); - addBlockSpacing(adjust, foSpaceBefore); + //double adjust = layoutContext.getSpaceAdjust(); + //addBlockSpacing(adjust, foSpaceBefore); + //addBlockSpacing(adjust, effSpaceBefore); foSpaceBefore = null; //if (bSpaceBefore) { // addBlockSpacing(0, new MinOptMax(adjustedSpaceBefore)); @@ -385,15 +409,19 @@ public class BlockLayoutManager extends BlockStackingLayoutManager { getCurrentPV().addMarkers(markers, false, isFirst(firstPos), isLast(lastPos)); } + TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), + effSpaceBefore, effSpaceAfter); flush(); // if adjusted space after - addBlockSpacing(adjust, foSpaceAfter); + //addBlockSpacing(adjust, foSpaceAfter); + //addBlockSpacing(adjust, effSpaceAfter); //if (bSpaceAfter) { // addBlockSpacing(0, new MinOptMax(adjustedSpaceAfter)); //} curBlockArea = null; + resetSpaces(); } /** @@ -426,7 +454,11 @@ 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(), @@ -533,6 +565,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..fb0df12cf 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -121,15 +121,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); @@ -232,7 +224,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (!bBreakBeforeServed) { try { - if (addKnuthElementsForBreakBefore(returnList)) { + if (addKnuthElementsForBreakBefore(returnList, context)) { return returnList; } } finally { @@ -246,9 +238,13 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } addKnuthElementsForBorderPaddingBefore(returnList); + + //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 @@ -311,17 +307,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 +335,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; @@ -382,7 +386,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager addKnuthElementsForBorderPaddingAfter(returnList); addKnuthElementsForSpaceAfter(returnList, alignment); - addKnuthElementsForBreakAfter(returnList); + addKnuthElementsForBreakAfter(returnList, context); if (mustKeepWithNext()) { context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); @@ -741,27 +745,143 @@ 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 { + 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 { + 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 { + 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) { + //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, true, false, this)); + } + if (borderAndPadding.getPaddingBefore(false, this) > 0) { + returnList.add(new PaddingElement( + getAuxiliaryPosition(), + borderAndPadding.getPaddingLengthProperty( + CommonBorderPaddingBackground.BEFORE), + RelSide.BEFORE, true, 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,29 @@ 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) { //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, true, this)); + } + if (borderAndPadding.getBorderAfterWidth(false) > 0) { + returnList.add(new BorderElement( + getAuxiliaryPosition(), + borderAndPadding.getBorderInfo(CommonBorderPaddingBackground.AFTER) + .getWidth(), RelSide.AFTER, false, true, 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 +920,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 +935,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 +950,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 +965,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 +982,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 +1006,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 +1015,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 +1031,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 +1053,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 +1062,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 +1449,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..d47e02148 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/BreakElement.java @@ -0,0 +1,127 @@ +/* + * 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 + } + + /** @return the penalty width */ + public int getPenaltyWidth() { + return this.penaltyWidth; + } + + /** @return the penalty value */ + public int getPenaltyValue() { + return this.penaltyValue; + } + + /** @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; + } + + /** @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..a606879ba 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -133,4 +133,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..fc52ce066 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -84,6 +84,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 +110,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 +124,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(returnedList)) { // a descendant of this flow has break-after + SpaceResolver.resolveElementList(returnList); return returnList; } } @@ -148,6 +148,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } } + SpaceResolver.resolveElementList(returnList); setFinished(true); if (returnList.size() > 0) { 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/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..e56b22b3e 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 @@ -424,6 +424,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..4faa92bde --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java @@ -0,0 +1,635 @@ +/* + * 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.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(first.size()); + while (iter.hasPrevious()) { + noBreak[i] = (UnresolvedListElementWithLength)iter.previous(); + 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) { + for (int i = 0; i < elems.length; i++) { + if (elems[i] instanceof BorderOrPaddingElement) { + BorderOrPaddingElement bop = (BorderOrPaddingElement)elems[i]; + if (bop.isConditional() && !(bop.isFirst() || bop.isLast())) { + if (log.isDebugEnabled()) { + log.debug("Nulling conditional element: " + bop); + } + lengths[i] = null; + } + } + } + if (log.isTraceEnabled() && elems.length > 0) { + log.trace("-->Resulting list: " + toString(elems, lengths)); + } + } + + private void performSpaceResolutionRule1(UnresolvedListElement[] elems, MinOptMax[] lengths) { + for (int i = 0; i < elems.length; i++) { + if (lengths[i] == null) { + //Zeroed border or padding doesn't create a fence + continue; + } else if (elems[i] instanceof BorderOrPaddingElement) { + //Border or padding form fences! + break; + } else if (!elems[i].isConditional()) { + break; + } + if (log.isDebugEnabled()) { + log.debug("Nulling conditional element using 4.3.1, rule 1: " + elems[i]); + } + lengths[i] = 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 void resolve() { + if (breakPoss != null) { + if (firstPart != null) { + removeConditionalBorderAndPadding(firstPart, firstPartLengths); + performSpaceResolutionRule1(firstPart, firstPartLengths); + performSpaceResolutionRules2to3(firstPart, firstPartLengths); + } + if (secondPart != null) { + removeConditionalBorderAndPadding(secondPart, secondPartLengths); + performSpaceResolutionRule1(secondPart, secondPartLengths); + performSpaceResolutionRules2to3(secondPart, secondPartLengths); + } + if (noBreak != null) { + performSpaceResolutionRules2to3(noBreak, noBreakLengths); + } + } else { + if (isFirst || isLast) { + performSpaceResolutionRule1(secondPart, secondPartLengths); + 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; + + + 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), 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)); + } + if (isLast) { + //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; + + /** + * Main constructor. + * @param resolver the space resolver that provides the info about the actual situation + */ + public SpaceHandlingBreakPosition(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. + * @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++) { + if (resolver.noBreak[i] instanceof SpaceElement) { + resolver.noBreak[i].notifyLayoutManager(resolver.noBreakLengths[i]); + } + } + } + } + + /** @see java.lang.Object#toString() */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("SpaceHandlingBreakPosition"); + return sb.toString(); + } + } + + /** + * 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++) { + if (resolver.secondPart[i] instanceof SpaceElement) { + 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) { + //The first list is reversed, so swap if this shouldn't happen + List swapList = unresolvedSecond; + unresolvedSecond = unresolvedFirst; + unresolvedFirst = swapList; + } + //Need to reverse the order of the first part + //From here on further down, the first part in the unresolved list is + //always the one nearest to the break. + if (unresolvedFirst.size() > 0) { + Collections.reverse(unresolvedFirst); + } + + 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; + } + } + +} diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 949594beb..b77275fa0 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -287,9 +287,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 d95525380..d5cf5cc6b 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; @@ -636,7 +637,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) { @@ -973,9 +974,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 @@ -994,7 +996,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager setFinished(true); //Post-process the line breaks found - return postProcessLineBreaks(alignment); + return postProcessLineBreaks(alignment, context); } /** @@ -1137,17 +1139,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); @@ -1181,11 +1185,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..e2334819d 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>"); @@ -122,8 +148,8 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager { } // if adjusted space before - double adjust = layoutContext.getSpaceAdjust(); - addBlockSpacing(adjust, foSpaceBefore); + //double adjust = layoutContext.getSpaceAdjust(); + //addBlockSpacing(adjust, foSpaceBefore); foSpaceBefore = null; getPSLM().addIDToPage(getListBlockFO().getId()); @@ -184,13 +210,16 @@ 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); + //addBlockSpacing(adjust, foSpaceAfter); curBlockArea = null; + resetSpaces(); } /** @@ -217,7 +246,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 +311,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..184b6f01d 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); @@ -173,11 +189,20 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { bSpaceBeforeServed = true; } + //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 +213,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 +240,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 +292,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]}; @@ -423,9 +431,10 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager { getParentArea(null); // if adjusted space before - double adjust = layoutContext.getSpaceAdjust(); - addBlockSpacing(adjust, foSpaceBefore); - foSpaceBefore = null; + //double adjust = layoutContext.getSpaceAdjust(); + //addBlockSpacing(adjust, foSpaceBefore); + //addBlockSpacing(adjust, effSpaceBefore); + //foSpaceBefore = null; getPSLM().addIDToPage(getListItemFO().getId()); @@ -508,13 +517,17 @@ 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); + //addBlockSpacing(adjust, foSpaceAfter); + //addBlockSpacing(adjust, effSpaceAfter); curBlockArea = null; + resetSpaces(); } /** @@ -550,7 +563,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 +627,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..80a394f28 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,7 +45,8 @@ 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; @@ -82,6 +85,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement return fobj.isSeparateBorderModel(); } + /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */ public void initialize() { borderAndPaddingBPD = 0; borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground().getBorderBeforeWidth(false); @@ -89,8 +93,10 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement if (!isSeparateBorderModel()) { borderAndPaddingBPD /= 2; } - borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground().getPaddingBefore(false, this); - borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground().getPaddingAfter(false, this); + borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground() + .getPaddingBefore(false, this); + borderAndPaddingBPD += fobj.getCommonBorderPaddingBackground() + .getPaddingAfter(false, this); } /** @@ -159,8 +165,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 +181,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 +197,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 +219,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 +230,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement returnedList = new LinkedList(); wrapPositionElements(contentList, returnList); + //Space resolution + SpaceResolver.resolveElementList(returnList); + return returnList; } } @@ -234,6 +247,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager implement returnedList = new LinkedList(); wrapPositionElements(contentList, returnList); + //Space resolution + SpaceResolver.resolveElementList(returnList); + setFinished(true); return returnList; } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index fd4a81b58..f5c28dfe4 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -48,6 +48,7 @@ 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; /** @@ -589,10 +590,12 @@ public class TableContentLayoutManager implements PercentBaseContext { Position lastPos = null; while (parentIter.hasNext()) { Position pos = (Position)parentIter.next(); - if (firstPos == null) { - firstPos = pos; + if (!(pos instanceof SpaceHandlingBreakPosition)) { + if (firstPos == null) { + firstPos = pos; + } + lastPos = pos; } - lastPos = pos; if (pos instanceof TableHeaderFooterPosition) { TableHeaderFooterPosition thfpos = (TableHeaderFooterPosition)pos; //these positions need to be unpacked diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index cda906c9e..feedf8acf 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -28,6 +28,7 @@ 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.TraitSetter; @@ -114,7 +115,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager if (!bBreakBeforeServed) { try { - if (addKnuthElementsForBreakBefore(returnList)) { + if (addKnuthElementsForBreakBefore(returnList, context)) { return returnList; } } finally { @@ -205,8 +206,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager 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 +250,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,7 +266,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager } } wrapPositionElements(contentList, returnList); - addKnuthElementsForBreakAfter(returnList); + addKnuthElementsForBreakAfter(returnList, context); setFinished(true); return returnList; } diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 16c8f75ae..764427357 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/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 2c69eee68..b61e99f2c 100644 --- a/test/layoutengine/disabled-testcases.txt +++ b/test/layoutengine/disabled-testcases.txt @@ -17,7 +17,7 @@ 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 +list-item_space-before_space-after_3.xml page-breaking_4.xml page-breaking_6.xml page-height_indefinite_simple.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..ed4615b9a --- /dev/null +++ b/test/layoutengine/testcases/block-container_space-before_space-after_1.xml @@ -0,0 +1,162 @@ + + + + + +

+ 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_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..14944f232 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,96 @@ 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/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/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_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..7c5aedacd --- /dev/null +++ b/test/layoutengine/testcases/list-block_space-before_space-after_1.xml @@ -0,0 +1,223 @@ + + + + + +

+ This test checks lists. Checks for the presence of space-before and space-after on list-items. +

+
+ + + + + + + + + + + + + • + + + +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/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 @@ - - - - - - + + + + + + + +