PdfEditor.cpp revision 12328c0fd190c7baddb5f412c48005371672dc55
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 1712328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann#include "PdfUtils.h" 1812328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann 1962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "jni.h" 2062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "JNIHelp.h" 21f4e341d99c4c29cb6cc7380829a316cf4847f3dfAndreas Gampe 22f4e341d99c4c29cb6cc7380829a316cf4847f3dfAndreas Gampe#pragma GCC diagnostic push 23f4e341d99c4c29cb6cc7380829a316cf4847f3dfAndreas Gampe#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" 2462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include "fpdfview.h" 25fbd02886559e7ca2b619ed0d9bff76b10cdb23c3Svet Ganov#include "fpdf_edit.h" 26fbd02886559e7ca2b619ed0d9bff76b10cdb23c3Svet Ganov#include "fpdf_save.h" 27bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav#include "fpdf_transformpage.h" 28f4e341d99c4c29cb6cc7380829a316cf4847f3dfAndreas Gampe#pragma GCC diagnostic pop 29f4e341d99c4c29cb6cc7380829a316cf4847f3dfAndreas Gampe 30bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav#include "SkMatrix.h" 3162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 32ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include <core_jni_helpers.h> 3362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <vector> 3462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <utils/Log.h> 3562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <unistd.h> 3662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <sys/types.h> 3762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav#include <unistd.h> 3862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 3962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavnamespace android { 4062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 41bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavenum PageBox {PAGE_BOX_MEDIA, PAGE_BOX_CROP}; 42bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 43bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic struct { 44bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jfieldID x; 45bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jfieldID y; 46bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} gPointClassInfo; 47bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 48bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic struct { 49bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jfieldID left; 50bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jfieldID top; 51bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jfieldID right; 52bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jfieldID bottom; 53bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} gRectClassInfo; 54bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 5562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic jint nativeRemovePage(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex) { 5662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 5712328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann 5862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDFPage_Delete(document, pageIndex); 5912328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) 6012328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann 6112328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann int pageCount = FPDF_GetPageCount(document); 6212328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) 6312328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann 6412328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann return pageCount; 6562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 6662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 6762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstruct PdfToFdWriter : FPDF_FILEWRITE { 6862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav int dstFd; 6962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 7062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 7162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic bool writeAllBytes(const int fd, const void* buffer, const size_t byteCount) { 7262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav char* writeBuffer = static_cast<char*>(const_cast<void*>(buffer)); 7362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav size_t remainingBytes = byteCount; 7462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav while (remainingBytes > 0) { 7562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav ssize_t writtenByteCount = write(fd, writeBuffer, remainingBytes); 7662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (writtenByteCount == -1) { 7762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (errno == EINTR) { 7862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav continue; 7962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 8062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, 8162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav "Error writing to buffer: %d", errno); 8262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return false; 8362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 8462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav remainingBytes -= writtenByteCount; 8562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav writeBuffer += writtenByteCount; 8662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 8762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return true; 8862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 8962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 9062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic int writeBlock(FPDF_FILEWRITE* owner, const void* buffer, unsigned long size) { 9162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const PdfToFdWriter* writer = reinterpret_cast<PdfToFdWriter*>(owner); 9262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const bool success = writeAllBytes(writer->dstFd, buffer, size); 9392ddfcfff5cec32456e2d1e0d96671f1eb0e2986Bernhard Rosenkränzer if (!success) { 9462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav ALOGE("Cannot write to file descriptor. Error:%d", errno); 9562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return 0; 9662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 9762ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav return 1; 9862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 9962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 10062ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavstatic void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) { 10162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 10262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav PdfToFdWriter writer; 10362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav writer.dstFd = fd; 10462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav writer.WriteBlock = &writeBlock; 10562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav const bool success = FPDF_SaveAsCopy(document, &writer, FPDF_NO_INCREMENTAL); 10662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav if (!success) { 10746d8444631b4b1253a76bfcc78a29d26014d022fDan Albert jniThrowExceptionFmt(env, "java/io/IOException", 10846d8444631b4b1253a76bfcc78a29d26014d022fDan Albert "cannot write to fd. Error: %d", errno); 10962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav } 11012328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE(env) 11162ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav} 11262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 113bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, 114bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jlong transformPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom) { 115bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 116bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 11761a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann FPDF_PAGE* page = (FPDF_PAGE*) FPDF_LoadPage(document, pageIndex); 118bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (!page) { 119bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jniThrowException(env, "java/lang/IllegalStateException", 120bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav "cannot open page"); 121bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return; 122bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 12312328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE(env); 124bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 125bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav double width = 0; 126bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav double height = 0; 127bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 128bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); 129bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (!result) { 130bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jniThrowException(env, "java/lang/IllegalStateException", 131bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav "cannot get page size"); 132bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return; 133bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 13412328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann bool isExceptionPending = forwardPdfiumError(env); 13512328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann if (isExceptionPending) { 13612328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann FPDF_ClosePage(page); 13712328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann return; 13812328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann } 139bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 14061a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann // PDF's coordinate system origin is left-bottom while in graphics it 14161a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann // is the top-left. So, translate the PDF coordinates to ours. 14261a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann SkMatrix reflectOnX = SkMatrix::MakeScale(1, -1); 14361a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann SkMatrix moveUp = SkMatrix::MakeTrans(0, FPDF_GetPageHeight(page)); 14461a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann SkMatrix coordinateChange = SkMatrix::Concat(moveUp, reflectOnX); 14561a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann 14661a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann // Apply the transformation what was created in our coordinates. 14761a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann SkMatrix matrix = SkMatrix::Concat(*reinterpret_cast<SkMatrix*>(transformPtr), 14861a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann coordinateChange); 14961a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann 15061a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann // Translate the result back to PDF coordinates. 15161a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann matrix.setConcat(coordinateChange, matrix); 152bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 153bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav SkScalar transformValues[6]; 15461a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann if (!matrix.asAffine(transformValues)) { 15512328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann FPDF_ClosePage(page); 15612328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann 15771487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed jniThrowException(env, "java/lang/IllegalArgumentException", 15871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed "transform matrix has perspective. Only affine matrices are allowed."); 15971487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed return; 16071487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed } 161bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 16261a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann FS_MATRIX transform = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], 16361a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], 16461a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann transformValues[SkMatrix::kATransX], 16561a530742f70e59d7fbd7c35a22292176ca554faPhilip P. Moltmann transformValues[SkMatrix::kATransY]}; 166bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 167bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; 168bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 169bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDFPage_TransFormWithClip(page, &transform, &clip); 17012328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann isExceptionPending = forwardPdfiumError(env); 17112328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann if (isExceptionPending) { 17212328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann FPDF_ClosePage(page); 17312328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann return; 17412328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann } 175bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 176bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_ClosePage(page); 17712328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE(env); 178bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 179bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 180bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, 181bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jint pageIndex, jobject outSize) { 182bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 183bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 184bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); 185bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (!page) { 186bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jniThrowException(env, "java/lang/IllegalStateException", 187bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav "cannot open page"); 188bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return; 189bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 19012328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE(env); 191bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 192bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav double width = 0; 193bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav double height = 0; 194bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 195bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); 196bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (!result) { 197bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jniThrowException(env, "java/lang/IllegalStateException", 198bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav "cannot get page size"); 199bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return; 200bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 20112328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann bool isExceptionPending = forwardPdfiumError(env); 20212328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann if (isExceptionPending) { 20312328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann FPDF_ClosePage(page); 20412328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann return; 20512328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann } 206bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 207bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav env->SetIntField(outSize, gPointClassInfo.x, width); 208bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav env->SetIntField(outSize, gPointClassInfo.y, height); 209bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 210bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_ClosePage(page); 21112328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE(env); 212bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 213bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 214bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, 215bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav PageBox pageBox, jobject outBox) { 216bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 217bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 218bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); 219bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (!page) { 220bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jniThrowException(env, "java/lang/IllegalStateException", 221bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav "cannot open page"); 222bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return false; 223bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 22412328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); 225bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 226bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav float left; 227bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav float top; 228bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav float right; 229bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav float bottom; 230bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 231bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const FPDF_BOOL success = (pageBox == PAGE_BOX_MEDIA) 232bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav ? FPDFPage_GetMediaBox(page, &left, &top, &right, &bottom) 233bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav : FPDFPage_GetCropBox(page, &left, &top, &right, &bottom); 23412328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann bool isExceptionPending = forwardPdfiumError(env); 23512328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann if (isExceptionPending) { 23612328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann FPDF_ClosePage(page); 23712328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann return false; 23812328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann } 239bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 240bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_ClosePage(page); 24112328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); 242bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 243bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (!success) { 244bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return false; 245bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 246bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 247bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav env->SetIntField(outBox, gRectClassInfo.left, (int) left); 248bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav env->SetIntField(outBox, gRectClassInfo.top, (int) top); 249bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav env->SetIntField(outBox, gRectClassInfo.right, (int) right); 250bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav env->SetIntField(outBox, gRectClassInfo.bottom, (int) bottom); 251bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 252bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return true; 253bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 254bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 255bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic jboolean nativeGetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, 256bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jobject outMediaBox) { 257bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const bool success = nativeGetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_MEDIA, 258bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav outMediaBox); 259bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return success ? JNI_TRUE : JNI_FALSE; 260bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 261bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 262bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic jboolean nativeGetPageCropBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, 263bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jobject outMediaBox) { 264bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const bool success = nativeGetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP, 265bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav outMediaBox); 266bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return success ? JNI_TRUE : JNI_FALSE; 267bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 268bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 269bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, 270bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav PageBox pageBox, jobject box) { 271bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); 272bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 273bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); 274bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (!page) { 275bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jniThrowException(env, "java/lang/IllegalStateException", 276bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav "cannot open page"); 277bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return; 278bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 27912328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE(env); 280bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 281bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const int left = env->GetIntField(box, gRectClassInfo.left); 282bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const int top = env->GetIntField(box, gRectClassInfo.top); 283bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const int right = env->GetIntField(box, gRectClassInfo.right); 284bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav const int bottom = env->GetIntField(box, gRectClassInfo.bottom); 285bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 286bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav if (pageBox == PAGE_BOX_MEDIA) { 287bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDFPage_SetMediaBox(page, left, top, right, bottom); 288bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } else { 289bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDFPage_SetCropBox(page, left, top, right, bottom); 290bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav } 29112328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann bool isExceptionPending = forwardPdfiumError(env); 29212328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann if (isExceptionPending) { 29312328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann FPDF_ClosePage(page); 29412328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann return; 29512328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann } 296bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 297bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav FPDF_ClosePage(page); 29812328c0fd190c7baddb5f412c48005371672dc55Philip P. Moltmann HANDLE_PDFIUM_ERROR_STATE(env); 299bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 300bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 301bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic void nativeSetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, 302bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jobject mediaBox) { 303bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_MEDIA, mediaBox); 304bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 305bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 306bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslavstatic void nativeSetPageCropBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, 307bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav jobject mediaBox) { 308bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP, mediaBox); 309bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav} 310bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 31176f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gPdfEditor_Methods[] = { 31262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeOpen", "(IJ)J", (void*) nativeOpen}, 31362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeClose", "(J)V", (void*) nativeClose}, 31462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, 31562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav {"nativeRemovePage", "(JI)I", (void*) nativeRemovePage}, 316bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeWrite", "(JI)V", (void*) nativeWrite}, 317bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeSetTransformAndClip", "(JIJIIII)V", (void*) nativeSetTransformAndClip}, 318bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeGetPageSize", "(JILandroid/graphics/Point;)V", (void*) nativeGetPageSize}, 319bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, 320bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeGetPageMediaBox", "(JILandroid/graphics/Rect;)Z", (void*) nativeGetPageMediaBox}, 321bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeSetPageMediaBox", "(JILandroid/graphics/Rect;)V", (void*) nativeSetPageMediaBox}, 322bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeGetPageCropBox", "(JILandroid/graphics/Rect;)Z", (void*) nativeGetPageCropBox}, 323bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav {"nativeSetPageCropBox", "(JILandroid/graphics/Rect;)V", (void*) nativeSetPageCropBox} 32462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 32562ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 32662ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslavint register_android_graphics_pdf_PdfEditor(JNIEnv* env) { 3277d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe const int result = RegisterMethodsOrDie( 32862ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav env, "android/graphics/pdf/PdfEditor", gPdfEditor_Methods, 32962ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav NELEM(gPdfEditor_Methods)); 330bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 3317d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe jclass pointClass = FindClassOrDie(env, "android/graphics/Point"); 3327d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe gPointClassInfo.x = GetFieldIDOrDie(env, pointClass, "x", "I"); 3337d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe gPointClassInfo.y = GetFieldIDOrDie(env, pointClass, "y", "I"); 334bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 3357d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe jclass rectClass = FindClassOrDie(env, "android/graphics/Rect"); 3367d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe gRectClassInfo.left = GetFieldIDOrDie(env, rectClass, "left", "I"); 3377d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe gRectClassInfo.top = GetFieldIDOrDie(env, rectClass, "top", "I"); 3387d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe gRectClassInfo.right = GetFieldIDOrDie(env, rectClass, "right", "I"); 3397d13d9db1ef90063cb542ccd6554042a6a3263b7Andreas Gampe gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClass, "bottom", "I"); 340bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav 341bec22beb99b279d381f720d761ca75fe3e7414dcSvetoslav return result; 34262ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 34362ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav 34462ce332c141cf7bc7200c4c87d63e395874fc3ecSvetoslav}; 345