aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKaren Lease <klease@apache.org>2002-05-10 12:38:16 +0000
committerKaren Lease <klease@apache.org>2002-05-10 12:38:16 +0000
commitb45cb4b5005f233e501e3ab815d362539af885e3 (patch)
treea133ffe50858fd97b1d58883db9a08db62651e5c /src
parentdb755bf42556bc19d396ae22cb919fdb995fe4cf (diff)
downloadxmlgraphics-fop-b45cb4b5005f233e501e3ab815d362539af885e3.tar.gz
xmlgraphics-fop-b45cb4b5005f233e501e3ab815d362539af885e3.zip
Add support for line-breaking in nested inlines using BreakPoss strategy
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194818 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/org/apache/fop/layoutmgr/AbstractBPLayoutManager.java73
-rw-r--r--src/org/apache/fop/layoutmgr/BPLayoutManager.java4
-rw-r--r--src/org/apache/fop/layoutmgr/BlockLayoutManager.java4
-rw-r--r--src/org/apache/fop/layoutmgr/BreakPoss.java6
-rw-r--r--src/org/apache/fop/layoutmgr/BreakPossPosIter.java8
-rw-r--r--src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java353
-rw-r--r--src/org/apache/fop/layoutmgr/LMiter.java88
-rw-r--r--src/org/apache/fop/layoutmgr/LineBPLayoutManager.java107
-rw-r--r--src/org/apache/fop/layoutmgr/LineLayoutManager.java2
-rw-r--r--src/org/apache/fop/layoutmgr/SpaceSpecifier.java15
-rw-r--r--src/org/apache/fop/layoutmgr/TextBPLayoutManager.java40
-rw-r--r--src/org/apache/fop/render/AbstractRenderer.java11
-rw-r--r--src/org/apache/fop/render/Renderer.java2
-rw-r--r--src/org/apache/fop/render/xml/XMLRenderer.java11
14 files changed, 619 insertions, 105 deletions
diff --git a/src/org/apache/fop/layoutmgr/AbstractBPLayoutManager.java b/src/org/apache/fop/layoutmgr/AbstractBPLayoutManager.java
index 9a0218f74..b3b3ffa01 100644
--- a/src/org/apache/fop/layoutmgr/AbstractBPLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/AbstractBPLayoutManager.java
@@ -24,10 +24,78 @@ public abstract class AbstractBPLayoutManager extends AbstractLayoutManager
/** True if this LayoutManager has handled all of its content. */
private boolean m_bFinished = false;
+ private BPLayoutManager m_curChildLM=null;
+ private ListIterator m_childLMiter;
+ private boolean m_bInited=false;
public AbstractBPLayoutManager(FObj fobj) {
+ this(fobj, new LMiter(fobj.getChildren()));
+ }
+
+
+ public AbstractBPLayoutManager(FObj fobj, ListIterator lmIter) {
super(fobj);
+ m_childLMiter = lmIter;
+ }
+
+
+ /**
+ * Return currently active child LayoutManager or null if
+ * all children have finished layout.
+ * Note: child must implement BPLayoutManager! If it doesn't, skip it
+ * and print a warning.
+ */
+ protected BPLayoutManager getChildLM() {
+ if (m_curChildLM != null && !m_curChildLM.isFinished()) {
+ return m_curChildLM;
+ }
+ while (m_childLMiter.hasNext()) {
+ Object obj = m_childLMiter.next();
+ if (obj instanceof BPLayoutManager) {
+ m_curChildLM = (BPLayoutManager)obj;
+ m_curChildLM.setParentLM(this);
+ m_curChildLM.init();
+ return m_curChildLM;
+ }
+ else {
+ m_childLMiter.remove();
+ System.err.println("WARNING: child LM not a BPLayoutManager: "
+ + obj.getClass().getName());
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Reset the layoutmanager "iterator" so that it will start
+ * with the passed bplm on the next call to getChildLM.
+ * @param bplm Reset iterator to this LayoutManager.
+ */
+ protected void reset(LayoutManager lm, BreakPoss.Position pos) {
+ //if (lm == null) return;
+ if (m_curChildLM != lm) {
+ // ASSERT m_curChildLM == (BPLayoutManager)m_childLMiter.previous()
+ if (m_curChildLM != (BPLayoutManager)m_childLMiter.previous()) {
+ System.err.println("LMiter problem!");
+ }
+ while (m_curChildLM != lm && m_childLMiter.hasPrevious()) {
+ m_curChildLM.resetPosition(null);
+ m_curChildLM = (BPLayoutManager)m_childLMiter.previous();
+ }
+ m_childLMiter.next(); // Otherwise next returns same object
+ }
+ m_curChildLM.resetPosition(pos);
+ if (isFinished()) {
+ setFinished(false);
+ }
+ }
+
+ public void resetPosition(BreakPoss.Position resetPos) {
+ if (resetPos == null) {
+ reset(null, null);
+ }
}
@@ -35,9 +103,10 @@ public abstract class AbstractBPLayoutManager extends AbstractLayoutManager
* This method provides a hook for a LayoutManager to intialize traits
* for the areas it will create, based on Properties set on its FO.
*/
- protected final void initProperties() {
- if (fobj != null) {
+ public void init() {
+ if (fobj != null && m_bInited == false) {
initProperties(fobj.getPropertyManager());
+ m_bInited=true;
}
}
diff --git a/src/org/apache/fop/layoutmgr/BPLayoutManager.java b/src/org/apache/fop/layoutmgr/BPLayoutManager.java
index 34bb5b126..32f7df9d7 100644
--- a/src/org/apache/fop/layoutmgr/BPLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/BPLayoutManager.java
@@ -64,4 +64,8 @@ public interface BPLayoutManager extends LayoutManager {
*/
public void addAreas(PositionIterator posIter) ;
+ public void init() ;
+
+ public void resetPosition(BreakPoss.Position position);
+
}
diff --git a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java
index d53511bd0..b82ba2edb 100644
--- a/src/org/apache/fop/layoutmgr/BlockLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/BlockLayoutManager.java
@@ -83,13 +83,13 @@ public class BlockLayoutManager extends BlockStackingLayoutManager {
break;
}
}
+ /*
lm = new LineLayoutManager(curFobj, inlines, lineHeight, lead,
follow);
+ */
// !!!! To test BreakPoss Line LayoutManager, uncomment!
- /*
lm = new LineBPLayoutManager(curFobj, inlines, lineHeight,
lead, follow);
- */
lms.set(count, lm);
}
lm.setParentLM(this);
diff --git a/src/org/apache/fop/layoutmgr/BreakPoss.java b/src/org/apache/fop/layoutmgr/BreakPoss.java
index eb4ad4200..80fa797c7 100644
--- a/src/org/apache/fop/layoutmgr/BreakPoss.java
+++ b/src/org/apache/fop/layoutmgr/BreakPoss.java
@@ -84,7 +84,7 @@ public class BreakPoss {
this(lm,position,0);
}
- public BreakPoss(BPLayoutManager lm, Position position, int flags) {
+ public BreakPoss(BPLayoutManager lm, Position position, long flags) {
m_lm = lm;
m_position = position;
m_flags = flags;
@@ -128,6 +128,10 @@ public class BreakPoss {
return this.m_nonStackSize ;
}
+ public long getFlags() {
+ return m_flags;
+ }
+
public void setFlag(int flagBit) {
setFlag(flagBit, true);
}
diff --git a/src/org/apache/fop/layoutmgr/BreakPossPosIter.java b/src/org/apache/fop/layoutmgr/BreakPossPosIter.java
index 0188b2731..a868ac5e5 100644
--- a/src/org/apache/fop/layoutmgr/BreakPossPosIter.java
+++ b/src/org/apache/fop/layoutmgr/BreakPossPosIter.java
@@ -21,7 +21,13 @@ public class BreakPossPosIter extends PositionIterator {
// Check position < endPos
protected boolean checkNext() {
- return (m_iterCount > 0 && super.checkNext());
+ if (m_iterCount > 0) {
+ return super.checkNext();
+ }
+ else {
+ endIter();
+ return false;
+ }
}
public Object next() {
diff --git a/src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java b/src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java
new file mode 100644
index 000000000..be87055c4
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/InlineStackingBPLayoutManager.java
@@ -0,0 +1,353 @@
+/*
+ * $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.PropertyManager;
+import org.apache.fop.layout.BorderAndPadding;
+import org.apache.fop.traits.InlineProps;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.MinOptMax;
+import org.apache.fop.area.inline.InlineArea;
+import org.apache.fop.area.inline.InlineParent;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * LayoutManager for objects which stack children in the inline direction,
+ * such as Inline or Line
+ */
+public class InlineStackingBPLayoutManager extends AbstractBPLayoutManager {
+
+ /**
+ * Private class to store information about a lower-level BreakPosition.
+ * Note: fields are directly readable in this class
+ */
+ private static class WrappedPosition implements BreakPoss.Position {
+ BPLayoutManager m_childLM;
+ BreakPoss.Position m_childPosition;
+
+ WrappedPosition(BPLayoutManager childLM,
+ BreakPoss.Position childPosition) {
+ m_childLM = childLM;
+ m_childPosition = childPosition;
+ }
+ }
+
+ private static class StackingIter extends PositionIterator {
+
+ StackingIter(Iterator parentIter) {
+ super(parentIter);
+ }
+
+ protected BPLayoutManager getLM(Object nextObj) {
+ return ((WrappedPosition)nextObj).m_childLM;
+ }
+
+ protected BreakPoss.Position getPos(Object nextObj) {
+ return ((WrappedPosition)nextObj).m_childPosition;
+ }
+
+ }
+
+
+ /**
+ * Holds IPD of all areas which would be generated by previously
+ * complete childLM since last area was generated.
+ */
+ private MinOptMax m_prevContentIPD = new MinOptMax(0);
+
+ /**
+ * Size of any start or end borders and padding.
+ */
+ private MinOptMax m_allocIPD = new MinOptMax(0);
+
+ /**
+ * Size of border and padding in BPD (ie, before and after).
+ */
+ private MinOptMax m_extraBPD;
+
+ /** Holds IPD of a child BP which had no break-after flag. We don't
+ * add this to m_previousIPD until we are sure that the next break
+ * position can really fit.
+ */
+ private MinOptMax m_pendingIPD = new MinOptMax(0);
+
+ private InlineProps m_inlineProps = null;
+ private BorderAndPadding m_borderProps = null;
+
+ private InlineParent m_inlineArea;
+
+ private boolean m_bFirstArea;
+ private BreakPoss m_prevBP;
+
+ public InlineStackingBPLayoutManager(FObj fobj, ListIterator childLMiter) {
+ super(fobj, childLMiter);
+ m_bFirstArea = true;
+ // Initialize inline properties (borders, padding, space)
+ // initProperties();
+ }
+
+ public boolean generatesInlineAreas() {
+ return true;
+ }
+
+ protected void initProperties(PropertyManager propMgr) {
+ // super.initProperties(propMgr);
+ System.err.println("InlineStackingBPLayoutManager.initProperties called");
+ m_inlineProps = propMgr.getInlineProps();
+ m_borderProps = propMgr.getBorderAndPadding();
+ // Calculdate border and padding size in BPD
+ int iPad = m_borderProps.getPadding(BorderAndPadding.BEFORE, false);
+ iPad += m_borderProps.getBorderWidth(BorderAndPadding.BEFORE, false);
+ iPad += m_borderProps.getPadding(BorderAndPadding.AFTER, false);
+ iPad += m_borderProps.getBorderWidth(BorderAndPadding.AFTER, false);
+ m_extraBPD = new MinOptMax(iPad);
+ }
+
+ private MinOptMax getExtraIPD(boolean bNotFirst, boolean bNotLast) {
+ int iBP = m_borderProps.getPadding(BorderAndPadding.START, bNotFirst);
+ iBP += m_borderProps.getBorderWidth(BorderAndPadding.START, bNotFirst);
+ iBP += m_borderProps.getPadding(BorderAndPadding.END, bNotLast);
+ iBP += m_borderProps.getBorderWidth(BorderAndPadding.END, bNotLast);
+ return new MinOptMax(iBP);
+ }
+
+ private boolean hasLeadingFence(boolean bNotFirst) {
+ int iBP = m_borderProps.getPadding(BorderAndPadding.START, bNotFirst);
+ iBP += m_borderProps.getBorderWidth(BorderAndPadding.START, bNotFirst);
+ return (iBP > 0);
+ }
+
+ private boolean hasTrailingFence(boolean bNotLast) {
+ int iBP = m_borderProps.getPadding(BorderAndPadding.END, bNotLast);
+ iBP += m_borderProps.getBorderWidth(BorderAndPadding.END, bNotLast);
+ return (iBP > 0);
+ }
+
+
+ /** Reset position for returning next BreakPossibility. */
+
+ public void resetPosition(BreakPoss.Position prevPos) {
+ WrappedPosition wrappedPos = (WrappedPosition)prevPos;
+ if (wrappedPos != null) {
+ // Back up the layout manager iterator
+ reset(wrappedPos.m_childLM, wrappedPos.m_childPosition);
+ }
+ else {
+ // Backup to first child layout manager
+ System.err.println("InlineStackingBPLM: resetPosition(null)");
+ super.resetPosition(prevPos);
+ }
+ // Do we need to reset some context like pending or prevContent?
+ }
+
+
+ /**
+ * Return value indicating whether the next area to be generated could
+ * start a new line. This should only be called in the "START" condition
+ * if a previous inline BP couldn't end the line.
+ * Return true if any space-start, border-start or padding-start, else
+ * propagate to first child LM
+ */
+ public boolean canBreakBefore(LayoutContext context) {
+ if (m_inlineProps.spaceStart.space.min > 0 ||
+ hasLeadingFence(false)) {
+ return true;
+ }
+ BPLayoutManager lm = getChildLM();
+ if (lm != null) {
+ return lm.canBreakBefore(context);
+ }
+ else return false; // ??? NO child LM?
+ }
+
+
+ public BreakPoss getNextBreakPoss(LayoutContext lc,
+ BreakPoss.Position pbp) {
+ // Get a break from currently active child LM
+ BreakPoss bp =null;
+ BPLayoutManager curLM ;
+ // Handle space before
+ boolean bIncludeStartSpace=false;
+ LayoutContext childLC = new LayoutContext(lc);
+ if (lc.isStart()) {
+ // First call to this LM in new parent "area", ie, this may
+ // not be the first area created by this inline
+ lc.getPendingSpace().addSpace(m_inlineProps.spaceStart);
+ // Check for "fence"
+ if (hasLeadingFence(!m_bFirstArea)) {
+ bIncludeStartSpace=true;
+ // Reset leading space sequence for child areas
+ childLC.setPendingSpace(new SpaceSpecifier(false));
+ }
+ // Reset state variables
+ m_pendingIPD = new MinOptMax(0);
+ m_prevContentIPD = new MinOptMax(0);
+ }
+ else {
+ // Handle pending IPD: if we are called again, we assume previous
+ // break was OK
+ m_prevContentIPD.add(m_pendingIPD);
+ m_pendingIPD = new MinOptMax(0);
+ }
+// if (m_prevChildLM != curLM && m_prevChildLM != null) {
+// // Change child LM
+// m_prevContentIPD.add(m_pendingIPD);
+// }
+
+ while ((curLM = getChildLM()) != null) {
+ // ????
+ /* If first break for this child, set START_AREA flag */
+ if (m_prevBP == null || m_prevBP.getLayoutManager()!=curLM) {
+ childLC.setFlags(LayoutContext.START_AREA);
+ if (m_prevBP != null) {
+ childLC.setPendingSpace(m_prevBP.getTrailingSpace());
+ }
+ }
+
+ if (((bp = curLM.getNextBreakPoss(childLC)) != null)) {
+ // && couldEndLine(bp)) {
+ break;
+ }
+// if (bp.isLastArea()) {
+// // NORMALLY IT MUST BE!
+// m_pendingIPD.add(bp.getStackingSize());
+// m_prevBP = bp;
+// }
+ }
+ if (bp==null) {
+ setFinished(true);
+ return null; // There was no childLM
+ // Alternative is to return a BP with the isLast flag set
+ }
+ else {
+ // TODO! need to know whether this BP is in the first area for FO!
+ return makeBreakPoss(bp, lc.isStart(),
+ (getChildLM() == null), lc);
+ }
+ }
+
+ protected boolean couldEndLine(BreakPoss bp) {
+ if (bp.canBreakAfter()) {
+ return true; // no keep, ends on break char
+ }
+ else if (bp.isSuppressible()) {
+ // NOTE: except at end of content for this LM!!
+ // Never break after only space chars or any other sequence
+ // of areas which would be suppressed at the end of the line.
+ return false;
+ }
+ else {
+ // See if could break before next area
+ LayoutContext lc=new LayoutContext();
+ BPLayoutManager nextLM = getChildLM();
+ return (nextLM == null ||
+ nextLM.canBreakBefore(lc));
+ }
+ }
+
+
+
+ protected BreakPoss makeBreakPoss(BreakPoss bp, boolean bIsFirst,
+ boolean bIsLast, LayoutContext lc) {
+ WrappedPosition inlbp =
+ new WrappedPosition(bp.getLayoutManager(), bp.getPosition());
+ BreakPoss myBP = new BreakPoss(this, inlbp, bp.getFlags());
+
+ // Update dimension information for our allocation area,
+ // including child areas
+ // generated by previous childLM which have completed layout
+ // Update pending area measure
+ // This includes all previous breakinfo
+
+ MinOptMax bpDim = (MinOptMax)bp.getStackingSize().clone();
+
+ if (m_prevBP == null ||
+ m_prevBP.getLayoutManager() != bp.getLayoutManager()) {
+ /* This is first bp generated by child (in this parent area).
+ * Calculate space-start on this area in combination with any
+ * pending space-end on previously generated break possibilities.
+ * Can also have leading space if this FO has fence-preceding.
+ */
+ bpDim.add(bp.resolveLeadingSpace());
+ }
+ if (bp.isLastArea()) {
+ m_pendingIPD.add(bpDim);
+ // See if our area is also done
+
+ }
+
+ // Start and end borders and padding
+ bpDim.add(m_prevContentIPD);
+ bpDim.add(getExtraIPD(!bIsFirst, !bIsLast));
+ myBP.setStackingSize(bpDim);
+ myBP.setNonStackingSize(MinOptMax.add(bp.getNonStackingSize(),
+ m_extraBPD));
+ if (bIsLast) {
+ setFinished(true); // Our last area, so indicate done
+ myBP.setFlag(BreakPoss.ISLAST, true);
+ }
+ else {
+ myBP.setFlag(BreakPoss.ISLAST, false);
+ }
+ myBP.setTrailingSpace((SpaceSpecifier)bp.getTrailingSpace().clone());
+ myBP.getTrailingSpace().addSpace(m_inlineProps.spaceEnd);
+ // If this FO doesn't have fence-start, then this value should
+ // come from the lower level BP!
+ myBP.setLeadingSpace(new SpaceSpecifier(false));
+ m_prevBP = bp;
+ return myBP;
+ }
+
+
+
+ /******
+ protected BreakableText getText(BreakPoss prevBP, BreakPoss lastBP) {
+ }
+ *****/
+
+ // Generate and add areas to parent area
+ // Set size etc
+ public void addAreas(PositionIterator parentIter) {
+ // Make areas from start to end
+ // Update childLM based on bpEnd
+ // It might be a previous sibling of the current one!
+
+ m_inlineArea = new InlineParent();
+
+ // Note: if first, bpStart is perhaps null????
+ // If we are first in parent, set ISFIRST...
+
+
+ // posIter iterates over positions returned by this LM
+ StackingIter childPosIter = new StackingIter(parentIter);
+ BPLayoutManager childLM ;
+ while ((childLM = childPosIter.getNextChildLM())!= null) {
+ childLM.addAreas(childPosIter);
+ }
+
+ parentLM.addChild(m_inlineArea);
+ }
+
+
+// protected Area createArea() {
+// return new InlineParent();
+// }
+
+ public boolean addChild(Area childArea) {
+ // Make sure childArea is inline area
+ if (childArea instanceof InlineArea) {
+ m_inlineArea.addChild((InlineArea)childArea);
+ }
+ return false;
+ }
+
+
+}
diff --git a/src/org/apache/fop/layoutmgr/LMiter.java b/src/org/apache/fop/layoutmgr/LMiter.java
new file mode 100644
index 000000000..fcb94748b
--- /dev/null
+++ b/src/org/apache/fop/layoutmgr/LMiter.java
@@ -0,0 +1,88 @@
+/*
+ * $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 java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+public class LMiter implements ListIterator {
+
+
+ private ListIterator m_baseIter;
+ private FObj m_curFO;
+ private ArrayList m_listLMs;
+ private int m_curPos=0;
+
+ public LMiter(ListIterator baseIter) {
+ m_baseIter = baseIter;
+ m_listLMs = new ArrayList(10);
+ }
+
+ public boolean hasNext() {
+ return (m_curPos < m_listLMs.size())? true :
+ preLoadNext();
+ }
+
+ private boolean preLoadNext() {
+ if (m_baseIter.hasNext()) {
+ FObj fobj = (FObj)m_baseIter.next();
+ //m_listLMs.add(fobj.getLayoutManager());
+ fobj.addLayoutManager(m_listLMs);
+ return true;
+ }
+ else return false;
+ }
+
+ public boolean hasPrevious() {
+ return (m_curPos > 0);
+ }
+
+ public Object previous() throws NoSuchElementException {
+ if (m_curPos > 0) {
+ return m_listLMs.get(--m_curPos);
+ }
+ else throw new NoSuchElementException();
+ }
+
+ public Object next() throws NoSuchElementException {
+ if (m_curPos < m_listLMs.size()) {
+ return m_listLMs.get(m_curPos++);
+ }
+ else throw new NoSuchElementException();
+ }
+
+ public void remove() throws NoSuchElementException {
+ if (m_curPos > 0) {
+ m_listLMs.remove(--m_curPos);
+ // Note: doesn't actually remove it from the base!
+ }
+ else throw new NoSuchElementException();
+
+ }
+
+
+ public void add(Object o) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("LMiter doesn't support add");
+ }
+
+ public void set(Object o) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("LMiter doesn't support set");
+ }
+
+ public int nextIndex() {
+ return m_curPos;
+ }
+
+ public int previousIndex() {
+ return m_curPos - 1;
+ }
+
+}
diff --git a/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java b/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java
index 86417d024..71339821d 100644
--- a/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java
@@ -33,7 +33,8 @@ import java.util.ArrayList;
* BPLayoutManager for lines. It builds one or more lines containing
* inline areas generated by its sub layout managers.
*/
-public class LineBPLayoutManager extends LineLayoutManager {
+public class LineBPLayoutManager extends
+ InlineStackingBPLayoutManager {
/**
* Private class to store information about inline breaks.
@@ -48,8 +49,6 @@ public class LineBPLayoutManager extends LineLayoutManager {
}
}
- private BPLayoutManager m_curChildLM=null;
- private ListIterator m_childLMiter;
private LineArea m_lineArea; // LineArea currently being filled
@@ -64,13 +63,13 @@ public class LineBPLayoutManager extends LineLayoutManager {
public LineBPLayoutManager(FObj fobj, List lms, int lh, int l, int f) {
- super(fobj, lms, lh, l, f);
- m_childLMiter = lms.listIterator();
- initProperties();
+ //super(fobj, lms, lh, l, f);
+ super(fobj, lms.listIterator());
+ // initProperties();
}
protected void initProperties(PropertyManager propMgr) {
- super.initProperties(propMgr);
+ // super.initProperties(propMgr);
System.err.println("LineBPLayoutManager.initProperties called");
MarginProps marginProps = propMgr.getMarginProps();
m_iIndents = marginProps.startIndent + marginProps.endIndent;
@@ -80,47 +79,6 @@ public class LineBPLayoutManager extends LineLayoutManager {
}
- /**
- * Return next child LayoutManager or null if there is none.
- * Note: child must implement BPLayoutManager! If it doesn't, skip it
- * and print a warning.
- * The list of all child layout managers is in lmList (in superclass!)
- */
- private BPLayoutManager getChildLM() {
- if (m_curChildLM != null && !m_curChildLM.isFinished()) {
- return m_curChildLM;
- }
- while (m_childLMiter.hasNext()) {
- Object obj = m_childLMiter.next();
- if (obj instanceof BPLayoutManager) {
- m_curChildLM = (BPLayoutManager)obj;
- m_curChildLM.setParentLM(this);
- return m_curChildLM;
- }
- else {
- m_childLMiter.remove();
- System.err.println("WARNING: child of LineLPLayoutManager not a BPLayoutManager: " + obj.getClass().getName());
- }
- }
- return null;
- }
-
- /**
- * Reset the layoutmanager "iterator" so that it will start
- * with the passed bplm on the next call to getChildLM.
- * @param bplm Reset iterator to this LayoutManager.
- */
- private void resetChildLM(BPLayoutManager bplm) {
- if (bplm == null) return;
- while (m_curChildLM != bplm && m_childLMiter.hasPrevious()) {
- m_curChildLM = (BPLayoutManager)m_childLMiter.previous();
- }
- if ( m_curChildLM.isFinished()) {
- m_curChildLM.setFinished(false);
- }
- }
-
-
/**
* Call child layout managers to generate content as long as they
@@ -183,10 +141,7 @@ public class LineBPLayoutManager extends LineLayoutManager {
inlineLC.unsetFlags(LayoutContext.SUPPRESS_LEADING_SPACE);
}
// GET NEXT POSSIBLE BREAK FROM CHILD LM
- if ((bp = curLM.getNextBreakPoss(inlineLC,
- (m_prevBP !=null ?
- m_prevBP.getPosition() :
- null))) != null) {
+ if ((bp = curLM.getNextBreakPoss(inlineLC, null)) != null) {
// check if this bp fits in line
MinOptMax bpDim = (MinOptMax)bp.getStackingSize().clone();
/* If first BP for this LM (in this call)
@@ -232,8 +187,12 @@ public class LineBPLayoutManager extends LineLayoutManager {
* This includes any previosly pending size,
* already calculated above.
*/
- pendingIPD = bpDim;
- // Add BP to the pending list
+ if (bp.isLastArea()) {
+ pendingIPD = bpDim;
+ }
+ // Add BP to the list even though we can't break here
+ // We need to keep it for area generation
+ m_vecInlineBreaks.add(bp);
}
}
else if (bpDim.min > availIPD.max) {
@@ -290,36 +249,17 @@ public class LineBPLayoutManager extends LineLayoutManager {
// No more content to layout!
setFinished(true);
}
- // Backup layoutmanager if necessary
- resetChildLM(m_prevBP.getLayoutManager());
+ // Backup child LM if necessary
+ if (bp != m_prevBP) {
+ // Remove any pending breaks from the vector
+ while (m_vecInlineBreaks.lastElement()!=m_prevBP) {
+ m_vecInlineBreaks.remove(m_vecInlineBreaks.size()-1);
+ }
+ reset(m_prevBP.getLayoutManager(), m_prevBP.getPosition());
+ }
return makeLineBreak(m_prevBP);
}
- /**
- * Return whether we could end the line at the proposed Position.
- * TODO: take keeps into account and distinguish the cost of a
- * the break-completely forbidden or some non-0 cost.
- * QUESTION: do we need to pass the current LineLM or childLM
- * LayoutContext?
- */
- private boolean couldEndLine(BreakPoss bp) {
- if (bp.canBreakAfter()) {
- return true; // no keep, ends on break char
- }
- else if (bp.isSuppressible()) {
- // NOTE: except at end of content for this LM!!
- // Never break after only space chars or any other sequence
- // of areas which would be suppressed at the end of the line.
- return false;
- }
- else {
- // See if could break before next area
- LayoutContext lc=new LayoutContext();
- BPLayoutManager nextLM = getChildLM();
- return (nextLM == null ||
- nextLM.canBreakBefore(lc));
- }
- }
private BreakPoss findHyphenPoss(BreakPoss prevBP, BreakPoss newBP) {
@@ -356,11 +296,10 @@ public class LineBPLayoutManager extends LineLayoutManager {
new BreakPossPosIter(m_vecInlineBreaks,
iStartPos, lbp.m_iPos+1);
iStartPos = lbp.m_iPos+1;
- while (inlinePosIter.hasNext() &&
- (childLM = inlinePosIter.getNextChildLM())!= null) {
+ while ((childLM = inlinePosIter.getNextChildLM())!= null) {
childLM.addAreas(inlinePosIter);
}
- verticalAlign(m_lineArea);
+ // verticalAlign(m_lineArea);
parentLM.addChild(m_lineArea);
}
m_lineArea = null;
diff --git a/src/org/apache/fop/layoutmgr/LineLayoutManager.java b/src/org/apache/fop/layoutmgr/LineLayoutManager.java
index 4a33190fb..6e8050996 100644
--- a/src/org/apache/fop/layoutmgr/LineLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/LineLayoutManager.java
@@ -44,7 +44,7 @@ import java.util.Iterator;
*
* How do we handle Unicode BIDI?
*/
-public class LineLayoutManager extends AbstractBPLayoutManager {
+public class LineLayoutManager extends AbstractLayoutManager {
private LineInfo currentLine = null;
private boolean bFirstLine = true;
private MinOptMax totalIPD;
diff --git a/src/org/apache/fop/layoutmgr/SpaceSpecifier.java b/src/org/apache/fop/layoutmgr/SpaceSpecifier.java
index 2908fe5aa..ad7193c4e 100644
--- a/src/org/apache/fop/layoutmgr/SpaceSpecifier.java
+++ b/src/org/apache/fop/layoutmgr/SpaceSpecifier.java
@@ -16,7 +16,7 @@ import java.util.Vector;
* areas with a stacking constraint. Provide a way to resolve these into
* a single MinOptMax value.
*/
-public class SpaceSpecifier {
+public class SpaceSpecifier implements Cloneable {
private boolean m_bStartsRefArea;
@@ -28,6 +28,19 @@ public class SpaceSpecifier {
m_bStartsRefArea = bStartsRefArea;
}
+ public Object clone() {
+ try {
+ SpaceSpecifier ss = (SpaceSpecifier)super.clone();
+ // Clone the vector, but share the objects in it!
+ ss.m_vecSpaceVals = new Vector(this.m_vecSpaceVals.size());
+ ss.m_vecSpaceVals.addAll(this.m_vecSpaceVals);
+ return ss;
+ } catch (CloneNotSupportedException cnse) {
+ return null;
+ }
+
+ }
+
/**
* Clear all space specifiers and fences.
*/
diff --git a/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java b/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java
index 8c99cbc3b..b0c28ec17 100644
--- a/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java
+++ b/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java
@@ -195,6 +195,30 @@ public class TextBPLayoutManager extends AbstractBPLayoutManager {
(CharUtilities.isSpace(c) || s_breakChars.indexOf(c)>=0)));
}
+ /** Reset position for returning next BreakPossibility. */
+
+ public void resetPosition(BreakPoss.Position prevPos) {
+ if (prevPos != null) {
+ TextBreakPosition tbp = (TextBreakPosition)prevPos;
+ AreaInfo ai =
+ (AreaInfo) m_vecAreaInfo.elementAt(tbp.m_iAreaIndex);
+ if (ai.m_iBreakIndex != m_iNextStart) {
+ m_iNextStart = ai.m_iBreakIndex;
+ m_vecAreaInfo.setSize(tbp.m_iAreaIndex+1);
+ System.err.println("Discarded previous text break pos");
+ setFinished(false);
+ }
+ }
+ else {
+ // Reset to beginning!
+ System.err.println("TextBPLM: resetPosition(null)");
+ m_vecAreaInfo.setSize(0);
+ m_iNextStart = 0;
+ setFinished(false);
+ }
+ }
+
+
/**
* Return the next break possibility that fits the constraints.
* @param context An object specifying the flags and input information
@@ -229,17 +253,6 @@ public class TextBPLayoutManager extends AbstractBPLayoutManager {
iFlags |= BreakPoss.ISFIRST;
}
- if (prevPos != null) {
- TextBreakPosition tbp = (TextBreakPosition)prevPos;
- AreaInfo ai =
- (AreaInfo) m_vecAreaInfo.elementAt(tbp.m_iAreaIndex);
- if (ai.m_iBreakIndex != m_iNextStart) {
- m_iNextStart = ai.m_iBreakIndex;
- m_vecAreaInfo.setSize(tbp.m_iAreaIndex+1);
- System.err.println("Discarded previous text break pos");
- }
- }
-
// HANDLE SUPPRESSED LEADING SPACES
if ((context.flags & LayoutContext.SUPPRESS_LEADING_SPACE)!=0) {
@@ -249,6 +262,7 @@ public class TextBPLayoutManager extends AbstractBPLayoutManager {
chars[m_iNextStart]==SPACE; m_iNextStart++);
// If now at end, nothing to compose here!
if (m_iNextStart >= chars.length) {
+ setFinished(true);
return null; // Or an "empty" BreakPoss?
}
}
@@ -364,6 +378,10 @@ public class TextBPLayoutManager extends AbstractBPLayoutManager {
if (trailingSpace != null) {
bp.setTrailingSpace(trailingSpace);
}
+ else {
+ bp.setTrailingSpace(new SpaceSpecifier(false));
+ }
+ bp.setLeadingSpace(new SpaceSpecifier(false));
return bp;
}
diff --git a/src/org/apache/fop/render/AbstractRenderer.java b/src/org/apache/fop/render/AbstractRenderer.java
index 9f564bf97..ddbece58f 100644
--- a/src/org/apache/fop/render/AbstractRenderer.java
+++ b/src/org/apache/fop/render/AbstractRenderer.java
@@ -10,10 +10,8 @@ package org.apache.fop.render;
// FOP
import org.apache.fop.apps.FOPException;
import org.apache.fop.area.*;
-import org.apache.fop.area.Span;
import org.apache.fop.area.inline.*;
import org.apache.fop.area.inline.Character;
-import org.apache.fop.area.inline.Space;
import org.apache.fop.fo.FOUserAgent;
// Avalon
@@ -25,6 +23,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
+import java.util.Iterator;
/**
* Abstract base class for all renderers.
@@ -308,6 +307,14 @@ public abstract class AbstractRenderer implements Renderer {
currentBlockIPPosition += word.getWidth();
}
+ public void renderInlineParent(InlineParent ip) {
+ // currentBlockIPPosition += ip.getWidth();
+ Iterator iter = ip.getChildAreas().iterator();
+ while (iter.hasNext()) {
+ ((InlineArea)iter.next()).render(this);
+ }
+ }
+
protected void renderBlocks(List blocks) {
for (int count = 0; count < blocks.size(); count++) {
Object obj = blocks.get(count);
diff --git a/src/org/apache/fop/render/Renderer.java b/src/org/apache/fop/render/Renderer.java
index a40de294a..488c4aad2 100644
--- a/src/org/apache/fop/render/Renderer.java
+++ b/src/org/apache/fop/render/Renderer.java
@@ -75,6 +75,8 @@ public interface Renderer {
public void renderWord(Word area);
+ public void renderInlineParent(InlineParent ip);
+
public void renderCharacter(
org.apache.fop.area.inline.Character ch);
diff --git a/src/org/apache/fop/render/xml/XMLRenderer.java b/src/org/apache/fop/render/xml/XMLRenderer.java
index 94ef5b1d2..85aa688ef 100644
--- a/src/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/org/apache/fop/render/xml/XMLRenderer.java
@@ -348,6 +348,17 @@ public class XMLRenderer extends AbstractRenderer {
super.renderWord(word);
}
+ public void renderInlineParent(InlineParent ip) {
+ String prop = "";
+ List list = ip.getTraitList();
+ if (list != null) {
+ prop = " props=\"" + getPropString(list) + "\"";
+ }
+ writeStartTag("<inlineparent" + prop + ">");
+ super.renderInlineParent(ip);
+ writeEndTag("</inlineparent>");
+ }
+
public void renderLeader(Leader area) {
String style = "solid";
switch (area.getRuleStyle()) {