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

Printing CJK characters using Graphics API is always at starting of the text

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 7
    • client-libs
    • None
    • 2d
    • windows

      FULL PRODUCT VERSION :
      java version " 1.7.0_15 "
      Java(TM) SE Runtime Environment (build 1.7.0_15-b03)
      Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      Printing a text containing normal characters and any CJK characters using java.awt.Graphics2D, the CJK characters are always printed at the starting position of the line in which they overlaps with the non-CJK characters in printout.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Printing a text with any Chinese, Japanese and Korean (CJK) character using java.awt.Graphics, for example, Graphics.drawString(String str, int x, int y).

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The characters are printed properly one-by-one.
      ACTUAL -
      CJK characters are always printed at starting position and overlap with non-CJK characters.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package demo;

      import java.awt.BorderLayout;
      import java.awt.Dimension;
      import java.awt.Font;
      import java.awt.FontMetrics;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.GraphicsEnvironment;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.event.ItemEvent;
      import java.awt.event.ItemListener;
      import java.awt.event.WindowAdapter;
      import java.awt.event.WindowEvent;
      import java.awt.print.PageFormat;
      import java.awt.print.Printable;
      import java.awt.print.PrinterException;
      import java.awt.print.PrinterJob;

      import javax.swing.JButton;
      import javax.swing.JComboBox;
      import javax.swing.JFrame;
      import javax.swing.JTextField;
      import javax.swing.UIManager;

      public class GraphicsPrinter implements Printable, ActionListener {
      // It can be replaced into JTextArea
      private static JTextField textfield;
      private static JComboBox<String> fontNameComboBox;
      private static JComboBox<Integer> fontSizeComboBox;

      static class FontChangeListener implements ItemListener {
          public void itemStateChanged(ItemEvent e) {
          textfield.setFont(new Font((String)fontNameComboBox.getSelectedItem(), Font.PLAIN, ((Integer)fontSizeComboBox.getSelectedItem()).intValue()));
          };
          }

          public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
              if (page > 0) {
                  return NO_SUCH_PAGE;
              }
              
              Graphics2D g2d = (Graphics2D)g;
              FontMetrics fm = textfield.getFontMetrics(textfield.getFont());
              // A more than enough line spacing to prevent ANOTHER JAVA BUG...
              int lineSpacing = fm.getMaxAscent() + fm.getHeight() + fm.getMaxDescent();
              String text = textfield.getText();
              
              g2d.translate(100, 100);
              g2d.setFont(textfield.getFont());
              g2d.drawString(text, 0, g2d.getFontMetrics().getHeight());
              
              g2d.translate(0, lineSpacing);
              g2d.drawGlyphVector(g2d.getFont().createGlyphVector(g2d.getFontRenderContext(), textfield.getText()), 0.0f, (float)g2d.getFontMetrics().getHeight());
              
              
              return PAGE_EXISTS;
          }

          public void actionPerformed(ActionEvent e) {
               PrinterJob job = PrinterJob.getPrinterJob();
               job.setPrintable(this);
               boolean ok = job.printDialog();
               if (ok) {
                   try {
                        job.print();
                   } catch (PrinterException ex) {
                    ex.printStackTrace();
                   }
               }
          }
          
          public static void main(String args[]) throws Exception {
              UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
              JFrame f = new JFrame( " Graphics Printer " );
              f.addWindowListener(new WindowAdapter() {
              public void windowClosing(WindowEvent e) {
              System.exit(0);
              }
              });
              
              // Default Text
              // The unicode characters are Chinese characters of 1234 correspondingly
              textfield = new JTextField( " 1234\u4E00\u4E8C\u4E09\u56DB " );
              textfield.setPreferredSize(new Dimension(200, 30));
              textfield.setBorder(null);
              
              // Prepare font name and size
              fontNameComboBox = new JComboBox<String>(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
              Integer[] fontSize = new Integer[50];
              for (int i = 0; i < fontSize.length; i++)
              fontSize[i] = new Integer(i + 1);
              fontSizeComboBox = new JComboBox<Integer>(fontSize);
              
              // Add change listener
              fontNameComboBox.addItemListener(new FontChangeListener());
              fontSizeComboBox.addItemListener(new FontChangeListener());
              
              fontNameComboBox.setSelectedItem( " SansSerif " );
              fontSizeComboBox.setSelectedItem(12);
              
              JButton printButton = new JButton( " Print using Graphics " );
              printButton.addActionListener(new GraphicsPrinter());
              
              f.setLayout(new BorderLayout(5, 5));
              f.add(textfield, BorderLayout.WEST);
              f.add(fontNameComboBox, BorderLayout.CENTER);
              f.add(fontSizeComboBox, BorderLayout.EAST);
              f.add(printButton, BorderLayout.SOUTH);
              f.pack();
              f.setVisible(true);
          }
      }

      ---------- END SOURCE ----------

      SUPPORT :
      YES

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

              Created:
              Updated:
              Resolved: