import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
-import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonMarginInline;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fo.properties.LengthRangeProperty;
/** used for FO validation */
private boolean blockItemFound;
- private CommonFont commonFont;
/**
* Creates a new instance.
@Override
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
- commonFont = pList.getFontProps(); // TODO get directly from parent?
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
return false;
}
- public CommonFont getCommonFont() {
- return commonFont;
+ @Override
+ public boolean generatesReferenceAreas() {
+ return true;
}
}
&& isFinished());
}
+ public boolean hasLineAreaDescendant() {
+ if (childLMs == null || childLMs.isEmpty()) {
+ return false;
+ } else {
+ for (LayoutManager childLM : childLMs) {
+ if (childLM.hasLineAreaDescendant()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public int getBaselineOffset() {
+ if (childLMs != null) {
+ for (LayoutManager childLM : childLMs) {
+ if (childLM.hasLineAreaDescendant()) {
+ return childLM.getBaselineOffset();
+ }
+ }
+ }
+ throw newNoLineAreaDescendantException();
+ }
+
+ protected IllegalStateException newNoLineAreaDescendantException() {
+ return new IllegalStateException("getBaselineOffset called on an object that has no line-area descendant");
+ }
+
/**
* Transfers foreign attributes from the formatting object to the area.
* @param targetArea the area to set the attributes on
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.flow.BlockContainer;
import org.apache.fop.fo.properties.CommonAbsolutePosition;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
/**
* LayoutManager for a block-container FO.
*/
-public class BlockContainerLayoutManager extends BlockStackingLayoutManager implements
- ConditionalElementListener, BreakOpportunity {
+public class BlockContainerLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
+ implements BreakOpportunity {
/**
* logging instance
private MinOptMax foBlockSpaceBefore;
private MinOptMax foBlockSpaceAfter;
- private boolean discardBorderBefore;
- private boolean discardBorderAfter;
- private boolean discardPaddingBefore;
- private boolean discardPaddingAfter;
- private MinOptMax effSpaceBefore;
- private MinOptMax effSpaceAfter;
-
private int horizontalOverflow;
private double contentRectOffsetX = 0;
private double contentRectOffsetY = 0;
.spaceAfter.getSpace().getOptimum(this).getLength().getValue(this);
}
+ @Override
+ protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+ return getBlockContainerFO().getCommonBorderPaddingBackground();
+ }
+
private void resetSpaces() {
this.discardBorderBefore = false;
this.discardBorderAfter = false;
return true;
}
- /** {@inheritDoc} */
- 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;
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
/** {@inheritDoc} */
public boolean handleOverflow(int milliPoints) {
if (milliPoints > this.horizontalOverflow) {
import org.apache.fop.area.LineArea;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
/**
* LayoutManager for a block FO.
*/
-public class BlockLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener,
- BreakOpportunity {
+public class BlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
+ implements BreakOpportunity {
/** logging instance */
private static Log log = LogFactory.getLog(BlockLayoutManager.class);
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;
-
/**
* Creates a new BlockLayoutManager.
* @param inBlock the block FO object to create the layout manager for.
.getOptimum(this).getLength().getValue(this);
}
+ @Override
+ protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+ return getBlockFO().getCommonBorderPaddingBackground();
+ }
+
/** {@inheritDoc} */
@Override
public List getNextKnuthElements(LayoutContext context, int alignment) {
return true;
}
- /** {@inheritDoc} */
- 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;
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
/** {@inheritDoc} */
@Override
public boolean isRestartable() {
*/
List getChangedKnuthElements(List oldList, int alignment);
+ /**
+ * Whether the FO handled by this layout manager had a descendant (including itself)
+ * that will generate a line-area.
+ *
+ * @return {@code true} if a descendant line-area will be generated, {@code false} otherwise
+ */
+ boolean hasLineAreaDescendant();
+
+ /**
+ * Returns the position of the dominant-baseline of this FO's first descendant
+ * line-area, if any.
+ *
+ * @return this FO's space-before plus the distance from the before-edge of its
+ * allocation-rectangle to the dominant-baseline of the first line-area descendant
+ */
+ int getBaselineOffset();
+
/**
* Returns the IPD of the content area
* @return the IPD of the content area
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.fo.FObj;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.traits.MinOptMax;
+
+/**
+ * A block-stacking layout manager for an FO that supports spaces, border and padding.
+ */
+public abstract class SpacedBorderedPaddedBlockLayoutManager extends BlockStackingLayoutManager
+ implements ConditionalElementListener {
+
+ private static final Log LOG = LogFactory.getLog(BlockLayoutManager.class);
+
+ protected MinOptMax effSpaceBefore;
+
+ protected MinOptMax effSpaceAfter;
+
+ protected boolean discardBorderBefore;
+ protected boolean discardBorderAfter;
+ protected boolean discardPaddingBefore;
+ protected boolean discardPaddingAfter;
+
+ public SpacedBorderedPaddedBlockLayoutManager(FObj node) {
+ super(node);
+ }
+
+ 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;
+ }
+ }
+
+ 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);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ @Override
+ public int getBaselineOffset() {
+ int baselineOffset = super.getBaselineOffset();
+ if (effSpaceBefore != null) {
+ baselineOffset += effSpaceBefore.getOpt();
+ }
+ if (!discardBorderBefore) {
+ baselineOffset += getCommonBorderPaddingBackground().getBorderBeforeWidth(false);
+ }
+ if (!discardPaddingBefore) {
+ baselineOffset += getCommonBorderPaddingBackground().getPaddingBefore(false, this);
+ }
+ return baselineOffset;
+ }
+
+ /**
+ * Returns the {@link CommonBorderPaddingBackground} instance from the FO handled by this layout manager.
+ */
+ protected abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground();
+
+}
return parentLM.getPSLM();
}
+
+ public boolean hasLineAreaDescendant() {
+ return true;
+ }
+
+ public int getBaselineOffset() {
+ return childLM.getBaselineOffset();
+ }
+
// --------- Property Resolution related functions --------- //
/**
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.LengthRangeProperty;
import org.apache.fop.fo.properties.Property;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.AbstractLayoutManager;
import org.apache.fop.layoutmgr.AreaAdditionUtil;
import org.apache.fop.layoutmgr.BlockLevelEventProducer;
private List<ListElement> childElements;
private int ipdOverflow;
+ private AlignmentContext alignmentContext;
private InlineViewport currentViewport;
private Container referenceArea;
childLC.setRefIPD(contentAreaIPD);
childElements = getChildKnuthElements(childLC, alignment); // TODO which alignment?
determineBPD();
- AlignmentContext alignmentContext = makeAlignmentContext(context); // TODO correct?
+ alignmentContext = makeAlignmentContext(context); // TODO correct?
Position position = new Position(this, 0);
KnuthSequence knuthSequence = new InlineKnuthSequence();
knuthSequence.add(new KnuthInlineBox(contentAreaIPD, alignmentContext, position, false));
handleIPDOverflow();
wrapPositions(allChildElements);
SpaceResolver.resolveElementList(allChildElements);
+ SpaceResolver.performConditionalsNotification(allChildElements, 0, allChildElements.size() - 1, -1);
// TODO break-before, break-after
return allChildElements;
}
protected AlignmentContext makeAlignmentContext(LayoutContext context) {
InlineContainer ic = (InlineContainer) fobj;
- FontInfo fi = fobj.getFOEventHandler().getFontInfo();
- FontTriplet[] fontkeys = ic.getCommonFont().getFontState(fi);
- Font fs = fi.getFontInstance(fontkeys[0], ic.getCommonFont().fontSize.getValue(this));
- return new AlignmentContext(contentAreaBPD,
+ AlignmentContext ac = new AlignmentContext(contentAreaBPD,
ic.getAlignmentAdjust(), ic.getAlignmentBaseline(),
ic.getBaselineShift(), ic.getDominantBaseline(),
context.getAlignmentContext());
+ int baselineOffset = hasLineAreaDescendant() ? getBaselineOffset() : contentAreaBPD;
+ ac.resizeLine(contentAreaBPD, baselineOffset);
+ return ac;
}
private void handleIPDOverflow() {
return ((InlineContainer) fobj).getOverflow() != EN_ERROR_IF_OVERFLOW;
}
+ @Override
+ public boolean getGeneratesReferenceArea() {
+ return true;
+ }
+
@Override
public void addAreas(PositionIterator posIter, LayoutContext context) {
Position inlineContainerPosition = null;
assert inlineContainerPosition.getLM() == this;
}
assert inlineContainerPosition != null;
- SpaceResolver.performConditionalsNotification(childElements, 0, childElements.size() - 1, -1);
KnuthPossPosIter childPosIter = new KnuthPossPosIter(childElements);
AreaAdditionUtil.addAreas(this, childPosIter, context);
TraitSetter.setProducerID(referenceArea, fobj.getId());
referenceArea.setIPD(contentAreaIPD);
currentViewport = new InlineViewport(referenceArea);
+ currentViewport.setBlockProgressionOffset(alignmentContext.getOffset());
currentViewport.addTrait(Trait.IS_VIEWPORT_AREA, Boolean.TRUE);
currentViewport.setIPD(getContentAreaIPD());
currentViewport.setBPD(getContentAreaBPD());
private final int follow;
private AlignmentContext alignmentContext;
+ private int baselineOffset = -1;
+
private List<KnuthSequence> knuthParagraphs;
private LineLayoutPossibilities lineLayouts;
private int constantLineHeight = 12000;
-
/**
* Create a new Line Layout Manager.
* This is used by the block layout manager to create
while (listIter.hasNext()) {
ListElement tempElement;
tempElement = (ListElement) listIter.next();
- if (tempElement.getLayoutManager() != this) {
+ LayoutManager lm = tempElement.getLayoutManager();
+ if (baselineOffset < 0 && lm != null && lm.hasLineAreaDescendant()) {
+ baselineOffset = lm.getBaselineOffset();
+ }
+ if (lm != this) {
tempElement.setPosition(notifyPos(new NonLeafPosition(this,
tempElement.getPosition())));
}
}
startIndex = endIndex + 1;
LineBreakPosition lbp = (LineBreakPosition) llPoss.getChosenPosition(i);
+ if (baselineOffset < 0) {
+ baselineOffset = lbp.spaceBefore + lbp.baseline;
+ }
returnList.add(new KnuthBlockBox(
lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
footnoteList, lbp, false));
}
}
+ @Override
+ public boolean hasLineAreaDescendant() {
+ return true;
+ }
+
+ @Override
+ public int getBaselineOffset() {
+ return baselineOffset;
+ }
+
/**
* Add the areas with the break points.
*
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
-import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
-import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.RelSide;
+import org.apache.fop.layoutmgr.SpacedBorderedPaddedBlockLayoutManager;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
* A list block contains list items which are stacked within
* the list block area..
*/
-public class ListBlockLayoutManager extends BlockStackingLayoutManager
- implements ConditionalElementListener {
+public class ListBlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManager {
/** logging instance */
private static Log log = LogFactory.getLog(ListBlockLayoutManager.class);
private Block curBlockArea;
- private boolean discardBorderBefore;
- private boolean discardBorderAfter;
- private boolean discardPaddingBefore;
- private boolean discardPaddingAfter;
- private MinOptMax effSpaceBefore;
- private MinOptMax effSpaceAfter;
-
/**
* Create a new list block layout manager.
* @param node list-block to create the layout manager for
super(node);
}
+ @Override
+ protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+ return getListBlockFO().getCommonBorderPaddingBackground();
+ }
+
/**
* Convenience method.
* @return the ListBlock node
return getListBlockFO().getKeepWithNext();
}
- /** {@inheritDoc} */
- 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;
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
}
import org.apache.fop.fo.flow.ListItem;
import org.apache.fop.fo.flow.ListItemBody;
import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
-import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.BreakOpportunity;
import org.apache.fop.layoutmgr.BreakOpportunityHelper;
-import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.ElementListObserver;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.RelSide;
import org.apache.fop.layoutmgr.SpaceResolver;
+import org.apache.fop.layoutmgr.SpacedBorderedPaddedBlockLayoutManager;
import org.apache.fop.layoutmgr.TraitSetter;
-import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
import org.apache.fop.util.BreakUtil;
* LayoutManager for a list-item FO.
* The list item contains a list item label and a list item body.
*/
-public class ListItemLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener,
- BreakOpportunity {
+public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
+ implements BreakOpportunity {
/** logging instance */
private static Log log = LogFactory.getLog(ListItemLayoutManager.class);
private List<ListElement> labelList = null;
private List<ListElement> bodyList = null;
- private boolean discardBorderBefore;
- private boolean discardBorderAfter;
- private boolean discardPaddingBefore;
- private boolean discardPaddingAfter;
- private MinOptMax effSpaceBefore;
- private MinOptMax effSpaceAfter;
-
private Keep keepWithNextPendingOnLabel;
private Keep keepWithNextPendingOnBody;
setBody(node.getBody());
}
+ @Override
+ protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+ return getListItemFO().getCommonBorderPaddingBackground();
+ }
+
/**
* Convenience method.
* @return the ListBlock node
return returnedList;
}
+
+ @Override
+ public boolean hasLineAreaDescendant() {
+ return label.hasLineAreaDescendant() || body.hasLineAreaDescendant();
+ }
+
+ @Override
+ public int getBaselineOffset() {
+ if (label.hasLineAreaDescendant()) {
+ return label.getBaselineOffset();
+ } else if (body.hasLineAreaDescendant()) {
+ return body.getBaselineOffset();
+ } else {
+ throw newNoLineAreaDescendantException();
+ }
+ }
+
/**
* Add the areas for the break points.
*
return getListItemFO().getKeepWithNext();
}
- /** {@inheritDoc} */
- 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;
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
/** {@inheritDoc} */
@Override
public void reset() {
import org.apache.fop.fo.flow.RetrieveTableMarker;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.BlockLevelEventProducer;
-import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.BreakOpportunity;
-import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.RelSide;
+import org.apache.fop.layoutmgr.SpacedBorderedPaddedBlockLayoutManager;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
* The table then creates areas for the columns, bodies and rows
* the render background.
*/
-public class TableLayoutManager extends BlockStackingLayoutManager
- implements ConditionalElementListener, BreakOpportunity {
+public class TableLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
+ implements BreakOpportunity {
/**
* logging instance
private double tableUnit;
private boolean autoLayout = true;
- private boolean discardBorderBefore;
- private boolean discardBorderAfter;
- private boolean discardPaddingBefore;
- private boolean discardPaddingAfter;
- private MinOptMax effSpaceBefore;
- private MinOptMax effSpaceAfter;
-
private int halfBorderSeparationBPD;
private int halfBorderSeparationIPD;
this.columns = new ColumnSetup(node);
}
+
+ @Override
+ protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+ return getTable().getCommonBorderPaddingBackground();
+ }
+
+
/** @return the table FO */
public Table getTable() {
return (Table)this.fobj;
}
}
- /** {@inheritDoc} */
- 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;
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
- /** {@inheritDoc} */
- 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);
- }
- }
-
/** {@inheritDoc} */
public void reset() {
super.reset();
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+ <info>
+ <p>
+ Checks that the inline-container is properly aligned with the parent area.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="320pt" page-width="220pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>By default the alignment is with the baseline of the first descendant
+ line-area.</fo:block>
+ <fo:block>The line before. The line before. Before: <fo:inline-container width="100pt">
+ <fo:block font-size="20pt">Inside the inline-container.</fo:block>
+ </fo:inline-container> After the inline-container.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>The line before. The line before. Before: <fo:inline-container width="100pt">
+ <fo:block space-before="20pt" space-before.conditionality="retain">
+ <fo:block-container space-before="10pt" space-before.conditionality="retain"
+ border="4pt solid" padding="2pt" start-indent="6pt" end-indent="6pt">
+ <fo:block font-size="20pt" start-indent="0" end-indent="0">Inside the
+ inline-container.</fo:block>
+ </fo:block-container>
+ </fo:block>
+ </fo:inline-container> After the inline-container.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>This inline-container has no line-area descendant. The after edge of its
+ allocation rectangle should be aligned with the baseline.</fo:block>
+ <fo:block>The line before. The line before. Before: <fo:inline-container width="100pt">
+ <fo:block border="6pt solid" padding="2pt" start-indent="8pt" end-indent="8pt"/>
+ </fo:inline-container> After the inline-container.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>The first line-area descendant is in fo:list-item-body.</fo:block>
+ <fo:block>The line before. The line before. Before: <fo:inline-container width="100pt">
+ <fo:list-block provisional-distance-between-starts="10pt"
+ provisional-label-separation="5pt">
+ <fo:list-item>
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block/>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block font-size="8pt">List item</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ </fo:inline-container> After the inline-container.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>This inline-container contains a block that contains an inline that contains a
+ block.</fo:block>
+ <fo:block>The line before. The line before. Before: <fo:inline-container width="100pt">
+ <fo:block><fo:inline><fo:block>inline</fo:block></fo:inline></fo:block>
+ </fo:inline-container> After the inline-container.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+
+ <checks>
+ <!-- Page sequence 1 -->
+ <eval expected="72000" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/@bpd"/>
+ <!--
+ The font used is Helvetica, ascender 718, descender −207.
+ Default font size is 12pt => baseline offset = 718 * 12 = 8616mpt
+ Default line height is 1.2 * font-size
+ => space-before = (line-height − (ascender − descender) * font-size) / 2
+ = (1.2 * 12000 − (718 + 207) * 12) / 2
+ = 1650
+ At font size 20, the distance between the before-edge of the inline-container’s child block
+ area and the first line area’s baseline is space-before + baseline-offset = 2750 + 14360 = 17110
+ So the word "Before:" must be offset by 17110 − 8616 = 8494
+ -->
+ <eval expected="Before: " xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/text[1]"/>
+ <eval expected="8494" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/text[1]/@offset"/>
+ <eval expected="8616" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/text[1]/@baseline"/>
+
+ <eval expected="72000" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/viewport/@bpd"/>
+ <eval expected="0" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/viewport/@offset"/>
+
+ <eval expected=" After the" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/text[2]"/>
+ <eval expected="8494" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/text[2]/@offset"/>
+ <eval expected="8616" xpath="//pageSequence[1]//flow/block[2]/lineArea[2]/text[2]/@baseline"/>
+
+ <!-- Page sequence 2 -->
+ <eval expected="34494" xpath="//pageSequence[2]//flow/block/lineArea[2]/text[1]/@offset"/>
+ <eval expected="8616" xpath="//pageSequence[2]//flow/block/lineArea[2]/text[1]/@baseline"/>
+ <eval expected="104000" xpath="//pageSequence[2]//flow/block/lineArea[2]/viewport/@bpd"/>
+ <eval expected="0" xpath="//pageSequence[2]//flow/block/lineArea[2]/viewport/@offset"/>
+
+ <!-- Page sequence 3 -->
+ <!-- bpd = max(text ascent, ascent of inline-container) + text descent
+ = 16000 + 207 * 12 -->
+ <eval expected="18484" xpath="//pageSequence[3]//flow/block[2]/lineArea[2]/@bpd"/>
+ <eval expected="7384" xpath="//pageSequence[3]//flow/block[2]/lineArea[2]/text[1]/@offset"/>
+ <eval expected="8616" xpath="//pageSequence[3]//flow/block[2]/lineArea[2]/text[1]/@baseline"/>
+ <eval expected="16000" xpath="//pageSequence[3]//flow/block[2]/lineArea[2]/viewport/@bpd"/>
+ <eval expected="0" xpath="//pageSequence[3]//flow/block[2]/lineArea[2]/viewport/@offset"/>
+
+ <!-- Page sequence 4 -->
+ <eval expected="11372" xpath="//pageSequence[4]//flow/block[2]/lineArea[2]/@bpd"/>
+ <eval expected="0" xpath="//pageSequence[4]//flow/block[2]/lineArea[2]/text[1]/@offset"/>
+ <eval expected="8616" xpath="//pageSequence[4]//flow/block[2]/lineArea[2]/text[1]/@baseline"/>
+ <eval expected="9600" xpath="//pageSequence[4]//flow/block[2]/lineArea[2]/viewport/@bpd"/>
+ <eval expected="1772" xpath="//pageSequence[4]//flow/block[2]/lineArea[2]/viewport/@offset"/>
+
+ <!-- Page sequence 5 -->
+ <eval expected="14400" xpath="//pageSequence[5]//flow/block[2]/lineArea[2]/@bpd"/>
+ <eval expected="1650" xpath="//pageSequence[5]//flow/block[2]/lineArea[2]/text[1]/@offset"/>
+ <eval expected="8616" xpath="//pageSequence[5]//flow/block[2]/lineArea[2]/text[1]/@baseline"/>
+ <eval expected="14400" xpath="//pageSequence[5]//flow/block[2]/lineArea[2]/viewport/@bpd"/>
+ <eval expected="0" xpath="//pageSequence[5]//flow/block[2]/lineArea[2]/viewport/@offset"/>
+ </checks>
+</testcase>