• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 <nativehelper/JNIHelp.h>
20 #include <utils/Log.h>
21 
22 #include "fpdfview.h"
23 #include "jni.h"
24 
25 namespace android {
26 
27 static int sUnmatchedPdfiumInitRequestCount = 0;
28 
getBlock(void * param,unsigned long position,unsigned char * outBuffer,unsigned long size)29 int getBlock(void* param, unsigned long position, unsigned char* outBuffer,
30         unsigned long size) {
31     const int fd = reinterpret_cast<intptr_t>(param);
32     const int readCount = pread(fd, outBuffer, size, position);
33     if (readCount < 0) {
34         ALOGE("Cannot read from file descriptor. Error:%d", errno);
35         return 0;
36     }
37     return 1;
38 }
39 
40 // Check if the last pdfium command failed and if so, forward the error to java via an exception. If
41 // this function returns true an exception is pending.
forwardPdfiumError(JNIEnv * env)42 bool forwardPdfiumError(JNIEnv* env) {
43     long error = FPDF_GetLastError();
44     switch (error) {
45         case FPDF_ERR_SUCCESS:
46             return false;
47         case FPDF_ERR_FILE:
48             jniThrowException(env, "java/io/IOException", "file not found or cannot be opened");
49             break;
50         case FPDF_ERR_FORMAT:
51             jniThrowException(env, "java/io/IOException", "file not in PDF format or corrupted");
52             break;
53         case FPDF_ERR_PASSWORD:
54             jniThrowException(env, "java/lang/SecurityException",
55                     "password required or incorrect password");
56             break;
57         case FPDF_ERR_SECURITY:
58             jniThrowException(env, "java/lang/SecurityException", "unsupported security scheme");
59             break;
60         case FPDF_ERR_PAGE:
61             jniThrowException(env, "java/io/IOException", "page not found or content error");
62             break;
63 #ifdef PDF_ENABLE_XFA
64         case FPDF_ERR_XFALOAD:
65             jniThrowException(env, "java/lang/Exception", "load XFA error");
66             break;
67         case FPDF_ERR_XFALAYOUT:
68             jniThrowException(env, "java/lang/Exception", "layout XFA error");
69             break;
70 #endif  // PDF_ENABLE_XFA
71         case FPDF_ERR_UNKNOWN:
72         default:
73             jniThrowExceptionFmt(env, "java/lang/Exception", "unknown error %d", error);
74     }
75 
76     return true;
77 }
78 
initializeLibraryIfNeeded(JNIEnv * env)79 static void initializeLibraryIfNeeded(JNIEnv* env) {
80     if (sUnmatchedPdfiumInitRequestCount == 0) {
81         FPDF_InitLibrary();
82     }
83 
84     sUnmatchedPdfiumInitRequestCount++;
85 }
86 
destroyLibraryIfNeeded(JNIEnv * env,bool handleError)87 static void destroyLibraryIfNeeded(JNIEnv* env, bool handleError) {
88     if (sUnmatchedPdfiumInitRequestCount == 1) {
89         FPDF_DestroyLibrary();
90     }
91 
92     sUnmatchedPdfiumInitRequestCount--;
93 }
94 
nativeOpen(JNIEnv * env,jclass thiz,jint fd,jlong size)95 jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) {
96     initializeLibraryIfNeeded(env);
97 
98     FPDF_FILEACCESS loader;
99     loader.m_FileLen = size;
100     loader.m_Param = reinterpret_cast<void*>(intptr_t(fd));
101     loader.m_GetBlock = &getBlock;
102 
103     FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL);
104     if (!document) {
105         forwardPdfiumError(env);
106         destroyLibraryIfNeeded(env, false);
107         return -1;
108     }
109 
110     return reinterpret_cast<jlong>(document);
111 }
112 
nativeClose(JNIEnv * env,jclass thiz,jlong documentPtr)113 void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) {
114     FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
115     FPDF_CloseDocument(document);
116 
117     destroyLibraryIfNeeded(env, true);
118 }
119 
nativeGetPageCount(JNIEnv * env,jclass thiz,jlong documentPtr)120 jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) {
121     FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
122 
123     return FPDF_GetPageCount(document);
124 }
125 
nativeScaleForPrinting(JNIEnv * env,jclass thiz,jlong documentPtr)126 jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) {
127     FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
128     FPDF_BOOL printScaling = FPDF_VIEWERREF_GetPrintScaling(document);
129 
130     return printScaling ? JNI_TRUE : JNI_FALSE;
131 }
132 
133 };
134