### Eclipse Workspace Patch 1.0 #P fop_trunk Index: src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java =================================================================== --- src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java (revision 720166) +++ src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java (working copy) @@ -29,6 +29,7 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOText; +import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontSelector; import org.apache.fop.layoutmgr.InlineKnuthSequence; @@ -544,6 +545,7 @@ final LineBreakStatus lbs = new LineBreakStatus(); this.thisStart = this.nextStart; boolean inWord = false; + boolean forceWrap = (foText.getWrapOption() == EN_WRAP); boolean inWhitespace = false; char ch = 0; while (this.nextStart < this.foText.length()) { @@ -571,7 +573,7 @@ || CharUtilities.isExplicitBreak(ch)) { // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN prevAi = this.processWord(alignment, sequence, prevAi, ch, - breakOpportunity, true); + breakOpportunity, true, context, forceWrap); } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { @@ -621,7 +623,7 @@ // Process any last elements if (inWord) { - this.processWord(alignment, sequence, prevAi, ch, false, false); + this.processWord(alignment, sequence, prevAi, ch, false, false, context, forceWrap); } else if (inWhitespace) { this.processWhitespace(alignment, sequence, true); } else if (ai != null) { @@ -687,7 +689,7 @@ private AreaInfo processWord(final int alignment, final KnuthSequence sequence, AreaInfo prevAi, final char ch, final boolean breakOpportunity, - final boolean checkEndsWithHyphen) { + final boolean checkEndsWithHyphen, LayoutContext context, boolean forceWrap) { AreaInfo ai; //Word boundary found, process widths and kerning int lastIndex = this.nextStart; @@ -726,40 +728,68 @@ } } } - if (kerning - && breakOpportunity - && !TextLayoutManager.isSpace(ch) - && lastIndex > 0 - && endsWithHyphen) { - final int kern = font.getKernValue( - this.foText.charAt(lastIndex - 1), ch) - * font.getFontSize() / 1000; - if (kern != 0) { - this.addToLetterAdjust(lastIndex, kern); - } + //Special handling for fo:list-item-label not to break + boolean breakExclusion = false; + if(foText.getParent() != null) { + if(foText.getParent().getParent() instanceof ListItemLabel) { + breakExclusion = true; + } } - 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++; + + if (forceWrap && wordIPD.min > context.getRefIPD() && !breakExclusion) { + for (int charIndex = this.thisStart; charIndex < lastIndex; ++charIndex) { + MinOptMax tmpwordIPD = new MinOptMax(0); + int charWidth = font.getCharWidth(this.foText.charAt(charIndex)); + tmpwordIPD.add(charWidth); + ai = new AreaInfo(charIndex, (charIndex+1), 0, + 1,tmpwordIPD, this.foText.charAt(charIndex) == CharUtilities.SOFT_HYPHEN, this.foText.charAt(charIndex)==' '? true: false, true, font); + vecAreaInfo.add(ai); + prevAi = ai; + this.tempStart = this.nextStart; + + tmpwordIPD.add(MinOptMax.multiply(letterSpaceIPD, 1)); + // create the elements + this.addElementsForAWordFragment(sequence, alignment, ai, vecAreaInfo.size() - 1, letterSpaceIPD); + ai = null; + } } - wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); - - // create the AreaInfo object - ai = new AreaInfo(this.thisStart, lastIndex, 0, - iLetterSpaces, wordIPD, - endsWithHyphen, - false, breakOpportunity, font); - prevAi = ai; - this.vecAreaInfo.add(ai); - this.tempStart = this.nextStart; - - //add the elements - this.addElementsForAWordFragment(sequence, alignment, ai, - this.vecAreaInfo.size() - 1, this.letterSpaceIPD); - ai = null; + else + { + if (kerning + && breakOpportunity + && !TextLayoutManager.isSpace(ch) + && lastIndex > 0 + && endsWithHyphen) { + final int kern = font.getKernValue( + this.foText.charAt(lastIndex - 1), ch) + * font.getFontSize() / 1000; + if (kern != 0) { + this.addToLetterAdjust(lastIndex, kern); + } + } + 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++; + } + wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); + + // create the AreaInfo object + ai = new AreaInfo(this.thisStart, lastIndex, 0, + iLetterSpaces, wordIPD, + endsWithHyphen, + false, breakOpportunity, font); + prevAi = ai; + this.vecAreaInfo.add(ai); + this.tempStart = this.nextStart; + + //add the elements + this.addElementsForAWordFragment(sequence, alignment, ai, + this.vecAreaInfo.size() - 1, this.letterSpaceIPD); + ai = null; + } this.thisStart = this.nextStart; return prevAi; } Index: src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java =================================================================== --- src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (revision 720166) +++ src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (working copy) @@ -62,6 +62,7 @@ import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.SpaceSpecifier; +import org.apache.fop.layoutmgr.BreakingAlgorithm.KnuthNode; import org.apache.fop.traits.MinOptMax; /** @@ -395,14 +396,43 @@ //log.debug("LLM> (" + (lineLayouts.getLineNumber(activePossibility) - addedPositions) // + ") difference = " + difference + " ratio = " + ratio); lineLayouts.addBreakPosition(makeLineBreakPosition(par, - (bestActiveNode.line > 1 ? bestActiveNode.previous.position + 1 : 0), - bestActiveNode.position, - bestActiveNode.availableShrink - (addedPositions > 0 - ? 0 : ((Paragraph)par).lineFiller.opt - ((Paragraph)par).lineFiller.min), - bestActiveNode.availableStretch, - difference, ratio, indent), activePossibility); + getFirstBestActiveNode(bestActiveNode), + getLastBestActiveNode(bestActiveNode), + bestActiveNode.availableShrink - (addedPositions > 0 + ? 0 : ((Paragraph)par).lineFiller.opt - ((Paragraph)par).lineFiller.min), + bestActiveNode.availableStretch, + difference, ratio, indent), activePossibility); addedPositions++; } + + /** + * Returns the index of the beginning of an element where a break position will be done. + * They are stored inside a list and sometimes there are more than one , and we need the last element. + * @param bestActiveNode KnuthNode + */ + private int getFirstBestActiveNode(KnuthNode bestActiveNode) { + if(bestActiveNode.line <= 1) { + return 0; + } + KnuthNode CurrNode=bestActiveNode.previous; + while(CurrNode.next != null) { + CurrNode=CurrNode.next; + } + return CurrNode.position; + } + + /** + * Returns the index of the end of an element where a break position will be done. + * The matching end index for the getFirstBestActiveNode function. + * @param bestActiveNode KnuthNode + */ + private int getLastBestActiveNode(KnuthNode bestActiveNode) { + KnuthNode CurrNode=bestActiveNode; + while(CurrNode.next != null) { + CurrNode=CurrNode.next; + } + return CurrNode.position; + } /* reset activePossibility, as if breakpoints have not yet been computed */