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