From 7d01c0732e96ddf3dac732bf177dd0513cd844b1 Mon Sep 17 00:00:00 2001 From: Luca Furini Date: Thu, 27 Oct 2005 14:38:12 +0000 Subject: [PATCH] Moved the text-splitting logic from TextArea to TextLM, as suggested by Manuel and Jeremias. Some simplification in TextLM#addAreas(). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@328882 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/area/inline/SpaceArea.java | 13 +++- .../org/apache/fop/area/inline/TextArea.java | 73 +++++++++--------- .../fop/area/inline/UnresolvedPageNumber.java | 4 +- .../org/apache/fop/area/inline/WordArea.java | 6 +- .../layoutmgr/inline/LeaderLayoutManager.java | 2 +- .../PageNumberCitationLayoutManager.java | 3 +- .../inline/PageNumberLayoutManager.java | 8 +- .../layoutmgr/inline/TextLayoutManager.java | 75 ++++++++++++------- .../apache/fop/render/AbstractRenderer.java | 2 +- .../fop/render/java2d/Java2DRenderer.java | 2 +- .../org/apache/fop/render/ps/PSRenderer.java | 2 +- .../apache/fop/render/svg/SVGRenderer.java | 2 +- .../org/apache/fop/util/CharUtilities.java | 13 ++++ 13 files changed, 127 insertions(+), 78 deletions(-) diff --git a/src/java/org/apache/fop/area/inline/SpaceArea.java b/src/java/org/apache/fop/area/inline/SpaceArea.java index 1b5a1ae6e..6ec573107 100644 --- a/src/java/org/apache/fop/area/inline/SpaceArea.java +++ b/src/java/org/apache/fop/area/inline/SpaceArea.java @@ -31,13 +31,22 @@ public class SpaceArea extends InlineArea { * The correction offset for the next area */ protected int offset = 0; + + /** + * Is this space adjustable? + */ + protected boolean isAdjustable; /** - * Create a text inline area + * Create a space area * @param s the space character + * @param o the offset for the next area + * @param a is this space adjustable? */ - public SpaceArea(char s) { + public SpaceArea(char s, int o, boolean a) { space = new String() + s; + offset = o; + isAdjustable = a; } /** diff --git a/src/java/org/apache/fop/area/inline/TextArea.java b/src/java/org/apache/fop/area/inline/TextArea.java index d57171e8a..3bee4254f 100644 --- a/src/java/org/apache/fop/area/inline/TextArea.java +++ b/src/java/org/apache/fop/area/inline/TextArea.java @@ -18,8 +18,6 @@ package org.apache.fop.area.inline; -import org.apache.fop.util.CharUtilities; - /** * A text inline area. */ @@ -43,46 +41,49 @@ public class TextArea extends AbstractTextArea { } /** - * Set the text string - * - * @param t the text string + * Remove the old text */ - public void setText(String t) { - // split the text and create WordAreas and SpaceAreas - char charArray[] = t.toCharArray(); - int wordStartIndex = -1; - for (int i = 0; i < charArray.length; i ++) { - if (CharUtilities.isAnySpace(charArray[i])) { - // a space character - // create a SpaceArea child - SpaceArea space = new SpaceArea(charArray[i]); - this.addChildArea(space); - space.setParentArea(this); - } else { - // a non-space character - if (wordStartIndex == -1) { - // first character of the text, or after a space - wordStartIndex = i; - } - if (i == charArray.length - 1 - || CharUtilities.isAnySpace(charArray[i + 1])) { - // last character before the end of the text or a space: - // create a WordArea child - WordArea word = new WordArea(t.substring(wordStartIndex, i + 1)); - this.addChildArea(word); - word.setParentArea(this); - wordStartIndex = -1; - } - } - } + public void removeText() { + inlines.clear(); } - + + /** + * Create and add a WordArea child to this TextArea. + * + * @param word the word string + * @param offset the offset for the next area + */ + public void addWord(String word, int offset) { + WordArea wordArea = new WordArea(word, offset); + addChildArea(wordArea); + wordArea.setParentArea(this); + } + + /** + * Create and add a SpaceArea child to this TextArea + * + * @param space the space character + * @param offset the offset for the next area + * @param adjustable is this space adjustable? + */ + public void addSpace(char space, int offset, boolean adjustable) { + SpaceArea spaceArea = new SpaceArea(space, offset, adjustable); + addChildArea(spaceArea); + spaceArea.setParentArea(this); + } + /** - * Get the text string. + * Get the whole text string. + * Renderers whose space adjustment handling is not affected + * by multi-byte characters can use this method to render the + * whole TextArea at once; the other renderers (for example + * PDFRenderer) have to implement renderWord(WordArea) and + * renderSpace(SpaceArea) in order to correctly place each + * text fragment. * * @return the text string */ - public String getTextArea() { + public String getText() { StringBuffer text = new StringBuffer(); InlineArea child; // assemble the text diff --git a/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java b/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java index 0b429b665..7b5eae941 100644 --- a/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java +++ b/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java @@ -70,7 +70,9 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable { if (pageIDRef.equals(id) && pages != null) { resolved = true; PageViewport page = (PageViewport)pages.get(0); - setText(page.getPageNumberString()); + // replace the text + removeText(); + addWord(page.getPageNumberString(), 0); // update ipd updateIPD(getStringWidth(text)); // set the Font object to null, as we don't need it any more diff --git a/src/java/org/apache/fop/area/inline/WordArea.java b/src/java/org/apache/fop/area/inline/WordArea.java index c766e0e62..b998b819e 100644 --- a/src/java/org/apache/fop/area/inline/WordArea.java +++ b/src/java/org/apache/fop/area/inline/WordArea.java @@ -33,11 +33,13 @@ public class WordArea extends InlineArea { protected int offset = 0; /** - * Create a text inline area + * Create a word area * @param w the word string + * @param o the offset for the next area */ - public WordArea(String w) { + public WordArea(String w, int o) { word = w; + offset = o; } /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index d7983a9f6..f16b78553 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -129,7 +129,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { char dot = '.'; // userAgent.getLeaderDotCharacter(); int width = font.getCharWidth(dot); - t.setText("" + dot); + t.addWord("" + dot, 0); t.setIPD(width); t.setBPD(width); t.setBaselineOffset(width); diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java index e1c8c29d6..37f23c947 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.Trait; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fonts.Font; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; @@ -105,7 +104,7 @@ public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager { TextArea text = new TextArea(); inline = text; int width = getStringWidth(str); - text.setText(str); + text.addWord(str, 0); inline.setIPD(width); resolved = true; diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java index 7cbcd77c4..09daeb212 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java @@ -22,7 +22,6 @@ import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.Trait; -import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fonts.Font; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.TraitSetter; @@ -75,7 +74,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { TextArea text = new TextArea(); String str = getCurrentPV().getPageNumberString(); int width = getStringWidth(str); - text.setText(str); + text.addWord(str, 0); text.setIPD(width); text.setBPD(font.getAscender() - font.getDescender()); text.setBaselineOffset(font.getAscender()); @@ -109,9 +108,10 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { private void updateContent(TextArea area) { // get the page number of the page actually being built - area.setText(getCurrentPV().getPageNumberString()); + area.removeText(); + area.addWord(getCurrentPV().getPageNumberString(), 0); // update the ipd of the area - area.updateIPD(getStringWidth(area.getTextArea())); + area.updateIPD(getStringWidth(area.getText())); // update the width stored in the AreaInfo object areaInfo.ipdArea = new MinOptMax(area.getIPD()); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index f2e1cde33..cbf798b03 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -24,7 +24,6 @@ import java.util.LinkedList; import java.util.ListIterator; import org.apache.fop.area.Trait; -import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.FOText; import org.apache.fop.fo.flow.Inline; @@ -41,6 +40,7 @@ import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; +import org.apache.fop.util.CharUtilities; /** * LayoutManager for text (a sequence of characters) which generates one @@ -260,9 +260,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // Add word areas AreaInfo ai = null; - int iStart = -1; int iWScount = 0; int iLScount = 0; + int firstAreaInfoIndex = -1; + int lastAreaInfoIndex = 0; MinOptMax realWidth = new MinOptMax(0); /* On first area created, add any leading space. @@ -273,12 +274,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if (tbpNext.getLeafPos() != -1) { ai = (AreaInfo) vecAreaInfo.get(tbpNext.getLeafPos()); - if (iStart == -1) { - iStart = ai.iStartIndex; + if (firstAreaInfoIndex == -1) { + firstAreaInfoIndex = tbpNext.getLeafPos(); } iWScount += ai.iWScount; iLScount += ai.iLScount; realWidth.add(ai.ipdArea); + lastAreaInfoIndex = tbpNext.getLeafPos(); } } if (ai == null) { @@ -291,20 +293,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { iLScount--; } - // Make an area containing all characters between start and end. - InlineArea word = null; - int adjust = 0; - - // ignore newline character - if (textArray[ai.iBreakIndex - 1] == NEWLINE) { - adjust = 1; - } - String str = new String(textArray, iStart, - ai.iBreakIndex - iStart - adjust); - // add hyphenation character if the last word is hyphenated if (context.isLastArea() && ai.bHyphenated) { - str += foText.getCommonHyphenation().hyphenationCharacter; realWidth.add(new MinOptMax(hyphIPD)); } @@ -355,8 +345,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { iTotalAdjust = iDifference; } - TextArea t = createTextArea(str, realWidth, iTotalAdjust, context, - wordSpaceIPD.opt - spaceCharIPD); + TextArea t = createTextArea(realWidth, iTotalAdjust, context, + wordSpaceIPD.opt - spaceCharIPD, + firstAreaInfoIndex, lastAreaInfoIndex, + context.isLastArea()); // iWordSpaceDim is computed in relation to wordSpaceIPD.opt // but the renderer needs to know the adjustment in relation @@ -378,25 +370,25 @@ public class TextLayoutManager extends LeafNodeLayoutManager { t.setSpaceDifference(wordSpaceIPD.opt - spaceCharIPD - 2 * t.getTextLetterSpaceAdjust()); } - word = t; - if (word != null) { - parentLM.addChildArea(word); - } + parentLM.addChildArea(t); } /** * Create an inline word area. * This creates a TextArea and sets up the various attributes. * - * @param str the string for the TextArea * @param width the MinOptMax width of the content * @param adjust the total ipd adjustment with respect to the optimal width * @param context the layout context * @param spaceDiff unused + * @param firstIndex the index of the first AreaInfo used for the TextArea + * @param lastIndex the index of the last AreaInfo used for the TextArea + * @param isLastArea is this TextArea the last in a line? * @return the new text area */ - protected TextArea createTextArea(String str, MinOptMax width, int adjust, - LayoutContext context, int spaceDiff) { + protected TextArea createTextArea(MinOptMax width, int adjust, + LayoutContext context, int spaceDiff, + int firstIndex, int lastIndex, boolean isLastArea) { TextArea textArea; if (context.getIPDAdjust() == 0.0) { // create just a TextArea @@ -417,7 +409,38 @@ public class TextLayoutManager extends LeafNodeLayoutManager { textArea.setOffset(alignmentContext.getOffset()); } - textArea.setText(str); + // set the text of the TextArea, split into words and spaces + int wordStartIndex = -1; + AreaInfo areaInfo; + for (int i = firstIndex; i <= lastIndex; i ++) { + areaInfo = (AreaInfo) vecAreaInfo.get(i); + if (areaInfo.iWScount > 0) { + // areaInfo stores information about a space + // add a space to the TextArea + char spaceChar = textArray[areaInfo.iStartIndex]; + textArea.addSpace(spaceChar, 0, + CharUtilities.isAdjustableSpace(spaceChar)); + } else { + // areaInfo stores information about a word fragment + if (wordStartIndex == -1) { + // here starts a new word + wordStartIndex = areaInfo.iStartIndex; + } + if (i == lastIndex || ((AreaInfo) vecAreaInfo.get(i + 1)).iWScount > 0) { + // here ends a new word + // add a word to the TextArea + String wordChars = new String(textArray, wordStartIndex, areaInfo.iBreakIndex - wordStartIndex); + if (isLastArea + && i == lastIndex + && areaInfo.bHyphenated) { + // add the hyphenation character + wordChars += foText.getCommonHyphenation().hyphenationCharacter; + } + textArea.addWord(wordChars, 0); + wordStartIndex = -1; + } + } + } textArea.addTrait(Trait.FONT_NAME, font.getFontName()); textArea.addTrait(Trait.FONT_SIZE, new Integer(font.getFontSize())); textArea.addTrait(Trait.COLOR, foText.getColor()); diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 0335c2089..6dd4c7510 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -188,7 +188,7 @@ public abstract class AbstractRenderer if (inline instanceof Character) { sb.append(((Character) inline).getChar()); } else if (inline instanceof TextArea) { - sb.append(((TextArea) inline).getTextArea()); + sb.append(((TextArea) inline).getText()); } else if (inline instanceof InlineParent) { sb.append(convertToString( ((InlineParent) inline).getChildAreas())); diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 4e6cfb20f..4661eb49d 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -741,7 +741,7 @@ public abstract class Java2DRenderer extends AbstractRenderer implements Printab ColorType ct = (ColorType) text.getTrait(Trait.COLOR); state.updateColor(ct, false, null); - String s = text.getTextArea(); + String s = text.getText(); state.getGraph().drawString(s, x / 1000f, y / 1000f); // getLogger().debug("renderText(): \"" + s + "\", x: " diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 5d72b8ca0..1902df16e 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -796,7 +796,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer { * @see org.apache.fop.render.AbstractRenderer#renderText(TextArea) */ public void renderText(TextArea area) { - String text = area.getTextArea(); + String text = area.getText(); renderText(area, text); super.renderText(area); //Updates IPD } diff --git a/src/java/org/apache/fop/render/svg/SVGRenderer.java b/src/java/org/apache/fop/render/svg/SVGRenderer.java index 74b418a5c..7a6109ed9 100644 --- a/src/java/org/apache/fop/render/svg/SVGRenderer.java +++ b/src/java/org/apache/fop/render/svg/SVGRenderer.java @@ -393,7 +393,7 @@ public class SVGRenderer extends AbstractRenderer implements XMLHandler { currentIPPosition / 1000, (currentBPPosition + text.getOffset() + text.getBaselineOffset()) / 1000, - text.getTextArea()); + text.getText()); currentPageG.appendChild(textElement); super.renderText(text); diff --git a/src/java/org/apache/fop/util/CharUtilities.java b/src/java/org/apache/fop/util/CharUtilities.java index c1a537521..43c2c3e41 100644 --- a/src/java/org/apache/fop/util/CharUtilities.java +++ b/src/java/org/apache/fop/util/CharUtilities.java @@ -119,6 +119,19 @@ public class CharUtilities { || c == ZERO_WIDTH_NOBREAK_SPACE); // zero width no-break space } + /** + * Method to determine if the character is an adjustable + * space. + * @param c character to check + * @return True if the character is adjustable + */ + public static boolean isAdjustableSpace(char c) { + //TODO: are there other kinds of adjustable spaces? + return + (c == '\u0020' // normal space + /*|| c == ''*/); + } + /** * Determines if the character represents any kind of space. * @param c character to check -- 2.39.5