summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2013-11-08 00:20:10 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-11-08 00:20:10 +0000
commit90242fe5581c8f665c09337a0971a7c3fc908f7c (patch)
tree2cbcc6d5f5ec60c53ecd34f72036c00bce6c03e5
parente81f9755d914b5b87f18e5ed201a4903dc09baa6 (diff)
parent35aacf2eb325d24c67d01f4dbd706ed26ab9e8c3 (diff)
downloadframeworks_base-90242fe5581c8f665c09337a0971a7c3fc908f7c.zip
frameworks_base-90242fe5581c8f665c09337a0971a7c3fc908f7c.tar.gz
frameworks_base-90242fe5581c8f665c09337a0971a7c3fc908f7c.tar.bz2
Merge "Switch to the new Skia PDF generation APIs." into klp-dev
-rw-r--r--core/jni/android/graphics/pdf/PdfDocument.cpp144
-rw-r--r--graphics/java/android/graphics/pdf/PdfDocument.java47
2 files changed, 137 insertions, 54 deletions
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index b57a0fe..6175a8f 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -17,62 +17,138 @@
#include "jni.h"
#include "GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>
+#include <vector>
+
+#include "CreateJavaOutputStreamAdaptor.h"
#include "SkCanvas.h"
-#include "SkPDFDevice.h"
-#include "SkPDFDocument.h"
+#include "SkDocument.h"
+#include "SkPicture.h"
+#include "SkStream.h"
#include "SkRect.h"
-#include "SkSize.h"
-#include "CreateJavaOutputStreamAdaptor.h"
-#include "JNIHelp.h"
namespace android {
-#define LOGD(x...) do { Log::Instance()->printf(Log::ELogD, x); } while(0)
+struct PageRecord {
-static jint nativeCreateDocument(JNIEnv* env, jobject clazz) {
- return reinterpret_cast<jint>(new SkPDFDocument());
-}
+ PageRecord(int width, int height, const SkRect& contentRect)
+ : mPicture(new SkPicture()), mWidth(width), mHeight(height) {
+ mContentRect = contentRect;
+ }
-static void nativeFinalize(JNIEnv* env, jobject thiz, jint documentPtr) {
- delete reinterpret_cast<SkPDFDocument*>(documentPtr);
-}
+ ~PageRecord() {
+ mPicture->unref();
+ }
-static jint nativeCreatePage(JNIEnv* env, jobject thiz, jint pageWidth, jint pageHeight,
- jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
+ SkPicture* const mPicture;
+ const int mWidth;
+ const int mHeight;
+ SkRect mContentRect;
+};
+
+class PdfDocument {
+public:
+ PdfDocument() {
+ mCurrentPage = NULL;
+ }
+
+ SkCanvas* startPage(int width, int height,
+ int contentLeft, int contentTop, int contentRight, int contentBottom) {
+ assert(mCurrentPage == NULL);
+
+ SkRect contentRect = SkRect::MakeLTRB(
+ contentLeft, contentTop, contentRight, contentBottom);
+ PageRecord* page = new PageRecord(width, height, contentRect);
+ mPages.push_back(page);
+ mCurrentPage = page;
+
+ SkCanvas* canvas = page->mPicture->beginRecording(
+ contentRect.width(), contentRect.height(), 0);
+
+ // We pass this canvas to Java where it is used to construct
+ // a Java Canvas object which dereferences the pointer when it
+ // is destroyed, so we have to bump up the reference count.
+ canvas->ref();
+
+ return canvas;
+ }
- SkMatrix transformation;
- transformation.setTranslate(contentLeft, contentTop);
+ void finishPage() {
+ assert(mCurrentPage != NULL);
+ mCurrentPage->mPicture->endRecording();
+ mCurrentPage = NULL;
+ }
- SkISize skPageSize = SkISize::Make(pageWidth, pageHeight);
- SkISize skContentSize = SkISize::Make(contentRight - contentLeft, contentBottom - contentTop);
+ void write(SkWStream* stream) {
+ SkDocument* document = SkDocument::CreatePDF(stream);
+ for (unsigned i = 0; i < mPages.size(); i++) {
+ PageRecord* page = mPages[i];
- SkPDFDevice* skPdfDevice = new SkPDFDevice(skPageSize, skContentSize, transformation);
- return reinterpret_cast<jint>(new SkCanvas(skPdfDevice));
+ SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight,
+ &(page->mContentRect));
+
+ canvas->clipRect(page->mContentRect);
+ canvas->translate(page->mContentRect.left(), page->mContentRect.top());
+ canvas->drawPicture(*page->mPicture);
+
+ document->endPage();
+ }
+ document->close();
+ }
+
+ void close() {
+ for (unsigned i = 0; i < mPages.size(); i++) {
+ delete mPages[i];
+ }
+ delete mCurrentPage;
+ mCurrentPage = NULL;
+ }
+
+private:
+ ~PdfDocument() {
+ close();
+ }
+
+ std::vector<PageRecord*> mPages;
+ PageRecord* mCurrentPage;
+};
+
+static jint nativeCreateDocument(JNIEnv* env, jobject thiz) {
+ return reinterpret_cast<jint>(new PdfDocument());
+}
+
+static jint nativeStartPage(JNIEnv* env, jobject thiz, jint documentPtr,
+ jint pageWidth, jint pageHeight,
+ jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
+ PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
+ return reinterpret_cast<jint>(document->startPage(pageWidth, pageHeight,
+ contentLeft, contentTop, contentRight, contentBottom));
}
-static void nativeAppendPage(JNIEnv* env, jobject thiz, jint documentPtr, jint pagePtr) {
- SkCanvas* page = reinterpret_cast<SkCanvas*>(pagePtr);
- SkPDFDocument* document = reinterpret_cast<SkPDFDocument*>(documentPtr);
- SkPDFDevice* device = static_cast<SkPDFDevice*>(page->getDevice());
- document->appendPage(device);
+static void nativeFinishPage(JNIEnv* env, jobject thiz, jint documentPtr) {
+ PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
+ document->finishPage();
}
-static void nativeWriteTo(JNIEnv* env, jobject clazz, jint documentPtr,
- jobject out, jbyteArray chunk) {
+static void nativeWriteTo(JNIEnv* env, jobject thiz, jint documentPtr, jobject out,
+ jbyteArray chunk) {
+ PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
- SkPDFDocument* document = reinterpret_cast<SkPDFDocument*>(documentPtr);
- document->emitPDF(skWStream);
+ document->write(skWStream);
delete skWStream;
}
+static void nativeClose(JNIEnv* env, jobject thiz, jint documentPtr) {
+ PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
+ document->close();
+}
+
static JNINativeMethod gPdfDocument_Methods[] = {
{"nativeCreateDocument", "()I", (void*) nativeCreateDocument},
- {"nativeFinalize", "(I)V", (void*) nativeFinalize},
- {"nativeCreatePage", "(IIIIII)I",
- (void*) nativeCreatePage},
- {"nativeAppendPage", "(II)V", (void*) nativeAppendPage},
- {"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo}
+ {"nativeStartPage", "(IIIIIII)I", (void*) nativeStartPage},
+ {"nativeFinishPage", "(I)V", (void*) nativeFinishPage},
+ {"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
+ {"nativeClose", "(I)V", (void*) nativeClose}
};
int register_android_graphics_pdf_PdfDocument(JNIEnv* env) {
diff --git a/graphics/java/android/graphics/pdf/PdfDocument.java b/graphics/java/android/graphics/pdf/PdfDocument.java
index 81e523d..29d14a2 100644
--- a/graphics/java/android/graphics/pdf/PdfDocument.java
+++ b/graphics/java/android/graphics/pdf/PdfDocument.java
@@ -18,6 +18,7 @@ package android.graphics.pdf;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Rect;
import dalvik.system.CloseGuard;
@@ -69,6 +70,12 @@ import java.util.List;
*/
public class PdfDocument {
+ // TODO: We need a constructor that will take an OutputStream to
+ // support online data serialization as opposed to the current
+ // on demand one. The current approach is fine until Skia starts
+ // to support online PDF generation at which point we need to
+ // handle this.
+
private final byte[] mChunk = new byte[4096];
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -111,7 +118,7 @@ public class PdfDocument {
if (pageInfo == null) {
throw new IllegalArgumentException("page cannot be null");
}
- Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageWidth,
+ Canvas canvas = new PdfCanvas(nativeStartPage(mNativeDocument, pageInfo.mPageWidth,
pageInfo.mPageHeight, pageInfo.mContentRect.left, pageInfo.mContentRect.top,
pageInfo.mContentRect.right, pageInfo.mContentRect.bottom));
mCurrentPage = new Page(canvas, pageInfo);
@@ -142,7 +149,7 @@ public class PdfDocument {
}
mPages.add(page.getInfo());
mCurrentPage = null;
- nativeAppendPage(mNativeDocument, page.mCanvas.mNativeCanvas);
+ nativeFinishPage(mNativeDocument);
page.finish();
}
@@ -204,7 +211,7 @@ public class PdfDocument {
private void dispose() {
if (mNativeDocument != 0) {
- nativeFinalize(mNativeDocument);
+ nativeClose(mNativeDocument);
mCloseGuard.close();
mNativeDocument = 0;
}
@@ -230,14 +237,14 @@ public class PdfDocument {
private native int nativeCreateDocument();
- private native void nativeFinalize(int document);
+ private native void nativeClose(int document);
- private native void nativeAppendPage(int document, int page);
+ private native void nativeFinishPage(int document);
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 static native int nativeStartPage(int documentPtr, int pageWidth, int pageHeight,
+ int contentLeft, int contentTop, int contentRight, int contentBottom);
private final class PdfCanvas extends Canvas {
@@ -392,28 +399,28 @@ public class PdfDocument {
* Gets the {@link Canvas} of the page.
*
* <p>
- * <strong>Note: </strong> There are some draw operations that are
- * not yet supported by the canvas returned by this method. More
- * specifically:
+ * <strong>Note: </strong> There are some draw operations that are not yet
+ * supported by the canvas returned by this method. More specifically:
* <ul>
- * <li>{@link Canvas#clipPath(android.graphics.Path)
- * Canvas.clipPath(android.graphics.Path)}</li>
- * <li>All flavors of {@link Canvas#drawText(String, float, float,
- * android.graphics.Paint) Canvas.drawText(String, float, float,
- * android.graphics.Paint)}</li>
- * <li>All flavors of {@link Canvas#drawPosText(String, float[],
- * android.graphics.Paint) Canvas.drawPosText(String, float[],
- * android.graphics.Paint)}</li>
+ * <li>Inverse path clipping performed via {@link Canvas#clipPath(android.graphics.Path,
+ * android.graphics.Region.Op) Canvas.clipPath(android.graphics.Path,
+ * android.graphics.Region.Op)} for {@link
+ * android.graphics.Region.Op#REVERSE_DIFFERENCE
+ * Region.Op#REVERSE_DIFFERENCE} operations.</li>
* <li>{@link Canvas#drawVertices(android.graphics.Canvas.VertexMode, int,
* float[], int, float[], int, int[], int, short[], int, int,
* android.graphics.Paint) Canvas.drawVertices(
* android.graphics.Canvas.VertexMode, int, float[], int, float[],
* int, int[], int, short[], int, int, android.graphics.Paint)}</li>
- * <li>{@link android.graphics.PorterDuff.Mode#SRC_ATOP PorterDuff.Mode SRC},
+ * <li>Color filters set via {@link Paint#setColorFilter(
+ * android.graphics.ColorFilter)}</li>
+ * <li>Mask filters set via {@link Paint#setMaskFilter(
+ * android.graphics.MaskFilter)}</li>
+ * <li>Some XFER modes such as
+ * {@link android.graphics.PorterDuff.Mode#SRC_ATOP PorterDuff.Mode SRC},
* {@link android.graphics.PorterDuff.Mode#DST_ATOP PorterDuff.DST_ATOP},
* {@link android.graphics.PorterDuff.Mode#XOR PorterDuff.XOR},
* {@link android.graphics.PorterDuff.Mode#ADD PorterDuff.ADD}</li>
- * <li>Perspective transforms</li>
* </ul>
*
* @return The canvas if the page is not finished, null otherwise.