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

1.4 REGRESSION: Rotated Sans Serif font doesn't render properly when scaled

XMLWordPrintable

    • 2d
    • b77
    • x86
    • windows_2000, windows_xp

      BCDEFGHIJKLMNOPQRSTUVWZXYZ",-470,650);
      g2d.drawString("Arial 18B scaleX 50%, rotated left",-470,725);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",-470,700);
      g2d.rotate(Math.PI / 2);

      g2d.drawString("Arial 18B SCALEX 50%, NOT ROTATED",520,75);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",520,100);
      g2d.drawString("Arial 18B scaleX 50%, not rotated",520,125);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz",520,150);
      }
      public Dimension getPreferredSize()
      { return new Dimension(750,550);
      }
      public Dimension getMinimumSize()
      { return this.getPreferredSize();
      } }

      ---------- END SOURCE ----------
      (Review ID: 183637)
      ======================================================================
      Name: jk109818 Date: 08/18/2003


      FULL PRODUCT VERSION :
      java version "1.4.1_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
      Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

      FULL OS VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      DELL Latitude 610 laptop with docking station
      Multiple displays on Radeon Mobility

      A DESCRIPTION OF THE PROBLEM :
      When displaying a rotated text string along the y-axis with a SansSerif font, the text string does not get rendered very well with Java 1.4.1. In Java 1.3.1 the rotated text string at least appeared legible and was acceptable even though it may have been "stretched" out.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Demo program provided below.
      Compile and run under 1.3.1
      Then
      Compile and run under 1.4.1

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected rotated text in 1.4.1 to scale as in the earlier version (1.3.1) of Java. Though scaled text in Java 1.3.1 may appear "stretched" it is at least still legible and acceptable.
      Rotated text string (representing Y-axis label) in SansSerif font does not scale nicely with verision 1.4.1. This was not the case with 1.3.1. With 1.4.1 depending on how a window (or panel) is sized the text can be:

      1.) Text can appear blotchy and illegible.
      2.) Single characters in text can appear to be a different font size than other characters within the text.
      3.) Large gaps between characters within a word of text.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      /*
         FontScalingProblem.java
      */
      //package fontscalingproblem;

      import javax.swing.UIManager;
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;

      public class FontScalingProblem
      {
        private boolean packFrame = false;

        public FontScalingProblem()
        {
          PlotFrame frame = new PlotFrame();
          if (packFrame)
          {
            frame.pack();
          }
          else
          {
            frame.validate();
          }
      //Center the window
          Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
          Dimension frameSize = frame.getSize();
          if (frameSize.height > screenSize.height)
          {
            frameSize.height = screenSize.height;
          }
          if (frameSize.width > screenSize.width)
          {
            frameSize.width = screenSize.width;
          }
          frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
          frame.setVisible(true);
        }
      //Main method
        public static void main(String[] args)
        {
          try
          {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
          }
          catch(Exception e)
          {
            e.printStackTrace();
          }
          new FontScalingProblem();
        }
      // Plot Frame
        public class PlotFrame extends JFrame
        {
          private JPanel contentPane;
          private GridLayout gridLayout1 = new GridLayout();
          private BorderLayout borderLayout1 = new BorderLayout();

          private static final int LABEL_PT_BASE = 36;
          private static final int windowWidth = 600, windowHeight = 600;
          private Font labelFont = new Font( "SansSerif", Font.PLAIN, LABEL_PT_BASE );
          private double baseWidth, baseHeight;

          public PlotFrame()
          {
            enableEvents(AWTEvent.WINDOW_EVENT_MASK);
            try
            {
              jbInit();
            }
            catch(Exception e)
            {
              e.printStackTrace();
            }
          }
      //Component initialization
          private void jbInit() throws Exception
          {
            contentPane = (JPanel) this.getContentPane();
            gridLayout1.setColumns(1);
            gridLayout1.setHgap(5);
            gridLayout1.setRows(0);
            gridLayout1.setVgap(5);
            contentPane.setLayout(gridLayout1);
            contentPane.add( new PlotPanel() );
            contentPane.add( new PlotPanel() );
            contentPane.add( new PlotPanel() );
      // contentPane.add( new PlotPanel() );
            baseWidth = windowWidth; baseHeight = windowHeight;
            this.setSize(new Dimension(windowWidth, windowHeight));
            this.setTitle("Font Rotation and Scaling Problem");
          }
      //Overridden so we can exit when window is closed
          protected void processWindowEvent(WindowEvent e)
          {
            super.processWindowEvent(e);
            if (e.getID() == WindowEvent.WINDOW_CLOSING)
            {
              System.exit(0);
            }
          }
      // Plot Panel
          class PlotPanel extends JPanel
          {
            public void paintComponent( Graphics g )
            {
              double xScale, yScale;

              super.paintComponent( g );

              Dimension windowSize = this.getSize();
              Graphics2D g2d = (Graphics2D)g;
      // Antialias text.
              g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
              g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
      // Set font
              g2d.setFont( labelFont );
      // Set current scale from original base setting
              xScale = windowSize.width / baseWidth; yScale = windowSize.height / baseHeight;
              g2d.scale( xScale, yScale );
      // Add axis lines
              g2d.drawLine( 80, 500, 525, 500 );
              g2d.drawLine( 80, 500, 80, 0 );
      // Add axis labels
              g2d.drawString( "This is a X-axis label.", 75f, 550f );
      // Rotate -90 degrees
              g2d.rotate( Math.toRadians( 270f ) );
              g2d.drawString( "This is a Y-axis label.", -500f, 75f );
            }
          }
        }
      }
      ---------- END SOURCE ----------

      Release Regression From : 1.3.1_08
      The above release value was the last known release where this
      bug was known to work. Since then there has been a regression.

      (Incident Review ID: 182386)
      ======================================================================

      Name: jk109818 Date: 08/25/2003


      FULL PRODUCT VERSION :
      java version "1.4.2-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-beta-b19)
      Java HotSpot(TM) Client VM (build 1.4.2-beta-b19, mixed mode)

      FULL OS VERSION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      Rotated, scaled Arial font is MANGLED on screen, but prints OK in J2SE 1.4.X.

      The letter "N" is particularly noticeable, but the other characters are also pretty bad.

      Problem ONLY OCCURS IN J2SE 1.4.X.

      Problem does NOT occur in J2SE 1.3.X - 1.3 looks just fine on screen.

      I have to keep all my customers on J2SE 1.3.1!

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run code below. Text with mangled fonts will display.

      Click on the "Print" button at the top of the JFrame to see that printing is OK.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The above code displays text in a JPanel, with a "Print" button to test how it prints.

      Fonts used are Arial 12pt, 16pt, and 18pt, BOLD. The fonts are scaled in the X dimension 75%, 60%, and 50%, respectively.

      I expected the fonts to display just like they do in J2SE 1.3.1, which is very nice.
      The fonts look TERRIBLE, especially the Arial 18pt Bold, scaleX = 50%.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import javax.swing.*;
      import java.awt.print.*;
      import java.awt.event.*;
      import java.awt.geom.*;

      public final class FontMain extends JApplet implements Pageable
      { private boolean inAnAppletFlag = false;
      //private boolean printFlag = false;
      PrinterJob pj = null;
      private FontPanel fontPanel = null;
      private JFrame localOwnerFrame = null;
      private JButton printButton = null;
      private BorderLayout borderLayout = new BorderLayout(5,10);
      private PageFormat localPageFormat = null;
      private Paper localPaper = null;

      public FontMain(JFrame ownerFrame)
      { super();
      localOwnerFrame = ownerFrame;
      localOwnerFrame.addWindowListener(new FontWindowAdapter(ownerFrame));
      inAnAppletFlag = false;
      }
      public FontMain() //**** constructor for Applet - need a Frame
      { super();
      inAnAppletFlag = true;
      }
      public void init() //**** APPLET init() method - also called by main()
      { if (printButton == null)
      { this.getContentPane().setLayout(borderLayout);
      this.getContentPane().setBackground(Color.white);
      if (localOwnerFrame != null)
      localOwnerFrame.setBackground(Color.white);

      printButton = new JButton("------------------- Click HERE to PRINT This Page -------------------");
      printButton.setBackground(Color.white);
      printButton.setForeground(Color.black);
      this.getContentPane().add("North", printButton);

      fontPanel = new FontPanel(this);
      this.getContentPane().add("Center", fontPanel);

      printButton.addActionListener(new FontActionListener());

      this.validate();
      } }
      public void start() {}
      public void stop() {}

      final void pageSetup()
      { if (pj == null)
      { pj = PrinterJob.getPrinterJob();
      pj.setPageable(this);
      }
      //First time thru
      if (localPageFormat == null)
      { localPageFormat = pj.defaultPage();
      localPageFormat.setOrientation(PageFormat.LANDSCAPE);
      }
      localPaper = localPageFormat.getPaper();
      localPaper.setImageableArea(8.0d,26.0d,(double)(localPaper.getWidth()-16),(double)(localPaper.getHeight()-52));
      localPageFormat.setPaper(localPaper);
      }
      void printDocument()
      { this.pageSetup();

      if (pj != null)
      { if (pj.printDialog())
      { try
      { pj.print();
      }
      catch(Throwable e)
      { System.err.println("print() Throwable = " + e);
      } } }
      else
      { System.err.println("Printing Canceled by User");
      }
      pj = null;
      }
      public final int getNumberOfPages()
      { return 1;
      }
      public final PageFormat getPageFormat(int parmpagenum)
      { return this.localPageFormat;
      }
      public final Printable getPrintable(int parmpagenum)
      { return this.fontPanel;
      }
      public final String getAppletInfo()
      { return "Rotated, Scaled Font Bug Test";
      }
      public Dimension getMinimumSize()
      { return this.getPreferredSize();
      }
      public Dimension getPreferredSize()
      { return new Dimension(800,570);
      }

      final class FontActionListener implements ActionListener
      { public void actionPerformed(ActionEvent e)
      { printDocument();
      } }

      final class FontWindowAdapter extends WindowAdapter
      { JFrame localOriginFrame;
      public FontWindowAdapter(Component comp)
      { if(comp instanceof JFrame)
      { localOriginFrame = (JFrame)comp;
      } }
      public void windowClosing(WindowEvent we)
      { if(! inAnAppletFlag)
      System.exit(0);
      } }

      public static void main(String args[])
      { JFrame frame1 = new JFrame("Rotated, Scaled Font Bug Test");

      FontMain fontPanel = new FontMain(frame1);

      fontPanel.inAnAppletFlag = false;

      fontPanel.init();
      fontPanel.resize(fontPanel.getPreferredSize());

      frame1.getContentPane().add(fontPanel);
      frame1.setSize(fontPanel.getSize());
      frame1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame1.pack();
      frame1.setVisible(true);
      fontPanel.start();
      } }

      final class FontPanel extends JPanel implements Printable
      { private FontMain fontMain = null;
      private Graphics2D g2d = null;
      private RepaintManager currentRepaintManager = null;
      private Font font12B = new Font("Arial", Font.BOLD, 12);
      private Font font16B = new Font("Arial", Font.BOLD, 16);
      private Font font18B = new Font("Arial", Font.BOLD, 18);
      private String version = System.getProperty("java.version");

      FontPanel(FontMain parentJApplet)
      { super();
      fontMain = parentJApplet;
      this.setLayout(null);
      this.setBackground(Color.white);
      }

      public int print(java.awt.Graphics parmg, java.awt.print.PageFormat parmPageFormat, int parmPageIndex)
      { if (parmPageIndex != 0)
      { return NO_SUCH_PAGE;
      }
      g2d = (Graphics2D) parmg;
      this.disableDoubleBuffering();

      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

      g2d.translate(26,8);
      this.drawFonts(g2d, parmPageIndex);
      return Printable.PAGE_EXISTS;
      }

      private void disableDoubleBuffering()
      { currentRepaintManager = RepaintManager.currentManager(this);
      currentRepaintManager.setDoubleBufferingEnabled(false);
      }

      private void enableDoubleBuffering()
      { currentRepaintManager = RepaintManager.currentManager(this);
      currentRepaintManager.setDoubleBufferingEnabled(true);
      }
      public void paintComponent(Graphics parmg)
      { super.paintComponent(parmg);
      g2d = (Graphics2D) parmg;
      this.enableDoubleBuffering();
      g2d.translate(36,18);
      this.drawFonts(g2d,0);
      }
      private void drawFonts(Graphics2D g2d, int parmPageIndex)
      { g2d.setColor(Color.black);
      g2d.setFont(font18B);

      g2d.drawString("Java version " + version, 25, 50);

      font12B = font12B.deriveFont(AffineTransform.getScaleInstance(0.75d,1.0d));
      g2d.setFont(font12B);

      g2d.rotate(Math.PI / 2);
      g2d.drawString("Arial 12B SCALEX 75%, ROTATED RIGHT",200,-100);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",200,-75);
      g2d.drawString("Arial 12B scaleX 75%, rotated right",200,-50);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",200,-25);
      g2d.rotate(-Math.PI / 2);

      g2d.rotate(-Math.PI / 2);
      g2d.drawString("Arial 12B SCALEX 75%, ROTATED LEFT",-470,150);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",-470,175);
      g2d.drawString("Arial 12B scaleX 75%, rotated left",-470,200);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",-470,225);
      g2d.rotate(Math.PI / 2);

      g2d.drawString("Arial 12B SCALEX 75%, NOT ROTATED",25,75);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",25,100);
      g2d.drawString("Arial 12B scaleX 75%, not rotated",25,125);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",25,150);

      font16B = font16B.deriveFont(AffineTransform.getScaleInstance(0.6d,1.0d));
      g2d.setFont(font16B);

      g2d.rotate(Math.PI / 2);
      g2d.drawString("Arial 16B SCALEX 60%, ROTATED RIGHT",200,-275);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",200,-250);
      g2d.drawString("Arial 16B scaleX 60%, rotated right",200,-325);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",200,-300);
      g2d.rotate(-Math.PI / 2);

      g2d.rotate(-Math.PI / 2);
      g2d.drawString("Arial 16B SCALEX 60%, ROTATED LEFT",-470,375);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",-470,400);
      g2d.drawString("Arial 16B scaleX 60%, rotated left",-470,425);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",-470,450);
      g2d.rotate(Math.PI / 2);

      g2d.drawString("Arial 16B SCALEX 60%, NOT ROTATED",275,75);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",275,100);
      g2d.drawString("Arial 16B scaleX 60%, not rotated",275,125);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",275,150);

      font18B = font18B.deriveFont(AffineTransform.getScaleInstance(0.5d,1.0d));
      g2d.setFont(font18B);

      g2d.rotate(Math.PI / 2);
      g2d.drawString("Arial 18B SCALEX 50%, ROTATED RIGHT",200,-525);
      g2d.drawString("ABCDEFGHIJKLMNOPQRSTUVWZXYZ",200,-500);
      g2d.drawString("Arial 18B scaleX 50%, rotated right",200,-575);
      g2d.drawString("abcdefghijklmnopqrstuvwxyz0123456789",200,-600);
      g2d.rotate(-Math.PI / 2);

      g2d.rotate(-Math.PI / 2);
      g2d.drawString("Arial 18B SCALEX 50%, ROTATED LEFT",-470,675);
      g2d.drawString("A

            igor Igor Nekrestyanov (Inactive)
            jkimsunw Jeffrey Kim (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: