United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 6452415 Swing text components using a physical font print text as filled shapes (bigger spool files).
6452415 : Swing text components using a physical font print text as filled shapes (bigger spool files).

Details
Type:
Bug
Submit Date:
2006-07-25
Status:
Closed
Updated Date:
2011-03-08
Project Name:
JDK
Resolved Date:
2011-03-08
Component:
client-libs
OS:
windows_xp,windows_2000
Sub-Component:
2d
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
5.0u7,6
Fixed Versions:
7

Related Reports
Backport:
Duplicate:

Sub Tasks

Description
FULL PRODUCT VERSION :
1.5.0_07

EXTRA RELEVANT SYSTEM CONFIGURATION :
HP Laser Jet 4000 PCL6

A DESCRIPTION OF THE PROBLEM :
Printer spool file created is much larger when running under 1.5.0_07 jre then what is created when running under 1.4.3_02 jre

Example: Original text file of 11,430 bytes (sample.txt) when printed:
1.4.2_03 file created is 74,367 bytes
1.5.0_07 file created is 1,578,860 bytes
21 Times larger.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I have create a test program that reads in an ASCII text file
(sample.txt) and launches our applications print screen.
When the print button is clicked, I choose a typical printer (in my case
- HP Laser Jet 4000 PCL6) that I have configured to print to a file.

I created 2 bat files:

run-spooltest14.bat - runs the test program under 1.4.2_03 and creates
the 74,367 byte file.
run-spooltest15.bat - runs the test program under 1.5.0_07 and creates
the 1,578,860 byte file.


I have also created bat files to compile TextReportScreen.java which has
all the printer specific code.

compile-spooltest14.bat - compiles TextReportScreen.java under 1.4
compile-spooltest15.bat - compiles TextReportScreen.java under 1.5 

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Generated same file size in 5.0_07
ACTUAL -
1.5.0_07 file created is 1,578,860 bytes
21 Times larger.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
1.5.0_07 file created is 1,578,860 bytes
21 Times larger.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Attached Seperatly
---------- END SOURCE ----------
That test case is too complex.
Here's a simpler one that's more to the point.
All that's needed is to print a Swing text component after setting a physical font
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.print.*;

public class PrintTextPane implements Printable, ActionListener {

    JTextPane pane;

    public int print(Graphics g, PageFormat pf, int page) throws
                                                        PrinterException {
        if (page > 0) {
            return NO_SUCH_PAGE;
        }
        Graphics2D g2d = (Graphics2D)g;
        System.out.println("BEFORE = " + g2d.getTransform());
        g2d.translate(pf.getImageableX(), pf.getImageableY());
        System.out.println("AFTER = " + g2d.getTransform());
        pane.printAll(g);
        return PAGE_EXISTS;
    }

    public void actionPerformed(ActionEvent e) {
/*
        try {
             pane.print();
         } catch (PrinterException ex) {
               throw new RuntimeException(ex);
         }
*/
         PrinterJob job = PrinterJob.getPrinterJob();
         job.setPrintable(this);
         boolean ok = job.printDialog();
         if (ok) {
             try {
                  job.print();
             } catch (PrinterException ex) {
                   throw new RuntimeException(ex);
             }
         }

    }

    public PrintTextPane(JTextPane f) {
        pane = f;
    }
   static String text = "Twinkle twinkle little star, \n" +
                        "How I wonder what you are.";

    public static void main(String args[]) {
        JFrame f = new JFrame("Print Text Pane");
        f.addWindowListener(new WindowAdapter() {
           public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        JTextPane pane = new JTextPane();
        SimpleAttributeSet aset = new SimpleAttributeSet();
        StyleConstants.setFontFamily(aset, "Courier New");
        //StyleConstants.setFontFamily(aset, "Monospaced");
        pane.setCharacterAttributes(aset, false);
        pane.setText(text);
        f.add("Center", pane);
        JButton printButton = new JButton("Print TextPane");
        printButton.addActionListener(new PrintTextPane(pane));
        f.add("South", printButton);
        f.pack();
        f.setVisible(true);
    }
}

                                    

Comments
WORK AROUND

Use a logical font instead of a physical font
(Serif, Sans Serif, Monospaced, Dialog, DialogInput)
*** (#1 of 1): [ UNSAVED ] ###@###.###
                                     
2006-07-25
EVALUATION

This problem is specific to printing Swing text components on windows
where the user specifies a physical font (eg Arial, Lucida Sans Regular)
instead of letting Swing use one of the standard logical fonts
(Serif, Sans Serif, Monospaced, Dialog, DialogInput)

This behaviour was introduced in 5.0 by the swing fix for 
5023890 : zh: Tooltip strings on Java ControlPanel are displayed as cubics

The problem there was that tooltips were using swing text components
but in a chinese (zh) locale they were not displaying chinese characters
because Swing saw only the default "Microsoft Sans Serif" font.

A fix was made in swing text code to use some internal API that
added fallback fonts.

The printing implementation has code to handle such fonts and passes
on to GDI just the cases it can handle. This works fine for 'drawString()'
and 'drawChars()'

However in this case that code is bypassed as Swing is printing using
a TextLayout constructed with the screen FontRenderContext in order to ensure
that text is not clipped. That was a long standing problem and the fix is
4352983 : Clipping of text when printing.

So what we have here is the combination of using TextLayout with a
non-standard font. That TexLayout printing code path is not optimised
to understand these special fonts. The fix is to add a simple piece of
logic to this printing path to see if GDI can handle it.
Its a few lines of extra code in WPathGraphics.java

But in testing this it was noted that the  new JDK 6 Swing text printing API
also was printing as shapes in this case.
This printing API is supposed to lay out for the printer, not the screen
so should not need to use TextLayout and so should have avoided this path
and taken the already optimised drawString path.
However it was noted that in comparing FontRenderContext's they were
spuriously considered to be different because of a different translation
component in the transforms of the component and the printer graphics.
Whilst the WPathGraphics.java fix will mostly resolve that, really this
text code should directly use drawString instead as unnecessary work
is being done because of this failed comparison.
The fix is to update Swing's comparison of FontRenderContexts to
ignore translations. This raises an interesting question as to whether
FontRenderContext.equals() should do this too, and also whether
Graphics2D.getFontRenderContext() should return a FontRenderContext
which has a translation at all. The latter probably wouldn't help
if a FRC was constructed by calling Graphics2D.getTransform() as
that must always include the translate. But this issue is beyond
the scope of this bug report which should address just the specific case
at hand.
                                     
2006-07-25



Hardware and Software, Engineered to Work Together