random memes }

PrinterJob.pageDialog() in Java is broken?

More specifically, the handling of margins, PageFormat, and the PrinterJob.pageDialog(PageFormat) seems to be broken.

Fixing up an old Java desktop application for viewing old "green-bar" reports. Should be pretty simple - the reports are all fixed pitch text. Given I like to do things that "just work" (from the users perspective), I'd added live "smart" definition of controllable font-auto-sizing, empty page suppression, and margins. Given that old printed reports may be formatted for paper sizes different than in your desktop (or network) printer, this was slightly tricky, but only that.

Of course, many of those old reports - meant for old line-printer green-bar paper - are best printed in landscape orientation. To my surprise, I find when in landscape orientation, the return from PrinterJob.pageDialog(PageFormat) consistently alters the margins, even when no changes were made, and the error is cumulative.

Um, what?

At first I assumed the error was in my code, but this bit of logged output caught the problem:

PageFormat validate:: paper dx: 792.0 dy: 612.0 margins top: 72 left: 72 bottom: 72 right: 72 orientation : LANDSCAPE PageFormat after pageDialog:: paper dx: 794.0 dy: 613.0 margins top: 72 left: 74 bottom: 73 right: 72 orientation : LANDSCAPE

The first is the contents of the PageFormat before calling PrinterJob.pageDialog(PageFormat), and the second is the new PageFormat returned. Note the +1 dy bump and +2 dx bump to the page extents (and the matching errors introduced to the left/bottom margins).

The code I used to remove the error:

controller.pageFormat = job.pageDialog(controller.pageFormat);

// Work around an interesting(?) bug in PrinterJob.pageDialog(). // For some reason the returned Paper is over-sized. (Why? Dunno.) // Use the Paper returned from PrinterJob.defaultPage() to get a proper size. // If the Java folk remove the bug, this code should change nothing. PageFormat pf = job.defaultPage(); Paper paper1 = controller.pageFormat.getPaper(); Paper paper2 = pf.getPaper(); double x = paper1.getImageableX(); double y = paper1.getImageableY(); double dx = paper1.getImageableWidth(); double dy = paper1.getImageableHeight(); paper2.setImageableArea(x,y,dx,dy); controller.pageFormat.setPaper(paper2);

The bug was encountered using Java 1.6.0_15 (64-bit) on Ubuntu (Linux 2.6.28-15-generic #52-Ubuntu SMP Wed Sep 9 10:48:52 UTC 2009 x86_64 GNU/Linux).