Loading core/jni/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ LOCAL_SRC_FILES:= \ android/graphics/pdf/PdfDocument.cpp \ android/graphics/pdf/PdfEditor.cpp \ android/graphics/pdf/PdfRenderer.cpp \ android/graphics/pdf/PdfUtils.cpp \ android_media_AudioRecord.cpp \ android_media_AudioSystem.cpp \ android_media_AudioTrack.cpp \ Loading core/jni/android/graphics/pdf/PdfEditor.cpp +45 −78 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include "PdfUtils.h" #include "jni.h" #include "JNIHelp.h" Loading Loading @@ -50,79 +52,16 @@ static struct { jfieldID bottom; } gRectClassInfo; // Also used in PdfRenderer.cpp int sUnmatchedPdfiumInitRequestCount = 0; static void initializeLibraryIfNeeded() { if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); } sUnmatchedPdfiumInitRequestCount++; } static void destroyLibraryIfNeeded() { sUnmatchedPdfiumInitRequestCount--; if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_DestroyLibrary(); } } static int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size) { const int fd = reinterpret_cast<intptr_t>(param); const int readCount = pread(fd, outBuffer, size, position); if (readCount < 0) { ALOGE("Cannot read from file descriptor. Error:%d", errno); return 0; } return 1; } static jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { initializeLibraryIfNeeded(); FPDF_FILEACCESS loader; loader.m_FileLen = size; loader.m_Param = reinterpret_cast<void*>(intptr_t(fd)); loader.m_GetBlock = &getBlock; FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL); if (!document) { const long error = FPDF_GetLastError(); switch (error) { case FPDF_ERR_PASSWORD: case FPDF_ERR_SECURITY: { jniThrowExceptionFmt(env, "java/lang/SecurityException", "cannot create document. Error: %ld", error); } break; default: { jniThrowExceptionFmt(env, "java/io/IOException", "cannot create document. Error: %ld", error); } break; } destroyLibraryIfNeeded(); return -1; } return reinterpret_cast<jlong>(document); } static void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_CloseDocument(document); destroyLibraryIfNeeded(); } static jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); return FPDF_GetPageCount(document); } static jint nativeRemovePage(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDFPage_Delete(document, pageIndex); return FPDF_GetPageCount(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) int pageCount = FPDF_GetPageCount(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) return pageCount; } struct PdfToFdWriter : FPDF_FILEWRITE { Loading Loading @@ -167,8 +106,8 @@ static void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) { if (!success) { jniThrowExceptionFmt(env, "java/io/IOException", "cannot write to fd. Error: %d", errno); destroyLibraryIfNeeded(); } HANDLE_PDFIUM_ERROR_STATE(env) } static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, Loading @@ -181,6 +120,7 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt "cannot open page"); return; } HANDLE_PDFIUM_ERROR_STATE(env); double width = 0; double height = 0; Loading @@ -191,7 +131,11 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt "cannot get page size"); return; } bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } // PDF's coordinate system origin is left-bottom while in graphics it // is the top-left. So, translate the PDF coordinates to ours. Loading @@ -208,6 +152,8 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt SkScalar transformValues[6]; if (!matrix.asAffine(transformValues)) { FPDF_ClosePage(page); jniThrowException(env, "java/lang/IllegalArgumentException", "transform matrix has perspective. Only affine matrices are allowed."); return; Loading @@ -221,8 +167,14 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; FPDFPage_TransFormWithClip(page, &transform, &clip); isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } FPDF_ClosePage(page); HANDLE_PDFIUM_ERROR_STATE(env); } static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, Loading @@ -235,6 +187,7 @@ static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, "cannot open page"); return; } HANDLE_PDFIUM_ERROR_STATE(env); double width = 0; double height = 0; Loading @@ -245,17 +198,17 @@ static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, "cannot get page size"); return; } bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } env->SetIntField(outSize, gPointClassInfo.x, width); env->SetIntField(outSize, gPointClassInfo.y, height); FPDF_ClosePage(page); } static jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_BOOL success = FPDF_VIEWERREF_GetPrintScaling(document); return success ? JNI_TRUE : JNI_FALSE; HANDLE_PDFIUM_ERROR_STATE(env); } static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, Loading @@ -268,6 +221,7 @@ static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p "cannot open page"); return false; } HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); float left; float top; Loading @@ -277,8 +231,14 @@ static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p const FPDF_BOOL success = (pageBox == PAGE_BOX_MEDIA) ? FPDFPage_GetMediaBox(page, &left, &top, &right, &bottom) : FPDFPage_GetCropBox(page, &left, &top, &right, &bottom); bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return false; } FPDF_ClosePage(page); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); if (!success) { return false; Loading Loading @@ -316,6 +276,7 @@ static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p "cannot open page"); return; } HANDLE_PDFIUM_ERROR_STATE(env); const int left = env->GetIntField(box, gRectClassInfo.left); const int top = env->GetIntField(box, gRectClassInfo.top); Loading @@ -327,8 +288,14 @@ static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p } else { FPDFPage_SetCropBox(page, left, top, right, bottom); } bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } FPDF_ClosePage(page); HANDLE_PDFIUM_ERROR_STATE(env); } static void nativeSetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, Loading core/jni/android/graphics/pdf/PdfRenderer.cpp +7 −78 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include "PdfUtils.h" #include "jni.h" #include "JNIHelp.h" #include "GraphicsJNI.h" Loading Loading @@ -43,86 +45,28 @@ static struct { jfieldID y; } gPointClassInfo; // See PdfEditor.cpp extern int sUnmatchedPdfiumInitRequestCount; static void initializeLibraryIfNeeded() { if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); } sUnmatchedPdfiumInitRequestCount++; } static void destroyLibraryIfNeeded() { sUnmatchedPdfiumInitRequestCount--; if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_DestroyLibrary(); } } static int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size) { const int fd = reinterpret_cast<intptr_t>(param); const int readCount = pread(fd, outBuffer, size, position); if (readCount < 0) { ALOGE("Cannot read from file descriptor. Error:%d", errno); return 0; } return 1; } static jlong nativeCreate(JNIEnv* env, jclass thiz, jint fd, jlong size) { initializeLibraryIfNeeded(); FPDF_FILEACCESS loader; loader.m_FileLen = size; loader.m_Param = reinterpret_cast<void*>(intptr_t(fd)); loader.m_GetBlock = &getBlock; FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL); if (!document) { const long error = FPDF_GetLastError(); switch (error) { case FPDF_ERR_PASSWORD: case FPDF_ERR_SECURITY: { jniThrowExceptionFmt(env, "java/lang/SecurityException", "cannot create document. Error: %ld", error); } break; default: { jniThrowExceptionFmt(env, "java/io/IOException", "cannot create document. Error: %ld", error); } break; } destroyLibraryIfNeeded(); return -1; } return reinterpret_cast<jlong>(document); } 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; } HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) double width = 0; double height = 0; const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); if (!result) { jniThrowException(env, "java/lang/IllegalStateException", "cannot get page size"); return -1; } HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) env->SetIntField(outSize, gPointClassInfo.x, width); env->SetIntField(outSize, gPointClassInfo.y, height); Loading @@ -133,22 +77,7 @@ static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPt static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); FPDF_ClosePage(page); } static void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_CloseDocument(document); destroyLibraryIfNeeded(); } static jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); return FPDF_GetPageCount(document); } static jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); return FPDF_VIEWERREF_GetPrintScaling(document); HANDLE_PDFIUM_ERROR_STATE(env) } static void DropContext(void* data) { Loading Loading @@ -284,7 +213,7 @@ static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong } static const JNINativeMethod gPdfRenderer_Methods[] = { {"nativeCreate", "(IJ)J", (void*) nativeCreate}, {"nativeCreate", "(IJ)J", (void*) nativeOpen}, {"nativeClose", "(J)V", (void*) nativeClose}, {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, Loading core/jni/android/graphics/pdf/PdfUtils.cpp 0 → 100644 +151 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 "jni.h" #include "JNIHelp.h" #include "fpdfview.h" #define LOG_TAG "PdfUtils" #include <utils/Log.h> namespace android { static int sUnmatchedPdfiumInitRequestCount = 0; int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size) { const int fd = reinterpret_cast<intptr_t>(param); const int readCount = pread(fd, outBuffer, size, position); if (readCount < 0) { ALOGE("Cannot read from file descriptor. Error:%d", errno); return 0; } return 1; } // Check if the last pdfium command failed and if so, forward the error to java via an exception. If // this function returns true an exception is pending. bool forwardPdfiumError(JNIEnv* env) { long error = FPDF_GetLastError(); switch (error) { case FPDF_ERR_SUCCESS: return false; case FPDF_ERR_FILE: jniThrowException(env, "java/io/IOException", "file not found or cannot be opened"); break; case FPDF_ERR_FORMAT: jniThrowException(env, "java/io/IOException", "file not in PDF format or corrupted"); break; case FPDF_ERR_PASSWORD: jniThrowException(env, "java/lang/SecurityException", "password required or incorrect password"); break; case FPDF_ERR_SECURITY: jniThrowException(env, "java/lang/SecurityException", "unsupported security scheme"); break; case FPDF_ERR_PAGE: jniThrowException(env, "java/io/IOException", "page not found or content error"); break; #ifdef PDF_ENABLE_XFA case FPDF_ERR_XFALOAD: jniThrowException(env, "java/lang/Exception", "load XFA error"); break; case FPDF_ERR_XFALAYOUT: jniThrowException(env, "java/lang/Exception", "layout XFA error"); break; #endif // PDF_ENABLE_XFA case FPDF_ERR_UNKNOWN: default: jniThrowExceptionFmt(env, "java/lang/Exception", "unknown error %d", error); } return true; } static bool initializeLibraryIfNeeded(JNIEnv* env) { if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); } sUnmatchedPdfiumInitRequestCount++; return true; } static void destroyLibraryIfNeeded(JNIEnv* env, bool handleError) { if (sUnmatchedPdfiumInitRequestCount == 1) { FPDF_DestroyLibrary(); if (handleError) { HANDLE_PDFIUM_ERROR_STATE(env); } } sUnmatchedPdfiumInitRequestCount--; } jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { bool isInitialized = initializeLibraryIfNeeded(env); if (!isInitialized) { return -1; } FPDF_FILEACCESS loader; loader.m_FileLen = size; loader.m_Param = reinterpret_cast<void*>(intptr_t(fd)); loader.m_GetBlock = &getBlock; FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL); if (!document) { forwardPdfiumError(env); destroyLibraryIfNeeded(env, false); return -1; } return reinterpret_cast<jlong>(document); } void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_CloseDocument(document); HANDLE_PDFIUM_ERROR_STATE(env) destroyLibraryIfNeeded(env, true); } jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); int pageCount = FPDF_GetPageCount(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1); return pageCount; } jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_BOOL printScaling = FPDF_VIEWERREF_GetPrintScaling(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); return printScaling ? JNI_TRUE : JNI_FALSE; } }; core/jni/android/graphics/pdf/PdfUtils.h 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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. */ #ifndef PDF_UTILS_H_ #define PDF_UTILS_H_ #include "jni.h" namespace android { int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size); bool forwardPdfiumError(JNIEnv* env); #define HANDLE_PDFIUM_ERROR_STATE(env) \ { \ bool isExceptionPending = forwardPdfiumError(env); \ if (isExceptionPending) { \ return; \ } \ } #define HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, retCode) \ { \ bool isExceptionPending = forwardPdfiumError(env); \ if (isExceptionPending) { \ return retCode; \ } \ } jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size); void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr); jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr); jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr); }; #endif /* PDF_UTILS_H_ */ Loading
core/jni/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ LOCAL_SRC_FILES:= \ android/graphics/pdf/PdfDocument.cpp \ android/graphics/pdf/PdfEditor.cpp \ android/graphics/pdf/PdfRenderer.cpp \ android/graphics/pdf/PdfUtils.cpp \ android_media_AudioRecord.cpp \ android_media_AudioSystem.cpp \ android_media_AudioTrack.cpp \ Loading
core/jni/android/graphics/pdf/PdfEditor.cpp +45 −78 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include "PdfUtils.h" #include "jni.h" #include "JNIHelp.h" Loading Loading @@ -50,79 +52,16 @@ static struct { jfieldID bottom; } gRectClassInfo; // Also used in PdfRenderer.cpp int sUnmatchedPdfiumInitRequestCount = 0; static void initializeLibraryIfNeeded() { if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); } sUnmatchedPdfiumInitRequestCount++; } static void destroyLibraryIfNeeded() { sUnmatchedPdfiumInitRequestCount--; if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_DestroyLibrary(); } } static int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size) { const int fd = reinterpret_cast<intptr_t>(param); const int readCount = pread(fd, outBuffer, size, position); if (readCount < 0) { ALOGE("Cannot read from file descriptor. Error:%d", errno); return 0; } return 1; } static jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { initializeLibraryIfNeeded(); FPDF_FILEACCESS loader; loader.m_FileLen = size; loader.m_Param = reinterpret_cast<void*>(intptr_t(fd)); loader.m_GetBlock = &getBlock; FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL); if (!document) { const long error = FPDF_GetLastError(); switch (error) { case FPDF_ERR_PASSWORD: case FPDF_ERR_SECURITY: { jniThrowExceptionFmt(env, "java/lang/SecurityException", "cannot create document. Error: %ld", error); } break; default: { jniThrowExceptionFmt(env, "java/io/IOException", "cannot create document. Error: %ld", error); } break; } destroyLibraryIfNeeded(); return -1; } return reinterpret_cast<jlong>(document); } static void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_CloseDocument(document); destroyLibraryIfNeeded(); } static jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); return FPDF_GetPageCount(document); } static jint nativeRemovePage(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDFPage_Delete(document, pageIndex); return FPDF_GetPageCount(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) int pageCount = FPDF_GetPageCount(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) return pageCount; } struct PdfToFdWriter : FPDF_FILEWRITE { Loading Loading @@ -167,8 +106,8 @@ static void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) { if (!success) { jniThrowExceptionFmt(env, "java/io/IOException", "cannot write to fd. Error: %d", errno); destroyLibraryIfNeeded(); } HANDLE_PDFIUM_ERROR_STATE(env) } static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, Loading @@ -181,6 +120,7 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt "cannot open page"); return; } HANDLE_PDFIUM_ERROR_STATE(env); double width = 0; double height = 0; Loading @@ -191,7 +131,11 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt "cannot get page size"); return; } bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } // PDF's coordinate system origin is left-bottom while in graphics it // is the top-left. So, translate the PDF coordinates to ours. Loading @@ -208,6 +152,8 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt SkScalar transformValues[6]; if (!matrix.asAffine(transformValues)) { FPDF_ClosePage(page); jniThrowException(env, "java/lang/IllegalArgumentException", "transform matrix has perspective. Only affine matrices are allowed."); return; Loading @@ -221,8 +167,14 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; FPDFPage_TransFormWithClip(page, &transform, &clip); isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } FPDF_ClosePage(page); HANDLE_PDFIUM_ERROR_STATE(env); } static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, Loading @@ -235,6 +187,7 @@ static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, "cannot open page"); return; } HANDLE_PDFIUM_ERROR_STATE(env); double width = 0; double height = 0; Loading @@ -245,17 +198,17 @@ static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, "cannot get page size"); return; } bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } env->SetIntField(outSize, gPointClassInfo.x, width); env->SetIntField(outSize, gPointClassInfo.y, height); FPDF_ClosePage(page); } static jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_BOOL success = FPDF_VIEWERREF_GetPrintScaling(document); return success ? JNI_TRUE : JNI_FALSE; HANDLE_PDFIUM_ERROR_STATE(env); } static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, Loading @@ -268,6 +221,7 @@ static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p "cannot open page"); return false; } HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); float left; float top; Loading @@ -277,8 +231,14 @@ static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p const FPDF_BOOL success = (pageBox == PAGE_BOX_MEDIA) ? FPDFPage_GetMediaBox(page, &left, &top, &right, &bottom) : FPDFPage_GetCropBox(page, &left, &top, &right, &bottom); bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return false; } FPDF_ClosePage(page); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); if (!success) { return false; Loading Loading @@ -316,6 +276,7 @@ static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p "cannot open page"); return; } HANDLE_PDFIUM_ERROR_STATE(env); const int left = env->GetIntField(box, gRectClassInfo.left); const int top = env->GetIntField(box, gRectClassInfo.top); Loading @@ -327,8 +288,14 @@ static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p } else { FPDFPage_SetCropBox(page, left, top, right, bottom); } bool isExceptionPending = forwardPdfiumError(env); if (isExceptionPending) { FPDF_ClosePage(page); return; } FPDF_ClosePage(page); HANDLE_PDFIUM_ERROR_STATE(env); } static void nativeSetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, Loading
core/jni/android/graphics/pdf/PdfRenderer.cpp +7 −78 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include "PdfUtils.h" #include "jni.h" #include "JNIHelp.h" #include "GraphicsJNI.h" Loading Loading @@ -43,86 +45,28 @@ static struct { jfieldID y; } gPointClassInfo; // See PdfEditor.cpp extern int sUnmatchedPdfiumInitRequestCount; static void initializeLibraryIfNeeded() { if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); } sUnmatchedPdfiumInitRequestCount++; } static void destroyLibraryIfNeeded() { sUnmatchedPdfiumInitRequestCount--; if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_DestroyLibrary(); } } static int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size) { const int fd = reinterpret_cast<intptr_t>(param); const int readCount = pread(fd, outBuffer, size, position); if (readCount < 0) { ALOGE("Cannot read from file descriptor. Error:%d", errno); return 0; } return 1; } static jlong nativeCreate(JNIEnv* env, jclass thiz, jint fd, jlong size) { initializeLibraryIfNeeded(); FPDF_FILEACCESS loader; loader.m_FileLen = size; loader.m_Param = reinterpret_cast<void*>(intptr_t(fd)); loader.m_GetBlock = &getBlock; FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL); if (!document) { const long error = FPDF_GetLastError(); switch (error) { case FPDF_ERR_PASSWORD: case FPDF_ERR_SECURITY: { jniThrowExceptionFmt(env, "java/lang/SecurityException", "cannot create document. Error: %ld", error); } break; default: { jniThrowExceptionFmt(env, "java/io/IOException", "cannot create document. Error: %ld", error); } break; } destroyLibraryIfNeeded(); return -1; } return reinterpret_cast<jlong>(document); } 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; } HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) double width = 0; double height = 0; const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); if (!result) { jniThrowException(env, "java/lang/IllegalStateException", "cannot get page size"); return -1; } HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) env->SetIntField(outSize, gPointClassInfo.x, width); env->SetIntField(outSize, gPointClassInfo.y, height); Loading @@ -133,22 +77,7 @@ static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPt static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); FPDF_ClosePage(page); } static void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_CloseDocument(document); destroyLibraryIfNeeded(); } static jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); return FPDF_GetPageCount(document); } static jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); return FPDF_VIEWERREF_GetPrintScaling(document); HANDLE_PDFIUM_ERROR_STATE(env) } static void DropContext(void* data) { Loading Loading @@ -284,7 +213,7 @@ static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong } static const JNINativeMethod gPdfRenderer_Methods[] = { {"nativeCreate", "(IJ)J", (void*) nativeCreate}, {"nativeCreate", "(IJ)J", (void*) nativeOpen}, {"nativeClose", "(J)V", (void*) nativeClose}, {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, Loading
core/jni/android/graphics/pdf/PdfUtils.cpp 0 → 100644 +151 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 "jni.h" #include "JNIHelp.h" #include "fpdfview.h" #define LOG_TAG "PdfUtils" #include <utils/Log.h> namespace android { static int sUnmatchedPdfiumInitRequestCount = 0; int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size) { const int fd = reinterpret_cast<intptr_t>(param); const int readCount = pread(fd, outBuffer, size, position); if (readCount < 0) { ALOGE("Cannot read from file descriptor. Error:%d", errno); return 0; } return 1; } // Check if the last pdfium command failed and if so, forward the error to java via an exception. If // this function returns true an exception is pending. bool forwardPdfiumError(JNIEnv* env) { long error = FPDF_GetLastError(); switch (error) { case FPDF_ERR_SUCCESS: return false; case FPDF_ERR_FILE: jniThrowException(env, "java/io/IOException", "file not found or cannot be opened"); break; case FPDF_ERR_FORMAT: jniThrowException(env, "java/io/IOException", "file not in PDF format or corrupted"); break; case FPDF_ERR_PASSWORD: jniThrowException(env, "java/lang/SecurityException", "password required or incorrect password"); break; case FPDF_ERR_SECURITY: jniThrowException(env, "java/lang/SecurityException", "unsupported security scheme"); break; case FPDF_ERR_PAGE: jniThrowException(env, "java/io/IOException", "page not found or content error"); break; #ifdef PDF_ENABLE_XFA case FPDF_ERR_XFALOAD: jniThrowException(env, "java/lang/Exception", "load XFA error"); break; case FPDF_ERR_XFALAYOUT: jniThrowException(env, "java/lang/Exception", "layout XFA error"); break; #endif // PDF_ENABLE_XFA case FPDF_ERR_UNKNOWN: default: jniThrowExceptionFmt(env, "java/lang/Exception", "unknown error %d", error); } return true; } static bool initializeLibraryIfNeeded(JNIEnv* env) { if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); } sUnmatchedPdfiumInitRequestCount++; return true; } static void destroyLibraryIfNeeded(JNIEnv* env, bool handleError) { if (sUnmatchedPdfiumInitRequestCount == 1) { FPDF_DestroyLibrary(); if (handleError) { HANDLE_PDFIUM_ERROR_STATE(env); } } sUnmatchedPdfiumInitRequestCount--; } jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { bool isInitialized = initializeLibraryIfNeeded(env); if (!isInitialized) { return -1; } FPDF_FILEACCESS loader; loader.m_FileLen = size; loader.m_Param = reinterpret_cast<void*>(intptr_t(fd)); loader.m_GetBlock = &getBlock; FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL); if (!document) { forwardPdfiumError(env); destroyLibraryIfNeeded(env, false); return -1; } return reinterpret_cast<jlong>(document); } void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_CloseDocument(document); HANDLE_PDFIUM_ERROR_STATE(env) destroyLibraryIfNeeded(env, true); } jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); int pageCount = FPDF_GetPageCount(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1); return pageCount; } jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_BOOL printScaling = FPDF_VIEWERREF_GetPrintScaling(document); HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); return printScaling ? JNI_TRUE : JNI_FALSE; } };
core/jni/android/graphics/pdf/PdfUtils.h 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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. */ #ifndef PDF_UTILS_H_ #define PDF_UTILS_H_ #include "jni.h" namespace android { int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size); bool forwardPdfiumError(JNIEnv* env); #define HANDLE_PDFIUM_ERROR_STATE(env) \ { \ bool isExceptionPending = forwardPdfiumError(env); \ if (isExceptionPending) { \ return; \ } \ } #define HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, retCode) \ { \ bool isExceptionPending = forwardPdfiumError(env); \ if (isExceptionPending) { \ return retCode; \ } \ } jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size); void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr); jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr); jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr); }; #endif /* PDF_UTILS_H_ */