org.apache.pdfbox.printing.PDFPageable.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.pdfbox.printing.PDFPageable.java

Source

/*
 * 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.printing;

import java.awt.RenderingHints;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;

/**
 * Prints a PDF document using its original paper size.
 *
 * @author John Hewson
 */
public final class PDFPageable extends Book {
    private final PDDocument document;
    private final boolean showPageBorder;
    private final float dpi;
    private final Orientation orientation;
    private boolean subsamplingAllowed = false;
    private RenderingHints renderingHints = null;

    /**
     * Creates a new PDFPageable.
     *
     * @param document the document to print
     */
    public PDFPageable(PDDocument document) {
        this(document, Orientation.AUTO, false, 0);
    }

    /**
     * Creates a new PDFPageable with the given page orientation.
     *
     * @param document the document to print
     * @param orientation page orientation policy
     */
    public PDFPageable(PDDocument document, Orientation orientation) {
        this(document, orientation, false, 0);
    }

    /**
     * Creates a new PDFPageable with the given page orientation and with optional page borders
     * shown. The image will be rasterized at the given DPI before being sent to the printer.
     *
     * @param document the document to print
     * @param orientation page orientation policy
     * @param showPageBorder true if page borders are to be printed
     */
    public PDFPageable(PDDocument document, Orientation orientation, boolean showPageBorder) {
        this(document, orientation, showPageBorder, 0);
    }

    /**
     * Creates a new PDFPageable with the given page orientation and with optional page borders
     * shown. The image will be rasterized at the given DPI before being sent to the printer.
     *
     * @param document the document to print
     * @param orientation page orientation policy
     * @param showPageBorder true if page borders are to be printed
     * @param dpi if non-zero then the image will be rasterized at the given DPI
     */
    public PDFPageable(PDDocument document, Orientation orientation, boolean showPageBorder, float dpi) {
        this.document = document;
        this.orientation = orientation;
        this.showPageBorder = showPageBorder;
        this.dpi = dpi;
    }

    /**
     * Get the rendering hints.
     *
     * @return the rendering hints or null if none are set.
     */
    public RenderingHints getRenderingHints() {
        return renderingHints;
    }

    /**
     * Set the rendering hints. Use this to influence rendering quality and speed. If you don't set
     * them yourself or pass null, PDFBox will decide <b><u>at runtime</u></b> depending on the
     * destination.
     *
     * @param renderingHints
     */
    public void setRenderingHints(RenderingHints renderingHints) {
        this.renderingHints = renderingHints;
    }

    /**
     * Value indicating if the renderer is allowed to subsample images before drawing, according to
     * image dimensions and requested scale.
     *
     * Subsampling may be faster and less memory-intensive in some cases, but it may also lead to
     * loss of quality, especially in images with high spatial frequency.
     *
     * @return true if subsampling of images is allowed, false otherwise.
     */
    public boolean isSubsamplingAllowed() {
        return subsamplingAllowed;
    }

    /**
     * Sets a value instructing the renderer whether it is allowed to subsample images before
     * drawing. The subsampling frequency is determined according to image size and requested scale.
     *
     * Subsampling may be faster and less memory-intensive in some cases, but it may also lead to
     * loss of quality, especially in images with high spatial frequency.
     *
     * @param subsamplingAllowed The new value indicating if subsampling is allowed.
     */
    public void setSubsamplingAllowed(boolean subsamplingAllowed) {
        this.subsamplingAllowed = subsamplingAllowed;
    }

    @Override
    public int getNumberOfPages() {
        return document.getNumberOfPages();
    }

    /**
     * {@inheritDoc}
     * 
     * Returns the actual physical size of the pages in the PDF file. May not fit the local printer.
     */
    @Override
    public PageFormat getPageFormat(int pageIndex) {
        PDPage page = document.getPage(pageIndex);
        PDRectangle mediaBox = PDFPrintable.getRotatedMediaBox(page);
        PDRectangle cropBox = PDFPrintable.getRotatedCropBox(page);

        // Java does not seem to understand landscape paper sizes, i.e. where width > height, it
        // always crops the imageable area as if the page were in portrait. I suspect that this is
        // a JDK bug but it might be by design, see PDFBOX-2922.
        //
        // As a workaround, we normalise all Page(s) to be portrait, then flag them as landscape in
        // the PageFormat.
        Paper paper;
        boolean isLandscape;
        if (mediaBox.getWidth() > mediaBox.getHeight()) {
            // rotate
            paper = new Paper();
            paper.setSize(mediaBox.getHeight(), mediaBox.getWidth());
            paper.setImageableArea(cropBox.getLowerLeftY(), cropBox.getLowerLeftX(), cropBox.getHeight(),
                    cropBox.getWidth());
            isLandscape = true;
        } else {
            paper = new Paper();
            paper.setSize(mediaBox.getWidth(), mediaBox.getHeight());
            paper.setImageableArea(cropBox.getLowerLeftX(), cropBox.getLowerLeftY(), cropBox.getWidth(),
                    cropBox.getHeight());
            isLandscape = false;
        }

        PageFormat format = new PageFormat();
        format.setPaper(paper);

        // auto portrait/landscape
        switch (orientation) {
        case AUTO:
            format.setOrientation(isLandscape ? PageFormat.LANDSCAPE : PageFormat.PORTRAIT);
            break;
        case LANDSCAPE:
            format.setOrientation(PageFormat.LANDSCAPE);
            break;
        case PORTRAIT:
            format.setOrientation(PageFormat.PORTRAIT);
            break;
        default:
            break;
        }

        return format;
    }

    @Override
    public Printable getPrintable(int i) {
        if (i >= getNumberOfPages()) {
            throw new IndexOutOfBoundsException(i + " >= " + getNumberOfPages());
        }
        PDFPrintable printable = new PDFPrintable(document, Scaling.ACTUAL_SIZE, showPageBorder, dpi);
        printable.setSubsamplingAllowed(subsamplingAllowed);
        printable.setRenderingHints(renderingHints);
        return printable;
    }
}