PdfDocument.cpp revision 424784d60e475cd1ce1d8168491f07a23f213109
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 "core_jni_helpers.h" 20#include <vector> 21 22#include "CreateJavaOutputStreamAdaptor.h" 23 24#include "SkDocument.h" 25#include "SkPicture.h" 26#include "SkPictureRecorder.h" 27#include "SkStream.h" 28#include "SkRect.h" 29 30#include <hwui/Canvas.h> 31 32namespace android { 33 34struct PageRecord { 35 36 PageRecord(int width, int height, const SkRect& contentRect) 37 : mPictureRecorder(new SkPictureRecorder()) 38 , mPicture(NULL) 39 , mWidth(width) 40 , mHeight(height) { 41 mContentRect = contentRect; 42 } 43 44 ~PageRecord() { 45 delete mPictureRecorder; 46 if (NULL != mPicture) { 47 mPicture->unref(); 48 } 49 } 50 51 SkPictureRecorder* mPictureRecorder; 52 SkPicture* mPicture; 53 const int mWidth; 54 const int mHeight; 55 SkRect mContentRect; 56}; 57 58class PdfDocument { 59public: 60 PdfDocument() { 61 mCurrentPage = NULL; 62 } 63 64 SkCanvas* startPage(int width, int height, 65 int contentLeft, int contentTop, int contentRight, int contentBottom) { 66 assert(mCurrentPage == NULL); 67 68 SkRect contentRect = SkRect::MakeLTRB( 69 contentLeft, contentTop, contentRight, contentBottom); 70 PageRecord* page = new PageRecord(width, height, contentRect); 71 mPages.push_back(page); 72 mCurrentPage = page; 73 74 SkCanvas* canvas = page->mPictureRecorder->beginRecording( 75 SkRect::MakeWH(contentRect.width(), contentRect.height())); 76 77 return canvas; 78 } 79 80 void finishPage() { 81 assert(mCurrentPage != NULL); 82 assert(mCurrentPage->mPictureRecorder != NULL); 83 assert(mCurrentPage->mPicture == NULL); 84 mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->endRecording(); 85 delete mCurrentPage->mPictureRecorder; 86 mCurrentPage->mPictureRecorder = NULL; 87 mCurrentPage = NULL; 88 } 89 90 void write(SkWStream* stream) { 91 SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(stream)); 92 for (unsigned i = 0; i < mPages.size(); i++) { 93 PageRecord* page = mPages[i]; 94 95 SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight, 96 &(page->mContentRect)); 97 98 canvas->drawPicture(page->mPicture); 99 100 document->endPage(); 101 } 102 document->close(); 103 } 104 105 void close() { 106 assert(NULL == mCurrentPage); 107 for (unsigned i = 0; i < mPages.size(); i++) { 108 delete mPages[i]; 109 } 110 } 111 112private: 113 ~PdfDocument() { 114 close(); 115 } 116 117 std::vector<PageRecord*> mPages; 118 PageRecord* mCurrentPage; 119}; 120 121static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) { 122 return reinterpret_cast<jlong>(new PdfDocument()); 123} 124 125static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr, 126 jint pageWidth, jint pageHeight, 127 jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) { 128 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 129 SkCanvas* canvas = document->startPage(pageWidth, pageHeight, 130 contentLeft, contentTop, contentRight, contentBottom); 131 return reinterpret_cast<jlong>(Canvas::create_canvas(canvas)); 132} 133 134static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) { 135 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 136 document->finishPage(); 137} 138 139static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out, 140 jbyteArray chunk) { 141 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 142 SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk); 143 document->write(skWStream); 144 delete skWStream; 145} 146 147static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) { 148 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); 149 document->close(); 150} 151 152static const JNINativeMethod gPdfDocument_Methods[] = { 153 {"nativeCreateDocument", "()J", (void*) nativeCreateDocument}, 154 {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage}, 155 {"nativeFinishPage", "(J)V", (void*) nativeFinishPage}, 156 {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo}, 157 {"nativeClose", "(J)V", (void*) nativeClose} 158}; 159 160int register_android_graphics_pdf_PdfDocument(JNIEnv* env) { 161 return RegisterMethodsOrDie( 162 env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods, 163 NELEM(gPdfDocument_Methods)); 164} 165 166}; 167