From 6811f4e92cbb64e72a0d13eb9b99b5894bd59c76 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Wed, 18 Sep 2013 15:58:28 -0700 Subject: Move PdfDocument to android.graphics.pdf 1. Move PdfDocument to android.graphics.pdf. 2. Changed the PdfDocument as per API concil request. 3. Updated the documentation. bug:10461180 bug:10552565 bug:10681585 bug:10552336 Change-Id: I08e15b34cf37bb064248c887e6f59808019cafe8 --- core/java/android/print/PrintDocumentAdapter.java | 10 +- core/java/android/print/pdf/PdfDocument.java | 416 --------------------- .../java/android/print/pdf/PrintedPdfDocument.java | 147 ++++---- core/java/android/printservice/package.html | 4 +- 4 files changed, 80 insertions(+), 497 deletions(-) delete mode 100644 core/java/android/print/pdf/PdfDocument.java (limited to 'core/java/android') diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java index 8ac34c1..4113ac7 100644 --- a/core/java/android/print/PrintDocumentAdapter.java +++ b/core/java/android/print/PrintDocumentAdapter.java @@ -74,10 +74,10 @@ import android.os.ParcelFileDescriptor; public abstract class PrintDocumentAdapter { /** - * Meta-data key: mapped to a boolean value that is true if + * Extra: mapped to a boolean value that is true if * the current layout is for a print preview, false otherwise. */ - public static final String METADATA_KEY_PRINT_PREVIEW = "KEY_METADATA_PRINT_PREVIEW"; + public static final String EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW"; /** * Called when printing starts. You can use this callback to allocate @@ -112,15 +112,15 @@ public abstract class PrintDocumentAdapter { * @param newAttributes The new print attributes. * @param cancellationSignal Signal for observing cancel layout requests. * @param callback Callback to inform the system for the layout result. - * @param metadata Additional information about how layout the content. + * @param extras Additional information about how to layout the content. * * @see LayoutResultCallback * @see CancellationSignal - * @see #METADATA_KEY_PRINT_PREVIEW + * @see #EXTRA_PRINT_PREVIEW */ public abstract void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, - Bundle metadata); + Bundle extras); /** * Called when specific pages of the content should be written in the diff --git a/core/java/android/print/pdf/PdfDocument.java b/core/java/android/print/pdf/PdfDocument.java deleted file mode 100644 index a2883cf..0000000 --- a/core/java/android/print/pdf/PdfDocument.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed 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 android.print.pdf; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; - -import dalvik.system.CloseGuard; - -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - *

- * This class enables generating a PDF document from native Android content. You - * open a new document and then for every page you want to add you start a page, - * write content to the page, and finish the page. After you are done with all - * pages, you write the document to an output stream and close the document. - * After a document is closed you should not use it anymore. - *

- *

- * A typical use of the APIs looks like this: - *

- *
- * // open a new document
- * PdfDocument document = PdfDocument.open();
- *
- * // crate a page description
- * PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1).create();
- *
- * // start a page
- * Page page = document.startPage(pageInfo);
- *
- * // draw something on the page
- * View content = getContentView();
- * content.draw(page.getCanvas());
- *
- * // finish the page
- * document.finishPage(page);
- * . . .
- * // add more pages
- * . . .
- * // write the document content
- * document.writeTo(getOutputStream());
- *
- * //close the document
- * document.close();
- * 
- */ -public final class PdfDocument { - - private final byte[] mChunk = new byte[4096]; - - private final CloseGuard mCloseGuard = CloseGuard.get(); - - private final List mPages = new ArrayList(); - - private int mNativeDocument; - - private Page mCurrentPage; - - /** - * Opens a new document. - *

- * Note: You must close the document after you are - * done by calling {@link #close()} - *

- * - * @return The document. - * - * @see #close() - */ - public static PdfDocument open() { - return new PdfDocument(); - } - - /** - * Creates a new instance. - */ - private PdfDocument() { - mNativeDocument = nativeCreateDocument(); - mCloseGuard.open("close"); - } - - /** - * Starts a page using the provided {@link PageInfo}. After the page - * is created you can draw arbitrary content on the page's canvas which - * you can get by calling {@link Page#getCanvas()}. After you are done - * drawing the content you should finish the page by calling - * {@link #finishPage(Page)}. After the page is finished you should - * no longer access the page or its canvas. - *

- * Note: Do not call this method after {@link #close()}. - *

- * - * @param pageInfo The page info. - * @return A blank page. - * - * @see #finishPage(Page) - */ - public Page startPage(PageInfo pageInfo) { - throwIfClosed(); - if (pageInfo == null) { - throw new IllegalArgumentException("page cannot be null!"); - } - if (mCurrentPage != null) { - throw new IllegalStateException("Previous page not finished!"); - } - Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageSize, - pageInfo.mContentSize, pageInfo.mInitialTransform.native_instance)); - mCurrentPage = new Page(canvas, pageInfo); - return mCurrentPage; - } - - /** - * Finishes a started page. You should always finish the last started page. - *

- * Note: Do not call this method after {@link #close()}. - *

- * - * @param page The page. - * - * @see #startPage(PageInfo) - */ - public void finishPage(Page page) { - throwIfClosed(); - if (page == null) { - throw new IllegalArgumentException("page cannot be null"); - } - if (page != mCurrentPage) { - throw new IllegalStateException("invalid page"); - } - mPages.add(page.getInfo()); - mCurrentPage = null; - nativeAppendPage(mNativeDocument, page.mCanvas.mNativeCanvas); - page.finish(); - } - - /** - * Writes the document to an output stream. - *

- * Note: Do not call this method after {@link #close()}. - *

- * - * @param out The output stream. - */ - public void writeTo(OutputStream out) { - throwIfClosed(); - if (out == null) { - throw new IllegalArgumentException("out cannot be null!"); - } - nativeWriteTo(mNativeDocument, out, mChunk); - } - - /** - * Gets the pages of the document. - * - * @return The pages. - */ - public List getPages() { - return Collections.unmodifiableList(mPages); - } - - /** - * Closes this document. This method should be called after you - * are done working with the document. After this call the document - * is considered closed and none of its methods should be called. - */ - public void close() { - dispose(); - } - - @Override - protected void finalize() throws Throwable { - try { - mCloseGuard.warnIfOpen(); - dispose(); - } finally { - super.finalize(); - } - } - - private void dispose() { - if (mNativeDocument != 0) { - nativeFinalize(mNativeDocument); - mCloseGuard.close(); - mNativeDocument = 0; - } - } - - /** - * Throws an exception if the document is already closed. - */ - private void throwIfClosed() { - if (mNativeDocument == 0) { - throw new IllegalStateException("document is closed!"); - } - } - - private native int nativeCreateDocument(); - - private native void nativeFinalize(int document); - - private native void nativeAppendPage(int document, int page); - - private native void nativeWriteTo(int document, OutputStream out, byte[] chunk); - - private static native int nativeCreatePage(Rect pageSize, - Rect contentSize, int nativeMatrix); - - - private final class PdfCanvas extends Canvas { - - public PdfCanvas(int nativeCanvas) { - super(nativeCanvas); - } - - @Override - public void setBitmap(Bitmap bitmap) { - throw new UnsupportedOperationException(); - } - } - - /** - * This class represents meta-data that describes a PDF {@link Page}. - */ - public static final class PageInfo { - private Rect mPageSize; - private Rect mContentSize; - private Matrix mInitialTransform; - private int mPageNumber; - - /** - * Creates a new instance. - */ - private PageInfo() { - /* do nothing */ - } - - /** - * Gets the page size in PostScript points (1/72th of an inch). - * - * @return The page size. - */ - public Rect getPageSize() { - return mPageSize; - } - - /** - * Get the content size in PostScript points (1/72th of an inch). - * - * @return The content size. - */ - public Rect getContentSize() { - return mContentSize; - } - - /** - * Gets the initial transform which is applied to the page. This may be - * useful to move the origin to account for a margin, apply scale, or - * apply a rotation. - * - * @return The initial transform. - */ - public Matrix getInitialTransform() { - return mInitialTransform; - } - - /** - * Gets the page number. - * - * @return The page number. - */ - public int getPageNumber() { - return mPageNumber; - } - - /** - * Builder for creating a {@link PageInfo}. - */ - public static final class Builder { - private final PageInfo mPageInfo = new PageInfo(); - - /** - * Creates a new builder with the mandatory page info attributes. - * - * @param pageSize The page size in PostScript (1/72th of an inch). - * @param pageNumber The page number. - */ - public Builder(Rect pageSize, int pageNumber) { - if (pageSize.width() == 0 || pageSize.height() == 0) { - throw new IllegalArgumentException("page width and height" + - " must be greater than zero!"); - } - if (pageNumber < 0) { - throw new IllegalArgumentException("pageNumber cannot be less than zero!"); - } - mPageInfo.mPageSize = pageSize; - mPageInfo.mPageNumber = pageNumber; - } - - /** - * Sets the content size in PostScript point (1/72th of an inch). - * - * @param contentSize The content size. - */ - public Builder setContentSize(Rect contentSize) { - Rect pageSize = mPageInfo.mPageSize; - if (contentSize != null && (pageSize.left > contentSize.left - || pageSize.top > contentSize.top - || pageSize.right < contentSize.right - || pageSize.bottom < contentSize.bottom)) { - throw new IllegalArgumentException("contentSize does not fit the pageSize!"); - } - mPageInfo.mContentSize = contentSize; - return this; - } - - /** - * Sets the initial transform which is applied to the page. This may be - * useful to move the origin to account for a margin, apply scale, or - * apply a rotation. - * - * @param transform The initial transform. - */ - public Builder setInitialTransform(Matrix transform) { - mPageInfo.mInitialTransform = transform; - return this; - } - - /** - * Creates a new {@link PageInfo}. - * - * @return The new instance. - */ - public PageInfo create() { - if (mPageInfo.mContentSize == null) { - mPageInfo.mContentSize = mPageInfo.mPageSize; - } - if (mPageInfo.mInitialTransform == null) { - mPageInfo.mInitialTransform = new Matrix(); - } - return mPageInfo; - } - } - } - - /** - * This class represents a PDF document page. It has associated - * a canvas on which you can draw content and is acquired by a - * call to {@link #getCanvas()}. It also has associated a - * {@link PageInfo} instance that describes its attributes. - */ - public static final class Page { - private final PageInfo mPageInfo; - private Canvas mCanvas; - - /** - * Creates a new instance. - * - * @param canvas The canvas of the page. - * @param pageInfo The info with meta-data. - */ - private Page(Canvas canvas, PageInfo pageInfo) { - mCanvas = canvas; - mPageInfo = pageInfo; - } - - /** - * Gets the {@link Canvas} of the page. - * - * @return The canvas if the page is not finished, null otherwise. - * - * @see PdfDocument#finishPage(Page) - */ - public Canvas getCanvas() { - return mCanvas; - } - - /** - * Gets the {@link PageInfo} with meta-data for the page. - * - * @return The page info. - * - * @see PdfDocument#finishPage(Page) - */ - public PageInfo getInfo() { - return mPageInfo; - } - - private void finish() { - if (mCanvas != null) { - mCanvas.release(); - mCanvas = null; - } - } - } -} diff --git a/core/java/android/print/pdf/PrintedPdfDocument.java b/core/java/android/print/pdf/PrintedPdfDocument.java index 1fd4646..2d8aafa 100644 --- a/core/java/android/print/pdf/PrintedPdfDocument.java +++ b/core/java/android/print/pdf/PrintedPdfDocument.java @@ -18,67 +18,81 @@ package android.print.pdf; import android.content.Context; import android.graphics.Rect; +import android.graphics.pdf.PdfDocument; +import android.graphics.pdf.PdfDocument.Page; +import android.graphics.pdf.PdfDocument.PageInfo; import android.print.PrintAttributes; import android.print.PrintAttributes.Margins; import android.print.PrintAttributes.MediaSize; -import android.print.pdf.PdfDocument; -import android.print.pdf.PdfDocument.Page; -import android.print.pdf.PdfDocument.PageInfo; - -import java.io.OutputStream; -import java.util.List; /** - * This class is a helper for printing content to a different media - * size. This class is responsible for computing a correct page size - * given some print constraints, i.e. {@link PrintAttributes}. It is - * an adapter around a {@link PdfDocument}. + * This class is a helper for creating a PDF file for given print + * attributes. It is useful for implementing printing via the native + * Android graphics APIs. + *

+ * This class computes the page width, page height, and content rectangle + * from the provided print attributes and these precomputed values can be + * accessed via {@link #getPageWidth()}, {@link #getPageHeight()}, and + * {@link #getPageContentRect()}, respectively. The {@link #startPage(int)} + * methods creates pages whose {@link PageInfo} is initialized with the + * precomputed values for width, height, and content rectangle. + *

+ * A typical use of the APIs looks like this: + *

+ *
+ * // open a new document
+ * PrintedPdfDocument document = new PrintedPdfDocument(context,
+ *         printAttributes);
+ *
+ * // start a page
+ * Page page = document.startPage(0);
+ *
+ * // draw something on the page
+ * View content = getContentView();
+ * content.draw(page.getCanvas());
+ *
+ * // finish the page
+ * document.finishPage(page);
+ * . . .
+ * // add more pages
+ * . . .
+ * // write the document content
+ * document.writeTo(getOutputStream());
+ *
+ * //close the document
+ * document.close();
+ * 
*/ -public final class PrintedPdfDocument { +public class PrintedPdfDocument extends PdfDocument { private static final int MILS_PER_INCH = 1000; private static final int POINTS_IN_INCH = 72; - private final PdfDocument mDocument = PdfDocument.open(); - private final Rect mPageSize = new Rect(); - private final Rect mContentSize = new Rect(); + private final int mPageWidth; + private final int mPageHeight; + private final Rect mContentRect; /** - * Opens a new document. The document pages are computed based on - * the passes in {@link PrintAttributes}. + * Creates a new document. *

* Note: You must close the document after you are - * done by calling {@link #close()} + * done by calling {@link #close()}. *

* * @param context Context instance for accessing resources. * @param attributes The print attributes. - * @return The document. - * - * @see #close() - */ - public static PrintedPdfDocument open(Context context, PrintAttributes attributes) { - return new PrintedPdfDocument(context, attributes); - } - - /** - * Creates a new instance. - * - * @param context Context instance for accessing resources and services. - * @param attributes The {@link PrintAttributes} to user. */ - private PrintedPdfDocument(Context context, PrintAttributes attributes) { + public PrintedPdfDocument(Context context, PrintAttributes attributes) { MediaSize mediaSize = attributes.getMediaSize(); // Compute the size of the target canvas from the attributes. - final int pageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH) + mPageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH) * POINTS_IN_INCH); - final int pageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH) + mPageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH) * POINTS_IN_INCH); - mPageSize.set(0, 0, pageWidth, pageHeight); // Compute the content size from the attributes. Margins minMargins = attributes.getMinMargins(); - final int marginLeft = (int) (((float) minMargins.getLeftMils() /MILS_PER_INCH) + final int marginLeft = (int) (((float) minMargins.getLeftMils() / MILS_PER_INCH) * POINTS_IN_INCH); final int marginTop = (int) (((float) minMargins.getTopMils() / MILS_PER_INCH) * POINTS_IN_INCH); @@ -86,14 +100,14 @@ public final class PrintedPdfDocument { * POINTS_IN_INCH); final int marginBottom = (int) (((float) minMargins.getBottomMils() / MILS_PER_INCH) * POINTS_IN_INCH); - mContentSize.set(mPageSize.left + marginLeft, mPageSize.top + marginTop, - mPageSize.right - marginRight, mPageSize.bottom - marginBottom); + mContentRect = new Rect(marginLeft, marginTop, mPageWidth - marginRight, + mPageHeight - marginBottom); } /** - * Starts a page using a page size computed from the print attributes - * passed in {@link #open(Context, PrintAttributes)} and the given page - * number to create appropriate {@link PageInfo}. + * Starts a new page. The page is created using width, height and content + * rectangle computed from the print attributes passed in the constructor + * and the given page number to create an appropriate {@link PageInfo}. *

* After the page is created you can draw arbitrary content on the page's * canvas which you can get by calling {@link Page#getCanvas() Page.getCanvas()}. @@ -103,63 +117,48 @@ public final class PrintedPdfDocument { *

*

* Note: Do not call this method after {@link #close()}. + * Also do not call this method if the last page returned by this method + * is not finished by calling {@link #finishPage(Page)}. *

* - * @param pageNumber The page number. + * @param pageNumber The page number. Must be a positive value. * @return A blank page. * * @see #finishPage(Page) */ public Page startPage(int pageNumber) { PageInfo pageInfo = new PageInfo - .Builder(mPageSize, 0) - .setContentSize(mContentSize) + .Builder(mPageWidth, mPageHeight, pageNumber) + .setContentRect(mContentRect) .create(); - Page page = mDocument.startPage(pageInfo); - return page; + return startPage(pageInfo); } /** - * Finishes a started page. You should always finish the last started page. - *

- * Note: Do not call this method after {@link #close()}. - *

+ * Gets the page width. * - * @param page The page. - * - * @see #startPage(int) + * @return The page width in PostScript points (1/72th of an inch). */ - public void finishPage(Page page) { - mDocument.finishPage(page); + public int getPageWidth() { + return mPageWidth; } /** - * Writes the document to an output stream. - *

- * Note: Do not call this method after {@link #close()}. - *

+ * Gets the page height. * - * @param out The output stream. + * @return The page height in PostScript points (1/72th of an inch). */ - public void writeTo(OutputStream out) { - mDocument.writeTo(out); + public int getPageHeight() { + return mPageHeight; } /** - * Gets the pages of the document. + * Gets the content rectangle. This is the area of the page that + * contains printed data and is relative to the page top left. * - * @return The pages. - */ - public List getPages() { - return mDocument.getPages(); - } - - /** - * Closes this document. This method should be called after you - * are done working with the document. After this call the document - * is considered closed and none of its methods should be called. + * @return The content rectangle. */ - public void close() { - mDocument.close(); + public Rect getPageContentRect() { + return mContentRect; } } diff --git a/core/java/android/printservice/package.html b/core/java/android/printservice/package.html index 7410a49..2fb06bd 100644 --- a/core/java/android/printservice/package.html +++ b/core/java/android/printservice/package.html @@ -4,12 +4,12 @@ Provides classes for implementing print services. Print services are plug-in components that know how to talk to printers via some standard protocols. These services serve as a bridge between the system and the printers. Hence, the printer and print protocol specific -implementation is factored out of the system and can by independently developed and updated. +implementation is factored out of the system and can be independently developed and updated.

A print service implementation should extend {@link android.printservice.PrintService} and implement its abstract methods. Also the print service has to follow the contract for -managing print {@link android.printservice.PrintJob}s. +managing {@link android.printservice.PrintJob}s.

The system is responsible for starting and stopping a print service depending on whether -- cgit v1.1