diff options
Diffstat (limited to 'src/java/org/apache/fop/layoutmgr/inline')
24 files changed, 643 insertions, 484 deletions
diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java index a74fac743..e090fbae6 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java @@ -30,7 +30,6 @@ import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; @@ -99,10 +98,9 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa } /** - * If id can be resolved then simply return a word, otherwise + * If id can be resolved then simply return a text area, otherwise * return a resolvable area * - * @param parentLM the parent LayoutManager * @return a corresponding InlineArea */ private InlineArea getPageNumberCitationInlineArea() { diff --git a/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java b/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java index 4eb0abd64..2e8a3aca7 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java @@ -237,6 +237,8 @@ public class AlignmentContext implements Constants { case EN_MATHEMATICAL: this.alignmentBaselineIdentifier = alignmentBaseline; break; + default: + break; } } @@ -307,7 +309,6 @@ public class AlignmentContext implements Constants { * Calculates the baseline shift value based on the baseline-shift * property value. * @param baselineShift the baseline shift property value - * @return the computed baseline shift value */ private void setBaselineShift(Length baselineShift) { baselineShiftValue = 0; @@ -331,6 +332,9 @@ public class AlignmentContext implements Constants { , LengthBase.CUSTOM_BASE , parentAlignmentContext.getLineHeight())); break; + default: + break; + } } @@ -354,10 +358,12 @@ public class AlignmentContext implements Constants { return parentAlignmentContext.getScaledBaselineTable() .getBaseline(alignmentBaselineIdentifier) - scaledBaselineTable - .deriveScaledBaselineTable(parentAlignmentContext.getDominantBaselineIdentifier()) + .deriveScaledBaselineTable(parentAlignmentContext + .getDominantBaselineIdentifier()) .getBaseline(alignmentBaselineIdentifier) - scaledBaselineTable - .getBaseline(parentAlignmentContext.getDominantBaselineIdentifier()) + .getBaseline(parentAlignmentContext + .getDominantBaselineIdentifier()) + baselineShiftValue; } @@ -514,11 +520,11 @@ public class AlignmentContext implements Constants { /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer(64); - sb.append("ah=" + areaHeight); - sb.append(" lp=" + lineHeight); - sb.append(" ap=" + alignmentPoint); - sb.append(" ab=" + alignmentBaselineIdentifier); - sb.append(" bs=" + baselineShiftValue); + sb.append("areaHeight=" + areaHeight); + sb.append(" lineHeight=" + lineHeight); + sb.append(" alignmentPoint=" + alignmentPoint); + sb.append(" alignmentBaselineID=" + alignmentBaselineIdentifier); + sb.append(" baselineShift=" + baselineShiftValue); return sb.toString(); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/BasicScaledBaselineTable.java b/src/java/org/apache/fop/layoutmgr/inline/BasicScaledBaselineTable.java index 73f414bf7..467f2e154 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/BasicScaledBaselineTable.java +++ b/src/java/org/apache/fop/layoutmgr/inline/BasicScaledBaselineTable.java @@ -21,9 +21,7 @@ package org.apache.fop.layoutmgr.inline; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.datatypes.Length; -import org.apache.fop.datatypes.LengthBase; -import org.apache.fop.datatypes.SimplePercentBaseContext; + import org.apache.fop.fo.Constants; @@ -96,39 +94,44 @@ public class BasicScaledBaselineTable implements ScaledBaselineTable, Constants * @return the baseline offset */ public int getBaseline(int baselineIdentifier) { - int offset = 0; + int offset; if (!isHorizontalWritingMode()) { switch (baselineIdentifier) { + default: case EN_TOP: case EN_TEXT_TOP: case EN_TEXT_BOTTOM: case EN_BOTTOM: log.warn("The given baseline is only supported for horizontal" + " writing modes"); - return 0; + offset = 0; + } + } else { + switch (baselineIdentifier) { + case EN_TOP: // fall through + case EN_BEFORE_EDGE: + offset = beforeEdgeOffset; + break; + case EN_TEXT_TOP: + case EN_TEXT_BEFORE_EDGE: + case EN_HANGING: + case EN_CENTRAL: + case EN_MIDDLE: + case EN_MATHEMATICAL: + case EN_ALPHABETIC: + case EN_IDEOGRAPHIC: + case EN_TEXT_BOTTOM: + case EN_TEXT_AFTER_EDGE: + offset = getBaselineDefaultOffset(baselineIdentifier) - dominantBaselineOffset; + break; + case EN_BOTTOM: // fall through + case EN_AFTER_EDGE: + offset = afterEdgeOffset; + break; + default: + offset = 0; + break; } - } - switch (baselineIdentifier) { - case EN_TOP: // fall through - case EN_BEFORE_EDGE: - offset = beforeEdgeOffset; - break; - case EN_TEXT_TOP: - case EN_TEXT_BEFORE_EDGE: - case EN_HANGING: - case EN_CENTRAL: - case EN_MIDDLE: - case EN_MATHEMATICAL: - case EN_ALPHABETIC: - case EN_IDEOGRAPHIC: - case EN_TEXT_BOTTOM: - case EN_TEXT_AFTER_EDGE: - offset = getBaselineDefaultOffset(baselineIdentifier) - dominantBaselineOffset; - break; - case EN_BOTTOM: // fall through - case EN_AFTER_EDGE: - offset = afterEdgeOffset; - break; } return offset; } @@ -168,6 +171,8 @@ public class BasicScaledBaselineTable implements ScaledBaselineTable, Constants case EN_TEXT_AFTER_EDGE: offset = depth; break; + default: + break; } return offset; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java index d5b2e5803..f342399fc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java @@ -35,6 +35,11 @@ public class BidiLayoutManager extends LeafNodeLayoutManager { private List children; + /** + * Construct bidi layout manager. + * @param node bidi override FO + * @param cLM parent layout manager + */ public BidiLayoutManager(BidiOverride node, InlineLayoutManager cLM) { super(node); setParent(cLM); @@ -53,10 +58,15 @@ public class BidiLayoutManager extends LeafNodeLayoutManager { */ } + /** @return number of children */ public int size() { return children.size(); } + /** + * @param index of child inline area + * @return a child inline area + */ public InlineArea get(int index) { return (InlineArea) children.get(index); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index a19680f51..66e162692 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -194,9 +194,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { areaInfo.alignmentContext, notifyPos(new LeafPosition(this, 0)), false)); if (areaInfo.bHyphenated) { - returnList.add - (new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true, - new LeafPosition(this, -1), false)); + returnList.add(new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true, + new LeafPosition(this, -1), false)); } } else { // adjustable letter space @@ -207,7 +206,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { new LeafPosition(this, -1), true)); returnList.add(new KnuthGlue(letterSpaceIPD.mult(areaInfo.iLScount), new LeafPosition(this, -1), true)); - returnList.add(new KnuthInlineBox(0, null, notifyPos(new LeafPosition(this, -1)), true)); + returnList.add ( + new KnuthInlineBox(0, null, notifyPos(new LeafPosition(this, -1)), true)); if (areaInfo.bHyphenated) { returnList.add(new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true, new LeafPosition(this, -1), false)); diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index d0dcc2bb8..c7eaa1820 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -67,6 +67,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager * Constructs a new ContentLayoutManager * * @param area The parent area + * @param parentLM the parent layout manager */ public ContentLayoutManager(Area area, LayoutManager parentLM) { holder = area; @@ -100,11 +101,12 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager } } + /** {@inheritDoc} */ public void initialize() { // Empty } - public void fillArea(LayoutManager curLM) { + private void fillArea(LayoutManager curLM) { int ipd = 1000000; @@ -150,6 +152,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager curLM.addAreas(contentPosIter, lc); } + /** {@inheritDoc} */ public void addAreas(PositionIterator posIter, LayoutContext context) { // add the content areas // the area width has already been adjusted, and it must remain unchanged @@ -163,6 +166,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager ((InlineArea)holder).setIPD(savedIPD); } + /** @return stack size */ public int getStackingSize() { return stackSize; } @@ -248,6 +252,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager } } + /** {@inheritDoc} */ public List getNextKnuthElements(LayoutContext context, int alignment) { List contentList = new LinkedList(); List returnedList; @@ -264,7 +269,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager Object obj = returnedList.remove(0); if (obj instanceof KnuthSequence) { KnuthSequence ks = (KnuthSequence)obj; - for (Iterator it = ks.iterator(); it.hasNext(); ) { + for (Iterator it = ks.iterator(); it.hasNext();) { contentElement = (KnuthElement)it.next(); stackSize += contentElement.getWidth(); contentList.add(contentElement); @@ -282,37 +287,46 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager return contentList; } + /** {@inheritDoc} */ public List addALetterSpaceTo(List oldList) { return oldList; } - /** - * Remove the word space represented by the given elements - * - * @param oldList the elements representing the word space - */ - public void removeWordSpace(List oldList) { - // do nothing - log.warn(this.getClass().getName() + " should not receive a call to removeWordSpace(list)"); + /** {@inheritDoc} */ + public List addALetterSpaceTo(List oldList, int depth) { + return addALetterSpaceTo(oldList); } + /** {@inheritDoc} */ public String getWordChars(Position pos) { return ""; } + /** {@inheritDoc} */ public void hyphenate(Position pos, HyphContext hc) { } + /** {@inheritDoc} */ public boolean applyChanges(List oldList) { return false; } - public List getChangedKnuthElements(List oldList, - /*int flaggedPenalty,*/ - int alignment) { + /** {@inheritDoc} */ + public boolean applyChanges(List oldList, int depth) { + return applyChanges(oldList); + } + + /** {@inheritDoc} */ + public List getChangedKnuthElements(List oldList, int alignment) { return null; } + /** {@inheritDoc} */ + public List getChangedKnuthElements(List oldList, int alignment, int depth) { + return getChangedKnuthElements(oldList, alignment); + } + + /** {@inheritDoc} */ public PageSequenceLayoutManager getPSLM() { return parentLM.getPSLM(); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java index 2cdc7a6fc..efa6f880a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java @@ -122,9 +122,8 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { /** * {@inheritDoc} */ - public List getChangedKnuthElements(List oldList, - int alignment) { - List returnedList = super.getChangedKnuthElements(oldList, alignment); + public List getChangedKnuthElements(List oldList, int alignment, int depth) { + List returnedList = super.getChangedKnuthElements(oldList, alignment, depth); addAnchor(returnedList); return returnedList; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/HyphContext.java b/src/java/org/apache/fop/layoutmgr/inline/HyphContext.java index 881608e08..ffc57fa16 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/HyphContext.java +++ b/src/java/org/apache/fop/layoutmgr/inline/HyphContext.java @@ -32,10 +32,14 @@ public class HyphContext { private int currentOffset = 0; private int currentIndex = 0; + /** + * @param hyphPoints number of hyphenation points + */ public HyphContext(int[] hyphPoints) { this.hyphPoints = hyphPoints; } + /** @return next hyphenation point */ public int getNextHyphPoint() { for (; currentIndex < hyphPoints.length; currentIndex++) { if (hyphPoints[currentIndex] > currentOffset) { @@ -45,6 +49,7 @@ public class HyphContext { return -1; // AT END! } + /** @return true if more hyphenation points */ public boolean hasMoreHyphPoints() { for (; currentIndex < hyphPoints.length; currentIndex++) { if (hyphPoints[currentIndex] > currentOffset) { @@ -54,6 +59,7 @@ public class HyphContext { return false; } + /** @param iCharsProcessed amount to extend offset */ public void updateOffset(int iCharsProcessed) { currentOffset += iCharsProcessed; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java index c47a7e682..7fe90f63c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java @@ -33,11 +33,20 @@ import org.apache.fop.fo.flow.InlineContainer; public class ICLayoutManager extends LeafNodeLayoutManager { private List childrenLM; + /** + * Construct inline container layout manager. + * @param node inline container FO node + * @param childLM child layout manager + */ public ICLayoutManager(InlineContainer node, List childLM) { super(node); childrenLM = childLM; } + /** + * @param index an integer + * @return an inline area or null + */ public InlineArea get(int index) { return null; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java index 338a58d9c..73235d2d1 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ImageLayout.java @@ -37,7 +37,7 @@ import org.apache.fop.fo.properties.LengthRangeProperty; public class ImageLayout implements Constants { /** logging instance */ - protected static Log log = LogFactory.getLog(ImageLayout.class); + protected static final Log log = LogFactory.getLog(ImageLayout.class); //Input private GraphicsProperties props; diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 26f8e3b97..1d3233112 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -239,7 +239,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public List getNextKnuthElements(LayoutContext context, int alignment) { + public List getNextKnuthElements // CSOK: MethodLength + (LayoutContext context, int alignment) { LayoutManager curLM; // the list returned by child LM @@ -434,7 +435,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // layout context given to the other LMs. List positionList = new LinkedList(); NonLeafPosition pos; - LayoutManager lastLM = null;// last child LM in this iterator + LayoutManager lastLM = null; // last child LM in this iterator Position lastPos = null; while (parentIter.hasNext()) { pos = (NonLeafPosition) parentIter.next(); @@ -531,10 +532,10 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { } /** {@inheritDoc} */ - public List getChangedKnuthElements(List oldList, int alignment) { + public List getChangedKnuthElements(List oldList, int alignment, int depth) { List returnedList = new LinkedList(); addKnuthElementsForBorderPaddingStart(returnedList); - returnedList.addAll(super.getChangedKnuthElements(oldList, alignment)); + returnedList.addAll(super.getChangedKnuthElements(oldList, alignment, depth)); addKnuthElementsForBorderPaddingEnd(returnedList); return returnedList; } @@ -553,13 +554,13 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { if (returnList instanceof BlockKnuthSequence) { return; } - CommonBorderPaddingBackground borderAndPadding = - ((InlineLevel)fobj).getCommonBorderPaddingBackground(); + CommonBorderPaddingBackground borderAndPadding + = ((InlineLevel)fobj).getCommonBorderPaddingBackground(); if (borderAndPadding != null) { int ipStart = borderAndPadding.getBorderStartWidth(false) + borderAndPadding.getPaddingStart(false, this); if (ipStart > 0) { - returnList.add(0,new KnuthBox(ipStart, getAuxiliaryPosition(), true)); + returnList.add(0, new KnuthBox(ipStart, getAuxiliaryPosition(), true)); } } } @@ -578,8 +579,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { if (returnList instanceof BlockKnuthSequence) { return; } - CommonBorderPaddingBackground borderAndPadding = - ((InlineLevel)fobj).getCommonBorderPaddingBackground(); + CommonBorderPaddingBackground borderAndPadding + = ((InlineLevel)fobj).getCommonBorderPaddingBackground(); if (borderAndPadding != null) { int ipEnd = borderAndPadding.getBorderEndWidth(false) + borderAndPadding.getPaddingEnd(false, this); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java index c9c65e769..f286fbf6c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelEventProducer.java @@ -32,7 +32,10 @@ public interface InlineLevelEventProducer extends EventProducer { /** * Provider class for the event producer. */ - class Provider { + final class Provider { + + private Provider() { + } /** * Returns an event producer. diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java index 525f0407d..ac829a2fc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java @@ -40,17 +40,21 @@ public interface InlineLevelLayoutManager extends LayoutManager { List addALetterSpaceTo(List oldList); /** - * Tell the LM to modify its data, removing the word space - * represented by the given elements + * Tell the LM to modify its data, adding a letter space + * to the word fragment represented by the given elements, + * and returning the corrected elements * - * @param oldList the elements representing the word space + * @param oldList the elements which must be given one more letter space + * @param depth the depth at which the Positions for this LM in oldList are found + * @return the new elements replacing the old ones */ - void removeWordSpace(List oldList); +List addALetterSpaceTo(List oldList, int depth); /** * Get the word chars corresponding to the given position. * * @param pos the position referring to the needed word chars. + * @return the word chars */ String getWordChars(Position pos); @@ -70,4 +74,23 @@ public interface InlineLevelLayoutManager extends LayoutManager { */ boolean applyChanges(List oldList); + /** + * Tell the LM to apply the changes due to hyphenation + * + * @param oldList the list of the old elements the changes refer to + * @param depth the depth at which the Positions for this LM in oldList are found + * @return true if the LM had to change its data, false otherwise + */ + boolean applyChanges(List oldList, int depth); + + /** + * Get a sequence of KnuthElements representing the content + * of the node assigned to the LM, after changes have been applied + * @param oldList the elements to replace + * @param alignment the desired text alignment + * @param depth the depth at which the Positions for this LM in oldList are found + * @return the updated list of KnuthElements + **/ + List getChangedKnuthElements(List oldList, int alignment, int depth); + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 375afb82f..d8c4966d0 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -46,16 +46,27 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager implements InlineLevelLayoutManager { + /** + * A stacking iterator. + */ protected static class StackingIter extends PositionIterator { StackingIter(Iterator parentIter) { super(parentIter); } + /** + * @param nextObj the next object + * @return layout manager of next object + */ protected LayoutManager getLM(Object nextObj) { return ((Position) nextObj).getLM(); } + /** + * @param nextObj the next object + * @return position of next object + */ protected Position getPos(Object nextObj) { return ((Position) nextObj); } @@ -206,54 +217,48 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager /** {@inheritDoc} */ public List addALetterSpaceTo(List oldList) { + return addALetterSpaceTo(oldList, 0); + } + + /** {@inheritDoc} */ + public List addALetterSpaceTo(List oldList, int thisDepth) { // old list contains only a box, or the sequence: box penalty glue box - ListIterator oldListIterator = oldList.listIterator(); - KnuthElement element = null; - // "unwrap" the Position stored in each element of oldList - while (oldListIterator.hasNext()) { - element = (KnuthElement) oldListIterator.next(); - element.setPosition(element.getPosition().getPosition()); - } + ListIterator oldListIterator = oldList.listIterator(oldList.size()); + KnuthElement element = (KnuthElement) oldListIterator.previous(); + int depth = thisDepth + 1; // The last element may not have a layout manager (its position == null); // this may happen if it is a padding box; see bug 39571. - InlineLevelLayoutManager LM = - (InlineLevelLayoutManager) element.getLayoutManager(); - if (LM != null) { - oldList = LM.addALetterSpaceTo(oldList); + Position pos = element.getPosition(); + InlineLevelLayoutManager lm = null; + if (pos != null) { + lm = (InlineLevelLayoutManager) pos.getLM(depth); } - // "wrap" again the Position stored in each element of oldList + if (lm == null) { + return oldList; + } + oldList = lm.addALetterSpaceTo(oldList, depth); + // "wrap" the Position stored in new elements of oldList oldListIterator = oldList.listIterator(); while (oldListIterator.hasNext()) { element = (KnuthElement) oldListIterator.next(); - element.setPosition(notifyPos(new NonLeafPosition(this, element.getPosition()))); + pos = element.getPosition(); + lm = null; + if (pos != null) { + lm = (InlineLevelLayoutManager) pos.getLM(thisDepth); + } + // in old elements the position at thisDepth is a position for this LM + // only wrap new elements + if (lm != this) { + // new element, wrap position + element.setPosition(notifyPos(new NonLeafPosition(this, element.getPosition()))); + } } return oldList; } - /** - * remove the AreaInfo object represented by the given elements, - * so that it won't generate any element when getChangedKnuthElements - * will be called - * - * @param oldList the elements representing the word space - */ - public void removeWordSpace(List oldList) { - ListIterator oldListIterator = oldList.listIterator(); - KnuthElement element = null; - // "unwrap" the Position stored in each element of oldList - while (oldListIterator.hasNext()) { - element = (KnuthElement) oldListIterator.next(); - element.setPosition(element.getPosition().getPosition()); - } - - ((InlineLevelLayoutManager) - element.getLayoutManager()).removeWordSpace(oldList); - - } - /** {@inheritDoc} */ public String getWordChars(Position pos) { Position newPos = pos.getPosition(); @@ -269,16 +274,14 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager /** {@inheritDoc} */ public boolean applyChanges(List oldList) { - // "unwrap" the Positions stored in the elements + return applyChanges(oldList, 0); + } + + /** {@inheritDoc} */ + public boolean applyChanges(List oldList, int depth) { ListIterator oldListIterator = oldList.listIterator(); KnuthElement oldElement; - while (oldListIterator.hasNext()) { - oldElement = (KnuthElement) oldListIterator.next(); - oldElement.setPosition - (oldElement.getPosition().getPosition()); - } - // reset the iterator - oldListIterator = oldList.listIterator(); + depth += 1; InlineLevelLayoutManager prevLM = null; InlineLevelLayoutManager currLM; @@ -287,7 +290,12 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager boolean bSomethingChanged = false; while (oldListIterator.hasNext()) { oldElement = (KnuthElement) oldListIterator.next(); - currLM = (InlineLevelLayoutManager) oldElement.getLayoutManager(); + Position pos = oldElement.getPosition(); + if (pos == null) { + currLM = null; + } else { + currLM = (InlineLevelLayoutManager) pos.getLM(depth); + } // initialize prevLM if (prevLM == null) { prevLM = currLM; @@ -298,38 +306,34 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager prevLM = currLM; } else if (oldListIterator.hasNext()) { bSomethingChanged - = prevLM.applyChanges(oldList.subList(fromIndex - , oldListIterator.previousIndex())) + = prevLM.applyChanges(oldList.subList(fromIndex, + oldListIterator.previousIndex()), + depth) || bSomethingChanged; prevLM = currLM; fromIndex = oldListIterator.previousIndex(); } else if (currLM == prevLM) { bSomethingChanged = (prevLM != null) - && prevLM.applyChanges(oldList.subList(fromIndex, oldList.size())) + && prevLM.applyChanges(oldList.subList(fromIndex, + oldList.size()), depth) || bSomethingChanged; } else { bSomethingChanged - = prevLM.applyChanges(oldList.subList(fromIndex - , oldListIterator.previousIndex())) + = prevLM.applyChanges(oldList.subList(fromIndex, + oldListIterator.previousIndex()), + depth) || bSomethingChanged; if (currLM != null) { bSomethingChanged - = currLM.applyChanges(oldList.subList(oldListIterator.previousIndex() - , oldList.size())) + = currLM.applyChanges(oldList.subList(oldListIterator.previousIndex(), + oldList.size()), depth) || bSomethingChanged; } } } } - // "wrap" again the Positions stored in the elements - oldListIterator = oldList.listIterator(); - while (oldListIterator.hasNext()) { - oldElement = (KnuthElement) oldListIterator.next(); - oldElement.setPosition - (notifyPos(new NonLeafPosition(this, oldElement.getPosition()))); - } return bSomethingChanged; } @@ -337,16 +341,15 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager * {@inheritDoc} */ public List getChangedKnuthElements(List oldList, int alignment) { + return getChangedKnuthElements(oldList, alignment, 0); + } + + /** {@inheritDoc} */ + public List getChangedKnuthElements(List oldList, int alignment, int depth) { // "unwrap" the Positions stored in the elements ListIterator oldListIterator = oldList.listIterator(); KnuthElement oldElement; - while (oldListIterator.hasNext()) { - oldElement = (KnuthElement) oldListIterator.next(); - oldElement.setPosition - (oldElement.getPosition().getPosition()); - } - // reset the iterator - oldListIterator = oldList.listIterator(); + depth += 1; KnuthElement returnedElement; LinkedList returnedList = new LinkedList(); @@ -357,7 +360,12 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager while (oldListIterator.hasNext()) { oldElement = (KnuthElement) oldListIterator.next(); - currLM = (InlineLevelLayoutManager) oldElement.getLayoutManager(); + Position pos = oldElement.getPosition(); + if (pos == null) { + currLM = null; + } else { + currLM = (InlineLevelLayoutManager) pos.getLM(depth); + } if (prevLM == null) { prevLM = currLM; } @@ -366,33 +374,31 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager if (oldListIterator.hasNext()) { returnedList.addAll (prevLM.getChangedKnuthElements - (oldList.subList(fromIndex, - oldListIterator.previousIndex()), - /*flaggedPenalty,*/ alignment)); + (oldList.subList(fromIndex, oldListIterator.previousIndex()), + alignment, depth)); prevLM = currLM; fromIndex = oldListIterator.previousIndex(); } else if (currLM == prevLM) { returnedList.addAll (prevLM.getChangedKnuthElements (oldList.subList(fromIndex, oldList.size()), - /*flaggedPenalty,*/ alignment)); + alignment, depth)); } else { returnedList.addAll (prevLM.getChangedKnuthElements - (oldList.subList(fromIndex, - oldListIterator.previousIndex()), - /*flaggedPenalty,*/ alignment)); + (oldList.subList(fromIndex, oldListIterator.previousIndex()), + alignment, depth)); if (currLM != null) { returnedList.addAll (currLM.getChangedKnuthElements - (oldList.subList(oldListIterator.previousIndex(), - oldList.size()), - /*flaggedPenalty,*/ alignment)); + (oldList.subList(oldListIterator.previousIndex(), oldList.size()), + alignment, depth)); } } } } + // this is a new list // "wrap" the Position stored in each element of returnedList ListIterator listIter = returnedList.listIterator(); while (listIter.hasNext()) { @@ -401,6 +407,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager (notifyPos(new NonLeafPosition(this, returnedElement.getPosition()))); returnList.add(returnedElement); } + return returnList; } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java b/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java index 7b08a67db..312a58fc0 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java +++ b/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java @@ -23,6 +23,9 @@ import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.Position; +/** + * A knuth inline box. + */ public class KnuthInlineBox extends KnuthBox { private FootnoteBodyLayoutManager footnoteBodyLM = null; @@ -36,7 +39,8 @@ public class KnuthInlineBox extends KnuthBox { * @param pos the Position stored in this box * @param auxiliary is this box auxiliary? */ - public KnuthInlineBox(int width, AlignmentContext alignmentContext, Position pos, boolean auxiliary) { + public KnuthInlineBox + (int width, AlignmentContext alignmentContext, Position pos, boolean auxiliary) { super(width, pos, auxiliary); this.alignmentContext = alignmentContext; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index c5f38134b..2a58b2018 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -344,4 +344,10 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { this.contentAreaIPD = contentAreaIPD; } + /** {@inheritDoc} */ + public void reset() { + childLMs.clear(); + super.reset(); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index e74b51d96..f3749f2ed 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -48,6 +48,7 @@ import org.apache.fop.traits.MinOptMax; * an exception to this rule.) * This class can be extended to handle the creation and adding of the * inline area. + * TODO [GA] replace use of hungarian notation with normalized java naming */ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager implements InlineLevelLayoutManager { @@ -55,7 +56,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager /** * logging instance */ - protected static Log log = LogFactory.getLog(LeafNodeLayoutManager.class); + protected static final Log log = LogFactory.getLog(LeafNodeLayoutManager.class); /** * The inline area that this leafnode will add. @@ -75,11 +76,22 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager * Store information about the inline area */ protected class AreaInfo { + /** letter space count */ protected short iLScount; + /** ipd of area */ protected MinOptMax ipdArea; + /** true if hyphenated */ protected boolean bHyphenated; + /** alignment context */ protected AlignmentContext alignmentContext; + /** + * Construct an area information item. + * @param iLS letter space count + * @param ipd inline progression dimension + * @param bHyph true if hyphenated + * @param alignmentContext an alignment context + */ public AreaInfo(short iLS, MinOptMax ipd, boolean bHyph, AlignmentContext alignmentContext) { iLScount = iLS; @@ -285,13 +297,11 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** - * Remove the word space represented by the given elements - * - * @param oldList the elements representing the word space + * {@inheritDoc} + * Only TextLM has a meaningful implementation of this method */ - public void removeWordSpace(List oldList) { - // do nothing - log.warn(this.getClass().getName() + " should not receive a call to removeWordSpace(list)"); + public List addALetterSpaceTo(List oldList, int depth) { + return addALetterSpaceTo(oldList); } /** {@inheritDoc} */ @@ -309,9 +319,24 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager return false; } + /** + * {@inheritDoc} + * Only TextLM has a meaningful implementation of this method + */ + public boolean applyChanges(List oldList, int depth) { + return applyChanges(oldList); + } + + /** + * {@inheritDoc} + * No subclass has a meaningful implementation of this method + */ + public List getChangedKnuthElements(List oldList, int alignment, int depth) { + return getChangedKnuthElements(oldList, alignment); + } + /** {@inheritDoc} */ - public List getChangedKnuthElements(List oldList, - int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 9e17a0368..2611a8cd5 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -27,7 +27,6 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.area.Area; import org.apache.fop.area.LineArea; import org.apache.fop.area.Trait; @@ -82,60 +81,45 @@ public class LineLayoutManager extends InlineStackingLayoutManager implements BlockLevelLayoutManager { /** + * this constant is used to create elements when text-align is center: + * every TextLM descendant of LineLM must use the same value, + * otherwise the line breaking algorithm does not find the right + * break point + */ + public static final int DEFAULT_SPACE_WIDTH = 3336; + + /** * logging instance */ private static Log log = LogFactory.getLog(LineLayoutManager.class); - private Block fobj; + private final Block fobj; private boolean isFirstInBlock; - /** {@inheritDoc} */ - public void initialize() { - textAlignment = fobj.getTextAlign(); - textAlignmentLast = fobj.getTextAlignLast(); - textIndent = fobj.getTextIndent(); - lastLineEndIndent = fobj.getLastLineEndIndent(); - hyphenationProperties = fobj.getCommonHyphenation(); - hyphenationLadderCount = fobj.getHyphenationLadderCount(); - wrapOption = fobj.getWrapOption(); - whiteSpaceTreament = fobj.getWhitespaceTreatment(); - // - effectiveAlignment = getEffectiveAlignment(textAlignment, textAlignmentLast); - isFirstInBlock = (this == getParent().getChildLMs().get(0)); - } - - private int getEffectiveAlignment(int alignment, int alignmentLast) { - if (textAlignment != EN_JUSTIFY && textAlignmentLast == EN_JUSTIFY) { - return 0; - } else { - return textAlignment; - } - } - /** * Private class to store information about inline breaks. * Each value holds the start and end indexes into a List of * inline break positions. */ private static class LineBreakPosition extends LeafPosition { - private int parIndex; // index of the Paragraph this Position refers to - private int startIndex; //index of the first element this Position refers to - private int availableShrink; - private int availableStretch; - private int difference; - private double dAdjust; // Percentage to adjust (stretch or shrink) - private double ipdAdjust; // Percentage to adjust (stretch or shrink) - private int startIndent; - private int lineHeight; - private int lineWidth; - private int spaceBefore; - private int spaceAfter; - private int baseline; - - LineBreakPosition(LayoutManager lm, int index, int startIndex, int breakIndex, - int shrink, int stretch, int diff, - double ipdA, double adjust, int ind, - int lh, int lw, int sb, int sa, int bl) { + private final int parIndex; // index of the Paragraph this Position refers to + private final int startIndex; //index of the first element this Position refers to + private final int availableShrink; + private final int availableStretch; + private final int difference; + private final double dAdjust; // Percentage to adjust (stretch or shrink) + private final double ipdAdjust; // Percentage to adjust (stretch or shrink) + private final int startIndent; + private final int lineHeight; + private final int lineWidth; + private final int spaceBefore; + private final int spaceAfter; + private final int baseline; + + LineBreakPosition( // CSOK: ParameterNumber + LayoutManager lm, int index, int startIndex, int breakIndex, + int shrink, int stretch, int diff, double ipdA, double adjust, int ind, + int lh, int lw, int sb, int sa, int bl) { super(lm, breakIndex); availableShrink = shrink; availableStretch = stretch; @@ -166,9 +150,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager private int whiteSpaceTreament; //private LayoutProps layoutProps; - private Length lineHeight; - private int lead; - private int follow; + private final Length lineHeight; + private final int lead; + private final int follow; private AlignmentContext alignmentContext; private List knuthParagraphs; @@ -183,24 +167,15 @@ public class LineLayoutManager extends InlineStackingLayoutManager private boolean hyphenationPerformed; /** - * this constant is used to create elements when text-align is center: - * every TextLM descendant of LineLM must use the same value, - * otherwise the line breaking algorithm does not find the right - * break point - */ - public static final int DEFAULT_SPACE_WIDTH = 3336; - - - /** * This class is used to remember * which was the first element in the paragraph * returned by each LM. */ - private class Update { - private InlineLevelLayoutManager inlineLM; - private int firstIndex; + private final class Update { + private final InlineLevelLayoutManager inlineLM; + private final int firstIndex; - public Update(InlineLevelLayoutManager lm, int index) { + private Update(InlineLevelLayoutManager lm, int index) { inlineLM = lm; firstIndex = index; } @@ -208,6 +183,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager // this class represents a paragraph private class Paragraph extends InlineKnuthSequence { + + private static final long serialVersionUID = 5862072380375189105L; + /** Number of elements to ignore at the beginning of the list. */ private int ignoreAtStart = 0; /** Number of elements to ignore at the end of the list. */ @@ -215,12 +193,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager // space at the end of the last line (in millipoints) private MinOptMax lineFiller; - private int textAlignment; - private int textAlignmentLast; - private int textIndent; - private int lastLineEndIndent; + private final int textAlignment; + private final int textAlignmentLast; + private final int textIndent; + private final int lastLineEndIndent; // the LM which created the paragraph - private LineLayoutManager layoutManager; + private final LineLayoutManager layoutManager; Paragraph(LineLayoutManager llm, int alignment, int alignmentLast, int indent, int endIndent) { @@ -232,6 +210,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager lastLineEndIndent = endIndent; } + @Override public void startSequence() { // set the minimum amount of empty space at the end of the // last line @@ -266,6 +245,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } } + @Override public KnuthSequence endSequence() { if (this.size() > ignoreAtStart) { if (textAlignment == EN_CENTER @@ -315,21 +295,19 @@ public class LineLayoutManager extends InlineStackingLayoutManager } private class LineBreakingAlgorithm extends BreakingAlgorithm { - private LineLayoutManager thisLLM; - private int pageAlignment; + private final LineLayoutManager thisLLM; + private final int pageAlignment; private int activePossibility; private int addedPositions; - private int textIndent; - private int lineHeight; - private int lead; - private int follow; + private final int textIndent; + private final int lineHeight; + private final int lead; + private final int follow; private static final double MAX_DEMERITS = 10e6; - public LineBreakingAlgorithm (int pageAlign, - int textAlign, int textAlignLast, - int indent, int fillerWidth, - int lh, int ld, int fl, boolean first, - int maxFlagCount, LineLayoutManager llm) { + public LineBreakingAlgorithm( // CSOK: ParameterNumber + int pageAlign, int textAlign, int textAlignLast, int indent, int fillerWidth, + int lh, int ld, int fl, boolean first, int maxFlagCount, LineLayoutManager llm) { super(textAlign, textAlignLast, first, false, maxFlagCount); pageAlignment = pageAlign; textIndent = indent; @@ -340,6 +318,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager activePossibility = -1; } + @Override public void updateData1(int lineCount, double demerits) { lineLayouts.addPossibility(lineCount, demerits); if (log.isTraceEnabled()) { @@ -347,6 +326,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } } + @Override public void updateData2(KnuthNode bestActiveNode, KnuthSequence par, int total) { @@ -357,7 +337,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager int textAlign = (bestActiveNode.line < total) ? alignment : alignmentLast; indent += (textAlign == Constants.EN_CENTER) ? difference / 2 : (textAlign == Constants.EN_END) ? difference : 0; - indent += (bestActiveNode.line == 1 && indentFirstPart && isFirstInBlock) ? textIndent : 0; + indent += (bestActiveNode.line == 1 && indentFirstPart && isFirstInBlock) + ? textIndent : 0; double ratio = (textAlign == Constants.EN_JUSTIFY || difference < 0 && -difference <= bestActiveNode.availableShrink) ? bestActiveNode.adjustRatio : 0; @@ -405,14 +386,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager activePossibility = -1; } - private LineBreakPosition makeLineBreakPosition(KnuthSequence par, - int firstElementIndex, - int lastElementIndex, - int availableShrink, - int availableStretch, - int difference, - double ratio, - int indent) { + private LineBreakPosition makeLineBreakPosition( // CSOK: ParameterNumber + KnuthSequence par, int firstElementIndex, int lastElementIndex, int availableShrink, + int availableStretch, int difference, double ratio, int indent) { // line height calculation - spaceBefore may differ from spaceAfter // by 1mpt due to rounding int spaceBefore = (lineHeight - lead - follow) / 2; @@ -493,6 +469,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } } + @Override protected int filterActiveNodes() { KnuthNode bestActiveNode = null; @@ -501,7 +478,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager //log.debug("LBA.filterActiveNodes> " + activeNodeCount + " layouts"); for (int i = startLine; i < endLine; i++) { for (KnuthNode node = getNode(i); node != null; node = node.next) { - //log.debug(" + lines = " + node.line + " demerits = " + node.totalDemerits); + //log.debug(" + lines = " + //+ node.line + " demerits = " + node.totalDemerits); bestActiveNode = compareNodes(bestActiveNode, node); } } @@ -514,10 +492,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager //if (false) { if (node.line != bestActiveNode.line && node.totalDemerits > MAX_DEMERITS) { - //log.debug(" XXX lines = " + node.line + " demerits = " + node.totalDemerits); + //log.debug(" XXX lines = " + //+ node.line + " demerits = " + node.totalDemerits); removeNode(i, node); } else { - //log.debug(" ok lines = " + node.line + " demerits = " + node.totalDemerits); + //log.debug(" ok lines = " + //+ node.line + " demerits = " + node.totalDemerits); } } } @@ -561,12 +541,39 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** {@inheritDoc} */ + @Override + public void initialize() { + textAlignment = fobj.getTextAlign(); + textAlignmentLast = fobj.getTextAlignLast(); + textIndent = fobj.getTextIndent(); + lastLineEndIndent = fobj.getLastLineEndIndent(); + hyphenationProperties = fobj.getCommonHyphenation(); + hyphenationLadderCount = fobj.getHyphenationLadderCount(); + wrapOption = fobj.getWrapOption(); + whiteSpaceTreament = fobj.getWhitespaceTreatment(); + // + effectiveAlignment = getEffectiveAlignment(textAlignment, textAlignmentLast); + isFirstInBlock = (this == getParent().getChildLMs().get(0)); + } + + private int getEffectiveAlignment(int alignment, int alignmentLast) { + if (textAlignment != EN_JUSTIFY && textAlignmentLast == EN_JUSTIFY) { + return 0; + } else { + return textAlignment; + } + } + + /** {@inheritDoc} */ + @Override public List getNextKnuthElements(LayoutContext context, int alignment) { - FontInfo fi = fobj.getFOEventHandler().getFontInfo(); - FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); - Font fs = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); - alignmentContext = new AlignmentContext(fs, lineHeight.getValue(this), - context.getWritingMode()); + if (alignmentContext == null) { + FontInfo fi = fobj.getFOEventHandler().getFontInfo(); + FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); + Font fs = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); + alignmentContext = new AlignmentContext(fs, lineHeight.getValue(this), + context.getWritingMode()); + } context.setAlignmentContext(alignmentContext); ipd = context.getRefIPD(); @@ -592,6 +599,15 @@ public class LineLayoutManager extends InlineStackingLayoutManager return createLineBreaks(context.getBPAlignment(), context); } + /** + * Get a sequence of KnuthElements representing the content + * of the node assigned to the LM. + * @param context the LayoutContext used to store layout information + * @param alignment the desired text alignment + * @param restartPosition position at restart + * @return the list of KnuthElements + * @see LayoutManager#getNextKnuthElements(LayoutContext,int) + */ public List getNextKnuthElements(LayoutContext context, int alignment, LeafPosition restartPosition) { log.trace("Restarting line breaking from index " + restartPosition.getIndex()); @@ -705,7 +721,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager // finish last paragraph if it was closed with a linefeed if (lastElement.isPenalty() - && ((KnuthPenalty) lastElement).getPenalty() == -KnuthPenalty.INFINITE) { + && ((KnuthPenalty) lastElement).getPenalty() + == -KnuthPenalty.INFINITE) { // a penalty item whose value is -inf // represents a preserved linefeed, // which forces a line break @@ -760,7 +777,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager // we only need an entry in lineLayoutsList. llPoss = new LineLayoutPossibilities(); } else { - llPoss = findOptimalBreakingPoints(alignment, (Paragraph) seq); + llPoss = findOptimalBreakingPoints(alignment, (Paragraph) seq, + !paragraphsIterator.hasNext()); } lineLayoutsList[i] = llPoss; } @@ -772,16 +790,17 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** - * Fint the optimal linebreaks for a paragraph + * Find the optimal linebreaks for a paragraph * @param alignment alignment of the paragraph * @param currPar the Paragraph for which the linebreaks are found + * @param isLastPar flag indicating whether currPar is the last paragraph * @return the line layout possibilities for the paragraph */ - private LineLayoutPossibilities findOptimalBreakingPoints(int alignment, Paragraph currPar) { + private LineLayoutPossibilities findOptimalBreakingPoints(int alignment, Paragraph currPar, + boolean isLastPar) { // use the member lineLayouts, which is read by LineBreakingAlgorithm.updateData1 and 2 lineLayouts = new LineLayoutPossibilities(); double maxAdjustment = 1; - int iBPcount = 0; LineBreakingAlgorithm alg = new LineBreakingAlgorithm(alignment, textAlignment, textAlignmentLast, textIndent.getValue(this), currPar.lineFiller.getOpt(), @@ -790,26 +809,26 @@ public class LineLayoutManager extends InlineStackingLayoutManager hyphenationLadderCount.getEnum() == EN_NO_LIMIT ? 0 : hyphenationLadderCount.getValue(), this); - - if (hyphenationProperties.hyphenate.getEnum() == EN_TRUE - && fobj.getWrapOption() != EN_NO_WRAP && !hyphenationPerformed) { - hyphenationPerformed = true; + alg.setConstantLineWidth(ipd); + boolean canWrap = (wrapOption != EN_NO_WRAP); + boolean canHyphenate = (canWrap && hyphenationProperties.hyphenate.getEnum() == EN_TRUE); + + // find hyphenation points, if allowed and not yet done + if (canHyphenate && !hyphenationPerformed) { + // make sure findHyphenationPoints() is bypassed if + // the method is called twice (e.g. due to changing page-ipd) + hyphenationPerformed = isLastPar; findHyphenationPoints(currPar); } - // first try - int allowedBreaks; - if (wrapOption == EN_NO_WRAP) { - allowedBreaks = BreakingAlgorithm.ONLY_FORCED_BREAKS; - } else { - allowedBreaks = BreakingAlgorithm.NO_FLAGGED_PENALTIES; - } - alg.setConstantLineWidth(ipd); - iBPcount = alg.findBreakingPoints(currPar, - maxAdjustment, false, allowedBreaks); - if (iBPcount == 0 || alignment == EN_JUSTIFY) { + // first try: do not consider hyphenation points as legal breaks + int allowedBreaks = (canWrap ? BreakingAlgorithm.NO_FLAGGED_PENALTIES + : BreakingAlgorithm.ONLY_FORCED_BREAKS); + int breakingPoints = alg.findBreakingPoints(currPar, maxAdjustment, false, allowedBreaks); + + if (breakingPoints == 0 || alignment == EN_JUSTIFY) { // if the first try found a set of breaking points, save them - if (iBPcount > 0) { + if (breakingPoints > 0) { alg.resetAlgorithm(); lineLayouts.savePossibilities(false); } else { @@ -818,9 +837,10 @@ public class LineLayoutManager extends InlineStackingLayoutManager } // now try something different - log.debug("Hyphenation possible? " + (hyphenationProperties.hyphenate.getEnum() == EN_TRUE)); - if (hyphenationProperties.hyphenate.getEnum() == EN_TRUE - && !(allowedBreaks == BreakingAlgorithm.ONLY_FORCED_BREAKS)) { + log.debug("Hyphenation possible? " + canHyphenate); + // Note: if allowedBreaks is guaranteed to be unchanged by alg.findBreakingPoints(), + // the below check can be simplified to 'if (canHyphenate) ...' + if (canHyphenate && allowedBreaks != BreakingAlgorithm.ONLY_FORCED_BREAKS) { // consider every hyphenation point as a legal break allowedBreaks = BreakingAlgorithm.ALL_BREAKS; } else { @@ -828,63 +848,22 @@ public class LineLayoutManager extends InlineStackingLayoutManager maxAdjustment = 5; } - if ((iBPcount - = alg.findBreakingPoints(currPar, - maxAdjustment, false, allowedBreaks)) == 0) { + breakingPoints = alg.findBreakingPoints(currPar, maxAdjustment, false, allowedBreaks); + if (breakingPoints == 0) { // the second try failed too, try with a huge threshold - // and force the algorithm to find - // a set of breaking points + // and force the algorithm to find a set of breaking points if (log.isDebugEnabled()) { log.debug("No set of breaking points found with maxAdjustment = " - + maxAdjustment - + (hyphenationProperties.hyphenate.getEnum() == EN_TRUE - ? " and hyphenation" : "")); + + maxAdjustment + (canHyphenate ? " and hyphenation" : "")); } maxAdjustment = 20; - iBPcount - = alg.findBreakingPoints(currPar, - maxAdjustment, true, allowedBreaks); + alg.findBreakingPoints(currPar, maxAdjustment, true, allowedBreaks); } // use non-hyphenated breaks, when possible lineLayouts.restorePossibilities(); - - /* extension (not in the XSL FO recommendation): if vertical alignment - is justify and the paragraph has only one layout, try using - shorter or longer lines */ - //TODO This code snippet is disabled. Reenable? - if (false && alignment == EN_JUSTIFY && textAlignment == EN_JUSTIFY) { - //log.debug("LLM.getNextKnuthElements> layouts with more lines? " + lineLayouts.canUseMoreLines()); - //log.debug(" layouts with fewer lines? " + lineLayouts.canUseLessLines()); - if (!lineLayouts.canUseMoreLines()) { - alg.resetAlgorithm(); - lineLayouts.savePossibilities(true); - // try with shorter lines - int savedLineWidth = ipd; - ipd = (int) (ipd * 0.95); - iBPcount = alg.findBreakingPoints(currPar, - maxAdjustment, true, allowedBreaks); - // use normal lines, when possible - lineLayouts.restorePossibilities(); - ipd = savedLineWidth; - } - if (!lineLayouts.canUseLessLines()) { - alg.resetAlgorithm(); - lineLayouts.savePossibilities(true); - // try with longer lines - int savedLineWidth = ipd; - ipd = (int) (ipd * 1.05); - alg.setConstantLineWidth(ipd); - iBPcount = alg.findBreakingPoints(currPar, - maxAdjustment, true, allowedBreaks); - // use normal lines, when possible - lineLayouts.restorePossibilities(); - ipd = savedLineWidth; - } - //log.debug("LLM.getNextKnuthElements> now, layouts with more lines? " + lineLayouts.canUseMoreLines()); - //log.debug(" now, layouts with fewer lines? " + lineLayouts.canUseLessLines()); - } } + return lineLayouts; } @@ -1068,7 +1047,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager //log.debug("first=" + firstLines + " inner=" + innerLines // + " optional=" + optionalLines + " eliminable=" + eliminableLines // + " last=" + lastLines - // + " (condOpt=" + conditionalOptionalLines + " condEl=" + conditionalEliminableLines + ")"); + // + " (condOpt=" + conditionalOptionalLines + // + " condEl=" + conditionalEliminableLines + ")"); // creation of the elements: // first group of lines @@ -1172,8 +1152,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager //} //int lineNumberDifference = (int)((double) totalAdj / constantLineHeight); int lineNumberDifference = (int) Math.round((double) adj / constantLineHeight - + (adj > 0 ? - 0.4 : 0.4)); - //log.debug(" LLM> variazione calcolata = " + ((double) totalAdj / constantLineHeight) + " variazione applicata = " + lineNumberDifference); + + (adj > 0 ? -0.4 : 0.4)); + //log.debug(" LLM> variazione calcolata = " + ((double) totalAdj / constantLineHeight) + //+ " variazione applicata = " + lineNumberDifference); LineLayoutPossibilities llPoss; llPoss = lineLayoutsList[pos.getLeafPos()]; lineNumberDifference = llPoss.applyLineCountAdjustment(lineNumberDifference); @@ -1185,6 +1166,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** {@inheritDoc} */ + @Override + public List getChangedKnuthElements(List oldList, int alignment, int depth) { + return getChangedKnuthElements(oldList, alignment); + } + + /** {@inheritDoc} */ public List getChangedKnuthElements(List oldList, int alignment) { List returnList = new LinkedList(); for (int p = 0; p < knuthParagraphs.size(); p++) { @@ -1198,10 +1185,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); } LineBreakPosition lbp = (LineBreakPosition) llPoss.getChosenPosition(i); - //log.debug("LLM.getChangedKnuthElements> lineWidth= " + lbp.lineWidth + " difference= " + lbp.difference); - //log.debug(" shrink= " + lbp.availableShrink + " stretch= " + lbp.availableStretch); - - //log.debug("linewidth= " + lbp.lineWidth + " difference= " + lbp.difference + " indent= " + lbp.startIndent); + //log.debug("LLM.getChangedKnuthElements> lineWidth= " + // + lbp.lineWidth + " difference= " + lbp.difference); + //log.debug(" shrink= " + // + lbp.availableShrink + " stretch= " + lbp.availableStretch); + //log.debug("linewidth= " + lbp.lineWidth + " difference= " + //+ lbp.difference + " indent= " + lbp.startIndent); MinOptMax contentIPD; if (alignment == EN_JUSTIFY) { contentIPD = MinOptMax.getInstance( @@ -1213,7 +1202,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager } else if (alignment == EN_END) { contentIPD = MinOptMax.getInstance(lbp.lineWidth - lbp.startIndent); } else { - contentIPD = MinOptMax.getInstance(lbp.lineWidth - lbp.difference + lbp.startIndent); + contentIPD + = MinOptMax.getInstance(lbp.lineWidth - lbp.difference + lbp.startIndent); } returnList.add(new KnuthBlockBox(lbp.lineHeight, contentIPD, (lbp.ipdAdjust != 0 ? lbp.lineWidth - lbp.difference : 0), @@ -1256,8 +1246,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager } else if (currLM == null) { break; } - //TODO Something's not right here. See block_hyphenation_linefeed_preserve.xml - //for more info: see also https://issues.apache.org/bugzilla/show_bug.cgi?id=38264 // collect word fragments, ignoring auxiliary elements; // each word fragment was created by a different TextLM @@ -1366,6 +1354,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param isNotFirst ignored * @return always true */ + @Override protected boolean hasLeadingFence(boolean isNotFirst) { return true; } @@ -1375,6 +1364,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param isNotLast ignored * @return always true */ + @Override protected boolean hasTrailingFence(boolean isNotLast) { return true; } @@ -1397,6 +1387,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager = Hyphenator.hyphenate(hyphenationProperties.language.getString(), hyphenationProperties.country.getString(), getFObj().getUserAgent().getFactory().getHyphenationTreeResolver(), + getFObj().getUserAgent().getFactory().getHyphPatNames(), sbChars.toString(), hyphenationProperties.hyphenationRemainCharacterCount.getValue(), hyphenationProperties.hyphenationPushCharacterCount.getValue()); @@ -1421,6 +1412,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param parentIter the iterator of break positions * @param context the context for adding areas */ + @Override public void addAreas(PositionIterator parentIter, LayoutContext context) { while (parentIter.hasNext()) { @@ -1449,8 +1441,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager */ private void addInlineArea(LayoutContext context, LineBreakPosition lbp, boolean isLastPosition) { - // the TLM which created the last KnuthElement in this line - LayoutManager lastLM = null; KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(lbp.parIndex); int startElementIndex = lbp.startIndex; @@ -1482,15 +1472,16 @@ public class LineLayoutManager extends InlineStackingLayoutManager } } - // Remove trailing spaces if allowed so - if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED - || whiteSpaceTreament == EN_IGNORE - || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) { - // ignore the last element in the line if it is a KnuthGlue object - ListIterator seqIterator = seq.listIterator(endElementIndex); - KnuthElement lastElement = (KnuthElement) seqIterator.next(); - lastLM = lastElement.getLayoutManager(); - if (lastElement.isGlue()) { + // ignore the last element in the line if it is a KnuthGlue object + ListIterator seqIterator = seq.listIterator(endElementIndex); + KnuthElement lastElement = (KnuthElement) seqIterator.next(); + // the TLM which created the last KnuthElement in this line + LayoutManager lastLM = lastElement.getLayoutManager(); + if (lastElement.isGlue()) { + // Remove trailing spaces if allowed so + if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED + || whiteSpaceTreament == EN_IGNORE + || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) { endElementIndex--; // this returns the same KnuthElement seqIterator.previous(); @@ -1506,7 +1497,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager || whiteSpaceTreament == EN_IGNORE_IF_AFTER_LINEFEED) { // ignore KnuthGlue and KnuthPenalty objects // at the beginning of the line - ListIterator seqIterator = seq.listIterator(startElementIndex); + seqIterator = seq.listIterator(startElementIndex); while (seqIterator.hasNext() && !((KnuthElement) seqIterator.next()).isBox()) { startElementIndex++; } @@ -1523,36 +1514,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager 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.getRefIPD() - - 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.getRefIPD() - lbp.lineWidth) / 2; - lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); - } else if (false && textAlignment == EN_END) { - // re-compute indent - int updatedIndent = lbp.startIndent - + (context.getRefIPD() - lbp.lineWidth); - lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); - } - setCurrentArea(lineArea); setChildContext(lc); LayoutManager childLM; @@ -1622,6 +1583,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** {@inheritDoc} */ + @Override public void addChildArea(Area childArea) { // Make sure childArea is inline area if (childArea instanceof InlineArea) { @@ -1637,19 +1599,21 @@ public class LineLayoutManager extends InlineStackingLayoutManager // --------- Property Resolution related functions --------- // /** {@inheritDoc} */ + @Override public boolean getGeneratesBlockArea() { return true; } /** {@inheritDoc} */ + @Override public boolean getGeneratesLineArea() { return true; } /** {@inheritDoc} */ + @Override public boolean isRestartable() { return true; } } - diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutPossibilities.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutPossibilities.java index c1b81c4ab..49c97b7b6 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutPossibilities.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutPossibilities.java @@ -23,14 +23,18 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.layoutmgr.Position; +/** + * Line layout possibilities. + */ public class LineLayoutPossibilities { /** logger instance */ - protected static Log log = LogFactory.getLog(LineLayoutPossibilities.class); + private static final Log LOG = LogFactory.getLog(LineLayoutPossibilities.class); - private class Possibility { + private final class Possibility { private int lineCount; private double demerits; private List breakPositions; @@ -69,12 +73,18 @@ public class LineLayoutPossibilities { private int chosenIndex; private int savedOptLineCount; + /** default constructor */ public LineLayoutPossibilities() { possibilitiesList = new java.util.ArrayList(); savedPossibilities = new java.util.ArrayList(); optimumIndex = -1; } + /** + * Add possibility. + * @param ln line number + * @param dem demerits + */ public void addPossibility(int ln, double dem) { possibilitiesList.add(new Possibility(ln, dem)); if (possibilitiesList.size() == 1) { @@ -97,8 +107,10 @@ public class LineLayoutPossibilities { } } - /* save in a different array the computed Possibilities, - * so possibilitiesList is ready to store different Possibilities + /** + * Save in a different array the computed Possibilities, + * so possibilitiesList is ready to store different Possibilities. + * @param bSaveOptLineCount true if should save optimum line count */ public void savePossibilities(boolean bSaveOptLineCount) { if (bSaveOptLineCount) { @@ -110,8 +122,9 @@ public class LineLayoutPossibilities { possibilitiesList = new java.util.ArrayList(); } - /* replace the Possibilities stored in possibilitiesList with - * the ones stored in savedPossibilities and having the same line number + /** + * Replace the Possibilities stored in possibilitiesList with + * the ones stored in savedPossibilities and having the same line number. */ public void restorePossibilities() { int index = 0; @@ -124,9 +137,9 @@ public class LineLayoutPossibilities { // update minimumIndex minimumIndex = 0; // shift the other indexes; - optimumIndex ++; - maximumIndex ++; - chosenIndex ++; + optimumIndex++; + maximumIndex++; + chosenIndex++; } else if (restoredPossibility.getLineCount() > getMaxLineCount()) { // if the line number of restoredPossibility is greater than the maximum one, // add restoredPossibility at the end of the list @@ -138,13 +151,13 @@ public class LineLayoutPossibilities { // find the index of the Possibility that will be replaced while (index < maximumIndex && getLineCount(index) < restoredPossibility.getLineCount()) { - index ++; + index++; } if (getLineCount(index) == restoredPossibility.getLineCount()) { possibilitiesList.set(index, restoredPossibility); } else { // this should not happen - log.error("LineLayoutPossibilities restorePossibilities()," + LOG.error("LineLayoutPossibilities restorePossibilities()," + " min= " + getMinLineCount() + " max= " + getMaxLineCount() + " restored= " + restoredPossibility.getLineCount()); @@ -152,8 +165,10 @@ public class LineLayoutPossibilities { } } // update optimumIndex and chosenIndex - if (savedOptLineCount == 0 && getDemerits(optimumIndex) > restoredPossibility.getDemerits() - || savedOptLineCount != 0 && restoredPossibility.getLineCount() == savedOptLineCount) { + if (savedOptLineCount == 0 + && getDemerits(optimumIndex) > restoredPossibility.getDemerits() + || savedOptLineCount != 0 + && restoredPossibility.getLineCount() == savedOptLineCount) { optimumIndex = index; chosenIndex = optimumIndex; } @@ -162,73 +177,102 @@ public class LineLayoutPossibilities { // + " optLineCount = " + getOptLineCount() + " maxLineCount() = " + getMaxLineCount()); } + /** + * @param pos a position + * @param i an index into posibilities list + */ public void addBreakPosition(Position pos, int i) { ((Possibility)possibilitiesList.get(i)).addBreakPosition(pos); } + /** @return true if can use more lines */ public boolean canUseMoreLines() { return (getOptLineCount() < getMaxLineCount()); } + /** @return true if can use fewer lines */ public boolean canUseLessLines() { return (getMinLineCount() < getOptLineCount()); } + /** @return the line count of the minimum index */ public int getMinLineCount() { return getLineCount(minimumIndex); } + /** @return the line count of the optimum index */ public int getOptLineCount() { return getLineCount(optimumIndex); } + /** @return the line count of the maximum index */ public int getMaxLineCount() { return getLineCount(maximumIndex); } + /** @return the line count of the chosen index */ public int getChosenLineCount() { return getLineCount(chosenIndex); } + /** + * @param i the posibilities list index + * @return the line count + */ public int getLineCount(int i) { return ((Possibility)possibilitiesList.get(i)).getLineCount(); } + /** @return the demerits of the chosen index */ public double getChosenDemerits() { return getDemerits(chosenIndex); } + /** + * @param i the posibilities list index + * @return the demerits + */ public double getDemerits(int i) { return ((Possibility)possibilitiesList.get(i)).getDemerits(); } + /** @return the possibilities count */ public int getPossibilitiesNumber() { return possibilitiesList.size(); } + /** + * @param i the break position index + * @return the chosen position + */ public Position getChosenPosition(int i) { return ((Possibility)possibilitiesList.get(chosenIndex)).getBreakPosition(i); } + /** + * @param adj the adjustment + * @return the adjustment or zero + */ public int applyLineCountAdjustment(int adj) { if (adj >= (getMinLineCount() - getChosenLineCount()) && adj <= (getMaxLineCount() - getChosenLineCount()) && getLineCount(chosenIndex + adj) == getChosenLineCount() + adj) { chosenIndex += adj; - log.debug("chosenLineCount= " + (getChosenLineCount() - adj) + " adjustment= " + adj + LOG.debug("chosenLineCount= " + (getChosenLineCount() - adj) + " adjustment= " + adj + " => chosenLineCount= " + getLineCount(chosenIndex)); return adj; } else { // this should not happen! - log.warn("Cannot apply the desired line count adjustment."); + LOG.warn("Cannot apply the desired line count adjustment."); return 0; } } + /** print all */ public void printAll() { System.out.println("++++++++++"); System.out.println(" " + possibilitiesList.size() + " possibility':"); - for (int i = 0; i < possibilitiesList.size(); i ++) { + for (int i = 0; i < possibilitiesList.size(); i++) { System.out.println(" " + ((Possibility)possibilitiesList.get(i)).getLineCount() + (i == optimumIndex ? " *" : "") + (i == minimumIndex ? " -" : "") diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java index a38e3e2d8..56bcdaa3b 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java @@ -37,7 +37,7 @@ public class PageNumberCitationLastLayoutManager extends AbstractPageNumberCitat * Constructor * * @param node the formatting object that creates this area - * @todo better retrieval of font info + * TODO better retrieval of font info */ public PageNumberCitationLastLayoutManager(PageNumberCitationLast node) { super(node); diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java index 583f73d24..958a854ac 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java @@ -25,7 +25,6 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.fo.flow.PageNumberCitation; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.LayoutManager; /** * LayoutManager for the fo:page-number-citation formatting object @@ -36,7 +35,7 @@ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationL * Constructor * * @param node the formatting object that creates this area - * @todo better retrieval of font info + * TODO better retrieval of font info */ public PageNumberCitationLayoutManager(PageNumberCitation node) { super(node); diff --git a/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java b/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java index a2a1dce27..19a1a1f8a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java @@ -19,8 +19,6 @@ package org.apache.fop.layoutmgr.inline; -import org.apache.fop.datatypes.Length; - /** * The FOP specific incarnation of the XSL-FO scaled baseline table. * All baseline tables are scaled to the font size of the font they diff --git a/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTableFactory.java b/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTableFactory.java index 1536552c4..0d48ccbfe 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTableFactory.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTableFactory.java @@ -28,7 +28,10 @@ import org.apache.fop.fonts.Font; * Currently supports alignment contexts for basic fonts * and graphic inlines. */ -public class ScaledBaselineTableFactory implements Constants { +public final class ScaledBaselineTableFactory implements Constants { + + private ScaledBaselineTableFactory() { + } /** * Creates a new instance of BasicScaledBaselineTable for the given diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 43e8c5a31..81240dec0 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -81,15 +81,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private boolean breakOppAfter; private final Font font; - AreaInfo(final int startIndex, - final int breakIndex, - final int wordSpaceCount, - final int letterSpaceCount, - final MinOptMax areaIPD, - final boolean isHyphenated, - final boolean isSpace, - final boolean breakOppAfter, - final Font font) { + AreaInfo( // CSOK: ParameterNumber + int startIndex, int breakIndex, int wordSpaceCount, int letterSpaceCount, + MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter, + Font font) { assert startIndex <= breakIndex; this.startIndex = startIndex; this.breakIndex = breakIndex; @@ -170,7 +165,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private int hyphIPD; private boolean hasChanged = false; - private int returnedIndex = 0; + private int[] returnedIndices = {0, 0}; + private int changeOffset = 0; private int thisStart = 0; private int tempStart = 0; private List changeList = new LinkedList(); @@ -709,7 +705,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (inWord) { processWord(alignment, sequence, prevAreaInfo, ch, false, false); } else if (inWhitespace) { - processWhitespace(alignment, sequence, true); + processWhitespace(alignment, sequence, !keepTogether); } else if (areaInfo != null) { processLeftoverAreaInfo(alignment, sequence, areaInfo, ch == CharUtilities.ZERO_WIDTH_SPACE); @@ -774,10 +770,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { while (lastIndex > 0 && foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { lastIndex--; } - final boolean endsWithHyphen = checkEndsWithHyphen - && foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; - Font font = FontSelector.selectFontForCharactersInText(foText, thisStart, lastIndex, foText, this); - int wordLength = lastIndex - thisStart; + Font font = FontSelector + .selectFontForCharactersInText(foText, thisStart, lastIndex, foText, this); boolean kerning = font.hasKerning(); MinOptMax wordIPD = MinOptMax.ZERO; for (int i = thisStart; i < lastIndex; i++) { @@ -793,7 +787,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (i > thisStart) { char previousChar = foText.charAt(i - 1); kern = font.getKernValue(previousChar, currentChar); - } else if (prevAreaInfo != null && !prevAreaInfo.isSpace && prevAreaInfo.breakIndex > 0) { + } else if (prevAreaInfo != null + && !prevAreaInfo.isSpace && prevAreaInfo.breakIndex > 0) { char previousChar = foText.charAt(prevAreaInfo.breakIndex - 1); kern = font.getKernValue(previousChar, currentChar); } @@ -803,30 +798,38 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } } + boolean endsWithHyphen = checkEndsWithHyphen + && foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; if (kerning && breakOpportunity && !TextLayoutManager.isSpace(ch) && lastIndex > 0 && endsWithHyphen) { - final int kern = font.getKernValue(foText.charAt(lastIndex - 1), ch); + int kern = font.getKernValue(foText.charAt(lastIndex - 1), ch); if (kern != 0) { addToLetterAdjust(lastIndex, kern); //TODO: add kern to wordIPD? } } - int iLetterSpaces = wordLength - 1; - // if there is a break opportunity and the next one - // is not a space, it could be used as a line end; - // add one more letter space, in case other text follows - if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { - iLetterSpaces++; + // shy+chars at start of word: wordLength == 0 && breakOpportunity + // shy only characters in word: wordLength == 0 && !breakOpportunity + int wordLength = lastIndex - thisStart; + int letterSpaces = 0; + if (wordLength != 0) { + letterSpaces = wordLength - 1; + // if there is a break opportunity and the next one + // is not a space, it could be used as a line end; + // add one more letter space, in case other text follows + if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { + letterSpaces++; + } } - assert iLetterSpaces >= 0; - wordIPD = wordIPD.plus(letterSpaceIPD.mult(iLetterSpaces)); + assert letterSpaces >= 0; + wordIPD = wordIPD.plus(letterSpaceIPD.mult(letterSpaces)); // create the AreaInfo object AreaInfo areaInfo = new AreaInfo(thisStart, lastIndex, 0, - iLetterSpaces, wordIPD, + letterSpaces, wordIPD, endsWithHyphen, false, breakOpportunity, font); prevAreaInfo = areaInfo; @@ -841,14 +844,20 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public List addALetterSpaceTo(final List oldList) { + public List addALetterSpaceTo(List oldList) { + return addALetterSpaceTo(oldList, 0); + } + + /** {@inheritDoc} */ + public List addALetterSpaceTo(final List oldList, int depth) { // old list contains only a box, or the sequence: box penalty glue box; // look at the Position stored in the first element in oldList // which is always a box ListIterator oldListIterator = oldList.listIterator(); KnuthElement knuthElement = (KnuthElement) oldListIterator.next(); - LeafPosition pos = (LeafPosition) ((KnuthBox) knuthElement).getPosition(); - int index = pos.getLeafPos(); + Position pos = knuthElement.getPosition(); + LeafPosition leafPos = (LeafPosition) pos.getPosition(depth); + int index = leafPos.getLeafPos(); //element could refer to '-1' position, for non-collapsed spaces (?) if (index > -1) { AreaInfo areaInfo = getAreaInfo(index); @@ -863,6 +872,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { oldListIterator.add(new KnuthGlue(letterSpaceIPD, auxiliaryPosition, false)); } else if (letterSpaceIPD.isStiff()) { // constant letter space: replace the box + // give it the unwrapped position of the replaced element oldListIterator.set(new KnuthInlineBox(areaInfo.areaIPD.getOpt(), alignmentContext, pos, false)); } else { @@ -876,41 +886,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return oldList; } - /** - * Removes the <code>AreaInfo</code> object represented by the given elements, so that it won't - * generate any element when <code>getChangedKnuthElements</code> is called. - * - * @param oldList the elements representing the word space - */ - public void removeWordSpace(final List oldList) { - // find the element storing the Position whose value - // points to the AreaInfo object - final ListIterator oldListIterator = oldList.listIterator(); - if (((KnuthElement) ((LinkedList) oldList).getFirst()).isPenalty()) { - // non breaking space: oldList starts with a penalty - oldListIterator.next(); - } - if (oldList.size() > 2) { - // alignment is either center, start or end: - // the first two elements does not store the needed Position - oldListIterator.next(); - oldListIterator.next(); - } - KnuthElement knuthElement = (KnuthElement) oldListIterator.next(); - int leafValue = ((LeafPosition) knuthElement.getPosition()).getLeafPos(); - // only the last word space can be a trailing space! - if (leafValue == areaInfos.size() - 1) { - areaInfos.remove(leafValue); - } else { - TextLayoutManager.LOG.error("trying to remove a non-trailing word space"); - } - } - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void hyphenate(Position pos, HyphContext hyphContext) { - AreaInfo areaInfo = getAreaInfo(((LeafPosition) pos).getLeafPos()); + AreaInfo areaInfo = getAreaInfo(((LeafPosition) pos).getLeafPos() + changeOffset); int startIndex = areaInfo.startIndex; int stopIndex; boolean nothingChanged = true; @@ -953,7 +931,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } // add letter spaces - boolean isWordEnd = stopIndex == areaInfo.breakIndex && areaInfo.letterSpaceCount < areaInfo.getCharLength(); + boolean isWordEnd + = stopIndex == areaInfo.breakIndex + && areaInfo.letterSpaceCount < areaInfo.getCharLength(); int letterSpaceCount = isWordEnd ? stopIndex - startIndex - 1 : stopIndex - startIndex; assert letterSpaceCount >= 0; @@ -963,7 +943,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // the new AreaInfo object is not equal to the old one changeList.add(new PendingChange(new AreaInfo(startIndex, stopIndex, 0, letterSpaceCount, newIPD, hyphenFollows, false, false, font), - ((LeafPosition) pos).getLeafPos())); + ((LeafPosition) pos).getLeafPos() + changeOffset)); nothingChanged = false; } startIndex = stopIndex; @@ -973,11 +953,48 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public boolean applyChanges(final List oldList) { + return applyChanges(oldList, 0); + } + + /** {@inheritDoc} */ + public boolean applyChanges(final List oldList, int depth) { + + // make sure the LM appears unfinished in between this call + // and the next call to getChangedKnuthElements() setFinished(false); + if (oldList.isEmpty()) { + return false; + } + + // Find the first and last positions in oldList that point to an AreaInfo + // (i.e. getLeafPos() != -1) + LeafPosition startPos = null, endPos = null; + ListIterator oldListIter; + for (oldListIter = oldList.listIterator(); oldListIter.hasNext();) { + Position pos = ((KnuthElement) oldListIter.next()).getPosition(); + startPos = (LeafPosition) pos.getPosition(depth); + if (startPos != null && startPos.getLeafPos() != -1) { + break; + } + } + for (oldListIter = oldList.listIterator(oldList.size()); oldListIter.hasPrevious();) { + Position pos = ((KnuthElement) oldListIter.previous()).getPosition(); + endPos = (LeafPosition) pos.getPosition(depth); + if (endPos != null && endPos.getLeafPos() != -1) { + break; + } + } + + // set start/end index, taking into account any offset due to + // changes applied to previous paragraphs + returnedIndices[0] = (startPos != null ? startPos.getLeafPos() : -1) + changeOffset; + returnedIndices[1] = (endPos != null ? endPos.getLeafPos() : -1) + changeOffset; + + int areaInfosAdded = 0; + int areaInfosRemoved = 0; + if (!changeList.isEmpty()) { - int areaInfosAdded = 0; - int areaInfosRemoved = 0; int oldIndex = -1, changeIndex; PendingChange currChange; ListIterator changeListIterator = changeList.listIterator(); @@ -998,7 +1015,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { changeList.clear(); } - returnedIndex = 0; + // increase the end index for getChangedKnuthElements() + returnedIndices[1] += (areaInfosAdded - areaInfosRemoved); + // increase offset to use for subsequent paragraphs + changeOffset += (areaInfosAdded - areaInfosRemoved); + return hasChanged; } @@ -1010,27 +1031,24 @@ public class TextLayoutManager extends LeafNodeLayoutManager { final LinkedList returnList = new LinkedList(); - while (returnedIndex < areaInfos.size()) { - AreaInfo areaInfo = getAreaInfo(returnedIndex); + for (; returnedIndices[0] <= returnedIndices[1]; returnedIndices[0]++) { + AreaInfo areaInfo = getAreaInfo(returnedIndices[0]); if (areaInfo.wordSpaceCount == 0) { // areaInfo refers either to a word or a word fragment - addElementsForAWordFragment(returnList, alignment, areaInfo, returnedIndex); + addElementsForAWordFragment(returnList, alignment, areaInfo, returnedIndices[0]); } else { // areaInfo refers to a space - addElementsForASpace(returnList, alignment, areaInfo, returnedIndex); + addElementsForASpace(returnList, alignment, areaInfo, returnedIndices[0]); } - returnedIndex++; } - setFinished(true); + setFinished(returnedIndices[0] == areaInfos.size() - 1); //ElementListObserver.observe(returnList, "text-changed", null); return returnList; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getWordChars(Position pos) { - int leafValue = ((LeafPosition) pos).getLeafPos(); + int leafValue = ((LeafPosition) pos).getLeafPos() + changeOffset; if (leafValue != -1) { AreaInfo areaInfo = getAreaInfo(leafValue); StringBuffer buffer = new StringBuffer(areaInfo.getCharLength()); @@ -1065,11 +1083,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (foText.charAt(areaInfo.startIndex) != CharUtilities.SPACE || foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved - baseList.addAll(getElementsForBreakingSpace(alignment, areaInfo, auxiliaryPosition, 0, + baseList + .addAll(getElementsForBreakingSpace(alignment, areaInfo, auxiliaryPosition, 0, mainPosition, areaInfo.areaIPD.getOpt(), true)); } else { // a (possible block) of breaking spaces - baseList.addAll(getElementsForBreakingSpace(alignment, areaInfo, mainPosition, + baseList + .addAll(getElementsForBreakingSpace(alignment, areaInfo, mainPosition, areaInfo.areaIPD.getOpt(), auxiliaryPosition, 0, false)); } } @@ -1103,17 +1123,31 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch + KnuthGlue g; if (skipZeroCheck || lineStartBAP != 0 || lineEndBAP != 0) { - elements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, auxiliaryPosition, false)); + g = new KnuthGlue + (lineEndBAP, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, auxiliaryPosition, false); + elements.add(g); elements.add(makeZeroWidthPenalty(0)); - elements.add(new KnuthGlue(p2WidthOffset - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); + g = new KnuthGlue + (p2WidthOffset - (lineStartBAP + lineEndBAP), + -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false); + elements.add(g); elements.add(makeAuxiliaryZeroWidthBox()); elements.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); - elements.add(new KnuthGlue(lineStartBAP + p3WidthOffset, 0, 0, pos3, false)); + g = new KnuthGlue(lineStartBAP + p3WidthOffset, 0, 0, pos3, false); + elements.add(g); } else { - elements.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, auxiliaryPosition, false)); + g = new KnuthGlue + (0, + 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, auxiliaryPosition, false); + elements.add(g); elements.add(makeZeroWidthPenalty(0)); - elements.add(new KnuthGlue(areaInfo.areaIPD.getOpt(), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); + g = new KnuthGlue + (areaInfo.areaIPD.getOpt(), + -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false); + elements.add(g); } break; @@ -1133,9 +1167,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return elements; } - private List getElementsForJustifiedText(AreaInfo areaInfo, Position pos2, int p2WidthOffset, - Position pos3, int p3WidthOffset, boolean skipZeroCheck, - int shrinkability) { + private List getElementsForJustifiedText + (AreaInfo areaInfo, Position pos2, int p2WidthOffset, + Position pos3, int p3WidthOffset, boolean skipZeroCheck, + int shrinkability) { int stretchability = areaInfo.areaIPD.getStretch(); |