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 2235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "CreateJavaOutputStreamAdaptor.h" 23ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 2435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "SkDocument.h" 2535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "SkPicture.h" 26b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips#include "SkPictureRecorder.h" 2735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav#include "SkStream.h" 28ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov#include "SkRect.h" 29ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 30dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Canvas.h> 31dccca44ffda4836b56a21da95a046c9708ffd49csergeyv 32ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganovnamespace android { 33ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 3435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavstruct PageRecord { 356811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav 3635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord(int width, int height, const SkRect& contentRect) 37b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips : mPictureRecorder(new SkPictureRecorder()) 38b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips , mPicture(NULL) 39b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips , mWidth(width) 40b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips , mHeight(height) { 4135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mContentRect = contentRect; 4235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 43ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 4435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav ~PageRecord() { 45b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips delete mPictureRecorder; 46b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips if (NULL != mPicture) { 47b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips mPicture->unref(); 48b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips } 4935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 50ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 51b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips SkPictureRecorder* mPictureRecorder; 52b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips SkPicture* mPicture; 5335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav const int mWidth; 5435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav const int mHeight; 5535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkRect mContentRect; 5635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav}; 5735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 5835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavclass PdfDocument { 5935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavpublic: 6035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument() { 6135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mCurrentPage = NULL; 6235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 6335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 6435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkCanvas* startPage(int width, int height, 6535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav int contentLeft, int contentTop, int contentRight, int contentBottom) { 6635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav assert(mCurrentPage == NULL); 6735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 6835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkRect contentRect = SkRect::MakeLTRB( 6935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav contentLeft, contentTop, contentRight, contentBottom); 7035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord* page = new PageRecord(width, height, contentRect); 7135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mPages.push_back(page); 7235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mCurrentPage = page; 7335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 74b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips SkCanvas* canvas = page->mPictureRecorder->beginRecording( 7571487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed SkRect::MakeWH(contentRect.width(), contentRect.height())); 7635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 7735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav return canvas; 7835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 79ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 8035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav void finishPage() { 8135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav assert(mCurrentPage != NULL); 82b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips assert(mCurrentPage->mPictureRecorder != NULL); 83b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips assert(mCurrentPage->mPicture == NULL); 84b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->endRecording(); 85b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips delete mCurrentPage->mPictureRecorder; 86b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips mCurrentPage->mPictureRecorder = NULL; 8735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav mCurrentPage = NULL; 8835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 89ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 9035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav void write(SkWStream* stream) { 91424784d60e475cd1ce1d8168491f07a23f213109Hal Canary SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(stream)); 9235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav for (unsigned i = 0; i < mPages.size(); i++) { 9335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord* page = mPages[i]; 94ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 9535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight, 9635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav &(page->mContentRect)); 9735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 98b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips canvas->drawPicture(page->mPicture); 9935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 10035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->endPage(); 10135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 10235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->close(); 10335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 10435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 10535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav void close() { 106b59508fce51b23f0201f4dcba7e4f18bab4f9d1aRobert Phillips assert(NULL == mCurrentPage); 10735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav for (unsigned i = 0; i < mPages.size(); i++) { 10835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav delete mPages[i]; 10935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 11035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 11135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 11235aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslavprivate: 11335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav ~PdfDocument() { 11435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav close(); 11535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav } 11635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 11735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav std::vector<PageRecord*> mPages; 11835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PageRecord* mCurrentPage; 11935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav}; 12035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 121cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic jlong nativeCreateDocument(JNIEnv* env, jobject thiz) { 122cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat return reinterpret_cast<jlong>(new PdfDocument()); 12335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav} 12435aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 125cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr, 12635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav jint pageWidth, jint pageHeight, 12735aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) { 12835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 1298872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger SkCanvas* canvas = document->startPage(pageWidth, pageHeight, 1308872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger contentLeft, contentTop, contentRight, contentBottom); 1318872b38ef403cc2c44aca07d392f5e9426fd7f54Derek Sollenberger return reinterpret_cast<jlong>(Canvas::create_canvas(canvas)); 132ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 133ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 134cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) { 13535aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 13635aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->finishPage(); 137ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 138ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 139cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out, 14035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav jbyteArray chunk) { 14135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 142ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk); 14335aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->write(skWStream); 144ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov delete skWStream; 145ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 146ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 147cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhatstatic void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) { 14835aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 14935aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav document->close(); 15035aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav} 15135aacf2eb325d24c67d01f4dbd706ed26ab9e8c3Svetoslav 15276f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gPdfDocument_Methods[] = { 153cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeCreateDocument", "()J", (void*) nativeCreateDocument}, 154cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage}, 155cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeFinishPage", "(J)V", (void*) nativeFinishPage}, 156cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo}, 157cdf34469b3a49b73ffa4ab2766b55d7c0946fab1Ashok Bhat {"nativeClose", "(J)V", (void*) nativeClose} 158ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov}; 159ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 1606811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslavint register_android_graphics_pdf_PdfDocument(JNIEnv* env) { 161ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie( 1626811f4e92cbb64e72a0d13eb9b99b5894bd59c76Svetoslav env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods, 163ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov NELEM(gPdfDocument_Methods)); 164ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov} 165ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov 166ff4adde5737be08d3e2d03fbe588c591d27d4a74Svetoslav Ganov}; 167