diff options
Diffstat (limited to 'src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java')
-rw-r--r-- | src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java new file mode 100644 index 000000000..749a0d0e1 --- /dev/null +++ b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -0,0 +1,293 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr; + +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.TextInfo; +import org.apache.fop.area.Area; +import org.apache.fop.area.BlockParent; +import org.apache.fop.area.BlockViewport; +import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; +import org.apache.fop.area.MinOptMax; +import org.apache.fop.fo.PropertyManager; +import org.apache.fop.layout.AbsolutePositionProps; +import org.apache.fop.fo.properties.AbsolutePosition; +import org.apache.fop.fo.properties.Overflow; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.area.CTM; +import org.apache.fop.datatypes.FODimension; + +import java.util.ListIterator; +import java.util.ArrayList; +import java.util.List; + +import java.awt.geom.Rectangle2D; + +/** + * LayoutManager for a block FO. + */ +public class BlockContainerLayoutManager extends BlockStackingLayoutManager { + + private BlockViewport viewportBlockArea; + private Block curBlockArea; + + ArrayList childBreaks = new ArrayList(); + + AbsolutePositionProps abProps; + FODimension relDims; + CTM absoluteCTM; + boolean clip = false; + int overflow; + PropertyManager propManager; + + public BlockContainerLayoutManager(FObj fobj) { + super(fobj); + } + + public void setOverflow(int of) { + overflow = of; + } + + protected void initProperties(PropertyManager pm) { + propManager = pm; + + abProps = pm.getAbsolutePositionProps(); + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + Rectangle2D rect = new Rectangle2D.Double(abProps.left, + abProps.top, abProps.right - abProps.left, + abProps.bottom - abProps.top); + relDims = new FODimension(0, 0); + absoluteCTM = pm.getCTMandRelDims(rect, relDims); + } + } + + protected int getRotatedIPD() { + PropertyList props = propManager.getProperties(); + int height = props.get("height").getLength().mvalue(); + height = props.get("inline-progression-dimension.optimum").getLength().mvalue(); + + return height; + } + + public BreakPoss getNextBreakPoss(LayoutContext context) { + + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + return getAbsoluteBreakPoss(context); + } + + Rectangle2D rect = new Rectangle2D.Double(0, 0, context.getRefIPD(), + context.getStackLimit().opt); + relDims = new FODimension(0, 0); + absoluteCTM = propManager.getCTMandRelDims(rect, relDims); + double[] vals = absoluteCTM.toArray(); + + MinOptMax stackLimit; + int ipd = context.getRefIPD(); + boolean rotated = vals[0] == 0.0; + if(rotated) { + // rotated 90 degrees + stackLimit = new MinOptMax(1000000); + ipd = getRotatedIPD(); + absoluteCTM = new CTM(vals[0], vals[1], vals[2], vals[3], 0, 0); + } else { + if(vals[0] == -1.0) { + absoluteCTM = new CTM(vals[0], vals[1], vals[2], vals[3], 0, 0); + } + stackLimit = context.getStackLimit(); + } + + BPLayoutManager curLM ; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + // if starting add space before + // stackSize.add(spaceBefore); + BreakPoss lastPos = null; + + while ((curLM = getChildLM()) != null) { + // Make break positions and return blocks! + // Set up a LayoutContext + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit( + MinOptMax.subtract(stackLimit, + stackSize)); + childLC.setRefIPD(ipd); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > stackLimit.max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + childBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + stackLimit, stackSize)); + } + } + if(!rotated) { + BreakPoss breakPoss; + breakPoss = new BreakPoss(new LeafPosition(this, + childBreaks.size() - 1)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + } + } + setFinished(true); + if(rotated) { + BreakPoss breakPoss; + breakPoss = new BreakPoss(new LeafPosition(this, + childBreaks.size() - 1)); + breakPoss.setStackingSize(new MinOptMax(ipd)); + return breakPoss; + } + return null; + } + + public BreakPoss getAbsoluteBreakPoss(LayoutContext context) { + + BPLayoutManager curLM ; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + + int ipd = relDims.ipd; + + while ((curLM = getChildLM()) != null) { + // Make break positions and return blocks! + // Set up a LayoutContext + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit(new MinOptMax(1000000)); + childLC.setRefIPD(ipd); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + childBreaks.add(bp); + } + } + } + setFinished(true); + BreakPoss breakPoss = new BreakPoss( + new LeafPosition(this, childBreaks.size() - 1)); + // absolutely positioned areas do not contribute + // to the normal stacking + breakPoss.setStackingSize(new MinOptMax(0)); + + if(stackSize.min > relDims.bpd) { + if(overflow == Overflow.HIDDEN) { + clip = true; + } else if(overflow == Overflow.ERROR_IF_OVERFLOW) { + //log.error("contents overflows block-container viewport: clipping"); + clip = true; + } + } + + return breakPoss; + } + + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + + BPLayoutManager childLM ; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + while (parentIter.hasNext()) { + LeafPosition lfp = (LeafPosition) parentIter.next(); + // Add the block areas to Area + PositionIterator breakPosIter = + new BreakPossPosIter(childBreaks, iStartPos, + lfp.getLeafPos() + 1); + iStartPos = lfp.getLeafPos() + 1; + while ((childLM = breakPosIter.getNextChildLM()) != null) { + childLM.addAreas(breakPosIter, lc); + } + } + + flush(); + + childBreaks.clear(); + viewportBlockArea = null; + curBlockArea = null; + } + + public Area getParentArea(Area childArea) { + if (curBlockArea == null) { + viewportBlockArea = new BlockViewport(); + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + Rectangle2D rect = new Rectangle2D.Double(abProps.left, + abProps.top, abProps.right - abProps.left, + abProps.bottom - abProps.top); + viewportBlockArea.setBounds(rect); + viewportBlockArea.setCTM(absoluteCTM); + viewportBlockArea.setClip(clip); + } else { + double[] vals = absoluteCTM.toArray(); + boolean rotated = vals[0] == 0.0; + if(rotated) { + Rectangle2D rect = new Rectangle2D.Double(0, 0, + relDims.bpd, getRotatedIPD()); + viewportBlockArea.setBounds(rect); + viewportBlockArea.setCTM(absoluteCTM); + viewportBlockArea.setClip(clip); + } else if(vals[0] == -1.0) { + // need to set bpd to actual size for rotation + // and stacking + Rectangle2D rect = new Rectangle2D.Double(0, 0, + relDims.ipd, relDims.bpd); + viewportBlockArea.setBounds(rect); + viewportBlockArea.setCTM(absoluteCTM); + viewportBlockArea.setClip(clip); + } + } + + curBlockArea = new Block(); + viewportBlockArea.addBlock(curBlockArea); + + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + viewportBlockArea.setPositioning(Block.ABSOLUTE); + } + + // Set up dimensions + // Must get dimensions from parent area + Area parentArea = parentLM.getParentArea(curBlockArea); + int referenceIPD = parentArea.getIPD(); + curBlockArea.setIPD(referenceIPD); + // Get reference IPD from parentArea + setCurrentArea(viewportBlockArea); // ??? for generic operations + } + return curBlockArea; + } + + + public boolean addChild(Area childArea) { + if (curBlockArea != null) { + curBlockArea.addBlock((Block) childArea); + //return super.addChild(childArea); + } + return false; + } + + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + |