diff options
author | Svetoslav <svetoslavganov@google.com> | 2013-09-18 15:58:28 -0700 |
---|---|---|
committer | Svetoslav <svetoslavganov@google.com> | 2013-09-19 17:12:47 -0700 |
commit | 6811f4e92cbb64e72a0d13eb9b99b5894bd59c76 (patch) | |
tree | 5b0ebddf52a449b1ea84d91d6313e897a03e2b3e /graphics | |
parent | f95c9aa7e1229963a4cb92eed46eafc205b03cb3 (diff) | |
download | frameworks_base-6811f4e92cbb64e72a0d13eb9b99b5894bd59c76.zip frameworks_base-6811f4e92cbb64e72a0d13eb9b99b5894bd59c76.tar.gz frameworks_base-6811f4e92cbb64e72a0d13eb9b99b5894bd59c76.tar.bz2 |
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
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/java/android/graphics/pdf/PdfDocument.java | 424 | ||||
-rw-r--r-- | graphics/java/android/graphics/pdf/package.html | 5 |
2 files changed, 429 insertions, 0 deletions
diff --git a/graphics/java/android/graphics/pdf/PdfDocument.java b/graphics/java/android/graphics/pdf/PdfDocument.java new file mode 100644 index 0000000..066ae2b --- /dev/null +++ b/graphics/java/android/graphics/pdf/PdfDocument.java @@ -0,0 +1,424 @@ +/* + * 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.graphics.pdf; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Rect; + +import dalvik.system.CloseGuard; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * <p> + * 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. Note that pages are + * created one by one, i.e. you can have only a single page to which you are + * writing at any given time. This class is not thread safe. + * </p> + * <p> + * A typical use of the APIs looks like this: + * </p> + * <pre> + * // create a new document + * PdfDocument document = new PdfDocument(); + * + * // 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(); + * </pre> + */ +public class PdfDocument { + + private final byte[] mChunk = new byte[4096]; + + private final CloseGuard mCloseGuard = CloseGuard.get(); + + private final List<PageInfo> mPages = new ArrayList<PageInfo>(); + + private int mNativeDocument; + + private Page mCurrentPage; + + /** + * Creates a new instance. + */ + public 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. + * <p> + * <strong>Note:</strong> 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)}. + * </p> + * + * @param pageInfo The page info. Cannot be null. + * @return A blank page. + * + * @see #finishPage(Page) + */ + public Page startPage(PageInfo pageInfo) { + throwIfClosed(); + throwIfCurrentPageNotFinished(); + if (pageInfo == null) { + throw new IllegalArgumentException("page cannot be null"); + } + Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageWidth, + pageInfo.mPageHeight, pageInfo.mContentRect.left, pageInfo.mContentRect.top, + pageInfo.mContentRect.right, pageInfo.mContentRect.bottom)); + mCurrentPage = new Page(canvas, pageInfo); + return mCurrentPage; + } + + /** + * Finishes a started page. You should always finish the last started page. + * <p> + * <strong>Note:</strong> Do not call this method after {@link #close()}. + * You should not finish the same page more than once. + * </p> + * + * @param page The page. Cannot be null. + * + * @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"); + } + if (page.isFinished()) { + throw new IllegalStateException("page already finished"); + } + mPages.add(page.getInfo()); + mCurrentPage = null; + nativeAppendPage(mNativeDocument, page.mCanvas.mNativeCanvas); + page.finish(); + } + + /** + * Writes the document to an output stream. You can call this method + * multiple times. + * <p> + * <strong>Note:</strong> Do not call this method after {@link #close()}. + * Also do not call this method if a page returned by {@link #startPage( + * PageInfo)} is not finished by calling {@link #finishPage(Page)}. + * </p> + * + * @param out The output stream. Cannot be null. + * + * @throws IOException If an error occurs while writing. + */ + public void writeTo(OutputStream out) throws IOException { + throwIfClosed(); + throwIfCurrentPageNotFinished(); + if (out == null) { + throw new IllegalArgumentException("out cannot be null!"); + } + nativeWriteTo(mNativeDocument, out, mChunk); + } + + /** + * Gets the pages of the document. + * + * @return The pages or an empty list. + */ + public List<PageInfo> 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. + * <p> + * <strong>Note:</strong> Do not call this method if the page + * returned by {@link #startPage(PageInfo)} is not finished by + * calling {@link #finishPage(Page)}. + * </p> + */ + public void close() { + throwIfCurrentPageNotFinished(); + 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!"); + } + } + + /** + * Throws an exception if the last started page is not finished. + */ + private void throwIfCurrentPageNotFinished() { + if (mCurrentPage != null) { + throw new IllegalStateException("Current page not finished!"); + } + } + + 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(int pageWidth, int pageHeight, int contentLeft, + int contentTop, int contentRight, int contentBottom); + + 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 int mPageWidth; + private int mPageHeight; + private Rect mContentRect; + private int mPageNumber; + + /** + * Creates a new instance. + */ + private PageInfo() { + /* do nothing */ + } + + /** + * Gets the page width in PostScript points (1/72th of an inch). + * + * @return The page width. + */ + public int getPageWidth() { + return mPageWidth; + } + + /** + * Gets the page height in PostScript points (1/72th of an inch). + * + * @return The page height. + */ + public int getPageHeight() { + return mPageHeight; + } + + /** + * Get the content rectangle in PostScript points (1/72th of an inch). + * This is the area that contains the page content and is relative to + * the page top left. + * + * @return The content rectangle. + */ + public Rect getContentRect() { + return mContentRect; + } + + /** + * 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 pageWidth The page width in PostScript (1/72th of an inch). + * @param pageHeight The page height in PostScript (1/72th of an inch). + * @param pageNumber The page number. + */ + public Builder(int pageWidth, int pageHeight, int pageNumber) { + if (pageWidth <= 0) { + throw new IllegalArgumentException("page width must be positive"); + } + if (pageHeight <= 0) { + throw new IllegalArgumentException("page width must be positive"); + } + if (pageNumber < 0) { + throw new IllegalArgumentException("pageNumber must be non negative"); + } + mPageInfo.mPageWidth = pageWidth; + mPageInfo.mPageHeight = pageHeight; + mPageInfo.mPageNumber = pageNumber; + } + + /** + * Sets the content rectangle in PostScript point (1/72th of an inch). + * This is the area that contains the page content and is relative to + * the page top left. + * + * @param contentRect The content rectangle. Must fit in the page. + */ + public Builder setContentRect(Rect contentRect) { + if (contentRect != null && (contentRect.left < 0 + || contentRect.top < 0 + || contentRect.right > mPageInfo.mPageWidth + || contentRect.bottom > mPageInfo.mPageHeight)) { + throw new IllegalArgumentException("contentRect does not fit the page"); + } + mPageInfo.mContentRect = contentRect; + return this; + } + + /** + * Creates a new {@link PageInfo}. + * + * @return The new instance. + */ + public PageInfo create() { + if (mPageInfo.mContentRect == null) { + mPageInfo.mContentRect = new Rect(0, 0, + mPageInfo.mPageWidth, mPageInfo.mPageHeight); + } + 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. Also + * a page has + */ + 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; + } + + boolean isFinished() { + return mCanvas == null; + } + + private void finish() { + if (mCanvas != null) { + mCanvas.release(); + mCanvas = null; + } + } + } +} diff --git a/graphics/java/android/graphics/pdf/package.html b/graphics/java/android/graphics/pdf/package.html new file mode 100644 index 0000000..51f2460 --- /dev/null +++ b/graphics/java/android/graphics/pdf/package.html @@ -0,0 +1,5 @@ +<HTML> +<BODY> +Contains classes for manipulation of PDF content. +</BODY> +</HTML>
\ No newline at end of file |