We are using PDFPageable to send PDF files to a Java print job. We are not in control of the PDF files themselves. Here is the document: https://drive.google.com/file/d/1iTKQ-xluJFXm5Qg4DJt2svQ64vi93a1U/view?usp=sharing
We are seeing some content that is failing to print (page 4), but with very, very strange behavior. The content that fails to print is complex (graphs, lots of fonts). - If the problem page is Page 4 of the document, then the print job prints Page 1-3 and only some of the content for Page 4 (page 4 is quite complex, and all that prints is the page footer content). - If the problem page is Page 1 of the document (i.e. we move pages around), then it prints fine. - The specific content of the problem page that actually prints depends on how many/which pages are printed before it. - The problem page prints fine on some printers but not others (I have it failing on a small laser printer, and two customers have it failing on large MFP devices). - If I print to the MS PDF Print driver, the problem pages are in the output. - If I print using a regular PDF viewer (Acrobat, Foxit), it prints fine. So the only way I can demonstrate the failure is to actually print to physical paper (you can imagine that this is driving us crazy). I am including code to actually run the print jobs at the bottom of this email. Diagnostic Attempts ----------------------- The problem page renders in the PDFDebugger without issues. I have added diagnostics to PageDrawer, and can confirm that the same rendering operations execute regardless of whether the page prints to paper or not. If I force rasterizing during printing (be specifying a dpi in the PDFPageable constructor), then the content prints fine (assuming the JVM has enough heap). I have tested with Java 11 and Java 23, with the same results. I'm not sure what to conclude at this point - maybe this is a rare JRE bug of some sort that is triggered by specific Graphics2D draw operations? I would love to hear what anything thinks might be going on. Next Steps --------------- At this point, unless someone can explain why we are observing this print behavior, it seems like my best bet is to switch to rasterizing. Assuming that I am going to need to switch to rasterizing, I would like to discuss an improvement to PDFPrintable so it doesn't require an explicit dpi to be provided. Printer DPI information is not readily available from PrinterJob, which makes it almost impossible to set this in a reliable way. Based on my research, I found that the affine transform of the graphics2d passed to PDFPrintable has the necessary scaling information to determine the dpi for the printer. So the idea would be to have a boolean autoRasterize setting, instead of an explicit dpi setting, then compute dpi from the affine transform like this: dpi = graphics2D.getTransform().getScaleX() * 72.0 (assuming that X and Y scaling are the same, of course). Would this be a reasonable enhancement? I'm happy to code it if you will accept a patch. A few final comments ---------------------------- A) Looking at the current PDFPrintable.print() method, I wonder if things wouldn't be simpler to create a raster at the top of the print() method? B) While unrelated to my current situation, I also note that there is an opportunity to improve printing performance quite a bit by: 1. In PDFPageable, cache the last PDFPrintable and page number. If the page is the same as previous, re-use the cached PDFPrintable instead of creating a new one. 2. then, in PDFPrintable, cach the raster BufferedImage and send it straight to the printer instead of re-rendering My debugging shows that the above caching changes would double the printing speed if rasterizing is enabled. My debugging also shows that rasterizing improves printing performance by a factor of 10. Thanks in advance, - K Code for running the print job ------------ public class Main { private static PrintService getPrintService(String name){ PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null); for (PrintService service : services) { if (service.getName().equalsIgnoreCase(name)){ return service; } } return null; } public static void main(String[] args) throws Exception { File pdf = new File("path to.pdf"); PrintService printService = getPrintService("printer name"); //PrintService printService = getPrintService("Microsoft Print to PDF"); PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintService(printService); try(PDDocument doc = Loader.loadPDF(pdf)){ final PDFPageable pageable = new PDFPageable(doc, Orientation.AUTO, false, 0, true); // change 0 to 300 or 600 to rasterize job.setPageable(pageable); job.setJobName(pdf.getName()); job.print(); } } }