blob: abc3599a48c1fd9e1bba78ea4581f5a247c98092 [file] [log] [blame]
Svetoslav Ganovff4adde52013-06-10 08:47:27 -07001/*
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"
Andreas Gampeed6b9df2014-11-20 22:02:20 -080019#include "core_jni_helpers.h"
Svetoslav35aacf22013-11-06 18:22:13 -080020#include <vector>
21
22#include "CreateJavaOutputStreamAdaptor.h"
Svetoslav Ganovff4adde52013-06-10 08:47:27 -070023
Matt Sarettea70d222017-03-29 16:25:10 -040024#include "SkColorSpaceXformCanvas.h"
Svetoslav35aacf22013-11-06 18:22:13 -080025#include "SkDocument.h"
26#include "SkPicture.h"
Robert Phillipsb59508f2014-04-23 12:31:37 -040027#include "SkPictureRecorder.h"
Svetoslav35aacf22013-11-06 18:22:13 -080028#include "SkStream.h"
Svetoslav Ganovff4adde52013-06-10 08:47:27 -070029#include "SkRect.h"
Svetoslav Ganovff4adde52013-06-10 08:47:27 -070030
sergeyvdccca442016-03-21 15:38:21 -070031#include <hwui/Canvas.h>
32
Svetoslav Ganovff4adde52013-06-10 08:47:27 -070033namespace android {
34
Svetoslav35aacf22013-11-06 18:22:13 -080035struct PageRecord {
Svetoslav6811f4e2013-09-18 15:58:28 -070036
Svetoslav35aacf22013-11-06 18:22:13 -080037 PageRecord(int width, int height, const SkRect& contentRect)
Robert Phillipsb59508f2014-04-23 12:31:37 -040038 : mPictureRecorder(new SkPictureRecorder())
39 , mPicture(NULL)
40 , mWidth(width)
41 , mHeight(height) {
Svetoslav35aacf22013-11-06 18:22:13 -080042 mContentRect = contentRect;
43 }
44
45 ~PageRecord() {
Robert Phillipsb59508f2014-04-23 12:31:37 -040046 delete mPictureRecorder;
47 if (NULL != mPicture) {
48 mPicture->unref();
49 }
Svetoslav35aacf22013-11-06 18:22:13 -080050 }
51
Robert Phillipsb59508f2014-04-23 12:31:37 -040052 SkPictureRecorder* mPictureRecorder;
53 SkPicture* mPicture;
Svetoslav35aacf22013-11-06 18:22:13 -080054 const int mWidth;
55 const int mHeight;
56 SkRect mContentRect;
57};
58
59class PdfDocument {
60public:
61 PdfDocument() {
62 mCurrentPage = NULL;
63 }
64
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
Robert Phillipsb59508f2014-04-23 12:31:37 -040075 SkCanvas* canvas = page->mPictureRecorder->beginRecording(
Mike Reed71487eb2014-11-19 16:13:20 -050076 SkRect::MakeWH(contentRect.width(), contentRect.height()));
Svetoslav35aacf22013-11-06 18:22:13 -080077
Svetoslav35aacf22013-11-06 18:22:13 -080078 return canvas;
79 }
80
81 void finishPage() {
82 assert(mCurrentPage != NULL);
Robert Phillipsb59508f2014-04-23 12:31:37 -040083 assert(mCurrentPage->mPictureRecorder != NULL);
84 assert(mCurrentPage->mPicture == NULL);
Mike Reed260ab722016-10-07 15:59:20 -040085 mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->finishRecordingAsPicture().release();
Robert Phillipsb59508f2014-04-23 12:31:37 -040086 delete mCurrentPage->mPictureRecorder;
87 mCurrentPage->mPictureRecorder = NULL;
Svetoslav35aacf22013-11-06 18:22:13 -080088 mCurrentPage = NULL;
89 }
90
91 void write(SkWStream* stream) {
Hal Canary4cb7bb52016-05-02 15:27:51 -040092 sk_sp<SkDocument> document = SkDocument::MakePDF(stream);
Svetoslav35aacf22013-11-06 18:22:13 -080093 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));
Matt Sarettea70d222017-03-29 16:25:10 -040098 std::unique_ptr<SkCanvas> toSRGBCanvas =
99 SkCreateColorSpaceXformCanvas(canvas, SkColorSpace::MakeSRGB());
Svetoslav35aacf22013-11-06 18:22:13 -0800100
Matt Sarettea70d222017-03-29 16:25:10 -0400101 toSRGBCanvas->drawPicture(page->mPicture);
Svetoslav35aacf22013-11-06 18:22:13 -0800102
103 document->endPage();
104 }
105 document->close();
106 }
107
108 void close() {
Robert Phillipsb59508f2014-04-23 12:31:37 -0400109 assert(NULL == mCurrentPage);
Svetoslav35aacf22013-11-06 18:22:13 -0800110 for (unsigned i = 0; i < mPages.size(); i++) {
111 delete mPages[i];
112 }
Svetoslav35aacf22013-11-06 18:22:13 -0800113 }
114
115private:
116 ~PdfDocument() {
117 close();
118 }
119
120 std::vector<PageRecord*> mPages;
121 PageRecord* mCurrentPage;
122};
123
Ashok Bhatcdf34462014-01-23 15:29:55 +0000124static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) {
125 return reinterpret_cast<jlong>(new PdfDocument());
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700126}
127
Ashok Bhatcdf34462014-01-23 15:29:55 +0000128static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr,
Svetoslav35aacf22013-11-06 18:22:13 -0800129 jint pageWidth, jint pageHeight,
Svetoslav6811f4e2013-09-18 15:58:28 -0700130 jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
Svetoslav35aacf22013-11-06 18:22:13 -0800131 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
Derek Sollenberger8872b382014-06-23 14:13:53 -0400132 SkCanvas* canvas = document->startPage(pageWidth, pageHeight,
133 contentLeft, contentTop, contentRight, contentBottom);
Matt Sarettea70d222017-03-29 16:25:10 -0400134 return reinterpret_cast<jlong>(Canvas::create_canvas(canvas, Canvas::XformToSRGB::kDefer));
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700135}
136
Ashok Bhatcdf34462014-01-23 15:29:55 +0000137static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
Svetoslav35aacf22013-11-06 18:22:13 -0800138 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
139 document->finishPage();
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700140}
141
Ashok Bhatcdf34462014-01-23 15:29:55 +0000142static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out,
Svetoslav35aacf22013-11-06 18:22:13 -0800143 jbyteArray chunk) {
144 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700145 SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
Svetoslav35aacf22013-11-06 18:22:13 -0800146 document->write(skWStream);
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700147 delete skWStream;
148}
149
Ashok Bhatcdf34462014-01-23 15:29:55 +0000150static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) {
Svetoslav35aacf22013-11-06 18:22:13 -0800151 PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
152 document->close();
153}
154
Daniel Micay76f6a862015-09-19 17:31:01 -0400155static const JNINativeMethod gPdfDocument_Methods[] = {
Ashok Bhatcdf34462014-01-23 15:29:55 +0000156 {"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}
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700161};
162
Svetoslav6811f4e2013-09-18 15:58:28 -0700163int register_android_graphics_pdf_PdfDocument(JNIEnv* env) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800164 return RegisterMethodsOrDie(
Svetoslav6811f4e2013-09-18 15:58:28 -0700165 env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods,
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700166 NELEM(gPdfDocument_Methods));
Svetoslav Ganovff4adde52013-06-10 08:47:27 -0700167}
168
169};