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