Package org.apache.pdfbox.printing

Source Code of org.apache.pdfbox.printing.PDFPrinter$PDFPrintable

/*
* 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 org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;

import javax.print.attribute.PrintRequestAttributeSet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
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.PrinterIOException;
import java.awt.print.PrinterJob;
import java.io.IOException;
import org.apache.pdfbox.rendering.PDFRenderer;

/**
* Prints a PDF document using AWT.
* This class may be overridden in order to perform custom printing.
*
* @author Andreas Lehmkühler
* @author John Hewson
*/
public class PDFPrinter
{
    protected final PDDocument document;
    protected final PDFRenderer renderer;
    protected final PrinterJob printerJob;
    protected final Scaling scaling;
    protected final Orientation orientation;
    protected final boolean showPageBorder;
    protected final Paper paper; // may be null
    protected final float dpi;

    /**
     * Creates a new PDFPrinter using the system's default printer.
     * @param document the document to print
     */
    public PDFPrinter(PDDocument document) throws PrinterException
    {
        this(document, PrinterJob.getPrinterJob());
    }

    /**
     * Creates a new PDFPrinter using the given printer.
     * @param document the document to print
     * @param printerJob the printer job to use
     */
    public PDFPrinter(PDDocument document, PrinterJob printerJob) throws PrinterException
    {
        this(document, printerJob, Scaling.SHRINK_TO_FIT, Orientation.AUTO, null, false, 0);
    }

    /**
     * Creates a new PDFPrinter using the system's default printer,
     * with the given page scaling and orientation.
     *
     * @param document the document to print
     * @param scaling page scaling policy
     * @param orientation page orientation policy
     */
    public PDFPrinter(PDDocument document, Scaling scaling, Orientation orientation)
            throws PrinterException
    {
        this(document, PrinterJob.getPrinterJob(), scaling, orientation, null, false, 0);
    }

    /**
     * Creates a new PDFPrinter using the system's default printer,
     * with the given page scaling and orientation.
     *
     * @param document the document to print
     * @param scaling page scaling policy
     * @param orientation page orientation policy
     */
    public PDFPrinter(PDDocument document, Scaling scaling, Orientation orientation, Paper paper)
            throws PrinterException
    {
        this(document, PrinterJob.getPrinterJob(), scaling, orientation, paper, false, 0);
    }

    /**
     * Creates a new PDFPrinter using the system's default printer,
     * with the given page scaling and orientation.
     *
     * @param document the document to print
     * @param scaling page scaling policy
     * @param orientation page orientation policy
     * @param dpi if non-zero then the image will be rasterized at the given DPI
     */
    public PDFPrinter(PDDocument document, Scaling scaling, Orientation orientation, Paper paper,
                      float dpi) throws PrinterException
    {
        this(document, PrinterJob.getPrinterJob(), scaling, orientation, paper, false, dpi);
    }

    /**
     * Creates a new PDFPrinter using the given printer, the given page scaling and orientation,
     * and with optional page borders shown.
     *
     * @param document the document to print
     * @param printerJob the printer job to use
     * @param scaling page scaling policy
     * @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
     * @throws PrinterException
     */
    public PDFPrinter(PDDocument document, PrinterJob printerJob, Scaling scaling,
                      Orientation orientation, Paper paper, boolean showPageBorder, float dpi)
            throws PrinterException
    {
        if (document == null)
        {
            throw new IllegalArgumentException("document");
        }
        else if (printerJob == null)
        {
            throw new IllegalArgumentException("printerJob");
        }
        else if (!document.getCurrentAccessPermission().canPrint())
        {
            throw new PrinterException("You do not have permission to print this document");
        }
        this.document = document;
        this.renderer = new PDFRenderer(document);
        this.printerJob = printerJob;
        this.scaling = scaling;
        this.orientation = orientation;
        this.showPageBorder = showPageBorder;
        this.paper = paper;
        this.dpi = dpi;
    }

    /**
     * Prints the given document using the default printer without prompting the user.
     * @throws java.awt.print.PrinterException if the document cannot be printed
     */
    public void silentPrint() throws PrinterException
    {
        silentPrint(printerJob);
    }

    /**
     * Prints the given document using the default printer without prompting the user.
     * @param attributes application supplied attributes
     * @throws PrinterException if the document cannot be printed
     */
    public boolean silentPrint(PrintRequestAttributeSet attributes) throws PrinterException
    {
        return print(printerJob, attributes, true);
    }

    /**
     * Prints the given document using the default printer without prompting the user.
     * @param printerJob a printer job definition
     * @throws PrinterException if the document cannot be printed
     */
    public void silentPrint(PrinterJob printerJob) throws PrinterException
    {
        print(printerJob, null, true);
    }

    /**
     * Prints the given document using the default printer without prompting the user.
     * The image is generated using {@link org.apache.pdfbox.rendering.PageDrawer}.
     * This is a convenience method to create the java.awt.print.PrinterJob.
     * Advanced printing tasks can be performed using {@link #getPageable()} instead.
     *
     * @return true if the user does not cancel the dialog
     * @throws PrinterException if the document cannot be printed
     */
    public boolean print() throws PrinterException
    {
        return print(printerJob);
    }

    /**
     * Prints the given document using the default printer without prompting the user.
     * The image is generated using {@link org.apache.pdfbox.rendering.PageDrawer}.
     * This is a convenience method to create the java.awt.print.PrinterJob.
     * Advanced printing tasks can be performed using {@link #getPageable()} instead.
     *
     * @param attributes application supplied attributes
     * @return true if the user does not cancel the dialog
     * @throws PrinterException if the document cannot be printed
     */
    public boolean print(PrintRequestAttributeSet attributes) throws PrinterException
    {
        return print(printerJob, attributes);
    }

    /**
     * Prints the given document using the default printer without prompting the user.
     * @param printerJob the printer job.
     * @return true if the user does not cancel the dialog
     * @throws PrinterException if the document cannot be printed
     */
    public boolean print(PrinterJob printerJob) throws PrinterException
    {
        return print(printerJob, null, false);
    }

    /**
     * Prints the given document using the default printer without prompting the user.
     * @param printerJob the printer job.
     * @param attributes application supplied attributes
     * @return true if the user does not cancel the dialog
     * @throws PrinterException if the document cannot be printed
     */
    public boolean print(PrinterJob printerJob, PrintRequestAttributeSet attributes) throws PrinterException
    {
        return print(printerJob, attributes, false);
    }

    // prints a document
    private boolean print(PrinterJob job, PrintRequestAttributeSet attributes, boolean isSilent)
        throws PrinterException
    {
        if (job == null)
        {
            throw new IllegalArgumentException("job cannot be null");
        }
        else
        {
            job.setPageable(getPageable());
            if (isSilent && attributes == null)
            {
                job.print();
                return true;
            }
            else if (isSilent)
            {
                job.print(attributes);
                return true;
            }
            else if (attributes == null)
            {
                if (job.printDialog())
                {
                    job.print();
                    return true;
                }
            }
            else
            {
                if (job.printDialog(attributes))
                {
                    job.print();
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns the Pageable instance used in this class. Can be overridden by subclasses.
     */
    public PDFPageable getPageable()
    {
      return new PDFPageable();
    }

    protected class PDFPageable implements Pageable
    {
        @Override
        public int getNumberOfPages()
        {
            return document.getNumberOfPages();
        }

        @Override
        public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException
        {
            // note: PDFPrintable#print() is responsible for fitting the current page to
            //       the printer's actual paper size, so this method must return the full
            //       physical, printable size of the actual paper in the printer.

            PageFormat format = printerJob.defaultPage();
            PDPage page = document.getPage(pageIndex);

            // auto portrait/landscape
            if (orientation == Orientation.AUTO)
            {
                PDRectangle cropBox = getRotatedCropBox(page);
                if (cropBox.getWidth() > cropBox.getHeight())
                {
                    format.setOrientation(PageFormat.LANDSCAPE);
                }
                else
                {
                    format.setOrientation(PageFormat.PORTRAIT);
                }
            }
            else if (orientation == Orientation.LANDSCAPE)
            {
                format.setOrientation(PageFormat.LANDSCAPE);
            }
            else if (orientation == Orientation.PORTRAIT)
            {
                format.setOrientation(PageFormat.PORTRAIT);
            }

            // custom paper
            if (paper != null)
            {
                format.setPaper(paper);
            }

            return format;
        }

        @Override
        public Printable getPrintable(int i) throws IndexOutOfBoundsException
        {
            if (i >= getNumberOfPages())
            {
                throw new IndexOutOfBoundsException(i + " >= " +  getNumberOfPages());
            }
            return new PDFPrintable();
        }
    }

    /**
     * This will find the CropBox with rotation applied, for this page by looking up the hierarchy
     * until it finds them.
     *
     * @return The CropBox at this level in the hierarchy.
     */
    private PDRectangle getRotatedCropBox(PDPage page)
    {
        PDRectangle cropBox = page.getCropBox();
        int rotation = page.getRotation();
        if (rotation == 90 || rotation == 270)
        {
            return new PDRectangle(cropBox.getLowerLeftY(), cropBox.getLowerLeftX(),
                    cropBox.getHeight(), cropBox.getWidth());
        }
        else
        {
            return cropBox;
        }
    }

    protected class PDFPrintable implements Printable
    {
        @Override
        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
                throws PrinterException
        {
            if (pageIndex < 0 || pageIndex >= document.getNumberOfPages())
            {
                return NO_SUCH_PAGE;
            }
            try
            {
                Graphics2D graphics2D = (Graphics2D)graphics;

                PDPage page = document.getPage(pageIndex);
                PDRectangle cropBox = getRotatedCropBox(page);

                // the imageable area is the area within the page margins
                final double imageableWidth = pageFormat.getImageableWidth();
                final double imageableHeight = pageFormat.getImageableHeight();

                double scale = 1;
                if (scaling != Scaling.ACTUAL_SIZE)
                {
                    // scale to fit
                    double scaleX = imageableWidth / cropBox.getWidth();
                    double scaleY = imageableHeight / cropBox.getHeight();
                    scale = Math.min(scaleX, scaleY);

                    // only shrink to fit when enabled
                    if (scale > 1 && scaling == Scaling.SHRINK_TO_FIT)
                    {
                        scale = 1;
                    }
                }

                // set the graphics origin to the origin of the imageable area (i.e the margins)
                graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

                // center on page
                graphics2D.translate((imageableWidth - cropBox.getWidth() * scale) / 2,
                        (imageableHeight - cropBox.getHeight() * scale) / 2);

                // rasterize to bitmap (optional)
                Graphics2D printerGraphics = null;
                BufferedImage image = null;
                if (dpi > 0)
                {
                    float dpiScale = dpi / 72;
                    image = new BufferedImage((int)(imageableWidth * dpiScale), (int)(imageableHeight * dpiScale),
                            BufferedImage.TYPE_INT_ARGB);

                    printerGraphics = graphics2D;
                    graphics2D = image.createGraphics();

                    // rescale
                    printerGraphics.scale(scale / dpiScale, scale / dpiScale);
                    scale = dpiScale;
                }

                // draw to graphics using PDFRender
                AffineTransform transform = (AffineTransform)graphics2D.getTransform().clone();
                graphics2D.setBackground(Color.WHITE);
                renderer.renderPageToGraphics(pageIndex, graphics2D, (float)scale);

                // draw crop box
                if (showPageBorder)
                {
                    graphics2D.setTransform(transform);
                    graphics2D.setClip(0, 0, (int)imageableWidth, (int)imageableHeight);
                    graphics2D.scale(scale, scale);
                    graphics2D.setColor(Color.GRAY);
                    graphics2D.setStroke(new BasicStroke(0.5f));
                    graphics.drawRect(0, 0, (int)cropBox.getWidth(), (int)cropBox.getHeight());
                }

                // draw rasterized bitmap (optional)
                if (printerGraphics != null)
                {
                    printerGraphics.setBackground(Color.WHITE);
                    printerGraphics.clearRect(0, 0, image.getWidth(), image.getHeight());
                    printerGraphics.drawImage(image, 0, 0, null);
                    graphics2D.dispose();
                }

                return PAGE_EXISTS;
            }
            catch (IOException e)
            {
                throw new PrinterIOException(e);
            }
        }
    }
}
TOP

Related Classes of org.apache.pdfbox.printing.PDFPrinter$PDFPrintable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.