| /* |
| * 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 <vector> |
| |
| #include "CreateJavaOutputStreamAdaptor.h" |
| |
| #include "SkPDFDocument.h" |
| #include "SkPicture.h" |
| #include "SkPictureRecorder.h" |
| #include "SkRect.h" |
| #include "SkStream.h" |
| |
| #include <hwui/Canvas.h> |
| |
| 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<SkDocument> 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<PageRecord*> mPages; |
| PageRecord* mCurrentPage; |
| }; |
| |
| static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) { |
| return reinterpret_cast<jlong>(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<PdfDocument*>(documentPtr); |
| SkCanvas* canvas = document->startPage(pageWidth, pageHeight, |
| contentLeft, contentTop, contentRight, contentBottom); |
| return reinterpret_cast<jlong>(Canvas::create_canvas(canvas)); |
| } |
| |
| static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) { |
| PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr); |
| document->finishPage(); |
| } |
| |
| static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out, |
| jbyteArray chunk) { |
| PdfDocument* document = reinterpret_cast<PdfDocument*>(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<PdfDocument*>(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)); |
| } |
| |
| }; |