Sunday, November 25, 2012

PDFBox Printing Greek Problem

Still working with PdfBox and got another obstacle to tackle...printing Pdf containing Geek text seems to be problematic. Most of the text prints out fine but there are some characters that do not print correctly.
For example small Greek letter  π  prints out as "pi", also there is an issue with small μ that prints out differently ... thought, at least it looks like μ.

Filled out bug report yesterday, hope this could be fixed.
So far no solution on the horizon ...I will update this blog in case the solution is found.
....

16.11.2013 
And so it's time to update (I know, I know... millions were expecting this update!! ;-)...this issue seams to be solved by Andreas Lehmkühler https://issues.apache.org/jira/browse/PDFBOX-1452 ... however there is a catch .. the solution is in version 2.0 and currently G.A. version is 1.8.2. I suppose, one could download and build 2.0 version from the trunk  http://svn.apache.org/repos/asf/pdfbox/trunk/ (use: svn checkout http://svn.apache.org/repos/asf/pdfbox/trunk/), but I haven't tried it yet.
If you do - let me know how it went for you.

Thursday, November 15, 2012

PdfBox LandScape Printing Problem and Solution

I tried to use Apache's PdfBox library to silently print documents from my applet.
No problem printing in "Portrait", as it was my printer's default setting...however pdfs containing Landscape pages wouldn't  print properly. The thing is that the orientation is always defined by the printer service and not by the Document itself.
It seems that there is a "problem" with PDPageable class, specifically with it's getPageFormat method.
So here is my temporary fix for this problem (temporary because I hope it will be fixed in following versions).
I must mention that my solution is based on Roberto Mazzola 's  findings and proposition
(see https://issues.apache.org/jira/browse/PDFBOX-985 for details)

Version I used : PdfBox-1.7.1 

Solution:
...
import org.apache.pdfbox.pdmodel.PDPageable;
...
public static class MyPDPageable extends PDPageable {
       PrinterJob myJob;
       PDDocument myDocument;
          public MyPDPageable() throws PrinterException{
              super(null);
             
          }
         
    public MyPDPageable(PDDocument document) throws PrinterException{
              super(document);
              this.myDocument = document;
     }
    public MyPDPageable(PDDocument document,PrinterJob job) throws PrinterException{
              super(document,job);
              this.myJob = job;
              this.myDocument = document;
    }
      @Override
      public PageFormat getPageFormat(int i) throws IndexOutOfBoundsException {
        PageFormat format = myJob.defaultPage();
        List<PDPage> allPages = myDocument.getDocumentCatalog().getAllPages();
        PDPage page = allPages.get(i); // can throw IOOBE
        Dimension media = page.findMediaBox().createDimension();
        Dimension crop = page.findCropBox().createDimension();
        // Center the ImageableArea if the crop is smaller than the media
        double diffWidth = 0.0;
        double diffHeight = 0.0;
        if (!media.equals(crop)) {
            diffWidth = (media.getWidth() - crop.getWidth()) / 2.0;
            diffHeight = (media.getHeight() - crop.getHeight()) / 2.0;
        }
        int vOrientation = PageFormat.PORTRAIT;
         if(media.getWidth() > media.getHeight())
                 vOrientation = PageFormat.LANDSCAPE;
       
        format.setOrientation(vOrientation);
        Paper paper = format.getPaper();
        if (vOrientation == PageFormat.LANDSCAPE) {
           paper.setImageableArea(
                   diffHeight, diffWidth, crop.getHeight(), crop.getWidth());
           paper.setSize(media.getHeight(), media.getWidth());
        } else {
           paper.setImageableArea(
                   diffWidth, diffHeight, crop.getWidth(), crop.getHeight());
           paper.setSize(media.getWidth(), media.getHeight());
        }
        format.setPaper(paper);
        return format;
    }    
      }
and then if I wanted to print
.... 
PDDocument doc = PDDocument.load(psStream,true);
 if (printService != null) {             
            PrinterJob pj =  PrinterJob.getPrinterJob();
            pj.defaultPage();
            pj.setCopies(Integer.parseInt(finalnumberOfCopies));
            pj.setPrintService(printService);
            pj.setPageable(new MyPDPageable(doc,pj));

            pj.print();
}
....
note that I don't use doc.silentPrint(pj) but pj.print() ...

It is a quick and dirty fix, obviously code could use some improvements..but it works for me...
Hope it will be useful and to somebody else..