summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2013-09-18 15:58:28 -0700
committerSvetoslav <svetoslavganov@google.com>2013-09-19 17:12:47 -0700
commit6811f4e92cbb64e72a0d13eb9b99b5894bd59c76 (patch)
tree5b0ebddf52a449b1ea84d91d6313e897a03e2b3e /graphics
parentf95c9aa7e1229963a4cb92eed46eafc205b03cb3 (diff)
downloadframeworks_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.java424
-rw-r--r--graphics/java/android/graphics/pdf/package.html5
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