blob: 6887fdacd68f02ae37d4579b40e78629432a988e [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
Steven Moreland60cc6c02017-08-25 15:49:25 -070019#include <nativehelper/JNIHelp.h>
Nolan Scobie7237e472023-08-04 16:50:41 -040020#include <utils/Log.h>
Philip P. Moltmann12328c02016-06-10 14:47:16 -070021
22#include "fpdfview.h"
Nolan Scobie7237e472023-08-04 16:50:41 -040023#include "jni.h"
Philip P. Moltmann12328c02016-06-10 14:47:16 -070024
25namespace android {
26
27static int sUnmatchedPdfiumInitRequestCount = 0;
28
29int 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.
42bool 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
Philip P. Moltmann7bc18b22017-08-28 15:13:09 -070079static void initializeLibraryIfNeeded(JNIEnv* env) {
Philip P. Moltmann12328c02016-06-10 14:47:16 -070080 if (sUnmatchedPdfiumInitRequestCount == 0) {
81 FPDF_InitLibrary();
Philip P. Moltmann12328c02016-06-10 14:47:16 -070082 }
83
84 sUnmatchedPdfiumInitRequestCount++;
Philip P. Moltmann12328c02016-06-10 14:47:16 -070085}
86
87static void destroyLibraryIfNeeded(JNIEnv* env, bool handleError) {
88 if (sUnmatchedPdfiumInitRequestCount == 1) {
Philip P. Moltmann7bc18b22017-08-28 15:13:09 -070089 FPDF_DestroyLibrary();
Philip P. Moltmann12328c02016-06-10 14:47:16 -070090 }
91
92 sUnmatchedPdfiumInitRequestCount--;
93}
94
95jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) {
Philip P. Moltmann7bc18b22017-08-28 15:13:09 -070096 initializeLibraryIfNeeded(env);
Philip P. Moltmann12328c02016-06-10 14:47:16 -070097
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
113void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) {
114 FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
115 FPDF_CloseDocument(document);
Philip P. Moltmann12328c02016-06-10 14:47:16 -0700116
117 destroyLibraryIfNeeded(env, true);
118}
119
120jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) {
121 FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
122
Philip P. Moltmann7bc18b22017-08-28 15:13:09 -0700123 return FPDF_GetPageCount(document);
Philip P. Moltmann12328c02016-06-10 14:47:16 -0700124}
125
126jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) {
127 FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
Philip P. Moltmann12328c02016-06-10 14:47:16 -0700128 FPDF_BOOL printScaling = FPDF_VIEWERREF_GetPrintScaling(document);
Philip P. Moltmann12328c02016-06-10 14:47:16 -0700129
130 return printScaling ? JNI_TRUE : JNI_FALSE;
131}
132
133};