1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.print.pdf;
18 
19 import android.annotation.IntRange;
20 import android.annotation.NonNull;
21 import android.content.Context;
22 import android.graphics.Rect;
23 import android.graphics.pdf.PdfDocument;
24 import android.print.PrintAttributes;
25 import android.print.PrintAttributes.Margins;
26 import android.print.PrintAttributes.MediaSize;
27 
28 /**
29  * This class is a helper for creating a PDF file for given print attributes. It is useful for
30  * implementing printing via the native Android graphics APIs.
31  * <p>
32  * This class computes the page width, page height, and content rectangle from the provided print
33  * attributes and these precomputed values can be accessed via {@link #getPageWidth()},
34  * {@link #getPageHeight()}, and {@link #getPageContentRect()}, respectively. The
35  * {@link #startPage(int)} methods creates pages whose
36  * {@link android.graphics.pdf.PdfDocument.PageInfo PageInfo} is initialized with the precomputed
37  * values for width, height, and content rectangle.
38  * <p>
39  * A typical use of the APIs looks like this:
40  * </p>
41  * <pre>
42  * // open a new document
43  * PrintedPdfDocument document = new PrintedPdfDocument(context,
44  *         printAttributes);
45  *
46  * // start a page
47  * Page page = document.startPage(0);
48  *
49  * // draw something on the page
50  * View content = getContentView();
51  * content.draw(page.getCanvas());
52  *
53  * // finish the page
54  * document.finishPage(page);
55  * . . .
56  * // add more pages
57  * . . .
58  * // write the document content
59  * document.writeTo(getOutputStream());
60  *
61  * //close the document
62  * document.close();
63  * </pre>
64  */
65 public class PrintedPdfDocument extends PdfDocument {
66     private static final int MILS_PER_INCH = 1000;
67     private static final int POINTS_IN_INCH = 72;
68 
69     private final int mPageWidth;
70     private final int mPageHeight;
71     private final Rect mContentRect;
72 
73     /**
74      * Creates a new document.
75      * <p>
76      * <strong>Note:</strong> You must close the document after you are
77      * done by calling {@link #close()}.
78      * </p>
79      *
80      * @param context Context instance for accessing resources.
81      * @param attributes The print attributes.
82      */
PrintedPdfDocument(@onNull Context context, @NonNull PrintAttributes attributes)83     public PrintedPdfDocument(@NonNull Context context, @NonNull PrintAttributes attributes) {
84         MediaSize mediaSize = attributes.getMediaSize();
85 
86         // Compute the size of the target canvas from the attributes.
87         mPageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH)
88                 * POINTS_IN_INCH);
89         mPageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH)
90                 * POINTS_IN_INCH);
91 
92         // Compute the content size from the attributes.
93         Margins minMargins = attributes.getMinMargins();
94         final int marginLeft = (int) (((float) minMargins.getLeftMils() / MILS_PER_INCH)
95                 * POINTS_IN_INCH);
96         final int marginTop = (int) (((float) minMargins.getTopMils() / MILS_PER_INCH)
97                 * POINTS_IN_INCH);
98         final int marginRight = (int) (((float) minMargins.getRightMils() / MILS_PER_INCH)
99                 * POINTS_IN_INCH);
100         final int marginBottom = (int) (((float) minMargins.getBottomMils() / MILS_PER_INCH)
101                 * POINTS_IN_INCH);
102         mContentRect = new Rect(marginLeft, marginTop, mPageWidth - marginRight,
103                 mPageHeight - marginBottom);
104     }
105 
106     /**
107      * Starts a new page. The page is created using width, height and content rectangle computed
108      * from the print attributes passed in the constructor and the given page number to create an
109      * appropriate {@link android.graphics.pdf.PdfDocument.PageInfo PageInfo}.
110      * <p>
111      * After the page is created you can draw arbitrary content on the page's canvas which you can
112      * get by calling {@link android.graphics.pdf.PdfDocument.Page#getCanvas() Page.getCanvas()}.
113      * After you are done drawing the content you should finish the page by calling
114      * {@link #finishPage(Page)}. After the page is finished you should no longer access the page or
115      * its canvas.
116      * </p>
117      * <p>
118      * <strong>Note:</strong> Do not call this method after {@link #close()}. Also do not call this
119      * method if the last page returned by this method is not finished by calling
120      * {@link #finishPage(Page)}.
121      * </p>
122      *
123      * @param pageNumber The page number. Must be a non negative.
124      * @return A blank page.
125      *
126      * @see #finishPage(Page)
127      */
startPage(@ntRangefrom = 0) int pageNumber)128     public @NonNull Page startPage(@IntRange(from = 0) int pageNumber) {
129         PageInfo pageInfo = new PageInfo
130                 .Builder(mPageWidth, mPageHeight, pageNumber)
131                 .setContentRect(mContentRect)
132                 .create();
133         return startPage(pageInfo);
134     }
135 
136     /**
137      * Gets the page width.
138      *
139      * @return The page width in PostScript points (1/72th of an inch).
140      */
getPageWidth()141     public @IntRange(from = 0) int getPageWidth() {
142         return mPageWidth;
143     }
144 
145     /**
146      * Gets the page height.
147      *
148      * @return The page height in PostScript points (1/72th of an inch).
149      */
getPageHeight()150     public @IntRange(from = 0) int getPageHeight() {
151         return mPageHeight;
152     }
153 
154     /**
155      * Gets the content rectangle. This is the area of the page that
156      * contains printed data and is relative to the page top left.
157      *
158      * @return The content rectangle.
159      */
getPageContentRect()160     public @NonNull Rect getPageContentRect() {
161         return mContentRect;
162     }
163 }
164