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