diff options
Diffstat (limited to 'libs/hwui/jni/pdf/PdfRenderer.cpp')
-rw-r--r-- | libs/hwui/jni/pdf/PdfRenderer.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/libs/hwui/jni/pdf/PdfRenderer.cpp b/libs/hwui/jni/pdf/PdfRenderer.cpp new file mode 100644 index 000000000000..cc1f96197c74 --- /dev/null +++ b/libs/hwui/jni/pdf/PdfRenderer.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2014 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 "PdfUtils.h" + +#include "GraphicsJNI.h" +#include "SkBitmap.h" +#include "SkMatrix.h" +#include "fpdfview.h" + +#include <vector> +#include <utils/Log.h> +#include <unistd.h> +#include <sys/types.h> +#include <unistd.h> + +namespace android { + +static const int RENDER_MODE_FOR_DISPLAY = 1; +static const int RENDER_MODE_FOR_PRINT = 2; + +static struct { + jfieldID x; + jfieldID y; +} gPointClassInfo; + +static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPtr, + jint pageIndex, jobject outSize) { + FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); + + FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); + if (!page) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot load page"); + return -1; + } + + double width = 0; + double height = 0; + + int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); + if (!result) { + jniThrowException(env, "java/lang/IllegalStateException", + "cannot get page size"); + return -1; + } + + env->SetIntField(outSize, gPointClassInfo.x, width); + env->SetIntField(outSize, gPointClassInfo.y, height); + + return reinterpret_cast<jlong>(page); +} + +static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { + FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); + FPDF_ClosePage(page); +} + +static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr, + jlong bitmapPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, + jlong transformPtr, jint renderMode) { + FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); + + SkBitmap skBitmap; + bitmap::toBitmap(bitmapPtr).getSkBitmap(&skBitmap); + + const int stride = skBitmap.width() * 4; + + FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(), + FPDFBitmap_BGRA, skBitmap.getPixels(), stride); + + int renderFlags = FPDF_REVERSE_BYTE_ORDER; + if (renderMode == RENDER_MODE_FOR_DISPLAY) { + renderFlags |= FPDF_LCD_TEXT; + } else if (renderMode == RENDER_MODE_FOR_PRINT) { + renderFlags |= FPDF_PRINTING; + } + + SkMatrix matrix = *reinterpret_cast<SkMatrix*>(transformPtr); + SkScalar transformValues[6]; + if (!matrix.asAffine(transformValues)) { + jniThrowException(env, "java/lang/IllegalArgumentException", + "transform matrix has perspective. Only affine matrices are allowed."); + return; + } + + FS_MATRIX transform = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], + transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], + transformValues[SkMatrix::kATransX], + transformValues[SkMatrix::kATransY]}; + + FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; + + FPDF_RenderPageBitmapWithMatrix(bitmap, page, &transform, &clip, renderFlags); + + skBitmap.notifyPixelsChanged(); +} + +static const JNINativeMethod gPdfRenderer_Methods[] = { + {"nativeCreate", "(IJ)J", (void*) nativeOpen}, + {"nativeClose", "(J)V", (void*) nativeClose}, + {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, + {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, + {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage}, + {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize}, + {"nativeClosePage", "(J)V", (void*) nativeClosePage} +}; + +int register_android_graphics_pdf_PdfRenderer(JNIEnv* env) { + int result = RegisterMethodsOrDie( + env, "android/graphics/pdf/PdfRenderer", gPdfRenderer_Methods, + NELEM(gPdfRenderer_Methods)); + + jclass clazz = FindClassOrDie(env, "android/graphics/Point"); + gPointClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "I"); + gPointClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "I"); + + return result; +}; + +}; |