Martin Černý Martin Černý - 9 days ago 7
Java Question

Java printing stretched on Konica - Minolta PagePro printers

I am using JasperReports to print from my Java application. All the prints were OK for all costumers for quite a bit of time, but recently we have installed the software for couple of costumers that all have Konica Minolta PagePro 1200 or 1350W printers. And all those costumers get the same result - the printing is "stretched" - as if I printed A4 report on A5 paper. Except that I am printing A4 on A4 and on all other printers it works fine.

Does anyone have any idea what might be the cause?

This questions seems similar to http://stackoverflow.com/questions/15854722/jasper-report-printing-stretched but the workaround presented there (messing with printer paper size etc.) did not lead to desired result.

Here is an example of the print:

Example print

And this is what the print should look like (there are slighlty different data, but I guess the problem is clear)

Desired print

Thanks for any suggestions.

EDIT:

The issue can be reproduced with a simple direct call to printing API:

import java.awt.*;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

/**
*
* @author MaCe
*/
public class PrintTest {

static Printable printable = new Printable() {
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
Graphics2D grx = (Graphics2D)graphics;
grx.drawLine(20,20, getPageWidth() / 2, 20);
return Printable.PAGE_EXISTS;
}

};
protected static int getPageWidth() {
//width of A4 in 1/72 of inches
return 595;
}

protected static int getPageHeight() {
//height of A4 in 1/72 of inches
return 842;
}

public static void main(String args[]) throws PrinterException {
Frame f = new Frame();
f.show();

//Build a buggy print job using PrinterJob class
PrinterJob printJob = PrinterJob.getPrinterJob();

/**
* Fix for bug ID 6255588 from Sun bug database
*/
try {
printJob.setPrintService(printJob.getPrintService());
} catch (PrinterException e) {
}

PageFormat pageFormat = printJob.defaultPage();
Paper paper = pageFormat.getPaper();

printJob.setJobName("Buggy output");

pageFormat.setOrientation(PageFormat.PORTRAIT);
paper.setSize(getPageWidth() , getPageHeight());
paper.setImageableArea(
0,
0, getPageWidth(), getPageHeight());

pageFormat.setPaper(paper);

Book book = new Book();
book.append(printable, pageFormat, 1);
printJob.setPageable(book);

if (printJob.printDialog()) {
printJob.print();
}

//Build a good print job using PrintJob class
PrintJob pjob = f.getToolkit().getPrintJob(f, "Good output", null);
if (pjob!=null) {
Graphics g = pjob.getGraphics();
g.drawLine(20, 20, pjob.getPageDimension().width / 2, 20);
pjob.end();
}

System.exit(0);
}
}


Now this code produces two prints that on most printers both print a line from the top left corner of the paper to the middle of the paper. However on the aforementioned printers the first print creates a thick line across the whole paper (200% scale) - the second variant is however OK even on Minolta printers.

Seems like a Java bug, since all other programs print normally with the printer. The bug was accepted by Sun, but closed as they could not get their hands on the correct printer (https://bugs.openjdk.java.net/browse/JDK-804159)

Answer

I have found a workaround to the problem. The solution is to scale the graphics to half before printing. This is not easy to do with JasperReports, as the graphics object is not exposed anywhere. However, my app uses @AspectJ so I managed to fiddle with the graphics through a custom aspect:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;


@Aspect
public class JRMinoltaAspect {        

    @Before("execution(int net.sf.jasperreports.engine.print.JRPrinterAWT.print(java.awt.Graphics, java.awt.print.PageFormat , int )) && args(g, pf, ..)")
    public void scalePrint(Graphics g, PageFormat pf){
        if(pf.getOrientation() == PageFormat.LANDSCAPE){
            g.translate(0, (int)pf.getHeight() / 2 );
        }
        ((Graphics2D)g).scale(0.5, 0.5);        
    }

}
Comments