Solved

Why does printing a StyledDocument produce misaligned text in Java 1.6 but not 1.5?

Posted on 2009-04-06
5
1,259 Views
Last Modified: 2013-11-23
The issue we are seeing is that text displayed onscreen looks different when printed in Java 1.6.  In particular, we are seeing text that is replaced within a StyledDocument is loosing it's whitespace when printed.  However the text looks fine onscreen.

For example:
EXPECTED - Note:  The underscores are really whitespaces.
Page_1_of_2

ACTUAL
Page_1_of2

On Java 1.5 everything looks fine.  We have narrowed down that passing in null for the ((AbstractDocument)document).replace(5, 1, "1", null); and ((AbstractDocument)document).replace(10, 1, "2", null); makes this issue go away but that is not an acceptable solution.

We have tried Java 1.6.0_11, 1.6.0_12, 1.6.0_13, and 1.7.0-ea but all versions produce the same problem.  Any ideas on what we're doing wrong?
import java.awt.Container;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.print.PageFormat;

import java.awt.print.Printable;

import java.awt.print.PrinterException;

import java.awt.print.PrinterJob;
 

import javax.swing.AbstractButton;

import javax.swing.BoxLayout;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JScrollPane;

import javax.swing.JTextPane;

import javax.swing.SwingUtilities;

import javax.swing.text.AbstractDocument;

import javax.swing.text.BadLocationException;

import javax.swing.text.MutableAttributeSet;

import javax.swing.text.SimpleAttributeSet;

import javax.swing.text.StyleConstants;

import javax.swing.text.StyledDocument;
 

public final class PrintingDemo implements Printable {
 

	private final JTextPane textPane;

	private static final String TEXT = "Page   of  " + '\n';
 

	public static void main(String[] args) {

        new PrintingDemo();

    }
 

	public PrintingDemo() {

        textPane = new JTextPane();

		textPane.setText(TEXT);

        final StyledDocument document = textPane.getStyledDocument();
 

		final MutableAttributeSet attributeSet = new SimpleAttributeSet();

		StyleConstants.setFontFamily(attributeSet, "Tahoma");

		StyleConstants.setFontSize(attributeSet, 12);

		document.setParagraphAttributes(0, TEXT.length(), attributeSet, true);
 

		try {

			((AbstractDocument)document).replace(5, 1, "1", attributeSet);

			((AbstractDocument)document).replace(10, 1, "2", attributeSet);

		} catch (BadLocationException ex) {

			throw new RuntimeException(ex);

		}
 

		final AbstractButton printContextButton = new JButton("Print Context");

		printContextButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				final PrinterJob job = PrinterJob.getPrinterJob();

				job.setPrintable(PrintingDemo.this);

				try {

					job.print();

				} catch (PrinterException ex) {

					throw new RuntimeException("Printing Failed.", ex);

				}

			}

		});
 

		final JFrame frame = new JFrame();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 

		final Container contentPane = frame.getContentPane();

		contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));

		contentPane.add(printContextButton);

		contentPane.add(new JScrollPane(textPane));

        frame.setSize(400, 200);
 

		SwingUtilities.invokeLater(new Runnable() {

			public void run() {

				frame.setVisible(true);

			};

		});

    }
 

	public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {

		if (pageIndex >= 1) return Printable.NO_SUCH_PAGE;

		final Graphics2D graphics2D = (Graphics2D)graphics;

		graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

		textPane.print(graphics);

		return Printable.PAGE_EXISTS;

	}

}

Open in new window

0
Comment
Question by:dlotts
  • 3
  • 2
5 Comments
 
LVL 20

Expert Comment

by:Venabili
ID: 24082054
Sounds like a bug to me - especially considering that it works in Java 5. Had you tried to submit it to Sun?
0
 
LVL 1

Author Comment

by:dlotts
ID: 24082522
Yep, we're waiting to hear back.

-----Original Message-----
From: IncidentDaemon@sun.com [mailto:IncidentDaemon@sun.com]
Sent: Thursday, April 02, 2009 2:39 PM
Subject: Your Report (Review ID: 1490132) - Printing a StyledDocument produces misaligned text

************************************************
Dear Java Developer,

Thank you for your interest in improving the quality of Java Technology.

Your report has been assigned an internal review ID of 1490132, which is NOT visible on the Sun Developer Network (SDN).

Please be aware that the large volume of reports we receive sometimes prevents us from responding individually to each message.

If the information is determined to be a new Bug or RFE, or a duplicate of a known Bug or RFE, you will receive a followup email containing a seven digit bug number.  You may search for, view, or vote for this bug in the Bug Database at http://bugs.sun.com/.

If you just reported an issue that could have a major impact on your project and require a timely response, please consider purchasing one of the support offerings described at http://developers.sun.com/services/.

The Sun Developer Network (http://developers.sun.com) is a free service that Sun offers. To join, visit http://developers.sun.com/global/join_sdn.html.

For a limited time, SDN members can obtain fully licensed Java IDEs for web and enterprise development.  More information is at http://developers.sun.com/prodtech/javatools/free/.

Thank you for using our bug submit page.

Regards,
Java Developer Bug Report Review Team



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


Date Created: Thu Apr 02 12:38:28 MST 2009
Type:        bug
SDN ID:      
status:      Waiting
Category:    java
Subcategory: classes_beans
release:     6u10
hardware:    x86
OSversion:   win_xp
priority:    4
Synopsis:    Printing a StyledDocument produces misaligned text
Description:
 FULL PRODUCT VERSION :
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP
Professional
Version 2002
Service Pack 2

A DESCRIPTION OF THE PROBLEM :
The issue we are seeing is that text displayed onscreen looks different when printed.  In particular, we are seeing that text that is replace within a StyledDocument is loosing it's whitespace when printed but looks fine onscreen.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the following code example.  Notice that the text displayed in the JTextPane is "Page 1 of 2".  Click the print button.  Look at the printed document and notice that the text is now "Page 1 of2".

This only seems to happen when replacing text around whitespace with at least two text replacements.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
With the example, we expect the following below to be printed.  Note:  The underscores are really whitespaces.

Page_1_of_2
ACTUAL -
Page_1_of2

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

import javax.swing.AbstractButton;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

public final class PrintingDemo implements Printable {

      private final JTextPane textPane;
      private static final String TEXT = "Page   of  " + '\n';

      public static void main(String[] args) {
        new PrintingDemo();
    }

      public PrintingDemo() {
        textPane = new JTextPane();
            textPane.setText(TEXT);
        final StyledDocument document = textPane.getStyledDocument();

            final MutableAttributeSet attributeSet = new SimpleAttributeSet();
            StyleConstants.setFontFamily(attributeSet, "Tahoma");
            StyleConstants.setFontSize(attributeSet, 12);
            document.setParagraphAttributes(0, TEXT.length(), attributeSet, true);

            try {
                  ((AbstractDocument)document).replace(5, 1, "1", attributeSet);
                  ((AbstractDocument)document).replace(10, 1, "2", attributeSet);
            } catch (BadLocationException ex) {
                  throw new RuntimeException(ex);
            }

            final AbstractButton printContextButton = new JButton("Print Context");
            printContextButton.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        final PrinterJob job = PrinterJob.getPrinterJob();
                        job.setPrintable(PrintingDemo.this);
                        try {
                              job.print();
                        } catch (PrinterException ex) {
                              throw new RuntimeException("Printing Failed.", ex);
                        }
                  }
            });

            final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            final Container contentPane = frame.getContentPane();
            contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
            contentPane.add(printContextButton);
            contentPane.add(new JScrollPane(textPane));
        frame.setSize(400, 200);

            SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                        frame.setVisible(true);
                  }
            });
    }

      public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
            if (pageIndex >= 1) return Printable.NO_SUCH_PAGE;
            final Graphics2D graphics2D = (Graphics2D)graphics;
            graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
            textPane.print(graphics);
            return Printable.PAGE_EXISTS;
      }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Instead of passing in an AttributeSet to the replace() methods on AbstractDocument, pass null.
workaround:  
0
 
LVL 20

Expert Comment

by:Venabili
ID: 24082572
Well - you have a workaround - as stupid as it is so it is the waiting game now I think.

Hm. Can you try something? Do the replacement in the opposite order - first the one later in the line? I recall something from the 1.4 days but had not touched printing for a while and might be ways off
0
 
LVL 1

Author Comment

by:dlotts
ID: 24102270
Well I tried switch the order of the two replace statements but that did not fix this issue.
0
 
LVL 1

Accepted Solution

by:
dlotts earned 0 total points
ID: 24102333
What we have found is that printing has changed for JTextComponents.  It appears that now user are supposed to use the following methods:

public boolean print()
public boolean print(MessageFormat headerFormat, MessageFormat footerFormat)
public boolean print(MessageFormat headerFormat, MessageFormat footerFormat, boolean showPrintDialog, PrintService service, PrintRequestAttributeSet attributes, boolean interactive)
public Printable getPrintable(MessageFormat headerFormat, MessageFormat footerFormat)

For the code snippet above, the ActionListener.actionPerformed(ActionEvent) method code can be replace with two possible solutions:

Solution 1:
try {
    textPane.print();
} catch (PrinterException ex) {
    throw new RuntimeException("Printing Failed.", ex);
}

Solution 2:
final Printable printable = textPane.getPrintable(null, null);
final PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(printable);
try {
    job.print();
} catch (PrinterException ex) {
    throw new RuntimeException("Printing Failed.", ex);
}
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org (http://seleniumhq.org) Go to that link and select download selenium in the right hand columnThat will then direct you to their downlo…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now