PdfDocument.cpp revision ed6b9dff563c5e22f040ff37e12c0d771e0478ae
1ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov/* 2ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * Copyright (C) 2013 The Android Open Source Project 3ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * 4ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 5ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * you may not use this file except in compliance with the License. 6ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * You may obtain a copy of the License at 7ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * 8ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 9ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * 10ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * Unless required by applicable law or agreed to in writing, software 11ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 12ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * See the License for the specific language governing permissions and 14ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov * limitations under the License. 15ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov */ 16ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 17ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov#include "jni.h" 18ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov#include "GraphicsJNI.h" 19ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 2035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include <vector> 2135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 228872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger#include "Canvas.h" 2335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "CreateJavaOutputStreamAdaptor.h" 24ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 2535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "SkDocument.h" 2635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "SkPicture.h" 27b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips#include "SkPictureRecorder.h" 2835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "SkStream.h" 29ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov#include "SkRect.h" 30ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 31ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganovnamespace android { 32ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 3335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavstruct PageRecord { 346811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav 3535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord(int width, int height, const SkRect& contentRect) 36b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips : mPictureRecorder(new SkPictureRecorder()) 37b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips , mPicture(NULL) 38b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips , mWidth(width) 39b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips , mHeight(height) { 4035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mContentRect = contentRect; 4135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 42ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 4335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav ~PageRecord() { 44b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips delete mPictureRecorder; 45b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips if (NULL != mPicture) { 46b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips mPicture->unref(); 47b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips } 4835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 49ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 50b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips SkPictureRecorder* mPictureRecorder; 51b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips SkPicture* mPicture; 5235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav const int mWidth; 5335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav const int mHeight; 5435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkRect mContentRect; 5535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav}; 5635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 5735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavclass PdfDocument { 5835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavpublic: 5935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument() { 6035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mCurrentPage = NULL; 6135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 6235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 6335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkCanvas* startPage(int width, int height, 6435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav int contentLeft, int contentTop, int contentRight, int contentBottom) { 6535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav assert(mCurrentPage == NULL); 6635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 6735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkRect contentRect = SkRect::MakeLTRB( 6835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav contentLeft, contentTop, contentRight, contentBottom); 6935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord* page = new PageRecord(width, height, contentRect); 7035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mPages.push_back(page); 7135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mCurrentPage = page; 7235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 73b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips SkCanvas* canvas = page->mPictureRecorder->beginRecording( 74b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips contentRect.width(), contentRect.height(), NULL, 0); 7535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 7635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav // We pass this canvas to Java where it is used to construct 7735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav // a Java Canvas object which dereferences the pointer when it 7835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav // is destroyed, so we have to bump up the reference count. 7935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav canvas->ref(); 8035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 8135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav return canvas; 8235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 83ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 8435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav void finishPage() { 8535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav assert(mCurrentPage != NULL); 86b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips assert(mCurrentPage->mPictureRecorder != NULL); 87b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips assert(mCurrentPage->mPicture == NULL); 88b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->endRecording(); 89b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips delete mCurrentPage->mPictureRecorder; 90b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips mCurrentPage->mPictureRecorder = NULL; 9135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mCurrentPage = NULL; 9235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 93ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 9435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav void write(SkWStream* stream) { 9535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkDocument* document = SkDocument::CreatePDF(stream); 9635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav for (unsigned i = 0; i < mPages.size(); i++) { 9735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord* page = mPages[i]; 98ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 9935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight, 10035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav &(page->mContentRect)); 10135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 10235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav canvas->clipRect(page->mContentRect); 10335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav canvas->translate(page->mContentRect.left(), page->mContentRect.top()); 104b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips canvas->drawPicture(page->mPicture); 10535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 10635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->endPage(); 10735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 10835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->close(); 10935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 11035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 11135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav void close() { 112b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips assert(NULL == mCurrentPage); 11335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav for (unsigned i = 0; i < mPages.size(); i++) { 11435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav delete mPages[i]; 11535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 11635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 11735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 11835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavprivate: 11935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav ~PdfDocument() { 12035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav close(); 12135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 12235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 12335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav std::vector<PageRecord*> mPages; 12435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord* mCurrentPage; 12535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav}; 12635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 127cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic jlong nativeCreateDocument(JNIEnv* env, jobject thiz) { 128cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat return reinterpret_cast<jlong>(new PdfDocument()); 12935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav} 13035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 131cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr, 13235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav jint pageWidth, jint pageHeight, 13335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) { 13435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 1358872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger SkCanvas* canvas = document->startPage(pageWidth, pageHeight, 1368872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger contentLeft, contentTop, contentRight, contentBottom); 1378872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger return reinterpret_cast<jlong>(Canvas::create_canvas(canvas)); 138ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 139ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 140cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) { 14135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 14235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->finishPage(); 143ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 144ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 145cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out, 14635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav jbyteArray chunk) { 14735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 148ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk); 14935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->write(skWStream); 150ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov delete skWStream; 151ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 152ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 153cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) { 15435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 15535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->close(); 15635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav} 15735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 158ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganovstatic JNINativeMethod gPdfDocument_Methods[] = { 159cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeCreateDocument", "()J", (void*) nativeCreateDocument}, 160cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage}, 161cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeFinishPage", "(J)V", (void*) nativeFinishPage}, 162cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo}, 163cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeClose", "(J)V", (void*) nativeClose} 164ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov}; 165ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 1666811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavint register_android_graphics_pdf_PdfDocument(JNIEnv* env) { 167ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie( 1686811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods, 169ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov NELEM(gPdfDocument_Methods)); 170ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 171ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 172ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov}; 173