137 lines
4.2 KiB
C++
137 lines
4.2 KiB
C++
/*
|
|
* 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 <nativehelper/JNIHelp.h>
|
|
|
|
#include "fpdfview.h"
|
|
|
|
#undef LOG_TAG
|
|
#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 void initializeLibraryIfNeeded(JNIEnv* env) {
|
|
if (sUnmatchedPdfiumInitRequestCount == 0) {
|
|
FPDF_InitLibrary();
|
|
}
|
|
|
|
sUnmatchedPdfiumInitRequestCount++;
|
|
}
|
|
|
|
static void destroyLibraryIfNeeded(JNIEnv* env, bool handleError) {
|
|
if (sUnmatchedPdfiumInitRequestCount == 1) {
|
|
FPDF_DestroyLibrary();
|
|
}
|
|
|
|
sUnmatchedPdfiumInitRequestCount--;
|
|
}
|
|
|
|
jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) {
|
|
initializeLibraryIfNeeded(env);
|
|
|
|
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);
|
|
|
|
destroyLibraryIfNeeded(env, true);
|
|
}
|
|
|
|
jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) {
|
|
FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
|
|
|
|
return FPDF_GetPageCount(document);
|
|
}
|
|
|
|
jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) {
|
|
FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
|
|
FPDF_BOOL printScaling = FPDF_VIEWERREF_GetPrintScaling(document);
|
|
|
|
return printScaling ? JNI_TRUE : JNI_FALSE;
|
|
}
|
|
|
|
};
|