6904962: GlyphVector.getVisualBounds should not be affected by leading or trailing white space.
authorprr
Mon, 30 Nov 2009 14:39:35 -0800
changeset 4358 0549f5b9abd1
parent 4252 0e645080f74b
child 4359 0e67801780f7
6904962: GlyphVector.getVisualBounds should not be affected by leading or trailing white space. Reviewed-by: igor, dougfelt
jdk/src/share/classes/sun/font/StandardGlyphVector.java
jdk/test/java/awt/font/GlyphVector/VisualBounds.java
--- a/jdk/src/share/classes/sun/font/StandardGlyphVector.java	Mon Nov 09 14:23:49 2009 -0800
+++ b/jdk/src/share/classes/sun/font/StandardGlyphVector.java	Mon Nov 30 14:39:35 2009 -0800
@@ -396,12 +396,19 @@
 
     // !!! not cached, assume TextLayout will cache if necessary
     public Rectangle2D getVisualBounds() {
-        if (glyphs.length == 0) {
-            return new Rectangle2D.Float(0, 0, 0, 0);
+        Rectangle2D result = null;
+        for (int i = 0; i < glyphs.length; ++i) {
+            Rectangle2D glyphVB = getGlyphVisualBounds(i).getBounds2D();
+            if (!glyphVB.isEmpty()) {
+                if (result == null) {
+                    result = glyphVB;
+                } else {
+                    Rectangle2D.union(result, glyphVB, result);
+                }
+            }
         }
-        Rectangle2D result = getGlyphVisualBounds(0).getBounds2D();
-        for (int i = 1; i < glyphs.length; ++i) {
-            Rectangle2D.union(result, getGlyphVisualBounds(i).getBounds2D(), result);
+        if (result == null) {
+            result = new Rectangle2D.Float(0, 0, 0, 0);
         }
         return result;
     }
@@ -1787,8 +1794,19 @@
                 gp.transform(sgv.invdtx);
                 result = gp.getBounds2D();
             }
-            result.setRect(result.getMinX() + x + dx, result.getMinY() + y + dy,
-                           result.getWidth(), result.getHeight());
+            /* Since x is the logical advance of the glyph to this point.
+             * Because of the way that Rectangle.union is specified, this
+             * means that subsequent unioning of a rect including that
+             * will be affected, even if the glyph is empty. So skip such
+             * cases. This alone isn't a complete solution since x==0
+             * may also not be what is wanted. The code that does the
+             * unioning also needs to be aware to ignore empty glyphs.
+             */
+            if (!result.isEmpty()) {
+                result.setRect(result.getMinX() + x + dx,
+                               result.getMinY() + y + dy,
+                               result.getWidth(), result.getHeight());
+            }
             return result;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/GlyphVector/VisualBounds.java	Mon Nov 30 14:39:35 2009 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @summary leading and trailing spaces must not affect visual bounds
+ * @bug 6904962
+ */
+
+
+import java.awt.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+
+public class VisualBounds {
+
+    public static void main(String args[]) {
+
+        String s1 = "a";
+        String s2 = s1+" ";
+        String s3 = " "+s1;
+        Font f = new Font("Dialog", Font.PLAIN, 12);
+        FontRenderContext frc = new FontRenderContext(null, false, false);
+        GlyphVector gv1 = f.createGlyphVector(frc, s1);
+        GlyphVector gv2 = f.createGlyphVector(frc, s2);
+        GlyphVector gv3 = f.createGlyphVector(frc, s3);
+        Rectangle2D bds1 = gv1.getVisualBounds();
+        Rectangle2D bds2 = gv2.getVisualBounds();
+        Rectangle2D bds3 = gv3.getVisualBounds();
+        GlyphVector gv4 = f.createGlyphVector(frc, " ");
+        Rectangle2D bds4 = gv4.getVisualBounds();
+        System.out.println(bds1);
+        System.out.println(bds2);
+        System.out.println(bds3);
+        System.out.println(bds4);
+
+        if (!bds1.equals(bds2)) {
+          throw new RuntimeException("Trailing space: Visual bounds differ");
+        }
+        if (bds2.getWidth() != bds3.getWidth()) {
+          throw new RuntimeException("Leading space: Visual widths differ");
+       }
+        if (!bds4.isEmpty()) {
+          throw new RuntimeException("Non empty bounds for space");
+       }
+    }
+}