Print a PDF Document in Java

For some time now I have searched for a way to print a PDF document from Java code. Up to now, I have had to shell out and invoke Acrobat from the command line but this hack has been painful to support in the field because of the multiple version of Acrobat and its quirks.

A new PDF Renderer project has recently been released on java.net which can in addition to rendering and viewing a PDF document, it can be used to print a PDF document. If you download the PDF Renderer you can run the jar to start a sample PDF viewer application which can print PDF documents. All the code listed below is inspired from the PDF Renderer sample application.

The following code uses classes from the PDF Renderer library and standard Java. Like usual, I have omitted all import statements.

// Create a PDFFile from a File reference
File f = new File("c:\\juixe\\techknow.pdf");
FileInputStream fis = new FileInputStream(f);
FileChannel fc = fis.getChannel();
ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
PDFFile pdfFile = new PDFFile(bb); // Create PDF Print Page
PDFPrintPage pages = new PDFPrintPage(pdfFile);

// Create Print Job
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
pjob.setJobName(f.getName());
Book book = new Book();
book.append(pages, pf, pdfFile.getNumPages());
pjob.setPageable(book);

// Send print job to default printer
pjob.print();

One critical class required to print a PDF document using PDF Renderer is the PDFPrintPage. The PDFPrintPage implements the Printable print method. The PDFPrintPage is included in the PDFRenderer.jar, but in the source distribution it is found under the demos project. I have included the source to PDFPrintPage print method here…

class PDFPrintPage implements Printable {
  private PDFFile file;
  PDFPrintPage(PDFFile file) {
    this.file = file;
  }

  public int print(Graphics g, PageFormat format, int index)
    throws PrinterException {
    int pagenum = index + 1;

    // don't bother if the page number is out of range.
    if ((pagenum >= 1) && (pagenum < = file.getNumPages())) {
      // fit the PDFPage into the printing area
      Graphics2D g2 = (Graphics2D)g;
      PDFPage page = file.getPage(pagenum);
      double pwidth = format.getImageableWidth();
      double pheight = format.getImageableHeight();

      double aspect = page.getAspectRatio();
      double paperaspect = pwidth / pheight;

      Rectangle imgbounds;

      if (aspect>paperaspect) {
        // paper is too tall / pdfpage is too wide
        int height= (int)(pwidth / aspect);
        imgbounds= new Rectangle(
          (int)format.getImageableX(),
          (int)(format.getImageableY() + ((pheight - height) / 2)),
          (int)pwidth,
          height
        );
      } else {
        // paper is too wide / pdfpage is too tall
        int width = (int)(pheight * aspect);
        imgbounds = new Rectangle(
          (int)(format.getImageableX() + ((pwidth - width) / 2)),
          (int)format.getImageableY(),
          width,
          (int)pheight
        );
      }

      // render the page
      PDFRenderer pgs = new PDFRenderer(page, g2, imgbounds, null, null);
      try {
        page.waitForFinish();
        pgs.run();
      } catch (InterruptedException ie) {}

      return PAGE_EXISTS;
    } else {
      return NO_SUCH_PAGE;
    }
  }
}

A final note, PDF Renderer does require Java 1.5 or greater.

Related posts:

  1. Word To PDF
  2. How To Print The Alphabet in Java?
  3. Rails PDF Plugin
  4. Print HTML Using IE
  5. The Word Is POI

This entry was posted in Java, TechKnow. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

55 Comments

  1. Posted January 18, 2008 at 12:39 am | Permalink

    Cool project, I have to check that out…

    Have you looked into iText from Lowagie?
    http://www.lowagie.com/iText/

  2. Posted January 18, 2008 at 2:54 am | Permalink

    [...] It’s very interesting and it answers a question that turns up on the mailing list once and again. [...]

  3. Posted January 18, 2008 at 4:27 pm | Permalink

    @Mike – I looked into iText sometime back, but if I remember correctly it is used to create PDF documents, not print them. Before writing this article, I did google for tutorials on how to print PDF documents from Java and all I got was forum posts asking for help with this…

  4. ahmet
    Posted January 19, 2008 at 12:33 am | Permalink

    Indeed, currently the biggest problem in the client area related with pdf’s is printing. there is no real library can be used by closed source applications. the commercial ones are extremely pricey. thanks for your example, it is nice. but unfortunately pdf renderer still requires a lot of work for complicated pages. it is definitely on the right track tough.

  5. Posted January 25, 2008 at 4:25 pm | Permalink

    @TechKnow – I wrote something like the PrintPDFPage impl above. If there is something iText can give you that this framework doesn’t, it’s worth the effort. If not, this looks like a good bet.

  6. jay019
    Posted February 6, 2008 at 9:39 pm | Permalink

    This is sweet! Thanks for sharing.

    Jay

  7. Walther H Diechmann
    Posted February 14, 2008 at 10:15 am | Permalink

    Hi – am I missing something crusial here?

    I mean – I can do “lp test.pdf” on my Mac (from a shell/Terminal), Windows is obviously not a problem, and most scripting frameworks (PHP, Ruby(OnRails), Perl, et al) on webservers will allow me a shell escape or the ability to run system commands of some sorts. In which case I’m full circle to my “lp test.pdf”.

    Excuse my ignorance if I am missing the entire focus of this post

  8. julie
    Posted March 14, 2008 at 9:33 am | Permalink

    I am attempting to print a simple pdf with the above code fragment.

    The fc.size is 3583 and pdfFile.getNumPages is 2. However the printed pages are blank. If I try to view it with PagePanel, it is also blank.

    Any ideas?

  9. pidzi
    Posted March 22, 2008 at 4:19 pm | Permalink

    thanks man….after hours of searching I finally found your solution.

  10. mert mert
    Posted April 8, 2008 at 6:36 am | Permalink

    Thanks for sharing. Really nice work. That s what I need;)

    I have difficulties in running the second code. I ll be glad if someone can helpme.

  11. Mike Bell
    Posted April 22, 2008 at 11:16 pm | Permalink

    When I print, it is printing in small fonts. Any one know how to change the font size , sucht that it prints in larger fonts.

  12. Niik
    Posted June 26, 2008 at 7:17 am | Permalink

    Very good article, it helped me a lot. PDFRenderer turned out to be a great library to complete iText.

    @Mike Bell: If you are talking about an overall small print of your pdf, it might be because of the huge default page margins. I added these lines after
    PageFormat pf = PrinterJob.getPrinterJob().defaultPage();

    Paper paper = new Paper();
    paper.setImageableArea(0,0,paper.getWidth(),paper.getHeight()); // no margin = no scaling
    pf.setPaper(paper);

  13. romulus
    Posted July 30, 2008 at 12:56 am | Permalink

    some pdf files failed,seems lack some font support

  14. Paul Giblock
    Posted August 21, 2008 at 10:07 am | Permalink

    @Walter: The point is, not every computer has a printer device-file you can just redirect to. This is Java after all.

    @mert mert: You are not supposed to run the second code. That is the implementation of the PDFPrintPage class

  15. LK
    Posted November 24, 2008 at 7:35 pm | Permalink

    “some pdf files failed,seems lack some font support”

    This is actually my problem with jPedal. I can open a PDF in the jPedal viewer just fine, but if I want to print the same PDF directly, I get errors and the print does not occur. The best I can do to decipher since the error messages are cryptic is that apparently required fonts or security are required.

    Does anyone have any ideas?

    thanks

  16. Posted December 17, 2008 at 12:03 pm | Permalink

    First , thanks for sharing your article.
    But when I run the program, I got the following Error Message , Why?

    java.lang.NegativeArraySizeException
    at com.sun.pdfview.font.ttf.LocaTable.(LocaTable.java:26)
    at com.sun.pdfview.font.ttf.TrueTypeTable.createTable(TrueTypeTable.java:96)
    at com.sun.pdfview.font.ttf.TrueTypeFont.getTable(TrueTypeFont.java:106)
    at com.sun.pdfview.font.ttf.GlyfTable.(GlyfTable.java:24)
    at com.sun.pdfview.font.ttf.TrueTypeTable.createTable(TrueTypeTable.java:84)
    at com.sun.pdfview.font.ttf.TrueTypeFont.getTable(TrueTypeFont.java:106)
    at com.sun.pdfview.font.TTFFont.getOutline(TTFFont.java:116)
    at com.sun.pdfview.font.CIDFontType2.getOutline(CIDFontType2.java:173)
    at com.sun.pdfview.font.OutlineFont.getGlyph(OutlineFont.java:118)
    at com.sun.pdfview.font.PDFFont.getCachedGlyph(PDFFont.java:307)
    at com.sun.pdfview.font.PDFFontEncoding.getGlyphFromCMap(PDFFontEncoding.java:146)
    at com.sun.pdfview.font.PDFFontEncoding.getGlyphs(PDFFontEncoding.java:106)
    at com.sun.pdfview.font.PDFFont.getGlyphs(PDFFont.java:273)
    at com.sun.pdfview.PDFTextFormat.doText(PDFTextFormat.java:283)
    at com.sun.pdfview.PDFParser.iterate(PDFParser.java:742)
    at com.sun.pdfview.BaseWatchable.run(BaseWatchable.java:88)
    at java.lang.Thread.run(Thread.java:619)

  17. Posted December 17, 2008 at 4:59 pm | Permalink

    @Dolph – We actually had this and other problems. A coworker of mine did fix the problem (I’ll have to check if it is the same problem). He intends or has submitted the fix to the project in java.net.

    We also had problems with images not showing up, and those where also fixed by just hacking away at the PDF Renderer code.

  18. CaptnTony
    Posted January 30, 2009 at 1:56 pm | Permalink

    I cannot find the com.sun.pdfview jar. A link would be greatly appreciated. Those I’ve found by searching google and yahoo seem to be no longer valid.

  19. CaptnTony
    Posted February 3, 2009 at 5:01 pm | Permalink

    Found it finally! Works quite well. A bit slow, okay VERY slow, but I’m sure it’s gotta do a lot of work getting that byte[] setup (very new to java programming). I do have one question though. Is there a way to send in a specific PrintService (so I can select which of my printers to send the pdf file to)? I’m going to generally be batch printing pdf files (150-450 at a time) created by a sales application. I prefer NOT to have to specify the printer each time if that is possible.

    Any hints, links or anything like that would be greatly appreciated.

  20. Mike
    Posted February 19, 2009 at 10:58 am | Permalink

    @TechKnow

    How did you fix the problem with images not showing up. Can you email me your hack to the PDF Renderer code? Greatly appreciated!

  21. Sudha
    Posted March 5, 2009 at 1:44 pm | Permalink

    Fantastic.. Thank you so very much for this code..I just chanced upon this in this morning..
    I had been agonizing and searching about printing PDF in Java, my requirement eventually is to create a batch printing process.
    I just plugged in the code and out came the pdf file on the printer..

    Thank you.
    Sudha.

  22. Rey
    Posted March 11, 2009 at 9:44 am | Permalink

    This library is fantastically good, but always throw a BufferUnderFlowException when using embedded fonts in a pdf file and the pdf file is not rendered properly. Any help for this one?

  23. Henry Zhi Lin
    Posted April 2, 2009 at 9:25 am | Permalink

    This PDFPrintPage is weired, when I called the jar file version it the format it printed out is landscape, when I debug into the code found out that this caused by the following code,

    if (paperaspect

  24. Vishnu
    Posted May 27, 2009 at 6:04 am | Permalink

    Hi
    I am getting te follwoing exception when I try to print the files using PDFRenderer

    java.lang.RuntimeException: Invalid code encountered.
    at com.sun.pdfview.decode.CCITTFaxDecoder.decodeNextScanline(CCITTFaxDecoder.java:703)
    at com.sun.pdfview.decode.CCITTFaxDecoder.decodeT41D(CCITTFaxDecoder.java:820)
    at com.sun.pdfview.decode.CCITTFaxDecode.decode(CCITTFaxDecode.java:51)
    at com.sun.pdfview.decode.CCITTFaxDecode.decode(CCITTFaxDecode.java:17)
    at com.sun.pdfview.decode.PDFDecoder.decodeStream(PDFDecoder.java:103)
    at com.sun.pdfview.PDFObject.decodeStream(PDFObject.java:331)
    at com.sun.pdfview.PDFObject.getStream(PDFObject.java:263)
    at com.sun.pdfview.PDFObject.getStream(PDFObject.java:257)
    at com.sun.pdfview.PDFImage.getImage(PDFImage.java:225)
    at com.sun.pdfview.PDFRenderer.drawImage(PDFRenderer.java:273)
    at com.sun.pdfview.PDFImageCmd.execute(PDFPage.java:643)
    at com.sun.pdfview.PDFRenderer.iterate(PDFRenderer.java:570)
    at com.sun.pdfview.BaseWatchable.run(BaseWatchable.java:101)
    at com.sun.pdfview.PDFPrintPage.print(PDFPrintPage.java:232)
    at sun.print.RasterPrinterJob.printPage(Unknown Source)
    at sun.print.RasterPrinterJob.print(Unknown Source)
    at sun.print.RasterPrinterJob.print(Unknown Source)
    at MergePDF.main(MergePDF.java:97)

    can any one help me to resolve this issue

  25. Posted May 27, 2009 at 11:28 am | Permalink

    @Vishnu – The source is open source, download it, attach your debugger, and step into it… If you find a fix, send a patch so we can all enjoy it… Thanks!!!

  26. shymaa
    Posted June 10, 2009 at 11:31 am | Permalink

    the library work fine with me on windows but when i try it on iseries it give null pointer exception on the line of (getPrinterJob), i stuck now with JPS api (main implementation of printing in java)of J2SE but it give a garbage output both on windows and iseries .can any body help me in any of the 2 api ,what i actually need is automatically print pdf from java program on iseries

  27. Naveed
    Posted June 22, 2009 at 4:47 am | Permalink

    TechKnow, thanks a lot for posting such good work. After a week of hit-the-wall and trial with javax.print; your code descended from heavens!

    All the best,
    Naveed.

  28. Posted June 24, 2009 at 3:34 pm | Permalink

    @Naveed – Wow, kewl! I never had code descend from the heavens before. Glad this was useful…

  29. Doug
    Posted July 3, 2009 at 7:04 pm | Permalink

    Does anyone know why this won’t work under Tomcat? Is it a permissions thing?
    I use the following code. When I run as a java app it works fine, when I execute from a web app running locally under tomcat it hangs on the pjob.print(); command. Any help would be greatly appreciated.

    private void printit( String pFileName ) throws Exception
    {
    log.debug(“>>>printit : ” + pFileName );
    File f = new File( pFileName );
    FileInputStream fis = new FileInputStream(f);
    FileChannel fc = fis.getChannel();
    ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
    PDFFile pdfFile = new PDFFile(bb); // Create PDF Print Page
    PDFPrintPage pages = new PDFPrintPage(pdfFile);

    //Create Print Job
    PrinterJob pjob = PrinterJob.getPrinterJob();
    PageFormat pf = PrinterJob.getPrinterJob().defaultPage();

    pjob.setJobName( f.getName() );
    Book book = new Book();
    book.append(pages, pf, pdfFile.getNumPages());
    pjob.setPageable(book);
    //Send print job to default printer
    pjob.print();
    log.debug(“<<<printit”);
    }

    Thanks!

  30. Tushar Kale
    Posted August 29, 2009 at 8:59 am | Permalink

    Thank you for sharing this code. It saved me hours of research!
    Really appreciated!

  31. Kenosi
    Posted October 5, 2009 at 3:34 am | Permalink

    wow! Thanx for the code. I just copied the code and ran it and the file was printed. I have be searching for a way to batch print pdf files for a while with no luck. I am having a few issues with the font size but I will work on that.

  32. Barrett
    Posted December 11, 2009 at 11:35 pm | Permalink

    @TechKnow:

    This is really great that you have published this as its the only solution I have been able to find anywhere. But 2 major flaws:

    1. There is something wrong with the margins, and any pdf that gets fed in is printed on letter papar in a very small area about 1/3 the size of the page. Many people, who I assume having only briefly tested the code, comment that they are having problems with font size, when really it is more to do with print area size.

    2. The first page of a print-job is in portrait and the second page forward is in landscape for some reason. Has no one noticed this?

    @Mike Bell encountered this problem and was responded to by Niik

    Niik Wrote:
    > because of the huge default page margins. I added these lines after
    > PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
    >
    > Paper paper = new Paper();
    > paper.setImageableArea(0,0,paper.getWidth(),paper.getHeight()); // no margin = no scaling
    > pf.setPaper(paper);

    @Niik:
    Your addition to the code helps this problem somewhat. However the print still only fills the page slightly more than originally. There is still a large area of the page not being printed onto and the image is shrunk.

    I checked the values of paper.getHeight() and paper.getWidth(), which returns inches * 72, and got w=612 and h=792. This adds up to 8.5×11 like it should for letter paper, yet still, when the imageable area is set like this, it doesn’t fill the page.

    I noticed that after Niiks addition, although the second page forward are still landscape, they do properly fill the landscape height. This then lead me to realize that the image printed on the first (portrait) page is actually properly sized for landscape. So something is going on where it is creating a document with proper-landscape-sized images, yet putting the first page in portrait orientation.

    Out of curiousity, I swapped the getWidth() and getHeight() arguments in setImageableArea like so:

    paper.setImageableArea(0,0,paper.getWidth(),paper.getHeight());

    Now this is stranger than ever: after doing this, the 2nd page forward are now printing in portrait like they are supposed to, yet still, all pages are SIZED for landscape.

    What is going on?
    Why would swapping those arguements fix this pg. 2+ landscape issue (which was present even before adding the paper-size code lines)?
    What is causing the pg. 2+ landscape issue in the first place?
    Why is it getting sizes for landscape and printing them in portrait, when it should be getting sizes for portrait and printing in portrait?

    This is as far as I have been able to figure out. I am certain these problems are inherent in the code somehow. If someone could figure out what is going on and post a full replacement of the code which fixes the margins and prints everything in portrait size with portrait orientation, it would benefit the entire java programming world who is coming to this thread from google for this problem and not getting a complete solution.

    Thank you all for your time!

    ————-
    Addition, I was thinking this was a problem with the source code given above, an argument wrong or something. Finally I ran the jar file itself and the Acrobat-ish application built into it. I open a document and try to print it and even that has this same problem. If you go into page settings, it defaults to landscape for some reason. When you change it to portrait, it turns back to landscape when you try to print….

    Seriously did sun just never actually try it out, and release something totally broken?

  33. ifi
    Posted December 18, 2009 at 12:28 pm | Permalink

    Having the same problems as Barrett. Anybody with a solution?

  34. Ram
    Posted December 19, 2009 at 1:17 am | Permalink

    I am also having the font issue, the printed document is in different format.. any help is appreciated.

  35. Barrett
    Posted December 19, 2009 at 7:47 pm | Permalink

    I found a working hack!!!

    First of all id like to mention that I created an issue on the development site here:
    Severe dealbreaking print layout problems, widely experienced

    If you are interested in following it. The hack I am about to give might start misbehaving if this issue gets fixed and you upgrade to a new JAR file, and leave the hacked code.

    Anyway here’s what you have to do: It is similar to the code Niik added. There are two issues going simultaneously. One is that the margins are retarded. Why would you default 1 inch margins on pdfs whose reason for existing is to have a universal fixed printable format that already includes things like margins? who knows. so there is that margin problem which Niiks code fixes.

    Then there is another fatal flaw in PDFRenderer where it first renders the page in landscape and then is trying to squeeze it into the space on a portrait page.
    All you have to do is give it a printable area wide enough that the extra space on the right of the would-be landscape print hangs off the physical page

    Here is the line from niiks code
    paper.setImageableArea(0,0,paper.getWidth(),paper.getHeight()); // no margin = no scaling

    change it to:

    paper.setImageableArea(0,0,paper.getWidth() * 2,paper.getHeight());

    Now the printable area is twice as wide and the extra space on the right of the landscape image can safely hang off without resizing our pdf.

    Here is the full code, updated with this hack

    // Create a PDFFile from a File reference
    02.File f = new File("c:\\juixe\\techknow.pdf");
    03.FileInputStream fis = new FileInputStream(f);
    04.FileChannel fc = fis.getChannel();
    05.ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
    06.PDFFile pdfFile = new PDFFile(bb); // Create PDF Print Page
    07.PDFPrintPage pages = new PDFPrintPage(pdfFile);
    08.
    09.// Create Print Job
    10.PrinterJob pjob = PrinterJob.getPrinterJob();
    11.PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
    
    Paper paper = new Paper();
    paper.setImageableArea(0,0,paper.getWidth() * 2,paper.getHeight());
    pf.setPaper(paper);
    
    12.pjob.setJobName(f.getName());
    13.Book book = new Book();
    14.book.append(pages, pf, pdfFile.getNumPages());
    15.pjob.setPageable(book);
    16.
    17.// Send print job to default printer
    18.pjob.print();
    

    of course remove the line numbers and this should finally work for everyone!!

  36. Ram
    Posted December 21, 2009 at 1:34 am | Permalink

    thanks Barrett.. it works fine..

  37. skyfyre
    Posted January 12, 2010 at 5:39 am | Permalink

    Thanks for exploring the bug and presenting a hack Barrett, it works like a charm.

    In case anyone wants to print to ISO A4 sized paper, use the following:
    Paper paper = new Paper();
    paper.setSize(595.275591, 841.889764); // width, height
    paper.setImageableArea(0, 0, paper.getWidth() * 2, paper.getHeight());

    The floating point values correspond to correct height/width for A4 paper in points (72pt/inch).

  38. Prabhat
    Posted February 4, 2010 at 5:56 am | Permalink

    Following is the error message that i get When i run this code with the input pdf file containing images . Can anyone help me :-
    Error reading image
    com.sun.pdfview.PDFParseException: Short stream in ASCIIHex decode
    at com.sun.pdfview.decode.ASCIIHexDecode.readHexDigit(ASCIIHexDecode.java:78)
    at com.sun.pdfview.decode.ASCIIHexDecode.decode(ASCIIHexDecode.java:94)
    at com.sun.pdfview.decode.ASCIIHexDecode.decode(ASCIIHexDecode.java:125)
    at com.sun.pdfview.decode.PDFDecoder.decodeStream(PDFDecoder.java:97)
    at com.sun.pdfview.PDFObject.decodeStream(PDFObject.java:331)
    at com.sun.pdfview.PDFObject.getStream(PDFObject.java:263)
    at com.sun.pdfview.PDFObject.getStream(PDFObject.java:257)
    at com.sun.pdfview.PDFImage.getImage(PDFImage.java:225)
    at com.sun.pdfview.PDFRenderer.drawImage(PDFRenderer.java:273)
    at com.sun.pdfview.PDFImageCmd.execute(PDFPage.java:643)
    at com.sun.pdfview.PDFRenderer.iterate(PDFRenderer.java:570)
    at com.sun.pdfview.BaseWatchable.run(BaseWatchable.java:101)
    at com.diesl.invoicePrinting.PDFPrintPage.print(InvoicePrinting.java:109)
    at sun.print.RasterPrinterJob.printPage(Unknown Source)
    at sun.print.RasterPrinterJob.print(Unknown Source)
    at sun.print.RasterPrinterJob.print(Unknown Source)
    at com.diesl.invoicePrinting.InvoicePrinting.main(InvoicePrinting.java:45)
    java.lang.NullPointerException
    at com.sun.pdfview.PDFRenderer.getMaskedImage(PDFRenderer.java:722)
    at com.sun.pdfview.PDFRenderer.drawImage(PDFRenderer.java:275)
    at com.sun.pdfview.PDFImageCmd.execute(PDFPage.java:643)
    at com.sun.pdfview.PDFRenderer.iterate(PDFRenderer.java:570)
    at com.sun.pdfview.BaseWatchable.run(BaseWatchable.java:101)
    at com.diesl.invoicePrinting.PDFPrintPage.print(InvoicePrinting.java:109)
    at sun.print.RasterPrinterJob.printPage(Unknown Source)
    at sun.print.RasterPrinterJob.print(Unknown Source)
    at sun.print.RasterPrinterJob.print(Unknown Source)
    at com.diesl.invoicePrinting.InvoicePrinting.main(InvoicePrinting.java:45)

  39. Rodrigo
    Posted February 11, 2010 at 7:44 am | Permalink

    Thanks Barret.

    But now I’m facing another problem when printing in a couple of network printers. I send jobs to hp printers, HP LaserJet P3005 and HP LaserJet 2300dn, and I frequently get these errors.
    “PCL XL error Warning: IllegalMediaSize”
    or
    PCL XL error subsystem: KERNEL
    Error: Illegal Tag
    Operator: (various hex numbers)
    Position: (various numbers)

    Any idea ???
    Thanks in advance.

  40. mdeguzman
    Posted July 6, 2010 at 9:17 pm | Permalink

    great article.

    @barrett and @skyfyre
    thanks for the fixes. had the same problem with the font/scaling and your codes worked perfectly.

  41. Tuyen Tran
    Posted August 13, 2010 at 11:01 am | Permalink

    A better way to fix the scaling issue is to just override the implementation of Printable, and use the newer Java Print API to send the PDF to the printer. As a bonus, you can also get Duplex working, which I never could using the example above.

    Here’s a sketch of the code:

    void print(PDFFile pdfFile) {
    PDFPrintPage pages = new PDFPrintPage(pdfFile) {
    @Override
    public int print(Graphics g, PageFormat format, int index) throws PrinterException {
    if (index >= pdfFile.getNumPages()) {
    return Printable.NO_SUCH_PAGE;
    }
    Graphics2D g2 = (Graphics2D) g;
    PDFPage page = pdfFile.getPage(index+1);

    // no scaling, center PDF
    Rectangle bounds = new Rectangle(
    (int) (format.getImageableX() + format.getImageableWidth()/2 – page.getWidth()/2),
    (int) (format.getImageableY() + format.getImageableHeight()/2 – page.getHeight()/2),
    (int) page.getWidth(),
    (int) page.getHeight()
    );

    PDFRenderer pgs = new PDFRenderer(page, g2, bounds, null, null);
    try {
    page.waitForFinish();
    pgs.run();
    } catch (InterruptedException ie) {}

    return PAGE_EXISTS;
    }
    };

    PrintService printService = …; // usual stuff to locate a PrintService
    DocPrintJob printJob = printService.createPrintJob();
    printJob.print(new SimpleDoc(pages, flavor, null), printRequestAttributeSet());
    }

    private PrintRequestAttributeSet printRequestAttributeSet() {
    final PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
    aset.add(new Copies(1));
    aset.add(MediaTray.MAIN);
    aset.add(MediaSizeName.NA_LETTER);
    aset.add(Sides.DUPLEX);
    aset.add(OrientationRequested.PORTRAIT);
    // use the entire surface of the media
    aset.add(new MediaPrintableArea(0.0f, 0.0f, 8.5f, 11.0f, MediaPrintableArea.INCH));

    return aset;
    }

  42. Tuyen Tran
    Posted August 13, 2010 at 11:05 am | Permalink

    Since you are formatting a Printable yourself, the DocFlavor is:

    DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;

  43. Tuyen Tran
    Posted August 13, 2010 at 11:14 am | Permalink

    There’s actually no need to use PDFPrintPage at all.

    void print(final PDFFile pdfFile) {

    Printable pages = new Printable() {

    }

    }

    I did say it was sketch…

  44. Ashley
    Posted August 30, 2010 at 11:39 am | Permalink

    I tried the code and it worked well with simple PDF files. But when I tried to print a PDF file with some images, it raised following exception. Does anyone have a solution?

    java.lang.NullPointerException
    at com.sun.pdfview.font.TTFFont.getOutline(TTFFont.java:170)
    at com.sun.pdfview.font.CIDFontType2.getOutline(CIDFontType2.java:270)
    at com.sun.pdfview.font.OutlineFont.getGlyph(OutlineFont.java:130)
    at com.sun.pdfview.font.PDFFont.getCachedGlyph(PDFFont.java:308)
    at com.sun.pdfview.font.PDFFontEncoding.getGlyphFromCMap(PDFFontEncoding.java:155)
    at com.sun.pdfview.font.PDFFontEncoding.getGlyphs(PDFFontEncoding.java:115)
    at com.sun.pdfview.font.PDFFont.getGlyphs(PDFFont.java:274)
    at com.sun.pdfview.PDFTextFormat.doText(PDFTextFormat.java:269)
    at com.sun.pdfview.PDFParser.iterate(PDFParser.java:752)
    at com.sun.pdfview.BaseWatchable.run(BaseWatchable.java:101)
    at java.lang.Thread.run(Unknown Source)

  45. Ashley
    Posted September 1, 2010 at 4:54 am | Permalink

    In case someone runs into this again, the following is how I got rid of the NullPointerException with TTFont. I added a if around the code in the following method:
    protected synchronized GeneralPath getOutline (int glyphId, float width) {
    GeneralPath gp = null;
    if (font != null ) {

    }
    return gp;
    }
    Good luck everyone!

  46. Carlos
    Posted September 9, 2010 at 3:24 pm | Permalink

    Works good for version 1.3 but no for version 1.5+ pdf’s birt generated. Any update somewhere? Good work tough. Greetings.

  47. Tony
    Posted October 2, 2010 at 6:01 am | Permalink

    I used PDFRenderer to create a Jar who’s main accepts two parameters: 1 = pdfFileName and 2. printerName.

    The Jar sets the papersize from the default Letter size to A4.

    When I call the Jar on my windows machine it works perfectly.

    When I call the Jar on our HP-UX machine or our Linux machine the print job is created and appears in the queue, but has an error status of “Letter not loaded in any tray”.

    Has anyone experienced this and are you able to offer any ideas?

  48. Tee
    Posted January 21, 2011 at 9:26 am | Permalink

    @Tuyen Tran
    Thanks a lot for your sketch. That’s working perfect for me !

  49. james
    Posted February 11, 2011 at 8:17 am | Permalink

    This is what i use to keep the original pdf size :

    	/* fit the PDFPage into the printing area */
    	Graphics2D a_o_graphic = (Graphics2D)the_o_graphics;
    	PDFPage a_o_page = my_o_file.getPage(a_i_pagenum);
    
    	double pwidth = the_o_format.getImageableWidth();
    	double pheight = the_o_format.getImageableHeight();
    
    	Rectangle a_o_imageArea;
    
        if (pwidth >= a_o_page.getWidth() || pheight >= a_o_page.getHeight()) {
    	/* Define the image area */
    		a_o_imageArea = new Rectangle((int) the_o_format.getImageableX(), (int) the_o_format.getImageableY(),
    		(int) a_o_page.getWidth(), (int) a_o_page.getHeight());
    		a_o_graphic.translate(0, 0);
        }
        else{
    	/* Define the image area */
    		a_o_imageArea = new Rectangle((int) the_o_format.getImageableX(), (int) the_o_format.getImageableY(),
    		(int) the_o_format.getImageableWidth(), (int) the_o_format.getImageableHeight());
    		a_o_graphic.translate(0, 0);
        }
    

    I hope it can be useful for someone :)

  50. Bainer
    Posted March 3, 2011 at 1:30 pm | Permalink

    Thank you Barrett for figuring this thing out!!

  51. Clement
    Posted November 21, 2011 at 2:13 am | Permalink

    Very nice code, very simple and useful.
    Thank you.

  52. Jhay
    Posted November 25, 2011 at 11:16 pm | Permalink

    How to use this through PHP where I can pass a variable that has the link to my PDF? For example, an external PDF or internal…

  53. Techie
    Posted December 8, 2011 at 7:03 am | Permalink

    Hi Friends,

    Thanks for sharing this example.

    I am facing issue when I print on Linux/Unix machine.
    It is printing Binary (Junk Chars) not the actual PDF Doc.
    Same code is working fine on Windows.
    If any one of you know the solution or any inputs, highly appreciated.

    Thanks in Advance.

  54. Shoaib Ahmed
    Posted January 24, 2012 at 2:55 am | Permalink

    this library is just superb… helped me a lot. i worked with it for the printinig purpose…

  55. cisq
    Posted January 31, 2012 at 5:18 am | Permalink

    Great work, many thanks

4 Trackbacks

  1. By Bookmarking the web - w04/2008 on January 26, 2008 at 4:07 am

    [...] On the blog Juixe TechKnow you can read how to print a PDF document from a Java program. [...]

  2. [...] che facevano al caso mio! Prima parte: per mandare in stampa il PDF ho seguito le istruzioni di questo post, che suggerisce l’utilizzo della libreria PDF Renderer. Solo una correzione al codice [...]

  3. By Stampare PDF da Java | Lady Blackice on March 24, 2011 at 8:40 am

    [...] che facevano al caso mio! Prima parte: per mandare in stampa il PDF ho seguito le istruzioni di questo post, che suggerisce l’utilizzo della libreria PDF Renderer. Solo una correzione al codice [...]

  4. By Print & PDF Document in Java | P3r3s' Notes on November 3, 2011 at 2:29 pm

    [...] Print a PDF Document in Java. This entry was posted in Code and tagged java by abrioso. Bookmark the permalink. [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*