From 5eed711853cc3cb871408f317487d065eeec22f7 Mon Sep 17 00:00:00 2001
From: Simon Pepping
Date: Wed, 28 Dec 2005 09:10:36 +0000
Subject: [PATCH] Each block in inline content now appears in its own line
area.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@359451 13f79535-47bb-0310-9956-ffa450edef68
---
.../layoutmgr/inline/LineLayoutManager.java | 393 +++++++++---------
.../inline_block_nested_5.xml | 64 ++-
.../inline_border_padding_block_nested_1.xml | 25 +-
.../inline_border_padding_block_nested_2.xml | 31 +-
4 files changed, 273 insertions(+), 240 deletions(-)
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
index b14293d89..aa6c4b862 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
@@ -949,7 +949,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager
while (paragraphsIterator.hasPrevious()) {
KnuthSequence seq = (KnuthSequence) paragraphsIterator.previous();
if (!seq.isInlineSequence()) {
- llPoss = createBlockLineBreak(seq);
+ // This set of line layout possibilities does not matter;
+ // we only need an entry in lineLayoutsList.
+ llPoss = new LineLayoutPossibilities();
} else {
llPoss = findOptimalBreakingPoints(alignment, (Paragraph) seq);
}
@@ -962,39 +964,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager
return postProcessLineBreaks(alignment, context);
}
- /**
- * create a single line layout possibility with a single linebreak
- * for a block sequence
- * @param seq the Knuth sequence for which the linebreak is created
- * @return the line layout possibilities for the paragraph
- */
- private LineLayoutPossibilities createBlockLineBreak(KnuthSequence seq) {
- //TODO Should this really create only a single LineBreakPosition???
- //This creates an implicit keep-together on the nested block-level FOs.
- LineLayoutPossibilities llPoss = new LineLayoutPossibilities();
- llPoss.addPossibility(1, 0);
- int localLineHeight = 0, lineStretch = 0, lineShrink = 0;
- ListIterator seqIterator = seq.listIterator();
- while (seqIterator.hasNext()) {
- ListElement elt = (ListElement) seqIterator.next();
- if (!(elt instanceof KnuthElement)) {
- continue;
- }
- KnuthElement element = (KnuthElement) elt;
- localLineHeight += element.getW();
- if (element.isGlue()) {
- lineStretch += element.getY();
- lineShrink += element.getZ();
- }
- }
- LineBreakPosition lbp = new LineBreakPosition(this,
- knuthParagraphs.indexOf(seq), 0, seq.size() - 1,
- lineShrink, lineStretch, 0, 0, 0, 0, localLineHeight,
- iLineWidth, 0, 0, 0);
- llPoss.addBreakPosition(lbp, 0);
- return llPoss;
- }
-
/**
* Fint the optimal linebreaks for a paragraph
* @param alignment alignment of the paragraph
@@ -1654,184 +1623,204 @@ public class LineLayoutManager extends InlineStackingLayoutManager
*/
public void addAreas(PositionIterator parentIter,
LayoutContext context) {
- LayoutManager childLM;
- LayoutContext lc = new LayoutContext(0);
- lc.setAlignmentContext(alignmentContext);
- int iCurrParIndex;
while (parentIter.hasNext()) {
Position pos = (Position) parentIter.next();
+ boolean isLastPosition = !parentIter.hasNext();
if (pos instanceof LineBreakPosition) {
- ListIterator seqIterator = null;
- KnuthElement tempElement = null;
- // the TLM which created the last KnuthElement in this line
- LayoutManager lastLM = null;
-
- LineBreakPosition lbp = (LineBreakPosition) pos;
- iCurrParIndex = lbp.iParIndex;
- KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(iCurrParIndex);
- int iStartElement = lbp.iStartIndex;
- int iEndElement = lbp.getLeafPos();
-
- LineArea lineArea
- = new LineArea((lbp.getLeafPos() < seq.size() - 1
- ? textAlignment : textAlignmentLast),
- lbp.difference, lbp.availableStretch, lbp.availableShrink);
- lineArea.setStartIndent(lbp.startIndent);
- lineArea.setBPD(lbp.lineHeight);
- lineArea.setIPD(lbp.lineWidth);
- lineArea.addTrait(Trait.SPACE_BEFORE, new Integer(lbp.spaceBefore));
- lineArea.addTrait(Trait.SPACE_AFTER, new Integer(lbp.spaceAfter));
- alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline);
-
- if (seq instanceof Paragraph) {
- Paragraph currPar = (Paragraph) seq;
- // ignore the first elements added by the LineLayoutManager
- iStartElement += (iStartElement == 0) ? currPar.ignoreAtStart : 0;
-
- // if this is the last line area that for this paragraph,
- // ignore the last elements added by the LineLayoutManager and
- // subtract the last-line-end-indent from the area ipd
- if (iEndElement == (currPar.size() - 1)) {
- iEndElement -= currPar.ignoreAtEnd;
- lineArea.setIPD(lineArea.getIPD() - lastLineEndIndent.getValue(this));
- }
- }
+ addInlineArea(context, pos, isLastPosition);
+ } else if ((pos instanceof NonLeafPosition) && pos.generatesAreas()) {
+ addBlockArea(context, pos, isLastPosition);
+ } else {
+ /*
+ * pos was the Position inside a penalty item, nothing to do;
+ * or Pos does not generate an area,
+ * i.e. it stand for spaces, borders and padding.
+ */
+ }
+ }
+ setCurrentArea(null); // ?? necessary
+ }
+
+ /**
+ * Add a line with inline content
+ * @param context the context for adding areas
+ * @param pos the position for which the line is generated
+ * @param isLastPosition true if this is the last position of this LM
+ */
+ private void addInlineArea(LayoutContext context, Position pos, boolean isLastPosition) {
+ ListIterator seqIterator = null;
+ KnuthElement tempElement = null;
+ // the TLM which created the last KnuthElement in this line
+ LayoutManager lastLM = null;
+
+ LineBreakPosition lbp = (LineBreakPosition) pos;
+ int iCurrParIndex;
+ iCurrParIndex = lbp.iParIndex;
+ KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(iCurrParIndex);
+ int iStartElement = lbp.iStartIndex;
+ int iEndElement = lbp.getLeafPos();
+
+ LineArea lineArea
+ = new LineArea((lbp.getLeafPos() < seq.size() - 1
+ ? textAlignment : textAlignmentLast),
+ lbp.difference, lbp.availableStretch, lbp.availableShrink);
+ lineArea.setStartIndent(lbp.startIndent);
+ lineArea.setBPD(lbp.lineHeight);
+ lineArea.setIPD(lbp.lineWidth);
+ lineArea.addTrait(Trait.SPACE_BEFORE, new Integer(lbp.spaceBefore));
+ lineArea.addTrait(Trait.SPACE_AFTER, new Integer(lbp.spaceAfter));
+ alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline);
+
+ if (seq instanceof Paragraph) {
+ Paragraph currPar = (Paragraph) seq;
+ // ignore the first elements added by the LineLayoutManager
+ iStartElement += (iStartElement == 0) ? currPar.ignoreAtStart : 0;
- // ignore the last element in the line if it is a KnuthGlue object
- seqIterator = seq.listIterator(iEndElement);
- tempElement = (KnuthElement) seqIterator.next();
- if (tempElement.isGlue()) {
- iEndElement--;
- // this returns the same KnuthElement
- seqIterator.previous();
- tempElement = (KnuthElement) seqIterator.previous();
+ // if this is the last line area that for this paragraph,
+ // ignore the last elements added by the LineLayoutManager and
+ // subtract the last-line-end-indent from the area ipd
+ if (iEndElement == (currPar.size() - 1)) {
+ iEndElement -= currPar.ignoreAtEnd;
+ lineArea.setIPD(lineArea.getIPD() - lastLineEndIndent.getValue(this));
}
- lastLM = tempElement.getLayoutManager();
-
- // ignore KnuthGlue and KnuthPenalty objects
- // at the beginning of the line
- seqIterator = seq.listIterator(iStartElement);
+ }
+
+ // ignore the last element in the line if it is a KnuthGlue object
+ seqIterator = seq.listIterator(iEndElement);
+ tempElement = (KnuthElement) seqIterator.next();
+ if (tempElement.isGlue()) {
+ iEndElement--;
+ // this returns the same KnuthElement
+ seqIterator.previous();
+ tempElement = (KnuthElement) seqIterator.previous();
+ }
+ lastLM = tempElement.getLayoutManager();
+
+ // ignore KnuthGlue and KnuthPenalty objects
+ // at the beginning of the line
+ seqIterator = seq.listIterator(iStartElement);
+ tempElement = (KnuthElement) seqIterator.next();
+ while (!tempElement.isBox() && seqIterator.hasNext()) {
tempElement = (KnuthElement) seqIterator.next();
- while (!tempElement.isBox() && seqIterator.hasNext()) {
- tempElement = (KnuthElement) seqIterator.next();
- iStartElement++;
- }
-
- // Add the inline areas to lineArea
- PositionIterator inlinePosIter
- = new KnuthPossPosIter(seq, iStartElement,
- iEndElement + 1);
-
- iStartElement = lbp.getLeafPos() + 1;
- if (iStartElement == seq.size()) {
- // advance to next paragraph
- iStartElement = 0;
+ iStartElement++;
+ }
+
+ // Add the inline areas to lineArea
+ PositionIterator inlinePosIter
+ = new KnuthPossPosIter(seq, iStartElement, iEndElement + 1);
+
+ iStartElement = lbp.getLeafPos() + 1;
+ if (iStartElement == seq.size()) {
+ // advance to next paragraph
+ iStartElement = 0;
+ }
+
+ LayoutContext lc = new LayoutContext(0);
+ lc.setAlignmentContext(alignmentContext);
+ lc.setSpaceAdjust(lbp.dAdjust);
+ lc.setIPDAdjust(lbp.ipdAdjust);
+ lc.setLeadingSpace(new SpaceSpecifier(true));
+ lc.setTrailingSpace(new SpaceSpecifier(false));
+ lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
+
+ /*
+ * extension (not in the XSL FO recommendation): if the left and right margins
+ * have been optimized, recompute indents and / or adjust ratio, according
+ * to the paragraph horizontal alignment
+ */
+ if (false && textAlignment == EN_JUSTIFY) {
+ // re-compute space adjust ratio
+ int updatedDifference = context.getStackLimit().opt
+ - lbp.lineWidth + lbp.difference;
+ double updatedRatio = 0.0;
+ if (updatedDifference > 0) {
+ updatedRatio = (float) updatedDifference / lbp.availableStretch;
+ } else if (updatedDifference < 0) {
+ updatedRatio = (float) updatedDifference / lbp.availableShrink;
}
-
- lc.setSpaceAdjust(lbp.dAdjust);
- lc.setIPDAdjust(lbp.ipdAdjust);
- lc.setLeadingSpace(new SpaceSpecifier(true));
+ lc.setIPDAdjust(updatedRatio);
+ //log.debug("LLM.addAreas> old difference = " + lbp.difference + " new difference = " + updatedDifference);
+ //log.debug(" old ratio = " + lbp.ipdAdjust + " new ratio = " + updatedRatio);
+ } else if (false && textAlignment == EN_CENTER) {
+ // re-compute indent
+ int updatedIndent = lbp.startIndent
+ + (context.getStackLimit().opt - lbp.lineWidth) / 2;
+ lineArea.setStartIndent(updatedIndent);
+ } else if (false && textAlignment == EN_END) {
+ // re-compute indent
+ int updatedIndent = lbp.startIndent
+ + (context.getStackLimit().opt - lbp.lineWidth);
+ lineArea.setStartIndent(updatedIndent);
+ }
+
+ setCurrentArea(lineArea);
+ setChildContext(lc);
+ LayoutManager childLM;
+ while ((childLM = inlinePosIter.getNextChildLM()) != null) {
+ lc.setFlags(LayoutContext.LAST_AREA, (childLM == lastLM));
+ childLM.addAreas(inlinePosIter, lc);
+ lc.setLeadingSpace(lc.getTrailingSpace());
lc.setTrailingSpace(new SpaceSpecifier(false));
- lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
-
- /* extension (not in the XSL FO recommendation): if the left and right margins
- have been optimized, recompute indents and / or adjust ratio, according
- to the paragraph horizontal alignment */
- if (false && textAlignment == EN_JUSTIFY) {
- // re-compute space adjust ratio
- int updatedDifference = context.getStackLimit().opt
- - lbp.lineWidth + lbp.difference;
- double updatedRatio = 0.0;
- if (updatedDifference > 0) {
- updatedRatio = (float) updatedDifference / lbp.availableStretch;
- } else if (updatedDifference < 0) {
- updatedRatio = (float) updatedDifference / lbp.availableShrink;
- }
- lc.setIPDAdjust(updatedRatio);
- //log.debug("LLM.addAreas> old difference = " + lbp.difference + " new difference = " + updatedDifference);
- //log.debug(" old ratio = " + lbp.ipdAdjust + " new ratio = " + updatedRatio);
- } else if (false && textAlignment == EN_CENTER) {
- // re-compute indent
- int updatedIndent = lbp.startIndent
- + (context.getStackLimit().opt - lbp.lineWidth) / 2;
- lineArea.setStartIndent(updatedIndent);
- } else if (false && textAlignment == EN_END) {
- // re-compute indent
- int updatedIndent = lbp.startIndent
- + (context.getStackLimit().opt - lbp.lineWidth);
- lineArea.setStartIndent(updatedIndent);
- }
-
- setCurrentArea(lineArea);
- setChildContext(lc);
- while ((childLM = inlinePosIter.getNextChildLM()) != null) {
- lc.setFlags(LayoutContext.LAST_AREA, (childLM == lastLM));
- childLM.addAreas(inlinePosIter, lc);
- lc.setLeadingSpace(lc.getTrailingSpace());
- lc.setTrailingSpace(new SpaceSpecifier(false));
- }
-
- // when can this be null?
- // if display-align is distribute, add space after
- if (context.getSpaceAfter() > 0
- && (!context.isLastArea() || parentIter.hasNext())) {
- lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter());
- }
- lineArea.finalise();
- parentLM.addChildArea(lineArea);
- } else if (pos instanceof NonLeafPosition) {
- // Nested block-level content;
- // go down the LM stack again;
- // collect all consecutive NonLeafPosition objects,
- // "unwrap" them and put the child positions in a new list.
- LinkedList positionList = new LinkedList();
- Position innerPosition;
- innerPosition = ((NonLeafPosition) pos).getPosition();
- positionList.add(innerPosition);
- while (parentIter.hasNext()) {
- pos = (Position)parentIter.peekNext();
- if (!(pos instanceof NonLeafPosition)) {
- break;
- }
- pos = (Position) parentIter.next();
- innerPosition = ((NonLeafPosition) pos).getPosition();
- positionList.add(innerPosition);
- }
-
- // do we have the last LM?
- LayoutManager lastLM = null;
- if (!parentIter.hasNext()) {
- lastLM = innerPosition.getLM();
- }
-
- // this may be wrong; not all areas belong inside a single line area
- // see InlineStackingLM.addChildArea
- LineArea lineArea = new LineArea();
- setCurrentArea(lineArea);
- setChildContext(lc);
-
- PositionIterator childPosIter = new StackingIter(positionList.listIterator());
- LayoutContext blocklc = new LayoutContext(0);
- blocklc.setLeadingSpace(new SpaceSpecifier(true));
- blocklc.setTrailingSpace(new SpaceSpecifier(false));
- blocklc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
- while ((childLM = childPosIter.getNextChildLM()) != null) {
- // set last area flag
- blocklc.setFlags(LayoutContext.LAST_AREA,
- (context.isLastArea() && childLM == lastLM));
- blocklc.setStackLimit(context.getStackLimit());
- // Add the line areas to Area
- childLM.addAreas(childPosIter, blocklc);
- blocklc.setLeadingSpace(blocklc.getTrailingSpace());
- blocklc.setTrailingSpace(new SpaceSpecifier(false));
- }
- lineArea.updateExtentsFromChildren();
- parentLM.addChildArea(lineArea);
- } else {
- // pos was the Position inside a penalty item, nothing to do
}
+
+ // when can this be null?
+ // if display-align is distribute, add space after
+ if (context.getSpaceAfter() > 0
+ && (!context.isLastArea() || !isLastPosition)) {
+ lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter());
+ }
+ lineArea.finalise();
+ parentLM.addChildArea(lineArea);
+ }
+
+ /**
+ * Add a line with block content
+ * @param context the context for adding areas
+ * @param pos the position for which the line is generated
+ * @param isLastPosition true if this is the last position of this LM
+ */
+ private void addBlockArea(LayoutContext context, Position pos, boolean isLastPosition) {
+ /* Nested block-level content;
+ * go down the LM stack again;
+ * "unwrap" the positions and put the child positions in a new list.
+ * The positionList must contain one area-generating position,
+ * which creates one line area.
+ */
+ List positionList = new ArrayList(1);
+ Position innerPosition;
+ innerPosition = ((NonLeafPosition) pos).getPosition();
+ positionList.add(innerPosition);
+
+ // do we have the last LM?
+ LayoutManager lastLM = null;
+ if (isLastPosition) {
+ lastLM = innerPosition.getLM();
}
- setCurrentArea(null); // ?? necessary
+
+ LineArea lineArea = new LineArea();
+ setCurrentArea(lineArea);
+ LayoutContext lc = new LayoutContext(0);
+ lc.setAlignmentContext(alignmentContext);
+ setChildContext(lc);
+
+ PositionIterator childPosIter = new StackingIter(positionList.listIterator());
+ LayoutContext blocklc = new LayoutContext(0);
+ blocklc.setLeadingSpace(new SpaceSpecifier(true));
+ blocklc.setTrailingSpace(new SpaceSpecifier(false));
+ blocklc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
+ LayoutManager childLM;
+ while ((childLM = childPosIter.getNextChildLM()) != null) {
+ // set last area flag
+ blocklc.setFlags(LayoutContext.LAST_AREA,
+ (context.isLastArea() && childLM == lastLM));
+ blocklc.setStackLimit(context.getStackLimit());
+ // Add the line areas to Area
+ childLM.addAreas(childPosIter, blocklc);
+ blocklc.setLeadingSpace(blocklc.getTrailingSpace());
+ blocklc.setTrailingSpace(new SpaceSpecifier(false));
+ }
+ lineArea.updateExtentsFromChildren();
+ parentLM.addChildArea(lineArea);
}
/**
diff --git a/test/layoutengine/standard-testcases/inline_block_nested_5.xml b/test/layoutengine/standard-testcases/inline_block_nested_5.xml
index 1dd64be6e..f1ef1d336 100644
--- a/test/layoutengine/standard-testcases/inline_block_nested_5.xml
+++ b/test/layoutengine/standard-testcases/inline_block_nested_5.xml
@@ -18,37 +18,63 @@
- This test checks whether inline block content does not generate
-ClassCastExceptions. The exceptions would occur because an
-UnresolvedElement in a list of ListElements is cast to a KnuthElement.
+ This test checks fo:inlines which generate multiple consecutive
+inlineblockparent areas. Each inlineblockparent area should appear in
+its own line area. Two cases: 1. A block containing multiple
+lines. 2. A block containing multiple child blocks which must be kept
+together (so that there are not break positions between the positions
+for the blocks).
+
+ Implicitly this test checks whether inline block content does
+not generate ClassCastExceptions. The exceptions would occur because
+an UnresolvedElement in a list of ListElements would be cast to a
+KnuthElement.
+
-
+
-
+
-
-
-
- This book is designed to be the clear, concise, normative reference to the DocBook DTD. This book is the official documentation for the DocBook DTD:A=BA1=B1,A2=B2.We hope to answer, definitively, all the questions you might have about all the elements and entities in DocBook. In particular, we cover the following subjects.End of the DocBook blurb.
+
+
+
+ before block
+
+As far as the laws of mathematics refer to reality, they are not
+certain, and as far as they are certain, they do not refer to reality
+- Albert Einstein
+
+after block
+
+
+ before block
+
+ A1=B1,
+ A2=B2.
+
+after block
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
diff --git a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml
index fc26c2b8f..62054b520 100755
--- a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml
+++ b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_1.xml
@@ -100,7 +100,6 @@
-
@@ -111,16 +110,24 @@
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml
index 345a2c4c3..4b1bf52d2 100755
--- a/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml
+++ b/test/layoutengine/standard-testcases/inline_border_padding_block_nested_2.xml
@@ -153,16 +153,27 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--
2.39.5