/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "GraphicsJNI.h" #include #include "CreateJavaOutputStreamAdaptor.h" #include "SkPDFDocument.h" #include "SkPicture.h" #include "SkPictureRecorder.h" #include "SkRect.h" #include "SkStream.h" #include namespace android { struct PageRecord { PageRecord(int width, int height, const SkRect& contentRect) : mPictureRecorder(new SkPictureRecorder()) , mPicture(NULL) , mWidth(width) , mHeight(height) { mContentRect = contentRect; } ~PageRecord() { delete mPictureRecorder; if (NULL != mPicture) { mPicture->unref(); } } SkPictureRecorder* mPictureRecorder; SkPicture* 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->mPictureRecorder->beginRecording( SkRect::MakeWH(contentRect.width(), contentRect.height())); return canvas; } void finishPage() { assert(mCurrentPage != NULL); assert(mCurrentPage->mPictureRecorder != NULL); assert(mCurrentPage->mPicture == NULL); mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->finishRecordingAsPicture().release(); delete mCurrentPage->mPictureRecorder; mCurrentPage->mPictureRecorder = NULL; mCurrentPage = NULL; } void write(SkWStream* stream) { sk_sp document = SkPDF::MakeDocument(stream); for (unsigned i = 0; i < mPages.size(); i++) { PageRecord* page = mPages[i]; SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight, &(page->mContentRect)); canvas->drawPicture(page->mPicture); document->endPage(); } document->close(); } void close() { assert(NULL == mCurrentPage); for (unsigned i = 0; i < mPages.size(); i++) { delete mPages[i]; } } private: ~PdfDocument() { close(); } std::vector mPages; PageRecord* mCurrentPage; }; static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) { return reinterpret_cast(new PdfDocument()); } static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr, jint pageWidth, jint pageHeight, jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) { PdfDocument* document = reinterpret_cast(documentPtr); SkCanvas* canvas = document->startPage(pageWidth, pageHeight, contentLeft, contentTop, contentRight, contentBottom); return reinterpret_cast(Canvas::create_canvas(canvas)); } static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) { PdfDocument* document = reinterpret_cast(documentPtr); document->finishPage(); } static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out, jbyteArray chunk) { PdfDocument* document = reinterpret_cast(documentPtr); SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk); document->write(skWStream); delete skWStream; } static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) { PdfDocument* document = reinterpret_cast(documentPtr); document->close(); } static const JNINativeMethod gPdfDocument_Methods[] = { {"nativeCreateDocument", "()J", (void*) nativeCreateDocument}, {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage}, {"nativeFinishPage", "(J)V", (void*) nativeFinishPage}, {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo}, {"nativeClose", "(J)V", (void*) nativeClose} }; int register_android_graphics_pdf_PdfDocument(JNIEnv* env) { return RegisterMethodsOrDie( env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods, NELEM(gPdfDocument_Methods)); } };