PrintedPdfDocument.java revision 6811f4e92cbb64e72a0d13eb9b99b5894bd59c76
1aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov/*
2aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project
3aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov *
4aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
5aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * you may not use this file except in compliance with the License.
6aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * You may obtain a copy of the License at
7aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov *
8aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
9aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov *
10aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software
11aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
12aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * See the License for the specific language governing permissions and
14aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * limitations under the License.
15aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */
16aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
17aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovpackage android.print.pdf;
18aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
19aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.content.Context;
20aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.graphics.Rect;
216811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavimport android.graphics.pdf.PdfDocument;
226811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavimport android.graphics.pdf.PdfDocument.Page;
236811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavimport android.graphics.pdf.PdfDocument.PageInfo;
24aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.print.PrintAttributes;
25aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.print.PrintAttributes.Margins;
26aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.print.PrintAttributes.MediaSize;
27aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
28aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov/**
296811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * This class is a helper for creating a PDF file for given print
306811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * attributes. It is useful for implementing printing via the native
316811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * Android graphics APIs.
326811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * <p>
336811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * This class computes the page width, page height, and content rectangle
346811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * from the provided print attributes and these precomputed values can be
356811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * accessed via {@link #getPageWidth()}, {@link #getPageHeight()}, and
366811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * {@link #getPageContentRect()}, respectively. The {@link #startPage(int)}
376811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * methods creates pages whose {@link PageInfo} is initialized with the
386811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * precomputed values for width, height, and content rectangle.
396811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * <p>
406811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * A typical use of the APIs looks like this:
416811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * </p>
426811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * <pre>
436811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // open a new document
446811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * PrintedPdfDocument document = new PrintedPdfDocument(context,
456811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav *         printAttributes);
466811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav *
476811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // start a page
486811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * Page page = document.startPage(0);
496811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav *
506811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // draw something on the page
516811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * View content = getContentView();
526811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * content.draw(page.getCanvas());
536811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav *
546811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // finish the page
556811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * document.finishPage(page);
566811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * . . .
576811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // add more pages
586811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * . . .
596811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // write the document content
606811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * document.writeTo(getOutputStream());
616811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav *
626811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * //close the document
636811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * document.close();
646811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * </pre>
65aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */
666811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavpublic class PrintedPdfDocument extends PdfDocument {
67aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    private static final int MILS_PER_INCH = 1000;
68aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    private static final int POINTS_IN_INCH = 72;
69aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
706811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav    private final int mPageWidth;
716811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav    private final int mPageHeight;
726811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav    private final Rect mContentRect;
73aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
74aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    /**
756811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * Creates a new document.
76aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * <p>
77aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * <strong>Note:</strong> You must close the document after you are
786811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * done by calling {@link #close()}.
79aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * </p>
80aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     *
81aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * @param context Context instance for accessing resources.
82aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * @param attributes The print attributes.
83aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     */
846811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav    public PrintedPdfDocument(Context context, PrintAttributes attributes) {
85aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov        MediaSize mediaSize = attributes.getMediaSize();
86aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
87aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov        // Compute the size of the target canvas from the attributes.
886811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        mPageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH)
89aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov                * POINTS_IN_INCH);
906811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        mPageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH)
91aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov                * POINTS_IN_INCH);
92aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
93aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov        // Compute the content size from the attributes.
94651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        Margins minMargins = attributes.getMinMargins();
956811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        final int marginLeft = (int) (((float) minMargins.getLeftMils() / MILS_PER_INCH)
96aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov                * POINTS_IN_INCH);
97651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        final int marginTop = (int) (((float) minMargins.getTopMils() / MILS_PER_INCH)
98aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov                * POINTS_IN_INCH);
99651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        final int marginRight = (int) (((float) minMargins.getRightMils() / MILS_PER_INCH)
100aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov                * POINTS_IN_INCH);
101651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav        final int marginBottom = (int) (((float) minMargins.getBottomMils() / MILS_PER_INCH)
102aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov                * POINTS_IN_INCH);
1036811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        mContentRect = new Rect(marginLeft, marginTop, mPageWidth - marginRight,
1046811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav                mPageHeight - marginBottom);
105aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    }
106aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
107aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    /**
1086811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * Starts a new page. The page is created using width, height  and content
1096811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * rectangle computed from the print attributes passed in the constructor
1106811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * and the given page number to create an appropriate {@link PageInfo}.
111aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * <p>
112aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * After the page is created you can draw arbitrary content on the page's
113aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * canvas which you can get by calling {@link Page#getCanvas() Page.getCanvas()}.
114aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * After you are done drawing the content you should finish the page by calling
115aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * {@link #finishPage(Page)}. After the page is finished you should no longer
116aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * access the page or its canvas.
117aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * </p>
118aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * <p>
119aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * <strong>Note:</strong> Do not call this method after {@link #close()}.
1206811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * Also do not call this method if the last page returned by this method
1216811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * is not finished by calling {@link #finishPage(Page)}.
122aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * </p>
123aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     *
1246811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * @param pageNumber The page number. Must be a positive value.
125aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * @return A blank page.
126aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     *
127aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     * @see #finishPage(Page)
128aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     */
129aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    public Page startPage(int pageNumber) {
130d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        PageInfo pageInfo = new PageInfo
1316811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav                .Builder(mPageWidth, mPageHeight, pageNumber)
1326811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav                .setContentRect(mContentRect)
133d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                .create();
1346811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        return startPage(pageInfo);
135aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    }
136aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
137aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    /**
1386811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * Gets the page width.
139aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     *
1406811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * @return The page width in PostScript points (1/72th of an inch).
141aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     */
1426811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav    public int getPageWidth() {
1436811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        return mPageWidth;
144aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    }
145aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
146aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    /**
1476811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * Gets the page height.
148aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     *
1496811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * @return The page height in PostScript points (1/72th of an inch).
150aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     */
1516811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav    public int getPageHeight() {
1526811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        return mPageHeight;
153aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    }
154aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov
155aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    /**
1566811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * Gets the content rectangle. This is the area of the page that
1576811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * contains printed data and is relative to the page top left.
158aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     *
1596811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav     * @return The content rectangle.
160aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov     */
1616811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav    public Rect getPageContentRect() {
1626811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav        return mContentRect;
163aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov    }
164aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov}
165