PdfDocument.cpp revision cdf34469b3a49b73ffa4ab2766b55d7c0946fab1
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "jni.h" 18#include "GraphicsJNI.h" 19#include <android_runtime/AndroidRuntime.h> 20#include <vector> 21 22#include "CreateJavaOutputStreamAdaptor.h" 23 24#include "SkCanvas.h" 25#include "SkDocument.h" 26#include "SkPicture.h" 27#include "SkStream.h" 28#include "SkRect.h" 29 30namespace android { 31 32struct PageRecord { 33 34 PageRecord(int width, int height, const SkRect& contentRect) 35 : mPicture(new SkPicture()), mWidth(width), mHeight(height) { 36 mContentRect = contentRect; 37 } 38 39 ~PageRecord() { 40 mPicture->unref(); 41 } 42 43 SkPicture* const mPicture; 44 const int mWidth; 45 const int mHeight; 46 SkRect mContentRect; 47}; 48 49class PdfDocument { 50public: 51 PdfDocument() { 52 mCurrentPage = NULL; 53 } 54 55 SkCanvas* startPage(int width, int height, 56 int contentLeft, int contentTop, int contentRight, int contentBottom) { 57 assert(mCurrentPage == NULL); 58 59 SkRect contentRect = SkRect::MakeLTRB( 60 contentLeft, contentTop, contentRight, contentBottom); 61 PageRecord* page = new PageRecord(width, height, contentRect); 62 mPages.push_back(page); 63 mCurrentPage = page; 64 65 SkCanvas* canvas = page->mPicture->beginRecording( 66 contentRect.width(), contentRect.height(), 0); 67 68 // We pass this canvas to Java where it is used to construct 69 // a Java Canvas object which dereferences the pointer when it 70 // is destroyed, so we have to bump up the reference count. 71 canvas->ref(); 72 73 return canvas; 74 } 75 76 void finishPage() { 77 assert(mCurrentPage != NULL); 78 mCurrentPage->mPicture->endRecording(); 79 mCurrentPage = NULL; 80 } 81 82 void write(SkWStream* stream) { 83 SkDocument* document = SkDocument::CreatePDF(stream); 84 for (unsigned i = 0; i < mPages.size(); i++) { 85 PageRecord* page = mPages[i]; 86 87 SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight, 88 &(page->mContentRect)); 89 90 canvas->clipRect(page->mContentRect); 91 canvas->translate(page->mContentRect.left(), page->mContentRect.top()); 92 canvas->drawPicture(*page->mPicture); 93 94 document->endPage(); 95 } 96 document->close(); 97 } 98 99 void close() { 100 for (unsigned i = 0; i < mPages.size(); i++) { 101 delete mPages[i]; 102 } 103 delete mCurrentPage; 104 mCurrentPage = NULL; 105 } 106 107private: 108 ~PdfDocument() { 109 close(); 110 } 111 112 std::vector<PageRecord*> mPages; 113 PageRecord* mCurrentPage; 114}; 115 116static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) { 117 return reinterpret_cast<jlong>(new PdfDocument()); 118} 119 120static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr, 121 jint pageWidth, jint pageHeight, 122 jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) { 123 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 124 return reinterpret_cast<jlong>(document->startPage(pageWidth, pageHeight, 125 contentLeft, contentTop, contentRight, contentBottom)); 126} 127 128static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) { 129 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 130 document->finishPage(); 131} 132 133static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out, 134 jbyteArray chunk) { 135 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 136 SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk); 137 document->write(skWStream); 138 delete skWStream; 139} 140 141static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) { 142 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 143 document->close(); 144} 145 146static JNINativeMethod gPdfDocument_Methods[] = { 147 {"nativeCreateDocument", "()J", (void*) nativeCreateDocument}, 148 {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage}, 149 {"nativeFinishPage", "(J)V", (void*) nativeFinishPage}, 150 {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo}, 151 {"nativeClose", "(J)V", (void*) nativeClose} 152}; 153 154int register_android_graphics_pdf_PdfDocument(JNIEnv* env) { 155 int result = android::AndroidRuntime::registerNativeMethods( 156 env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods, 157 NELEM(gPdfDocument_Methods)); 158 return result; 159} 160 161}; 162