/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.pdfbox.pdmodel; import static javax.print.attribute.standard.OrientationRequested.LANDSCAPE; import java.awt.Dimension; import java.awt.Graphics; import java.awt.print.PageFormat; import java.awt.print.Pageable; import java.awt.print.Paper; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.util.ArrayList; import java.util.List; import javax.print.PrintService; import javax.print.attribute.standard.OrientationRequested; /** * Adapter class that implements the {@link Pageable} and {@link Printable} * interfaces for printing a given PDF document. Note that the given PDF * document should not be modified (pages added, removed, etc.) while an * instance of this class is being used. * * @since Apache PDFBox 1.3.0 * @see <a href="https://issues.apache.org/jira/browse/PDFBOX-788">PDFBOX-788</a> */ public class PDPageable implements Pageable, Printable { /** * List of all pages in the given PDF document. */ private final List<PDPage> pages = new ArrayList<PDPage>(); /** * The printer job for printing the given PDF document. */ private final PrinterJob job; /** * Creates a {@link Pageable} adapter for the given PDF document and * printer job. * * @param document PDF document * @param job printer job * @throws IllegalArgumentException if an argument is <code>null</code> * @throws PrinterException if the document permissions prevent printing */ public PDPageable(PDDocument document, PrinterJob job) throws IllegalArgumentException, PrinterException { if (document == null || job == null) { throw new IllegalArgumentException( "PDPageable(" + document + ", " + job + ")"); } else if (!document.getCurrentAccessPermission().canPrint()) { throw new PrinterException( "You do not have permission to print this document"); } else { document.getDocumentCatalog().getPages().getAllKids(pages); this.job = job; } } /** * Creates a {@link Pageable} adapter for the given PDF document using * a default printer job returned by {@link PrinterJob#getPrinterJob()}. * * @param document PDF document * @throws IllegalArgumentException if the argument is <code>null</code> * @throws PrinterException if the document permissions prevent printing */ public PDPageable(PDDocument document) throws IllegalArgumentException, PrinterException { this(document, PrinterJob.getPrinterJob()); } /** * Returns the printer job for printing the given PDF document. * * @return printer job */ public PrinterJob getPrinterJob() { return job; } //------------------------------------------------------------< Pageable > /** * Returns the number of pages in the given PDF document. * * @return number of pages */ public int getNumberOfPages() { return pages.size(); } /** * Returns the format of the page at the given index. * * @param i page index, zero-based * @return page format * @throws IndexOutOfBoundsException if the page index is invalid */ public PageFormat getPageFormat(int i) throws IndexOutOfBoundsException { PageFormat format = job.defaultPage(); PDPage page = pages.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; } Paper paper = format.getPaper(); PrintService service = job.getPrintService(); // can be null Class<OrientationRequested> orientation = OrientationRequested.class; if (service != null && service.getDefaultAttributeValue(orientation) == LANDSCAPE) { format.setOrientation(PageFormat.LANDSCAPE); paper.setImageableArea( diffHeight, diffWidth, crop.getHeight(), crop.getWidth()); paper.setSize(media.getHeight(), media.getWidth()); } else { format.setOrientation(PageFormat.PORTRAIT); paper.setImageableArea( diffWidth, diffHeight, crop.getWidth(), crop.getHeight()); paper.setSize(media.getWidth(), media.getHeight()); } format.setPaper(paper); return format; } /** * Returns a {@link Printable} for the page at the given index. * Currently this method simply returns the underlying {@link PDPage} * object that directly implements the {@link Printable} interface, but * future versions may choose to return a different adapter instance. * * @param i page index, zero-based * @return printable * @throws IndexOutOfBoundsException if the page index is invalid */ public Printable getPrintable(int i) throws IndexOutOfBoundsException { return pages.get(i); } //-----------------------------------------------------------< Printable > /** * Prints the page at the given index. * * @param graphics printing target * @param format page format * @param i page index, zero-based * @return {@link Printable#PAGE_EXISTS} if the page was printed, * or {@link Printable#NO_SUCH_PAGE} if page index was invalid * @throws PrinterException if printing failed */ @SuppressWarnings("deprecation") public int print(Graphics graphics, PageFormat format, int i) throws PrinterException { if (0 <= i && i < pages.size()) { return pages.get(i).print(graphics, format, i); } else { return NO_SUCH_PAGE; } } }