]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Added support for default alignment of inline-container areas with their parent areas
authorVincent Hennebert <vhennebert@apache.org>
Wed, 6 Nov 2013 19:52:38 +0000 (19:52 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Wed, 6 Nov 2013 19:52:38 +0000 (19:52 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_InlineContainer@1539441 13f79535-47bb-0310-9956-ffa450edef68

13 files changed:
src/java/org/apache/fop/fo/flow/InlineContainer.java
src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/LayoutManager.java
src/java/org/apache/fop/layoutmgr/SpacedBorderedPaddedBlockLayoutManager.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/InlineContainerLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
test/layoutengine/standard-testcases/inline-container_alignment.xml [new file with mode: 0644]

index d3a80eb3f35d3dbad89667c307dfd591ec2652d8..13ea9943ac0de9d099183739e7424643d86d580c 100644 (file)
@@ -29,7 +29,6 @@ import org.apache.fop.fo.FObj;
 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;
@@ -59,7 +58,6 @@ public class InlineContainer extends FObj {
 
     /** used for FO validation */
     private boolean blockItemFound;
-    private CommonFont commonFont;
 
     /**
      * Creates a new instance.
@@ -73,7 +71,6 @@ public class InlineContainer extends FObj {
     @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();
@@ -214,8 +211,9 @@ public class InlineContainer extends FObj {
         return false;
     }
 
-    public CommonFont getCommonFont() {
-        return commonFont;
+    @Override
+    public boolean generatesReferenceAreas() {
+        return true;
     }
 
 }
index 0285a41e7fe3153fb900c754606058fa253ae5a7..2dd18e4ee381e5019d73d02fe214705fab5e3ad0 100644 (file)
@@ -342,6 +342,34 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im
                 && 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
index a23cd28f1c4ec574512d31a62beb14e1f74fdb79..83990797ba7b5830e3c8ff056ee6f6b83ad3c255 100644 (file)
@@ -37,6 +37,7 @@ import org.apache.fop.datatypes.FODimension;
 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;
@@ -44,8 +45,8 @@ 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
@@ -79,13 +80,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl
     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;
@@ -128,6 +122,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl
             .spaceAfter.getSpace().getOptimum(this).getLength().getValue(this);
     }
 
+    @Override
+    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+        return getBlockContainerFO().getCommonBorderPaddingBackground();
+    }
+
     private void resetSpaces() {
         this.discardBorderBefore = false;
         this.discardBorderAfter = false;
@@ -993,51 +992,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl
         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) {
index 0fb738aea446c0baccc3273be0dde1f3fa360e92..4129b65bd8cc02cbb2ee511865507d30c25f6c6f 100644 (file)
@@ -32,6 +32,7 @@ import org.apache.fop.area.Block;
 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;
@@ -44,8 +45,8 @@ import org.apache.fop.traits.SpaceVal;
 /**
  * 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);
@@ -60,13 +61,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co
     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.
@@ -100,6 +94,11 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co
                                     .getOptimum(this).getLength().getValue(this);
     }
 
+    @Override
+    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+        return getBlockFO().getCommonBorderPaddingBackground();
+    }
+
     /** {@inheritDoc} */
     @Override
     public List getNextKnuthElements(LayoutContext context, int alignment) {
@@ -456,51 +455,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co
         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() {
index 985131bf12eae1f9d283d1fb289f7bece2ec4027..107a252b02c6859e812e9e251ec80b2ba5e33545 100644 (file)
@@ -177,6 +177,23 @@ public interface LayoutManager extends PercentBaseContext {
      */
     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
diff --git a/src/java/org/apache/fop/layoutmgr/SpacedBorderedPaddedBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/SpacedBorderedPaddedBlockLayoutManager.java
new file mode 100644 (file)
index 0000000..2ac41e9
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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();
+
+}
index b3c768987fdbd06cf0600bf419d322347a4280ce..c067b040f9b6797513d7060ae4c2488226b18804 100644 (file)
@@ -332,6 +332,15 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager
         return parentLM.getPSLM();
     }
 
+
+    public boolean hasLineAreaDescendant() {
+        return true;
+    }
+
+    public int getBaselineOffset() {
+        return childLM.getBaselineOffset();
+    }
+
     // --------- Property Resolution related functions --------- //
 
     /**
index 75eb12d5b3df102ebfbc20d2d286975984fe16a8..9495e2c7317b38f1e73d0ebff5e35f54b960d098 100644 (file)
@@ -31,9 +31,6 @@ import org.apache.fop.fo.flow.InlineContainer;
 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;
@@ -64,6 +61,7 @@ public class InlineContainerLayoutManager extends AbstractLayoutManager implemen
 
     private List<ListElement> childElements;
     private int ipdOverflow;
+    private AlignmentContext alignmentContext;
     private InlineViewport currentViewport;
     private Container referenceArea;
 
@@ -84,7 +82,7 @@ public class InlineContainerLayoutManager extends AbstractLayoutManager implemen
         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));
@@ -121,6 +119,7 @@ public class InlineContainerLayoutManager extends AbstractLayoutManager implemen
         handleIPDOverflow();
         wrapPositions(allChildElements);
         SpaceResolver.resolveElementList(allChildElements);
+        SpaceResolver.performConditionalsNotification(allChildElements, 0, allChildElements.size() - 1, -1);
         // TODO break-before, break-after
         return allChildElements;
     }
@@ -149,13 +148,13 @@ public class InlineContainerLayoutManager extends AbstractLayoutManager implemen
 
     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() {
@@ -183,6 +182,11 @@ public class InlineContainerLayoutManager extends AbstractLayoutManager implemen
         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;
@@ -196,7 +200,6 @@ public class InlineContainerLayoutManager extends AbstractLayoutManager implemen
             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);
 
@@ -212,6 +215,7 @@ public class InlineContainerLayoutManager extends AbstractLayoutManager implemen
             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());
index b3987a0751374719b9a728255e0baccad915057b..25d8c08721b989ad1e89dd3b93df7bd523a3447b 100644 (file)
@@ -160,6 +160,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager
     private final int follow;
     private AlignmentContext alignmentContext;
 
+    private int baselineOffset = -1;
+
     private List<KnuthSequence> knuthParagraphs;
 
     private LineLayoutPossibilities lineLayouts;
@@ -556,7 +558,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager
 
     private int constantLineHeight = 12000;
 
-
     /**
      * Create a new Line Layout Manager.
      * This is used by the block layout manager to create
@@ -939,7 +940,11 @@ public class LineLayoutManager extends InlineStackingLayoutManager
                 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())));
                     }
@@ -987,6 +992,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager
                     }
                     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));
@@ -1424,6 +1432,16 @@ public class LineLayoutManager extends InlineStackingLayoutManager
         }
     }
 
+    @Override
+    public boolean hasLineAreaDescendant() {
+        return true;
+    }
+
+    @Override
+    public int getBaselineOffset() {
+        return baselineOffset;
+    }
+
     /**
      * Add the areas with the break points.
      *
index 61d8a891d48cacb4a3e53f7980fb715eec3c2420..44a9720a4bf9cb11824c1434ea7c4f75a5115b6b 100644 (file)
@@ -28,16 +28,15 @@ import org.apache.commons.logging.LogFactory;
 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;
@@ -47,21 +46,13 @@ 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
@@ -70,6 +61,11 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
         super(node);
     }
 
+    @Override
+    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+        return getListBlockFO().getCommonBorderPaddingBackground();
+    }
+
     /**
      * Convenience method.
      * @return the ListBlock node
@@ -277,50 +273,5 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
         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);
-        }
-    }
-
 }
 
index 083e4ee1bb5bf86348023bac7ad918a0d990f886..344f6722b1aa14b1e4ed3de270da29f1429928e6 100644 (file)
@@ -32,12 +32,11 @@ import org.apache.fop.area.Block;
 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;
@@ -53,10 +52,9 @@ import org.apache.fop.layoutmgr.ListElement;
 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;
 
@@ -64,8 +62,8 @@ 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);
@@ -78,13 +76,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager implements
     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;
 
@@ -145,6 +136,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager implements
         setBody(node.getBody());
     }
 
+    @Override
+    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+        return getListItemFO().getCommonBorderPaddingBackground();
+    }
+
     /**
      * Convenience method.
      * @return the ListBlock node
@@ -475,6 +471,23 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager implements
         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.
      *
@@ -652,51 +665,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager implements
         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() {
index 7f1754064f7f5dfbefd842d1118bd3224aff1cf3..afb6547c08ae1f84b679aedb128409f3c4c48390 100644 (file)
@@ -39,12 +39,11 @@ import org.apache.fop.fo.flow.Markers;
 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;
@@ -52,7 +51,7 @@ import org.apache.fop.layoutmgr.LeafPosition;
 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;
@@ -66,8 +65,8 @@ import org.apache.fop.util.BreakUtil;
  * 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
@@ -82,13 +81,6 @@ public class TableLayoutManager extends BlockStackingLayoutManager
     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;
 
@@ -132,6 +124,13 @@ public class TableLayoutManager extends BlockStackingLayoutManager
         this.columns = new ColumnSetup(node);
     }
 
+
+    @Override
+    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+        return getTable().getCommonBorderPaddingBackground();
+    }
+
+
     /** @return the table FO */
     public Table getTable() {
         return (Table)this.fobj;
@@ -521,51 +520,6 @@ public class TableLayoutManager extends BlockStackingLayoutManager
         }
     }
 
-    /** {@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();
diff --git a/test/layoutengine/standard-testcases/inline-container_alignment.xml b/test/layoutengine/standard-testcases/inline-container_alignment.xml
new file mode 100644 (file)
index 0000000..153d9a9
--- /dev/null
@@ -0,0 +1,154 @@
+<?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>