PdfEditor.cpp revision ed6b9dff563c5e22f040ff37e12c0d771e0478ae
162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav/* 262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * Copyright (C) 2014 The Android Open Source Project 362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * 462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * Licensed under the Apache License, Version 2.0 (the "License"); 562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * you may not use this file except in compliance with the License. 662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * You may obtain a copy of the License at 762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * 862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * http://www.apache.org/licenses/LICENSE-2.0 962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * 1062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * Unless required by applicable law or agreed to in writing, software 1162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * distributed under the License is distributed on an "AS IS" BASIS, 1262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * See the License for the specific language governing permissions and 1462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav * limitations under the License. 1562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav */ 1662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 1762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "jni.h" 1862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "JNIHelp.h" 1962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "fpdfview.h" 2062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "fpdfedit.h" 2162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "fpdfsave.h" 2262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 23ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include <core_jni_helpers.h> 2462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <vector> 2562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <utils/Log.h> 2662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <unistd.h> 2762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <sys/types.h> 2862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <unistd.h> 2962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 3062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavnamespace android { 3162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 3262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic Mutex sLock; 3362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 3462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic int sUnmatchedInitRequestCount = 0; 3562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 3662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic void initializeLibraryIfNeeded() { 3762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav Mutex::Autolock _l(sLock); 3862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (sUnmatchedInitRequestCount == 0) { 3962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_InitLibrary(NULL); 4062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 4162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav sUnmatchedInitRequestCount++; 4262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 4362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 4462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic void destroyLibraryIfNeeded() { 4562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav Mutex::Autolock _l(sLock); 4662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav sUnmatchedInitRequestCount--; 4762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (sUnmatchedInitRequestCount == 0) { 4862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DestroyLibrary(); 4962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 5062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 5162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 5262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic int getBlock(void* param, unsigned long position, unsigned char* outBuffer, 5362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav unsigned long size) { 5462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const int fd = reinterpret_cast<intptr_t>(param); 5562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const int readCount = pread(fd, outBuffer, size, position); 5662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (readCount < 0) { 5762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav ALOGE("Cannot read from file descriptor. Error:%d", errno); 5862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return 0; 5962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 6062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return 1; 6162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 6262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 6362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { 6462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav initializeLibraryIfNeeded(); 6562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 6662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_FILEACCESS loader; 6762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav loader.m_FileLen = size; 6862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav loader.m_Param = reinterpret_cast<void*>(intptr_t(fd)); 6962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav loader.m_GetBlock = &getBlock; 7062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 7162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL); 7262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 7362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (!document) { 7462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const long error = FPDF_GetLastError(); 7546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert jniThrowExceptionFmt(env, "java/io/IOException", 7646d8444631b4b1253a76bfcc78a29d26014d022fDan Albert "cannot create document. Error: %ld", error); 7762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav destroyLibraryIfNeeded(); 7862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return -1; 7962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 8062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 8162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return reinterpret_cast<jlong>(document); 8262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 8362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 8462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { 8562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 8662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_CloseDocument(document); 8762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav destroyLibraryIfNeeded(); 8862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 8962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 9062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { 9162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 9262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return FPDF_GetPageCount(document); 9362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 9462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 9562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic jint nativeRemovePage(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex) { 9662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 9762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDFPage_Delete(document, pageIndex); 9862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return FPDF_GetPageCount(document); 9962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 10062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 10162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstruct PdfToFdWriter : FPDF_FILEWRITE { 10262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav int dstFd; 10362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 10462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 10562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic bool writeAllBytes(const int fd, const void* buffer, const size_t byteCount) { 10662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav char* writeBuffer = static_cast<char*>(const_cast<void*>(buffer)); 10762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav size_t remainingBytes = byteCount; 10862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav while (remainingBytes > 0) { 10962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav ssize_t writtenByteCount = write(fd, writeBuffer, remainingBytes); 11062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (writtenByteCount == -1) { 11162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (errno == EINTR) { 11262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav continue; 11362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 11462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, 11562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav "Error writing to buffer: %d", errno); 11662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return false; 11762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 11862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav remainingBytes -= writtenByteCount; 11962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav writeBuffer += writtenByteCount; 12062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 12162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return true; 12262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 12362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 12462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic int writeBlock(FPDF_FILEWRITE* owner, const void* buffer, unsigned long size) { 12562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const PdfToFdWriter* writer = reinterpret_cast<PdfToFdWriter*>(owner); 12662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const bool success = writeAllBytes(writer->dstFd, buffer, size); 12792ddfcfff5cec32456e2d1e0d96671f1eb0e2986Bernhard Rosenkränzer if (!success) { 12862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav ALOGE("Cannot write to file descriptor. Error:%d", errno); 12962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return 0; 13062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 13162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return 1; 13262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 13362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 13462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) { 13562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 13662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav PdfToFdWriter writer; 13762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav writer.dstFd = fd; 13862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav writer.WriteBlock = &writeBlock; 13962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const bool success = FPDF_SaveAsCopy(document, &writer, FPDF_NO_INCREMENTAL); 14062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (!success) { 14146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert jniThrowExceptionFmt(env, "java/io/IOException", 14246d8444631b4b1253a76bfcc78a29d26014d022fDan Albert "cannot write to fd. Error: %d", errno); 14362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav destroyLibraryIfNeeded(); 14462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 14562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 14662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 14762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic JNINativeMethod gPdfEditor_Methods[] = { 14862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeOpen", "(IJ)J", (void*) nativeOpen}, 14962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeClose", "(J)V", (void*) nativeClose}, 15062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, 15162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeRemovePage", "(JI)I", (void*) nativeRemovePage}, 15262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeWrite", "(JI)V", (void*) nativeWrite} 15362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 15462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 15562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavint register_android_graphics_pdf_PdfEditor(JNIEnv* env) { 156ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return android::RegisterMethodsOrDie( 15762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav env, "android/graphics/pdf/PdfEditor", gPdfEditor_Methods, 15862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav NELEM(gPdfEditor_Methods)); 15962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 16062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 16162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 162