164 lines
5.0 KiB
C++
164 lines
5.0 KiB
C++
/*
|
|
* Copyright (C) 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "GraphicsJNI.h"
|
|
#include <vector>
|
|
|
|
#include "CreateJavaOutputStreamAdaptor.h"
|
|
|
|
#include "SkPDFDocument.h"
|
|
#include "SkPicture.h"
|
|
#include "SkPictureRecorder.h"
|
|
#include "SkRect.h"
|
|
#include "SkStream.h"
|
|
|
|
#include <hwui/Canvas.h>
|
|
|
|
namespace android {
|
|
|
|
struct PageRecord {
|
|
|
|
PageRecord(int width, int height, const SkRect& contentRect)
|
|
: mPictureRecorder(new SkPictureRecorder())
|
|
, mPicture(NULL)
|
|
, mWidth(width)
|
|
, mHeight(height) {
|
|
mContentRect = contentRect;
|
|
}
|
|
|
|
~PageRecord() {
|
|
delete mPictureRecorder;
|
|
if (NULL != mPicture) {
|
|
mPicture->unref();
|
|
}
|
|
}
|
|
|
|
SkPictureRecorder* mPictureRecorder;
|
|
SkPicture* mPicture;
|
|
const int mWidth;
|
|
const int mHeight;
|
|
SkRect mContentRect;
|
|
};
|
|
|
|
class PdfDocument {
|
|
public:
|
|
PdfDocument() {
|
|
mCurrentPage = NULL;
|
|
}
|
|
|
|
SkCanvas* startPage(int width, int height,
|
|
int contentLeft, int contentTop, int contentRight, int contentBottom) {
|
|
assert(mCurrentPage == NULL);
|
|
|
|
SkRect contentRect = SkRect::MakeLTRB(
|
|
contentLeft, contentTop, contentRight, contentBottom);
|
|
PageRecord* page = new PageRecord(width, height, contentRect);
|
|
mPages.push_back(page);
|
|
mCurrentPage = page;
|
|
|
|
SkCanvas* canvas = page->mPictureRecorder->beginRecording(
|
|
SkRect::MakeWH(contentRect.width(), contentRect.height()));
|
|
|
|
return canvas;
|
|
}
|
|
|
|
void finishPage() {
|
|
assert(mCurrentPage != NULL);
|
|
assert(mCurrentPage->mPictureRecorder != NULL);
|
|
assert(mCurrentPage->mPicture == NULL);
|
|
mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->finishRecordingAsPicture().release();
|
|
delete mCurrentPage->mPictureRecorder;
|
|
mCurrentPage->mPictureRecorder = NULL;
|
|
mCurrentPage = NULL;
|
|
}
|
|
|
|
void write(SkWStream* stream) {
|
|
sk_sp<SkDocument> document = SkPDF::MakeDocument(stream);
|
|
for (unsigned i = 0; i < mPages.size(); i++) {
|
|
PageRecord* page = mPages[i];
|
|
|
|
SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight,
|
|
&(page->mContentRect));
|
|
canvas->drawPicture(page->mPicture);
|
|
|
|
document->endPage();
|
|
}
|
|
document->close();
|
|
}
|
|
|
|
void close() {
|
|
assert(NULL == mCurrentPage);
|
|
for (unsigned i = 0; i < mPages.size(); i++) {
|
|
delete mPages[i];
|
|
}
|
|
}
|
|
|
|
private:
|
|
~PdfDocument() {
|
|
close();
|
|
}
|
|
|
|
std::vector<PageRecord*> mPages;
|
|
PageRecord* mCurrentPage;
|
|
};
|
|
|
|
static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) {
|
|
return reinterpret_cast<jlong>(new PdfDocument());
|
|
}
|
|
|
|
static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr,
|
|
jint pageWidth, jint pageHeight,
|
|
jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
|
|
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
|
|
SkCanvas* canvas = document->startPage(pageWidth, pageHeight,
|
|
contentLeft, contentTop, contentRight, contentBottom);
|
|
return reinterpret_cast<jlong>(Canvas::create_canvas(canvas));
|
|
}
|
|
|
|
static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
|
|
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
|
|
document->finishPage();
|
|
}
|
|
|
|
static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out,
|
|
jbyteArray chunk) {
|
|
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
|
|
SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
|
|
document->write(skWStream);
|
|
delete skWStream;
|
|
}
|
|
|
|
static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) {
|
|
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
|
|
document->close();
|
|
}
|
|
|
|
static const JNINativeMethod gPdfDocument_Methods[] = {
|
|
{"nativeCreateDocument", "()J", (void*) nativeCreateDocument},
|
|
{"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage},
|
|
{"nativeFinishPage", "(J)V", (void*) nativeFinishPage},
|
|
{"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
|
|
{"nativeClose", "(J)V", (void*) nativeClose}
|
|
};
|
|
|
|
int register_android_graphics_pdf_PdfDocument(JNIEnv* env) {
|
|
return RegisterMethodsOrDie(
|
|
env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods,
|
|
NELEM(gPdfDocument_Methods));
|
|
}
|
|
|
|
};
|