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