Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6313761

FontMetrics.getStringBounds() floating point overflow problems

    • Icon: Bug Bug
    • Resolution: Cannot Reproduce
    • Icon: P4 P4
    • None
    • 1.4.2
    • client-libs
    • 2d
    • itanium
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.5.0_04"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
      Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      There seems to be a pretty serious bug in FontMetrics.getStringBounds() whereby the font width will keep on increasing as the font size grows but then all of a sudden on larger values it'll shrink. I'm expecting the font width to always get bigger as the font size increases. Here are two data points that show what I'm seeing...

      java.awt.Font[family=Georgia,name=Georgia,style=bold,size=268435488]
      \-> width("SAMPLE")=145

      java.awt.Font[family=Georgia,name=Georgia,style=bold,size=134217776]
      \-> width("SAMPLE")=218

      Notice how the text width grows as the font size shrinks.

      This is a serious problem for me because I'm trying to programmatically detect what font size (in point units) will produce a certain text width (in pixel units). I can't use a binary search algorithm with the above bug.


      REPRODUCIBILITY :
      This bug can be reproduced always.
      The submitter provided this additional information

      import java.awt.Font;
      import java.awt.Graphics;
      import javax.swing.JFrame;

      public class FontMetricsBug
      {
         public static void main(String[] args)
         {
           Font bigFont = new Font("Times New Roman", Font.PLAIN, 268435488);
           Font smallFont = new Font("Times New Roman", Font.PLAIN, 134217776);
           JFrame frame = new JFrame();
           frame.setVisible(true);
           Graphics graphics = frame.getGraphics();
           final String text = "test";
           int bigWidth = graphics.getFontMetrics(bigFont).stringWidth(text);
           int smallWidth = graphics.getFontMetrics(smallFont).stringWidth(text);
           assert(bigWidth >= smallWidth): "bigWidth=" + bigWidth + ",
      smallWidth=" +
             smallWidth;
         }
      }

      I get an output of "bigWidth=43, smallWidth=66" on my end which clearly
      indicates a problem :) Also, on a related note, I noticed that
      FontMetrics.getStringBounds() returns a Rectangle2D and then you can
      invoke Rectangle2D.getBounds() to cast the bounds from float/double into
      an int. I looked at the underlying code and there is no checking for
      overflow. Isn't it possible for an overflow to occur if the original
      coordinates were double and were being cast to an int? Should I file a
      separate issue for this? (it is somewhat related to FontMetrics and
      overflow problems)

      I also see problems with the following test case:

      import java.awt.*;
      import java.awt.image.*;

      public class FM {

          public static void main(String args[]) {
             BufferedImage bi = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D)bi.getGraphics();

              double sf = 1;
              //double sf = 0.0000001;
              //double sf = 10000;
              g.scale(sf, sf);
              for (int i=0;i<31;i++){
                  int sz = (int)Math.pow(2, i);
                  Font f = new Font("Arial", Font.PLAIN, sz);
                  g.setFont(f);
                  FontMetrics fm = g.getFontMetrics();
                  System.out.println(f.getSize() + " " + fm.stringWidth("SAMPLE") +
                                      " " + fm.getStringBounds("SAMPLE", g));
              }
          }
      }
      % java FM
      1 6 java.awt.geom.Rectangle2D$Float[x=0.0,y=-0.92163086,w=6.0,h=1.1499023]
      2 7 java.awt.geom.Rectangle2D$Float[x=0.0,y=-1.8432617,w=7.0,h=2.2998047]
      4 17 java.awt.geom.Rectangle2D$Float[x=0.0,y=-3.6865234,w=17.0,h=4.5996094]
      8 31 java.awt.geom.Rectangle2D$Float[x=0.0,y=-7.373047,w=31.0,h=9.199219]
      16 66 java.awt.geom.Rectangle2D$Float[x=0.0,y=-14.746094,w=66.0,h=18.398438]
      32 129 java.awt.geom.Rectangle2D$Float[x=0.0,y=-29.492188,w=129.0,h=36.796875]
      64 261 java.awt.geom.Rectangle2D$Float[x=0.0,y=-58.984375,w=261.0,h=73.59375]
      128 516 java.awt.geom.Rectangle2D$Float[x=0.0,y=-117.96875,w=516.0,h=147.1875]
      256 1039 java.awt.geom.Rectangle2D$Float[x=0.0,y=-235.9375,w=1039.0,h=294.375]
      512 2080 java.awt.geom.Rectangle2D$Float[x=0.0,y=-471.875,w=2080.0,h=588.75]
      1024 4155 java.awt.geom.Rectangle2D$Float[x=0.0,y=-943.75,w=4155.0,h=1177.5]
      2048 8310 java.awt.geom.Rectangle2D$Float[x=0.0,y=-1887.5,w=8310.0,h=2355.0]
      4096 16619 java.awt.geom.Rectangle2D$Float[x=0.0,y=-3775.0,w=16619.0,h=4710.0]
      8192 33237 java.awt.geom.Rectangle2D$Float[x=0.0,y=-7550.0,w=33237.0,h=9420.0]
      16384 66473 java.awt.geom.Rectangle2D$Float[x=0.0,y=-15100.0,w=66473.0,h=18840.0]
      32768 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      65536 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      131072 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      262144 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      524288 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      1048576 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      2097152 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      4194304 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      8388608 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      16777216 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      33554432 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      67108864 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      134217728 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      268435456 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      536870912 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]
      1073741824 0 java.awt.geom.Rectangle2D$Float[x=0.0,y=0.0,w=0.0,h=0.0]

            pbansal Pankaj Bansal (Inactive)
            prr Philip Race
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: