Skip to main content

Printing regression in update 10?

3 replies [Last post]
cowwoc
Offline
Joined: 2003-08-24

I seem to be on a roll today, not that I much enjoy running across bugs ;)

I am trying to print a JTable under Java6 update 10 beta 25 and I noticed that the print output is blurry. I created the testcase and produced screenshots under Java5, Java6 beta 24 and beta 25. What makes this bug even more interesting is that b25 is supposed to change the print behavior (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6696292) yet I see no difference between beta 24 and beta 25.

Can someone in Sun please double check that this fix actually rolled out in beta 25?

Here are the relevant screenshots:

http://bbs.darktech.org/java5-nodialog.pdf
http://bbs.darktech.org/java5-dialog.pdf
http://bbs.darktech.org/java6-nodialog-b24.pdf
http://bbs.darktech.org/java6-dialog-b24.pdf
http://bbs.darktech.org/java6-nodialog-b25.pdf
http://bbs.darktech.org/java6-dialog-b25.pdf

and the testcase:

http://bbs.darktech.org/TestPrinting.zip

Please download a copy of these files soon because I plan on removing them in the near future.

Discussion
----------------

The testcase contains a boolean "showDialog". When set to true, the testcase will prompt the user to select the printer. When set to false, it will automatically try to print using "Bullzip PDF Printer" (discussed below). The screenshots show that two distinct set of bugs:

1) Java5 and Java6 update 10 generate different output. Java6 update 10 produces blurry output and looks like a regression to me. I tried playing around with RenderingHints to disable any sort of anti-aliasing but it made no noticeable difference.

2) dialog vs no-dialog generate different output. I am not sure why no-dialog produces a corrupt output. As far as I can tell the same PrinterService is being used.

As you will see from the testcase, I tested the output using the "Bullzip PDF Printer" which you can download for free from http://www.bullzip.com/products/pdf/info.php

I used it to avoid having to print out hard-copies (instead I view the output on the screen). The added benefit is that it lets me take screenshots of any problems I encounter.

I look forward to your reply,
Gili

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
philrace
Offline
Joined: 2003-06-09

> (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6696292)

I don't think this has any relationship to what you are doing so wouldn't
be expected to change it.
That's a corner case of printing some images under unusual transforms.

I need to recap what your code does to help set the scene.

In the print(..) method, you create a BufferedImage as large in pixels
as the imageable area is in user space.
This means that you are guaranteed that when you print it, the image
pixels will be scaled up, and you'll get blocky output.
I'm not sure you intend this since you also call
setDoubleBuffering(table, false);
and rendering to this BI defeats the purpose of this call, which
ought to be unnecessary anyway as Swing knows when its being
printed to a PrinterGraphics and will do this anyway

That BufferedImage is created to be translucent (ARGB), which means that
it can't be printed directly to the device. Instead it needs to
be drawn first on to an opaque BI. This could further affect quality
in some cases, but here I think mostly affects your performance.
An opaque BI would have been better, but printing directly to the
printer graphics would have been better still.

The print method should start with a call to
g2d.translate( pageFormat.getImageableX(), pageFormat.getImageableY());
you are missing that call, so when you subsequently paint the
BufferedImage at (0,0) some of it is inevitably clipped.
This isn't apparent because you aren't rendering content
along the top or left of the image. The JTable print(..)
method you invoke is helping here in its positioning of the table.
Its also appaears that the Zebra PDF renderer reports it can
print to the entire paper area, so its not representative of real printers.

But the lack of this translate also plays a role in the second of your problems.

You are printing two tables, each by invoking its printable and asking it
to center align, and passing it the printer graphics, which it is free to
mutate. I don't know if this plays a role in how you've structured some
of the code, but you should be passing it a copy.
ie
Graphics2D tpg = (Graphics2D)g2d.create();
table.getPrintable(PrintMode.FIT_WIDTH, null, null).print(
tpg, pageFormat, pageIndex);
^^^

Lets look at each of the problems

>1) Java5 and Java6 update 10 generate different output.

You are referring to the first image. That's going to be there since JDK 6 (not 6u10)
As outlined above you are painting the Swing component into an image at screen
resolution and then scaling the image to the printer. Thus you get scaled up whatever
Swing would paint to the screen. In this case that means LCD text since that's
apparently how your desktop font smoothing settings are configured.
Setting rendering hints on the graphics is not going to make a difference.
Swing controls the hints it wants when it paints and in JDK6 it will paint LCD text
to the screen if that's your desktop preference.
So you are really getting what you asked for - the same pixels that would
be painted to the screen blown up to the printer size.
If you want to avoid that then you should have Swing paint at device resolution.

> 2) dialog vs no-dialog generate different output.

You aren't specific about what you mean here, so I'm going to have to guess.
I see the second of the images looks like its painted in slightly misaligned parts
in the no dialog case, but with both your PDFs and my HP printer, both dialog and
non-dialog look misaligned in 1.5. So that does not seem to be in a regression
in any release. In 1.6 it in fact looks OK in the dialog case, but that is
partly down to luck.
The reason for the misalignment goes back to your painting over the entire
imageable area with a screen resolution BufferedImage, and without accounting
for the imageable X/Y.
Since you paint at (0,0) you leave the rightmost part of the imageable area
untouched, and the second translated one is still partially visible.
Since the BI you drew is aligned at user space resolution, I can see how
it could be marginally off from a table drawn at a higher resolution.
The difference isn't apparent in the "dialog" case with JDk6 because
the printable area in the no dialog case is right up against the hardware
margins, but in the no "dialog case" (and both cases on 1.5) its
specifying an imageable area with 1 inch margins all round. So your
BI is smaller. The translate(150,150) together with the instruction
to the table to center align itself is enough to cause this.
I don't know off hand why the non-dialog case can't pick up the
margins of the specified printer, it looks like a residual unfixed
case, and it should not be a problem if the code pays attention to the
imageable X/Y/W/H

So with a few small modifications your print out will be smaller, faster
of high quality output without any of these artefacts.

Here's a diff, not including any clean up, just enough to get what I
think are your expected results.

diff Main.java.orig Main.java
145,149d144
< final BufferedImage image = new BufferedImage(
< (int) pageFormat.getImageableWidth(),
< (int) pageFormat.getImageableHeight(),
< BufferedImage.TYPE_INT_ARGB);
< Graphics2D imageGraphics = (Graphics2D) image.getGraphics();
150a146,147
> Graphics2D imageGraphics = g2d;
> g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
172a170
> Graphics2D tpg = (Graphics2D)g2d.create();
174,176c172,174
< imageGraphics, pageFormat, pageIndex);
< g2d.drawImage(image, 0, 0, null);
< g2d.translate(150, 150);
---
> tpg, pageFormat, pageIndex);
> g2d.translate(0, 150);
> tpg = (Graphics2D)g2d.create();
178c176
< g2d, pageFormat, pageIndex);
---
> tpg, pageFormat, pageIndex);

-phil.

cowwoc
Offline
Joined: 2003-08-24

I just fixed some broken links in the above post, you can now download the PDF files for Java6 Update 10.

Another thing I noticed is that if you zoom in on the bad table you will notice some sort of anti-aliasing going on whereas the table on the right is crisp. I'm not sure where this is coming from because as I've mentioned the Testcase code disables all anti-aliasing using RenderingHints (at least as far as I can tell).

trembovetski
Offline
Joined: 2003-12-31

Thanks. This is being looked at.

Dmitri