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 19c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmannimport android.annotation.IntRange; 20c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmannimport android.annotation.NonNull; 21aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.content.Context; 22aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.graphics.Rect; 236811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavimport android.graphics.pdf.PdfDocument; 24aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.print.PrintAttributes; 25aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.print.PrintAttributes.Margins; 26aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganovimport android.print.PrintAttributes.MediaSize; 27aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 28aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov/** 29c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * This class is a helper for creating a PDF file for given print attributes. It is useful for 30c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * implementing printing via the native Android graphics APIs. 316811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * <p> 32c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * This class computes the page width, page height, and content rectangle from the provided print 33c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * attributes and these precomputed values can be accessed via {@link #getPageWidth()}, 34c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * {@link #getPageHeight()}, and {@link #getPageContentRect()}, respectively. The 35c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * {@link #startPage(int)} methods creates pages whose 36c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * {@link android.graphics.pdf.PdfDocument.PageInfo PageInfo} is initialized with the precomputed 37c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * values for width, height, and content rectangle. 386811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * <p> 396811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * A typical use of the APIs looks like this: 406811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * </p> 416811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * <pre> 426811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // open a new document 436811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * PrintedPdfDocument document = new PrintedPdfDocument(context, 446811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * printAttributes); 456811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * 466811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // start a page 476811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * Page page = document.startPage(0); 486811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * 496811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // draw something on the page 506811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * View content = getContentView(); 516811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * content.draw(page.getCanvas()); 526811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * 536811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // finish the page 546811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * document.finishPage(page); 556811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * . . . 566811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // add more pages 576811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * . . . 586811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * // write the document content 596811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * document.writeTo(getOutputStream()); 606811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * 616811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * //close the document 626811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * document.close(); 636811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * </pre> 64aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */ 656811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavpublic class PrintedPdfDocument extends PdfDocument { 66aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov private static final int MILS_PER_INCH = 1000; 67aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov private static final int POINTS_IN_INCH = 72; 68aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 696811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav private final int mPageWidth; 706811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav private final int mPageHeight; 716811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav private final Rect mContentRect; 72aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 73aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov /** 746811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * Creates a new document. 75aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * <p> 76aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * <strong>Note:</strong> You must close the document after you are 776811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * done by calling {@link #close()}. 78aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * </p> 79aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * 80aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * @param context Context instance for accessing resources. 81aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * @param attributes The print attributes. 82aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */ 83c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann public PrintedPdfDocument(@NonNull Context context, @NonNull PrintAttributes attributes) { 84aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov MediaSize mediaSize = attributes.getMediaSize(); 85aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 86aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov // Compute the size of the target canvas from the attributes. 876811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav mPageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH) 88aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * POINTS_IN_INCH); 896811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav mPageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH) 90aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * POINTS_IN_INCH); 91aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 92aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov // Compute the content size from the attributes. 93651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav Margins minMargins = attributes.getMinMargins(); 946811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav final int marginLeft = (int) (((float) minMargins.getLeftMils() / MILS_PER_INCH) 95aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * POINTS_IN_INCH); 96651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav final int marginTop = (int) (((float) minMargins.getTopMils() / MILS_PER_INCH) 97aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * POINTS_IN_INCH); 98651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav final int marginRight = (int) (((float) minMargins.getRightMils() / MILS_PER_INCH) 99aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * POINTS_IN_INCH); 100651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav final int marginBottom = (int) (((float) minMargins.getBottomMils() / MILS_PER_INCH) 101aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * POINTS_IN_INCH); 1026811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav mContentRect = new Rect(marginLeft, marginTop, mPageWidth - marginRight, 1036811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav mPageHeight - marginBottom); 104aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov } 105aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 106aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov /** 107c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * Starts a new page. The page is created using width, height and content rectangle computed 108c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * from the print attributes passed in the constructor and the given page number to create an 109c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * appropriate {@link android.graphics.pdf.PdfDocument.PageInfo PageInfo}. 110aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * <p> 111c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * After the page is created you can draw arbitrary content on the page's canvas which you can 112c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * get by calling {@link android.graphics.pdf.PdfDocument.Page#getCanvas() Page.getCanvas()}. 113aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * After you are done drawing the content you should finish the page by calling 114c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * {@link #finishPage(Page)}. After the page is finished you should no longer access the page or 115c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * its canvas. 116aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * </p> 117aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * <p> 118c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * <strong>Note:</strong> Do not call this method after {@link #close()}. Also do not call this 119c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * method if the last page returned by this method is not finished by calling 120c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * {@link #finishPage(Page)}. 121aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * </p> 122aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * 123c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * @param pageNumber The page number. Must be a non negative. 124aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * @return A blank page. 125aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * 126aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * @see #finishPage(Page) 127aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */ 128c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann public @NonNull Page startPage(@IntRange(from = 0) int pageNumber) { 129d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov PageInfo pageInfo = new PageInfo 1306811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav .Builder(mPageWidth, mPageHeight, pageNumber) 1316811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav .setContentRect(mContentRect) 132d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov .create(); 1336811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav return startPage(pageInfo); 134aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov } 135aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 136aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov /** 1376811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * Gets the page width. 138aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * 1396811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * @return The page width in PostScript points (1/72th of an inch). 140aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */ 141c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann public @IntRange(from = 0) int getPageWidth() { 1426811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav return mPageWidth; 143aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov } 144aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 145aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov /** 1466811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * Gets the page height. 147aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * 1486811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * @return The page height in PostScript points (1/72th of an inch). 149aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */ 150c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann public @IntRange(from = 0) int getPageHeight() { 1516811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav return mPageHeight; 152aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov } 153aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov 154aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov /** 1556811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * Gets the content rectangle. This is the area of the page that 1566811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * contains printed data and is relative to the page top left. 157aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov * 1586811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav * @return The content rectangle. 159aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov */ 160c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann public @NonNull Rect getPageContentRect() { 1616811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav return mContentRect; 162aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov } 163aec1417ca9eb63209668ac17da90cf8a07c6076cSvetoslav Ganov} 164