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

StandardGlyphVector.getGlyphMetrics creates metrics with erroneous bounds for characters with no outline (e.g., the space character ' ')

XMLWordPrintable

    • 2d
    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      java version "1.8.0_101"
      Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      GlyphMetric objects returned by StandardGlyphVector.getGlyphMetrics contain bounds that are calculated by taking the glyph’s visual bounds and normalizing them by subtracting the glyph’s position.

      However, some glyphs (e.g., the glyph for the space character) do not have visual bounds. Their outline is an empty shape. In such a case the bounds in the metrics should not be normalized by the glyph’s position. The code erroneously ignores this special case, thus producing bounds with inconsistent negative positions.

      The test code below demonstrates this.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test code below.

      The test code prints the bounds of the metric objects returned by glyphVector.getGlyphMetrics for the characters in the string "This is a bug".

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expect the metrics to be the same for the same characters.

      I expect the x value of the bounds for the space character to be 0.

      ACTUAL -
      The results for the three space characters in this string are:

      ' ' yeilds bounds java.awt.geom.Rectangle2D$Float[x=-34.004883,y=0.0,w=0.0,h=0.0]
      ' ' yeilds bounds java.awt.geom.Rectangle2D$Float[x=-52.004883,y=0.0,w=0.0,h=0.0]
      ' ' yeilds bounds java.awt.geom.Rectangle2D$Float[x=-67.0166,y=0.0,w=0.0,h=0.0]

      The x value is not zero. It is not the same for identical characters. It is erroneously being set to the negative value of the glyph's position.

      This is the full output of the test program:

      'T' yeilds bounds java.awt.geom.Rectangle2D$Float[x=0.421875,y=-12.890625,w=10.21875,h=12.890625]
      'h' yeilds bounds java.awt.geom.Rectangle2D$Float[x=1.1875,y=-12.890625,w=7.609375,h=12.890625]
      'i' yeilds bounds java.awt.geom.Rectangle2D$Float[x=1.203125,y=-12.890625,w=1.578125,h=12.890625]
      's' yeilds bounds java.awt.geom.Rectangle2D$Float[x=0.546875,y=-9.546875,w=7.765625,h=9.765625]
      ' ' yeilds bounds java.awt.geom.Rectangle2D$Float[x=-34.004883,y=0.0,w=0.0,h=0.0]
      'i' yeilds bounds java.awt.geom.Rectangle2D$Float[x=1.203125,y=-12.890625,w=1.578125,h=12.890625]
      's' yeilds bounds java.awt.geom.Rectangle2D$Float[x=0.546875,y=-9.546875,w=7.765625,h=9.765625]
      ' ' yeilds bounds java.awt.geom.Rectangle2D$Float[x=-52.004883,y=0.0,w=0.0,h=0.0]
      'a' yeilds bounds java.awt.geom.Rectangle2D$Float[x=0.65625,y=-9.546875,w=8.59375,h=9.765625]
      ' ' yeilds bounds java.awt.geom.Rectangle2D$Float[x=-67.0166,y=0.0,w=0.0,h=0.0]
      'b' yeilds bounds java.awt.geom.Rectangle2D$Float[x=1.171875,y=-12.890625,w=8.09375,h=13.109375]
      'u' yeilds bounds java.awt.geom.Rectangle2D$Float[x=1.15625,y=-9.328125,w=7.5625,h=9.546875]
      'g' yeilds bounds java.awt.geom.Rectangle2D$Float[x=0.578125,y=-9.546875,w=8.234375,h=13.328125]

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package com.sundaysky.bugdemo;

      import java.awt.*;
      import java.awt.font.FontRenderContext;
      import java.awt.font.GlyphMetrics;
      import java.awt.font.GlyphVector;
      import java.awt.geom.AffineTransform;

      /**
       * Created by Jamie Julius on 9/28/2016.
       */
      public class StandardGlyphVectorBug
      {
          public static void main(String args[])
          {
              String text = "This is a bug";

              Font font = new Font("Arial", Font.PLAIN, 18);
              FontRenderContext fontRenderContext = new FontRenderContext(new AffineTransform(), true, true);
              GlyphVector glyphVector = font.createGlyphVector(fontRenderContext, text);

              for (int i = 0; i < glyphVector.getNumGlyphs(); ++i) {
                  GlyphMetrics metrics = glyphVector.getGlyphMetrics(i);
                  System.out.println(String.format("'%c' yeilds bounds %s", text.charAt(i), metrics.getBounds2D()));
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The bounds returned by the metrics object can be fixed if necessary.

            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: