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

Disproportionate scaling on rotated GlyphVectors places characters wrong

XMLWordPrintable

    • 2d
    • generic, x86, sparc
    • generic, solaris_2.6, windows_nt



      Name: gsC80088 Date: 11/10/98


      TextLayout renders incorrectly when rotated
      and scaled with different values for x and y.
      The letters are incorrectly placed.

      import javax.swing.*;
      import java.awt.*;
      import java.awt.font.*;
      import java.awt.geom.*;

      class TextTest
      {
        public static void main (String args[])
          {
            JFrame frame = new JFrame ("Text test");

            final String sample = "alAL";
            final Font font = new Font ("Helvetica", Font.PLAIN, 32);
            final FontRenderContext context = new FontRenderContext(null, true, true);
            final TextLayout layout = new TextLayout (sample, font, context);
            final Rectangle2D bounds = layout.getBounds();

            double angle = Math.toRadians (45);

            final AffineTransform xform1 = new AffineTransform ();
            xform1.translate (100, 100);
            xform1.rotate (angle);
            xform1.scale (4, 4);

            final AffineTransform xform2 = new AffineTransform ();
            xform2.translate (300, 100);
            xform2.rotate (angle);
            xform2.scale (4, 2);

            JComponent text = new JComponent ()
              {
                public void paint (Graphics g)
                  {
                    Graphics2D g2 = (Graphics2D) g;
                    AffineTransform oldXform = g2.getTransform ();

                    g2.setColor (Color.black);

                    g2.setTransform (xform1);
                    g2.draw (bounds);
                    layout.draw (g2, 0, 0);

                    g2.setTransform (xform2);
                    g2.draw (bounds);
                    layout.draw (g2, 0, 0);

                    g2.setTransform (oldXform);
                  }
              };
            text.setPreferredSize (new Dimension (600, 400));

            frame.getContentPane ().add (text);
            frame.pack ();
            frame.show ();
          }
      }
      (Review ID: 41437)
      ======================================================================

      Name: gsC80088 Date: 03/11/99


      1. Problem seems to occur when drawing text (with drawString())
      into a Graphics context (with translate()). The problem is
      platform independant (tested on Solaris x86 and Windows),
      and appears to be a Java2D problem, since it doesn't occur
      under Java 1.1 . It may be related to bug # 4174542 . The
      problem does not occur with line drawing, only text rendering.

      2. See applet code (with HTML) at end of bug report.

      3, 4 None.

      5.
      JAVA.EXE full version "JDK-1.2-V"

      6. No special configuration.

      This applet writes "Hello" with an underline, and
      then translates the graphics context. It then
      attempts to write "Hello" again next to the first
      with an underline. The second "Hello" doesn't
      appear under Java 1.2, whereas the underline does.
      --- BEGIN APPLET CODE ---
      import java.awt.*;
      import java.applet.*;

      public class TestApp extends Applet {

      public void paint(Graphics g) {
      if(miOffscreen != null)
      g.drawImage(miOffscreen, 0, 0, this);
      else {
      Thread t = new Thread(new Runnable() {
      public void run() {
      draw();
      }
      });
      t.start();
      }
      }

      private void draw() {
      Image iTemp = createImage(getBounds().width, getBounds().height);
      Graphics gImage = iTemp.getGraphics();

      gImage.drawString("Hello",20,20);
      gImage.drawLine(20,40,40,40);
      gImage.translate(0,-500);
      gImage.drawString("Hello",50,520);
      gImage.drawLine(50,540,70,540);
      miOffscreen = iTemp;
      repaint();
      }

      private Image miOffscreen;
      }
      --- END APPLET CODE ---
      --- BEGIN HTML ---
      <body>
      <applet code="TestApp" WIDTH="200" HEIGHT="200">
      </applet>
      </body>
      --- END HTML ---
      ======================================================================

      Name: krT82822 Date: 05/03/99


      /*

      Rotated text is not drawn correctly at certain angles


      I have an application that draws some text annotations at various
      angles, and I noticed at certain angles the text does not line up
      as expected. This sample program shows the problem; the slider at the
      top of the window can be adjusted, causing the angle of the line drawn
      (and its accompanying text) to vary from 0 to 360 degrees. At some angles
      all is well, but at others the text "wobbles" along the line segment.

      This can be easily seem by just moving the slider back and forth (or using
      the keyboard to change the angle 1 degree at a time.) Try some angles like
      3 or 349; the problem seems especially acute.

      Am I missing something? Is there a reason why the text is not expected to line
      up?

      My guess is that there is a problem somewhere converting doubles to integers; I
      think some numbers are being truncated rather than rounded.

      This is happening on JDK 1.2.1 under NT 4.0. (It also happened on a recent
      1.2.2 Beta. so I don't think this has been addressed yet.)

      java version "1.2"
      Classic VM (build JDK-1.2-V, native threads)

      java full version "JDK-1.2-V"

      */

      import java.awt.*;
      import java.awt.geom.*;
      import javax.swing.*;
      import javax.swing.border.*;
      import javax.swing.event.*;

      public class RotateTest implements ChangeListener
      {
          public static void main(String args[])
          {
              new RotateTest();
          }

          public JFrame jf;
          public JSlider js1;
          public MyCanvas canvas;

          int degrees = 0;
          double theta = 0.0;

          public RotateTest()
          {
              jf = new JFrame("Test Text Rotation");

              js1 = new JSlider(0,359,0);
              js1.setPaintLabels(true);
              js1.setPaintTicks(true);
              js1.setMajorTickSpacing(30);

              canvas = new MyCanvas();

              jf.setSize(500,500);
              jf.getContentPane().setLayout(new BorderLayout());
              jf.getContentPane().add(js1,"North");
              jf.getContentPane().add(canvas,"Center");
                                      
              js1.addChangeListener(this);
              jf.show();
          }

          public void stateChanged(ChangeEvent e)
          {
              if (e.getSource() == js1)
              {
                  degrees = js1.getValue();
                  
                  theta = java.lang.Math.toRadians(degrees);
                  canvas.repaint();
              }
          }

          class MyCanvas extends JComponent
          {
              public void paint(Graphics g)
              {
                  if (g instanceof Graphics2D)
                  {
                      String legend;
                      Rectangle2D legendBounds;
                      int x,y;
                      double xoff,yoff;
                      int diameter;
                      Graphics2D g2 = (Graphics2D)g;
                      Dimension d = this.getSize();
          
                      g2.setColor(Color.red);
          
                      //
                      // Draw a line segment that will fit inside the canvas.
                      //
                      if (d.width > d.height)
                      {
                          diameter = d.height/2;
                      }
                      else
                      {
                          diameter = d.width/2;
                      }

                      //
                      // Draw a line segment annotated by rotated text. An annotation is drawn
                      // at the same angle and parallel to the line.
                      //

                      //
                      // The starting point is the center of the canvas.
                      //
                      x = d.width/2;
                      y = d.height/2;

                      //
                      // Get the legend to draw and it's size
                      //
                      legend = "" + degrees + " Degrees - ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
                      legendBounds = g2.getFontMetrics().getStringBounds(legend,g2);

                      //
                      // Compute an offset along the line segment where the text
                      // should start.
                      //
                      xoff = 0.0;
                      yoff = -legendBounds.getHeight() / 2.0;

                      //
                      // Adjust the Graphics context; set the origin to the center
                      // and rotate the coordinate system to match the line.
                      //
                      g2.translate(x, y);
                      g2.rotate(theta);

                      //
                      // Draw the line segment
                      //
                      g2.drawLine(0,0,diameter,0);

                      //
                      // Draw the legend; note that the text "wobbles" along the line;
                      // sometimes its close and sometimes it far off.
                      //
                      g2.drawString(legend,(float)xoff, (float)yoff);

                      //
                      // Draw a box around the text; this shows the effect even more
                      // dramatically.
                      //
      // g2.drawRect((int)Math.round(xoff),(int)Math.round(yoff-legendBounds.getHeight()),(int)Math.round(legendBounds.getWidth()),(int)Math.round(legendBounds.getHeight()));
                  }
              }
          }
      }
      (Review ID: 57758)
      ======================================================================

      Name: krT82822 Date: 06/16/99


      Depending on the transformation matrix in use, drawGlyphVector
      sometimes draws the text in the wrong direction. Orientation
      of each glyph is correct. However, the escapement vector is
      wrong. Because of this the glyphs do not share the same
      baseline.

      Put another way, the x and y increments made after drawing
      each glyph is incorrect. So the text is not drawn on a
      single line.

      java version "1.2.1"
      HotSpot VM (1.0fcs, mixed mode, build E)

      java full version "JDK-1.2.1-A"

      ------------------------------------------------------------

      import java.awt.*;
      import java.awt.event.*;
      import java.awt.font.*;
      import java.awt.geom.*;

      // Program demonstrates bug in Graphics2D.drawGlyphVector()
      // The bug is that the text is laid out in the wrong direction.
      // author: ###@###.###
      // JDK 1.2.1 on Windows NT 4.0

      class Test extends Canvas
      {
         final int canvasHeight = 500;
         final int canvasWidth = 500;

         Test()
         {
            setSize(canvasWidth, canvasHeight);
         }

         public void paint(Graphics g)
         {
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);

            // We need a PostScript-like co-ordinate system
            AffineTransform at1 = new AffineTransform();
            at1.translate(0, canvasHeight - 1);
            at1.scale(1, -1);
            g2.transform(at1); // program works correctly if you comment this line

            // We want to draw rotated text
            AffineTransform at2 = new AffineTransform();
            at2.rotate((30*Math.PI)/180);
            g2.transform(at2); // program works correctly if you comment this line

            // Create font
            // Note: Since co-ordinate axes are reflected, font must be
            // reflected too, in order to get upright text.
            Font f1 = new Font("Arial", Font.PLAIN, 1);
            Font f2 = f1.deriveFont(new AffineTransform(24, 0, 0, -24, 0, 0));

            // Draw text using drawGlyphVector
            float x = 200, y = 200;
            GlyphVector gv = f2.createGlyphVector(g2.getFontRenderContext(),
                                                    "Hello World!");
            float w = (float)gv.getVisualBounds().getWidth();
            g2.drawGlyphVector(gv, x, y);
            g2.draw(new Line2D.Float(x, y - 2, x + w, y - 2)); // underline text

            // drawString works correctly
            // g2.setFont(f2);
            // g2.drawString("Hello World!", x, y);

            // Reset transforms
            g2.setTransform(new AffineTransform());
         }

         public static void main(String args[])
         {
            Frame frame = new Frame("Test");
            WindowListener l = new WindowAdapter()
            {
               public void windowClosing(WindowEvent e)
               {
                  System.exit(0);
               }
            };

            frame.addWindowListener(l);
            frame.add("Center", new Test());
            frame.pack();
            frame.setLocation(new java.awt.Point(100, 0));
            frame.setVisible(true);
         }
      }
      (Review ID: 68093)
      ======================================================================

            prr Philip Race
            gstone Greg Stone
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: