1 /* 2 * Copyright (C) 2014 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 "PdfUtils.h" 18 19 #include "jni.h" 20 #include <nativehelper/JNIHelp.h> 21 #include "GraphicsJNI.h" 22 #include "SkBitmap.h" 23 #include "SkMatrix.h" 24 #include "fpdfview.h" 25 26 #include "core_jni_helpers.h" 27 #include <vector> 28 #include <utils/Log.h> 29 #include <unistd.h> 30 #include <sys/types.h> 31 #include <unistd.h> 32 33 namespace android { 34 35 static const int RENDER_MODE_FOR_DISPLAY = 1; 36 static const int RENDER_MODE_FOR_PRINT = 2; 37 38 static struct { 39 jfieldID x; 40 jfieldID y; 41 } gPointClassInfo; 42 43 static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPtr, 44 jint pageIndex, jobject outSize) { 45 FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 46 47 FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); 48 if (!page) { 49 jniThrowException(env, "java/lang/IllegalStateException", 50 "cannot load page"); 51 return -1; 52 } 53 54 double width = 0; 55 double height = 0; 56 57 int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); 58 if (!result) { 59 jniThrowException(env, "java/lang/IllegalStateException", 60 "cannot get page size"); 61 return -1; 62 } 63 64 env->SetIntField(outSize, gPointClassInfo.x, width); 65 env->SetIntField(outSize, gPointClassInfo.y, height); 66 67 return reinterpret_cast<jlong>(page); 68 } 69 70 static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { 71 FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); 72 FPDF_ClosePage(page); 73 } 74 75 static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr, 76 jobject jbitmap, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, 77 jlong transformPtr, jint renderMode) { 78 FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); 79 80 SkBitmap skBitmap; 81 GraphicsJNI::getSkBitmap(env, jbitmap, &skBitmap); 82 83 const int stride = skBitmap.width() * 4; 84 85 FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(), 86 FPDFBitmap_BGRA, skBitmap.getPixels(), stride); 87 88 int renderFlags = FPDF_REVERSE_BYTE_ORDER; 89 if (renderMode == RENDER_MODE_FOR_DISPLAY) { 90 renderFlags |= FPDF_LCD_TEXT; 91 } else if (renderMode == RENDER_MODE_FOR_PRINT) { 92 renderFlags |= FPDF_PRINTING; 93 } 94 95 SkMatrix matrix = *reinterpret_cast<SkMatrix*>(transformPtr); 96 SkScalar transformValues[6]; 97 if (!matrix.asAffine(transformValues)) { 98 jniThrowException(env, "java/lang/IllegalArgumentException", 99 "transform matrix has perspective. Only affine matrices are allowed."); 100 return; 101 } 102 103 FS_MATRIX transform = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], 104 transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], 105 transformValues[SkMatrix::kATransX], 106 transformValues[SkMatrix::kATransY]}; 107 108 FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; 109 110 FPDF_RenderPageBitmapWithMatrix(bitmap, page, &transform, &clip, renderFlags); 111 112 skBitmap.notifyPixelsChanged(); 113 } 114 115 static const JNINativeMethod gPdfRenderer_Methods[] = { 116 {"nativeCreate", "(IJ)J", (void*) nativeOpen}, 117 {"nativeClose", "(J)V", (void*) nativeClose}, 118 {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, 119 {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, 120 {"nativeRenderPage", "(JJLandroid/graphics/Bitmap;IIIIJI)V", (void*) nativeRenderPage}, 121 {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize}, 122 {"nativeClosePage", "(J)V", (void*) nativeClosePage} 123 }; 124 125 int register_android_graphics_pdf_PdfRenderer(JNIEnv* env) { 126 int result = RegisterMethodsOrDie( 127 env, "android/graphics/pdf/PdfRenderer", gPdfRenderer_Methods, 128 NELEM(gPdfRenderer_Methods)); 129 130 jclass clazz = FindClassOrDie(env, "android/graphics/Point"); 131 gPointClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "I"); 132 gPointClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "I"); 133 134 return result; 135 }; 136 137 }; 138