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