JDK-8016589 : Printing CJK characters using Graphics API is always at starting of the text
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows
  • Submitted: 2013-04-04
  • Updated: 2013-06-13
  • Resolved: 2013-06-13
Related Reports
Duplicate :  
Description
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