]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugfix: The combination of hyphenation and kerning resulted in slightly ragged right...
authorJeremias Maerki <jeremias@apache.org>
Fri, 19 May 2006 11:51:40 +0000 (11:51 +0000)
committerJeremias Maerki <jeremias@apache.org>
Fri, 19 May 2006 11:51:40 +0000 (11:51 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@407774 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
status.xml
test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml [new file with mode: 0644]

index 1582ea30dd06d3682d6c0460af0840d3b50c31a3..159ece158d55372981c0f3225076c11adc30aebb 100644 (file)
@@ -106,12 +106,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
     /** Non-space characters on which we can end a line. */
     private static final String BREAK_CHARS = "-/";
 
+    /** Used to reduce instantiation of MinOptMax with zero length. Do not modify! */
+    private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0);
+    
     private FOText foText;
     private char[] textArray;
-    /** Contains an array of widths to adjust for kerning and letter spacing */
+    /**
+     * Contains an array of widths to adjust for kerning. The first entry can
+     * be used to influence the start position of the first letter. The entry i+1 defines the
+     * cursor advancement after the character i. A null entry means no special advancement.
+     */
     private MinOptMax[] letterAdjustArray; //size = textArray.length + 1
-    /** The sum of all entries in the letterAdjustArray */
-    private MinOptMax totalLetterAdjust = new MinOptMax(0);
 
     private static final char NEWLINE = '\n';
 
@@ -310,8 +315,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
             iLScount--;
         }
         
-        for (int i = ai.iStartIndex + 1; i < ai.iBreakIndex + 1; i++) {
-            MinOptMax ladj = letterAdjustArray[i]; 
+        for (int i = ai.iStartIndex; i < ai.iBreakIndex; i++) {
+            MinOptMax ladj = letterAdjustArray[i + 1]; 
             if (ladj != null && ladj.isElastic()) {
                 iLScount++;
             }
@@ -466,8 +471,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
                     int[] letterAdjust = new int[wordChars.length()];
                     int lsCount = areaInfo.iLScount;
                     for (int letter = 0; letter < len; letter++) {
-                        MinOptMax adj = letterAdjustArray[letter + wordStartIndex + 1];
-                        letterAdjust[letter] = (adj != null ? adj.opt : 0);
+                        MinOptMax adj = letterAdjustArray[letter + wordStartIndex];
+                        if (letter > 0) {
+                            letterAdjust[letter] = (adj != null ? adj.opt : 0);
+                        }
                         if (lsCount > 0) {
                             letterAdjust[letter] += textArea.getTextLetterSpaceAdjust();
                             lsCount--;
@@ -492,7 +499,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
         } else {
             letterAdjustArray[index].add(width);
         }
-        totalLetterAdjust.add(width);
     }
 
     private void addToLetterAdjust(int index, MinOptMax width) {
@@ -501,7 +507,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
         } else {
             letterAdjustArray[index].add(width);
         }
-        totalLetterAdjust.add(width);
     }
 
     /**
@@ -625,7 +630,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
                         char previous = textArray[i - 1];
                         kern = font.getKernValue(previous, c) * font.getFontSize() / 1000;
                         if (kern != 0) {
-                            addToLetterAdjust(i + 1, kern);
+                            //log.info("Kerning between " + previous + " and " + c + ": " + kern);
+                            addToLetterAdjust(i, kern);
                         }
                         wordIPD.add(kern);
                     }
@@ -761,9 +767,22 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
 
             hc.updateOffset(iStopIndex - iStartIndex);
 
+            //log.info("Word: " + new String(textArray, iStartIndex, iStopIndex - iStartIndex));
             for (int i = iStartIndex; i < iStopIndex; i++) {
                 char c = textArray[i];
                 newIPD.add(new MinOptMax(font.getCharWidth(c)));
+                //if (i > iStartIndex) {
+                if (i < iStopIndex) {
+                    MinOptMax la = this.letterAdjustArray[i + 1];
+                    if ((i == iStopIndex - 1) && bHyphenFollows) {
+                        //the letter adjust here needs to be handled further down during
+                        //element generation because it depends on hyph/no-hyph condition
+                        la = null;
+                    }
+                    if (la != null) {
+                        newIPD.add(la);
+                    }
+                }
             }
             // add letter spaces
             boolean bIsWordEnd
@@ -854,6 +873,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
             iReturnedIndex++;
         } // end of while
         setFinished(true);
+        //ElementListObserver.observe(returnList, "text-changed", null);
         return returnList;
     }
 
@@ -1152,10 +1172,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
         // extra-elements if the word fragment is the end of a syllable,
         // or it ends with a character that can be used as a line break
         if (ai.bHyphenated) {
+            MinOptMax widthIfNoBreakOccurs = null;
+            if (ai.iBreakIndex < textArray.length) {
+                //Add in kerning in no-break condition
+                widthIfNoBreakOccurs = letterAdjustArray[ai.iBreakIndex];
+            }
+            //if (ai.iBreakIndex)
+            
             // the word fragment ends at the end of a syllable:
             // if a break occurs the content width increases,
             // otherwise nothing happens
-            wordElements.addAll(createElementsForAHyphen(alignment, hyphIPD, new MinOptMax(0)));
+            wordElements.addAll(createElementsForAHyphen(alignment, hyphIPD, widthIfNoBreakOccurs));
         } else if (bSuppressibleLetterSpace) {
             // the word fragment ends with a character that acts as a hyphen
             // if a break occurs the width does not increase,
@@ -1167,6 +1194,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
 
     private LinkedList createElementsForAHyphen(int alignment,
             int widthIfBreakOccurs, MinOptMax widthIfNoBreakOccurs) {
+        if (widthIfNoBreakOccurs == null) {
+            widthIfNoBreakOccurs = ZERO_MINOPTMAX;
+        }
         LinkedList hyphenElements = new LinkedList();
         
         switch (alignment) {
index 7848f22f570025fcad18e87bd085dd656c41d1ab..765a0fcc4b85872c2581aae7beac302fe508f6b5 100644 (file)
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="JM" type="fix">
+        Bugfix: The combination of hyphenation and kerning resulted in slightly ragged 
+        right ends for right-aligned and justified text.
+      </action>
+      <action context="Code" dev="JM" type="fix">
+        Bugfix: NullPointerException in AreaAdditionUtil in a table-cell spanning
+        multiple pages and with a marker.
+      </action>
+      <action context="Code" dev="JM" type="fix" fixes-bug="39533">
+        Bugfix: NullPointerException in RTF output when a table does not contain
+        table-columns.
+      </action>
+      <action context="Code" dev="JM" type="fix" fixes-bug="39607" due-to="Julien AymĂ©">
+        Bugfix: NullPointerException in RTF library when there are no borders on 
+        the parent table.
+      </action>
       <action context="Code" dev="JM" type="add">
        Automatic support for all fonts available to the Java2D subsystem for all
        Java2D-descendant renderers (TIFF, PNG, print, AWT).
diff --git a/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml b/test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml
new file mode 100644 (file)
index 0000000..5ee6c9b
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2006 The Apache Software Foundation
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      Checks hyphenation in combination with kerning.
+    </p>
+  </info>
+  <cfg>
+    <base14kerning>true</base14kerning>
+  </cfg>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" hyphenate="true">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="simple" page-height="5in" page-width="5in">
+          <fo:region-body/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="simple">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block font-size="20pt" line-height="1.0" text-align="justify" text-align-last="justify" background-color="lightgray" start-indent="10pt" end-indent="10pt" border="solid 1pt">
+            hyphenation regression advantage foundation vandalism AVAVAVA vandavanda
+            hyphenation regression advantage foundation vandalism AVAVAVA vandavanda
+            hyphenation regression
+          </fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="1" xpath="count(//pageViewport)"/>
+    
+    <eval expected="17230" xpath="//flow/block[1]/lineArea[1]/text[1]/@twsadjust"/>
+    <eval expected="-1339" xpath="//flow/block[1]/lineArea[2]/text[1]/@twsadjust"/>
+    <eval expected="2393" xpath="//flow/block[1]/lineArea[3]/text[1]/@twsadjust"/>
+    <eval expected="5900" xpath="//flow/block[1]/lineArea[4]/text[1]/@twsadjust"/>
+    <eval expected="9900" xpath="//flow/block[1]/lineArea[5]/text[1]/@twsadjust"/>
+    
+    <!-- In no-break condition there's a -400 kerning between a and v. It musn't occur if "vandavanda" is hyphenated. -->
+    <eval expected="vanda-" xpath="//flow/block[1]/lineArea[2]/text[1]/word[4]"/>
+    <eval expected="0 -500 0 0 0 0" xpath="//flow/block[1]/lineArea[2]/text[1]/word[4]/@letter-adjust"/>
+    <eval expected="vanda" xpath="//flow/block[1]/lineArea[3]/text[1]/word[1]"/>
+    <eval expected="0 -500 0 0 0" xpath="//flow/block[1]/lineArea[3]/text[1]/word[1]/@letter-adjust"/>
+  </checks>
+</testcase>