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