]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Fix for bug 36238 (at least in the PDFRenderer)
authorLuca Furini <lfurini@apache.org>
Tue, 25 Oct 2005 15:14:10 +0000 (15:14 +0000)
committerLuca Furini <lfurini@apache.org>
Tue, 25 Oct 2005 15:14:10 +0000 (15:14 +0000)
The text is split into WordAreas and SpaceAreas: the latters (when the font is multibyte) are not affected by the Tw operator, so they are shifted in the inline progression dimension instead.

The behaviour of the other renderers should be the same as before this change.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@328381 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
src/java/org/apache/fop/area/inline/AbstractTextArea.java
src/java/org/apache/fop/area/inline/SpaceArea.java [new file with mode: 0644]
src/java/org/apache/fop/area/inline/TextArea.java
src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java
src/java/org/apache/fop/area/inline/WordArea.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
src/java/org/apache/fop/render/AbstractRenderer.java
src/java/org/apache/fop/render/pdf/PDFRenderer.java
src/java/org/apache/fop/render/xml/XMLRenderer.java

index a50500979919f6ece8a9f68667ad13b1e55d9a9e..200b3e5680a923d5625ccb019758935e2250b2ec 100644 (file)
@@ -21,7 +21,7 @@ package org.apache.fop.area.inline;
 /**
  * Abstract base class for both TextArea and Character.
  */
-public abstract class AbstractTextArea extends InlineArea {
+public abstract class AbstractTextArea extends InlineParent {
 
     /**
      * this class stores information about spaces and potential adjustments
diff --git a/src/java/org/apache/fop/area/inline/SpaceArea.java b/src/java/org/apache/fop/area/inline/SpaceArea.java
new file mode 100644 (file)
index 0000000..1b5a1ae
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+ * Copyright 2004-2005 The Apache Software Foundation.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id$ */\r
+package org.apache.fop.area.inline;\r
+\r
+/**\r
+ * A space\r
+ */\r
+public class SpaceArea extends InlineArea {\r
+    \r
+    /**\r
+     * The space for this space area\r
+     */\r
+    protected String space;\r
+\r
+    /**\r
+     * The correction offset for the next area\r
+     */\r
+    protected int offset = 0;\r
+\r
+    /**\r
+     * Create a text inline area\r
+     * @param s the space character\r
+     */\r
+    public SpaceArea(char s) {\r
+        space = new String() + s;\r
+    }\r
+    \r
+    /**\r
+     * @return Returns the space.\r
+     */\r
+    public String getSpace() {\r
+        return new String(space);\r
+    }\r
+\r
+    /**\r
+     * @return Returns the offset.\r
+     */\r
+    public int getOffset() {\r
+        return offset;\r
+    }\r
+    /**\r
+     * @param o The offset to set.\r
+     */\r
+    public void setOffset(int o) {\r
+        offset = o;\r
+    }\r
+}\r
index 5f58f989be27a887bb464a76a147c2deeb523edf..d57171e8ac486a9ecd16be7124656033cff0f072 100644 (file)
 
 package org.apache.fop.area.inline;
 
+import org.apache.fop.util.CharUtilities;
+
 /**
  * A text inline area.
  */
 public class TextArea extends AbstractTextArea {
 
-    /**
-     * The text for this inline area
-     */
-    protected String text;
-
     /**
      * Create a text inline area
      */
@@ -50,8 +47,34 @@ public class TextArea extends AbstractTextArea {
      *
      * @param t the text string
      */
-    public void setTextArea(String t) {
-        text = t;
+    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;
+                }
+            }
+        }
     }
 
     /**
@@ -60,7 +83,18 @@ public class TextArea extends AbstractTextArea {
      * @return the text string
      */
     public String getTextArea() {
-        return text;
+        StringBuffer text = new StringBuffer();
+        InlineArea child;
+        // assemble the text
+        for (int i = 0; i < inlines.size(); i ++) {
+            child = (InlineArea) inlines.get(i);
+            if (child instanceof WordArea) {
+                text.append(((WordArea) child).getWord());
+            } else {
+                text.append(((SpaceArea) child).getSpace());
+            }
+        }
+        return text.toString();
     }
 
     /**
index 3d2d44689ca8989a1555f402af68e247499dd21b..0b429b6651a33fd69bcc2d7e9806c008bc8fa8b5 100644 (file)
@@ -33,6 +33,7 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable {
     private boolean resolved = false;
     private String pageIDRef;
     private Font font;
+    private String text;
 
     /**
      * Create a new unresolvable page number.
@@ -69,7 +70,7 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable {
         if (pageIDRef.equals(id) && pages != null) {
             resolved = true;
             PageViewport page = (PageViewport)pages.get(0);
-            setTextArea(page.getPageNumberString());
+            setText(page.getPageNumberString());
             // 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
new file mode 100644 (file)
index 0000000..c766e0e
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+ * Copyright 2004-2005 The Apache Software Foundation.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id$ */\r
+package org.apache.fop.area.inline;\r
+\r
+/**\r
+ * A string of characters without spaces\r
+ */\r
+public class WordArea extends InlineArea {\r
+\r
+    /**\r
+     * The text for this word area\r
+     */\r
+    protected String word;\r
+    \r
+    /**\r
+     * The correction offset for the next area\r
+     */\r
+    protected int offset = 0;\r
+\r
+    /**\r
+     * Create a text inline area\r
+     * @param w the word string\r
+     */\r
+    public WordArea(String w) {\r
+        word = w;\r
+    }\r
+\r
+    /**\r
+     * @return Returns the word.\r
+     */\r
+    public String getWord() {\r
+        return word;\r
+    }\r
+\r
+    /**\r
+     * @return Returns the offset.\r
+     */\r
+    public int getOffset() {\r
+        return offset;\r
+    }\r
+    /**\r
+     * @param o The offset to set.\r
+     */\r
+    public void setOffset(int o) {\r
+        offset = o;\r
+    }\r
+}\r
index 162397217c6e2fd2462bba290279d84adb76b1c9..502d3ed6f7acd6c23ca5083cd4881af20a3c3941 100644 (file)
@@ -129,7 +129,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager {
             char dot = '.'; // userAgent.getLeaderDotCharacter();
 
             int width = font.getCharWidth(dot);
-            t.setTextArea("" + dot);
+            t.setText("" + dot);
             t.setIPD(width);
             t.setBPD(width);
             t.setBaselineOffset(width);
index 083d7838fd18aadaa2173250812d110f1384ea16..9badf69863490534ec47ea3d1d7f88aaf3bc380d 100644 (file)
@@ -110,7 +110,7 @@ public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager {
             TextArea text = new TextArea();
             inline = text;
             int width = getStringWidth(str);
-            text.setTextArea(str);
+            text.setText(str);
             inline.setIPD(width);
             
             resolved = true;
index d6cc739f2917f6ddc1d43e98222171302c729117..2cabaa8a3432ce960de984a369fe7ee6b57f2b2a 100644 (file)
@@ -75,7 +75,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager {
         TextArea text = new TextArea();
         String str = getCurrentPV().getPageNumberString();
         int width = getStringWidth(str);
-        text.setTextArea(str);
+        text.setText(str);
         text.setIPD(width);
         text.setBPD(font.getAscender() - font.getDescender());
         text.setBaselineOffset(font.getAscender());
@@ -114,7 +114,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager {
     
     private void updateContent(TextArea area) {
         // get the page number of the page actually being built
-        area.setTextArea(getCurrentPV().getPageNumberString());
+        area.setText(getCurrentPV().getPageNumberString());
         // update the ipd of the area
         area.updateIPD(getStringWidth(area.getTextArea()));
         // update the width stored in the AreaInfo object
index 2ab8fd1a8e8bbd4db3f6e7645b5eaeccff20b903..1755dd4fd3eb9b67811fc06b0ff2698dcf979584 100644 (file)
@@ -393,6 +393,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
      * @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
      * @return the new text area
      */
     protected TextArea createTextArea(String str, MinOptMax width, int adjust,
@@ -417,7 +419,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
             textArea.setOffset(alignmentContext.getOffset());
         }
 
-        textArea.setTextArea(str);
+        textArea.setText(str);
         textArea.addTrait(Trait.FONT_NAME, font.getFontName());
         textArea.addTrait(Trait.FONT_SIZE, new Integer(font.getFontSize()));
         textArea.addTrait(Trait.COLOR, foText.getColor());
index ab2fc8588d6179a3c1296b14afc6de4cb557d076..0335c2089541163444e24ee19615b353759605c7 100644 (file)
@@ -59,6 +59,8 @@ import org.apache.fop.area.inline.Space;
 import org.apache.fop.area.inline.Viewport;
 import org.apache.fop.area.inline.TextArea;
 import org.apache.fop.area.inline.Character;
+import org.apache.fop.area.inline.WordArea;
+import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fonts.FontInfo;
@@ -587,14 +589,18 @@ public abstract class AbstractRenderer
     protected void renderInlineArea(InlineArea inlineArea) {
         if (inlineArea instanceof TextArea) {
             renderText((TextArea) inlineArea);
+        } else if (inlineArea instanceof Character) {
+            renderCharacter((Character) inlineArea);
+        } else if (inlineArea instanceof WordArea) {
+            renderWord((WordArea) inlineArea);
+        } else if (inlineArea instanceof SpaceArea) {
+            renderSpace((SpaceArea) inlineArea);
         } else if (inlineArea instanceof InlineParent) {
             renderInlineParent((InlineParent) inlineArea);
         } else if (inlineArea instanceof InlineBlockParent) {
             renderInlineBlockParent((InlineBlockParent) inlineArea);
         } else if (inlineArea instanceof Space) {
             renderInlineSpace((Space) inlineArea);
-        } else if (inlineArea instanceof Character) {
-            renderCharacter((Character) inlineArea);
         } else if (inlineArea instanceof Viewport) {
             renderViewport((Viewport) inlineArea);
         } else if (inlineArea instanceof Leader) {
@@ -602,7 +608,6 @@ public abstract class AbstractRenderer
         }
     }
 
-
     /**
      * Render the given Character.
      * @param ch the character to render
@@ -636,7 +641,29 @@ public abstract class AbstractRenderer
      * @param text the text to render
      */
     protected void renderText(TextArea text) {
-        currentIPPosition += text.getAllocIPD();
+        int saveIP = currentIPPosition;
+        int saveBP = currentBPPosition;
+        Iterator iter = text.getChildAreas().iterator();
+        while (iter.hasNext()) {
+            renderInlineArea((InlineArea) iter.next()); 
+        }
+        currentIPPosition = saveIP + text.getAllocIPD();
+    }
+
+    /**
+     * Render the given WordArea.
+     * @param word the word to render
+     */
+    protected void renderWord(WordArea word) {
+        currentIPPosition += word.getAllocIPD();
+    }
+
+    /**
+     * Render the given SpaceArea.
+     * @param space the space to render
+     */
+    protected void renderSpace(SpaceArea space) {
+        currentIPPosition += space.getAllocIPD();
     }
 
     /**
index 70beb20fb89d6d0e10a0996c759a751f81e212c9..69a96f432ba43cb630e6df14e91924f9553e8b9c 100644 (file)
@@ -52,6 +52,8 @@ import org.apache.fop.area.inline.ForeignObject;
 import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.WordArea;
+import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.datatypes.ColorType;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.fonts.Font;
@@ -1095,11 +1097,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
         // This assumes that *all* CIDFonts use a /ToUnicode mapping
         Typeface tf = (Typeface) fontInfo.getFonts().get(name);
         boolean useMultiByte = tf.isMultiByte();
-
-        // String startText = useMultiByte ? "<FEFF" : "(";
-        String startText = useMultiByte ? "<" : "(";
-        String endText = useMultiByte ? "> " : ") ";
-
+        
         updateFont(name, size, pdf);
         ColorType ct = (ColorType) text.getTrait(Trait.COLOR);
         updateColor(ct, true, pdf);
@@ -1125,7 +1123,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
 
             pdf.append("1 0 0 -1 " + (rx / 1000f) + " " + (bl / 1000f) + " Tm "
                        + (text.getTextLetterSpaceAdjust() / 1000f) + " Tc "
-                       + (text.getTextWordSpaceAdjust() / 1000f) + " Tw [" + startText);
+                       + (text.getTextWordSpaceAdjust() / 1000f) + " Tw [");
             prevWordY = bl;
             textOpen = true;
         } else {
@@ -1133,24 +1131,77 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
 
             pdf.append("1 0 0 -1 " + (rx / 1000f) + " " + (bl / 1000f) + " Tm "
                        + (text.getTextLetterSpaceAdjust() / 1000f) + " Tc "
-                       + (text.getTextWordSpaceAdjust() / 1000f) + " Tw [" + startText);
+                       + (text.getTextWordSpaceAdjust() / 1000f) + " Tw [");
             textOpen = true;
         }
         prevWordWidth = text.getIPD();
         prevWordX = rx;
 
-        String s = text.getTextArea();
+        currentStream.add(pdf.toString());
 
+        renderTextDecoration(tf, size, text, bl, rx);
+        
+        super.renderText(text);
+    }
+    
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderWord(WordArea)
+     */
+    public void renderWord(WordArea word) {
+        String name = (String) word.getParentArea().getTrait(Trait.FONT_NAME);
+        int size = ((Integer) word.getParentArea().getTrait(Trait.FONT_SIZE)).intValue();
+        Typeface tf = (Typeface) fontInfo.getFonts().get(name);
+        boolean useMultiByte = tf.isMultiByte();
+
+        String startText = useMultiByte ? "<" : "(";
+        String endText = useMultiByte ? "> " : ") ";
+        
+        StringBuffer pdf = new StringBuffer();
+        
+        pdf.append(startText);
+
+        String s = word.getWord();
+        
         FontMetrics metrics = fontInfo.getMetricsFor(name);
         Font fs = new Font(name, metrics, size);
         escapeText(s, fs, useMultiByte, pdf);
         pdf.append(endText);
-
+        
         currentStream.add(pdf.toString());
 
-        renderTextDecoration(tf, size, text, bl, rx);
+        super.renderWord(word);
+    }
+    
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderSpace(SpaceArea)
+     */
+    public void renderSpace(SpaceArea space) {
+        String name = (String) space.getParentArea().getTrait(Trait.FONT_NAME);
+        int size = ((Integer) space.getParentArea().getTrait(Trait.FONT_SIZE)).intValue();
+        Typeface tf = (Typeface) fontInfo.getFonts().get(name);
+        boolean useMultiByte = tf.isMultiByte();
+
+        String startText = useMultiByte ? "<" : "(";
+        String endText = useMultiByte ? "> " : ") ";
         
-        super.renderText(text);
+        StringBuffer pdf = new StringBuffer();
+        
+        pdf.append(startText);
+
+        String s = space.getSpace();
+        
+        FontMetrics metrics = fontInfo.getMetricsFor(name);
+        Font fs = new Font(name, metrics, size);
+        escapeText(s, fs, useMultiByte, pdf);
+        pdf.append(endText);
+        
+        if (useMultiByte) {
+            pdf.append(-(((TextArea) space.getParentArea()).getTextWordSpaceAdjust() / (size / 1000)) + " ");
+        }
+        
+        currentStream.add(pdf.toString());
+
+        super.renderSpace(space);
     }
     
     /**
index 71d47df40fae887b3e01d7302dbe39f156b163f7..da3260d544a6fa68d661bda7b7a2f9d7a24b49e0 100644 (file)
@@ -66,6 +66,8 @@ import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.Space;
 import org.apache.fop.area.inline.Viewport;
 import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.inline.SpaceArea;
+import org.apache.fop.area.inline.WordArea;
 
 /**
  * Renderer that renders areas to XML for debugging purposes.
@@ -613,9 +615,32 @@ public class XMLRenderer extends PrintRenderer {
         addAreaAttributes(text);
         addTraitAttributes(text);
         startElement("text", atts);
-        characters(text.getTextArea());
-        endElement("text");
         super.renderText(text);
+        endElement("text");
+    }
+    
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderWord(WordArea)
+     */
+    protected void renderWord(WordArea word) {
+        atts.clear();
+        addAttribute("offset", word.getOffset());
+        startElement("word", atts);
+        characters(word.getWord());
+        endElement("word");
+        super.renderWord(word);
+    }
+    
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderSpace(SpaceArea)
+     */
+    protected void renderSpace(SpaceArea space) {
+        atts.clear();
+        addAttribute("offset", space.getOffset());
+        startElement("space", atts);
+        characters(space.getSpace());
+        endElement("space");
+        super.renderSpace(space);
     }
 
     /**