Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/platform/java/jni/pdfdocument.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/platform/java/jni/pdfdocument.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,2035 @@ +// Copyright (C) 2004-2025 Artifex Software, Inc. +// +// This file is part of MuPDF. +// +// MuPDF is free software: you can redistribute it and/or modify it under the +// terms of the GNU Affero General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. +// +// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +// details. +// +// You should have received a copy of the GNU Affero General Public License +// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> +// +// Alternative licensing terms are available from the licensor. +// For commercial licensing, see <https://www.artifex.com/> or contact +// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, +// CA 94129, USA, for further information. + +/* PDFDocument interface */ + +static void free_event_cb_data(fz_context *ctx, void *data) +{ + jobject jlistener = (jobject)data; + jboolean detach = JNI_FALSE; + JNIEnv *env; + + env = jni_attach_thread(&detach); + if (env == NULL) + fz_warn(ctx, "cannot attach to JVM in free_event_cb_data"); + else + { + (*env)->DeleteGlobalRef(env, jlistener); + jni_detach_thread(detach); + } +} + +static void event_cb(fz_context *ctx, pdf_document *pdf, pdf_doc_event *event, void *data) +{ + jobject jlistener = (jobject)data; + jboolean detach = JNI_FALSE; + JNIEnv *env; + + env = jni_attach_thread(&detach); + if (env == NULL) + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in event_cb"); + + switch (event->type) + { + case PDF_DOCUMENT_EVENT_ALERT: + { + pdf_alert_event *alert; + jstring jtitle = NULL; + jstring jmessage = NULL; + jstring jcheckboxmsg = NULL; + jobject jalertresult; + jobject jpdf; + + alert = pdf_access_alert_event(ctx, event); + + jpdf = to_PDFDocument_safe(ctx, env, pdf); + if (!jpdf || (*env)->ExceptionCheck(env)) + fz_throw_java_and_detach_thread(ctx, env, detach); + + jtitle = (*env)->NewStringUTF(env, alert->title); + if (!jtitle || (*env)->ExceptionCheck(env)) + fz_throw_java_and_detach_thread(ctx, env, detach); + + jmessage = (*env)->NewStringUTF(env, alert->message); + if (!jmessage || (*env)->ExceptionCheck(env)) + fz_throw_java_and_detach_thread(ctx, env, detach); + + if (alert->has_check_box) { + jcheckboxmsg = (*env)->NewStringUTF(env, alert->check_box_message); + if (!jcheckboxmsg || (*env)->ExceptionCheck(env)) + fz_throw_java_and_detach_thread(ctx, env, detach); + } + + jalertresult = (*env)->CallObjectMethod(env, jlistener, mid_PDFDocument_JsEventListener_onAlert, jpdf, jtitle, jmessage, alert->icon_type, alert->button_group_type, alert->has_check_box, jcheckboxmsg, alert->initially_checked); + if ((*env)->ExceptionCheck(env)) + fz_throw_java_and_detach_thread(ctx, env, detach); + + if (jalertresult) + { + alert->button_pressed = (*env)->GetIntField(env, jalertresult, fid_AlertResult_buttonPressed); + alert->finally_checked = (*env)->GetBooleanField(env, jalertresult, fid_AlertResult_checkboxChecked); + } + } + break; + + default: + fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "event not yet implemented"); + break; + } + + jni_detach_thread(detach); +} + +JNIEXPORT jlong JNICALL +FUN(PDFDocument_newNative)(JNIEnv *env, jclass cls) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = NULL; + + if (!ctx) return 0; + + fz_try(ctx) + doc = pdf_create_document(ctx); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return jlong_cast(doc); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_finalize)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + if (!ctx || !pdf) return; + FUN(Document_finalize)(env, self); /* Call super.finalize() */ +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_countObjects)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + int count = 0; + + if (!ctx || !pdf) return 0; + + fz_try(ctx) + count = pdf_xref_len(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return count; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newNull)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = NULL; + jobject jobj; + + if (!ctx) return NULL; + + obj = PDF_NULL; + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newBoolean)(JNIEnv *env, jobject self, jboolean b) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = NULL; + jobject jobj; + + if (!ctx) return NULL; + + obj = b ? PDF_TRUE : PDF_FALSE; + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newInteger)(JNIEnv *env, jobject self, jint i) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = NULL; + jobject jobj; + + if (!ctx) return NULL; + + fz_try(ctx) + obj = pdf_new_int(ctx, i); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newReal)(JNIEnv *env, jobject self, jfloat f) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = NULL; + jobject jobj; + + if (!ctx) return NULL; + + fz_try(ctx) + obj = pdf_new_real(ctx, f); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newString)(JNIEnv *env, jobject self, jstring jstring) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = NULL; + const char *s = NULL; + jobject jobj; + + if (!ctx) return NULL; + if (!jstring) jni_throw_arg(env, "string must not be null"); + + s = (*env)->GetStringUTFChars(env, jstring, NULL); + if (!s) return NULL; + + fz_try(ctx) + obj = pdf_new_text_string(ctx, s); + fz_always(ctx) + (*env)->ReleaseStringUTFChars(env, jstring, s); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newByteString)(JNIEnv *env, jobject self, jobject jbs) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = NULL; + jbyte *bs; + size_t bslen; + jobject jobj; + + if (!ctx) return NULL; + if (!jbs) jni_throw_arg(env, "bs must not be null"); + + bslen = (*env)->GetArrayLength(env, jbs); + + fz_try(ctx) + bs = Memento_label(fz_malloc(ctx, bslen), "PDFDocument_newByteString"); + fz_catch(ctx) + jni_rethrow(env, ctx); + + (*env)->GetByteArrayRegion(env, jbs, 0, bslen, bs); + if ((*env)->ExceptionCheck(env)) + { + fz_free(ctx, bs); + return NULL; + } + + fz_try(ctx) + obj = pdf_new_string(ctx, (char *) bs, bslen); + fz_always(ctx) + fz_free(ctx, bs); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newName)(JNIEnv *env, jobject self, jstring jname) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = NULL; + const char *name = NULL; + jobject jobj; + + if (!ctx) return NULL; + if (!jname) jni_throw_arg(env, "name must not be null"); + + name = (*env)->GetStringUTFChars(env, jname, NULL); + if (!name) return NULL; + + fz_try(ctx) + obj = pdf_new_name(ctx, name); + fz_always(ctx) + (*env)->ReleaseStringUTFChars(env, jname, name); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newIndirect)(JNIEnv *env, jobject self, jint num, jint gen) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = NULL; + jobject jobj; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + obj = pdf_new_indirect(ctx, pdf, num, gen); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newArray)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = NULL; + jobject jobj; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + obj = pdf_new_array(ctx, pdf, 0); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newDictionary)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = NULL; + jobject jobj; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + obj = pdf_new_dict(ctx, pdf, 0); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jobj = (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj)); + if (!jobj) + pdf_drop_obj(ctx, obj); + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_findPage)(JNIEnv *env, jobject self, jint jat) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = NULL; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + obj = pdf_lookup_page_obj(ctx, pdf, jat); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe(ctx, env, obj); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_getTrailer)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = NULL; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + obj = pdf_trailer(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe(ctx, env, obj); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addObject)(JNIEnv *env, jobject self, jobject jobj) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = from_PDFObject(env, jobj); + + if (!ctx || !pdf) return NULL; + if (!jobj) jni_throw_arg(env, "object must not be null"); + + fz_try(ctx) + obj = pdf_add_object_drop(ctx, pdf, obj); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return jobj; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_createObject)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + ind = pdf_new_indirect(ctx, pdf, pdf_create_object(ctx, pdf), 0); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_deleteObject)(JNIEnv *env, jobject self, jint num) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_delete_object(ctx, pdf, num); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_newPDFGraftMap)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_graft_map *map = NULL; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + map = pdf_new_graft_map(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFGraftMap_safe_own(ctx, env, self, map); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_graftObject)(JNIEnv *env, jobject self, jobject jobj) +{ + fz_context *ctx = get_context(env); + pdf_obj *obj = from_PDFObject(env, jobj); + pdf_document *dst = from_PDFDocument(env, self); + + if (!ctx || !dst) return NULL; + if (!dst) jni_throw_arg(env, "dst must not be null"); + if (!obj) jni_throw_arg(env, "object must not be null"); + + fz_try(ctx) + obj = pdf_graft_object(ctx, dst, obj); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, obj); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addStreamBuffer)(JNIEnv *env, jobject self, jobject jbuf, jobject jobj, jboolean compressed) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = from_PDFObject(env, jobj); + fz_buffer *buf = from_Buffer(env, jbuf); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + if (!jbuf) jni_throw_arg(env, "buffer must not be null"); + + fz_try(ctx) + ind = pdf_add_stream(ctx, pdf, buf, obj, compressed); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addStreamString)(JNIEnv *env, jobject self, jstring jbuf, jobject jobj, jboolean compressed) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + pdf_obj *obj = from_PDFObject(env, jobj); + fz_buffer *buf = NULL; + const char *sbuf = NULL; + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + if (!jbuf) jni_throw_arg(env, "buffer must not be null"); + + sbuf = (*env)->GetStringUTFChars(env, jbuf, NULL); + if (!sbuf) return NULL; + + fz_var(buf); + + fz_try(ctx) + { + buf = fz_new_buffer_from_copied_data(ctx, (const unsigned char *)sbuf, strlen(sbuf)); + ind = pdf_add_stream(ctx, pdf, buf, obj, compressed); + } + fz_always(ctx) + { + fz_drop_buffer(ctx, buf); + (*env)->ReleaseStringUTFChars(env, jbuf, sbuf); + } + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addPageBuffer)(JNIEnv *env, jobject self, jobject jmediabox, jint rotate, jobject jresources, jobject jcontents) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + fz_rect mediabox = from_Rect(env, jmediabox); + pdf_obj *resources = from_PDFObject(env, jresources); + fz_buffer *contents = from_Buffer(env, jcontents); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + + fz_try(ctx) + ind = pdf_add_page(ctx, pdf, mediabox, rotate, resources, contents); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addPageString)(JNIEnv *env, jobject self, jobject jmediabox, jint rotate, jobject jresources, jstring jcontents) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + fz_rect mediabox = from_Rect(env, jmediabox); + pdf_obj *resources = from_PDFObject(env, jresources); + const char *scontents = NULL; + fz_buffer *contents = NULL; + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + + scontents = (*env)->GetStringUTFChars(env, jcontents, NULL); + if (!scontents) return NULL; + + fz_var(contents); + + fz_try(ctx) + { + contents = fz_new_buffer_from_copied_data(ctx, (const unsigned char *)scontents, strlen(scontents)); + ind = pdf_add_page(ctx, pdf, mediabox, rotate, resources, contents); + } + fz_always(ctx) + { + fz_drop_buffer(ctx, contents); + (*env)->ReleaseStringUTFChars(env, jcontents, scontents); + } + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_insertPage)(JNIEnv *env, jobject self, jint jat, jobject jpage) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + int at = jat; + pdf_obj *page = from_PDFObject(env, jpage); + + if (!ctx || !pdf) return; + if (!page) jni_throw_arg_void(env, "page must not be null"); + + fz_try(ctx) + pdf_insert_page(ctx, pdf, at, page); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_deletePage)(JNIEnv *env, jobject self, jint jat) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + int at = jat; + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_delete_page(ctx, pdf, at); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addImage)(JNIEnv *env, jobject self, jobject jimage) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + fz_image *image = from_Image(env, jimage); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + if (!image) jni_throw_arg(env, "image must not be null"); + + fz_try(ctx) + ind = pdf_add_image(ctx, pdf, image); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addFont)(JNIEnv *env, jobject self, jobject jfont) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + fz_font *font = from_Font(env, jfont); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + if (!font) jni_throw_arg(env, "font must not be null"); + + fz_try(ctx) + ind = pdf_add_cid_font(ctx, pdf, font); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addCJKFont)(JNIEnv *env, jobject self, jobject jfont, jint ordering, jint wmode, jboolean serif) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + fz_font *font = from_Font(env, jfont); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + if (!font) jni_throw_arg(env, "font must not be null"); + + fz_try(ctx) + ind = pdf_add_cjk_font(ctx, pdf, font, ordering, wmode, serif); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addSimpleFont)(JNIEnv *env, jobject self, jobject jfont, jint encoding) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + fz_font *font = from_Font(env, jfont); + pdf_obj *ind = NULL; + + if (!ctx || !pdf) return NULL; + if (!font) jni_throw_arg(env, "font must not be null"); + + fz_try(ctx) + ind = pdf_add_simple_font(ctx, pdf, font, encoding); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, ind); +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_hasUnsavedChanges)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + if (!ctx || !pdf) return JNI_FALSE; + return pdf_has_unsaved_changes(ctx, pdf) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_wasRepaired)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + if (!ctx || !pdf) return JNI_FALSE; + return pdf_was_repaired(ctx, pdf) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_canBeSavedIncrementally)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + if (!ctx || !pdf) return JNI_FALSE; + return pdf_can_be_saved_incrementally(ctx, pdf) ? JNI_TRUE : JNI_FALSE; +} + +static fz_stream * +SeekableOutputStream_as_stream(fz_context *ctx, void *opaque) +{ + SeekableStreamState *in_state = opaque; + SeekableStreamState *state; + fz_stream *stm; + + state = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_state"); + state->stream = in_state->stream; + state->array = in_state->array; + + stm = fz_new_stream(ctx, state, SeekableInputStream_next, fz_free); + stm->seek = SeekableInputStream_seek; + + return stm; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_nativeSaveWithStream)(JNIEnv *env, jobject self, jobject jstream, jstring joptions) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + SeekableStreamState *state = NULL; + jobject stream = NULL; + jbyteArray array = NULL; + fz_output *out = NULL; + const char *options = NULL; + pdf_write_options pwo; + + fz_var(state); + fz_var(out); + fz_var(stream); + fz_var(array); + + if (!ctx || !pdf) return; + if (!jstream) jni_throw_arg_void(env, "stream must not be null"); + + if (joptions) + { + options = (*env)->GetStringUTFChars(env, joptions, NULL); + if (!options) return; + } + + stream = (*env)->NewGlobalRef(env, jstream); + if (!stream) + { + if (options) (*env)->ReleaseStringUTFChars(env, joptions, options); + return; + } + + array = (*env)->NewByteArray(env, sizeof state->buffer); + if ((*env)->ExceptionCheck(env)) + { + if (options) (*env)->ReleaseStringUTFChars(env, joptions, options); + (*env)->DeleteGlobalRef(env, stream); + return; + } + if (!array) + { + if (options) (*env)->ReleaseStringUTFChars(env, joptions, options); + (*env)->DeleteGlobalRef(env, stream); + jni_throw_run_void(env, "cannot create byte array"); + } + + array = (*env)->NewGlobalRef(env, array); + if (!array) + { + if (options) (*env)->ReleaseStringUTFChars(env, joptions, options); + (*env)->DeleteGlobalRef(env, stream); + jni_throw_run_void(env, "cannot create global reference"); + } + + fz_try(ctx) + { + if (jstream) + { + /* No exceptions can occur from here to stream owning state, so we must not free state. */ + state = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_state"); + state->stream = stream; + state->array = array; + + /* Ownership transferred to state. */ + stream = NULL; + array = NULL; + + /* Stream takes ownership of state. */ + out = fz_new_output(ctx, sizeof state->buffer, state, SeekableOutputStream_write, NULL, SeekableOutputStream_drop); + out->seek = SeekableOutputStream_seek; + out->tell = SeekableOutputStream_tell; + out->truncate = SeekableOutputStream_truncate; + out->as_stream = SeekableOutputStream_as_stream; + + /* these are now owned by 'out' */ + state = NULL; + } + + pdf_parse_write_options(ctx, &pwo, options); + pdf_write_document(ctx, pdf, out, &pwo); + fz_close_output(ctx, out); + } + fz_always(ctx) + { + fz_drop_output(ctx, out); + if (options) + (*env)->ReleaseStringUTFChars(env, joptions, options); + } + fz_catch(ctx) + { + (*env)->DeleteGlobalRef(env, array); + (*env)->DeleteGlobalRef(env, stream); + jni_rethrow_void(env, ctx); + } +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_save)(JNIEnv *env, jobject self, jstring jfilename, jstring joptions) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + const char *filename = NULL; + const char *options = NULL; + pdf_write_options pwo; + + if (!ctx || !pdf) return; + if (!jfilename) jni_throw_arg_void(env, "filename must not be null"); + + filename = (*env)->GetStringUTFChars(env, jfilename, NULL); + if (!filename) return; + + if (joptions) + { + options = (*env)->GetStringUTFChars(env, joptions, NULL); + if (!options) + { + (*env)->ReleaseStringUTFChars(env, jfilename, filename); + return; + } + } + + fz_try(ctx) + { + pdf_parse_write_options(ctx, &pwo, options); + pdf_save_document(ctx, pdf, filename, &pwo); + } + fz_always(ctx) + { + if (options) + (*env)->ReleaseStringUTFChars(env, joptions, options); + (*env)->ReleaseStringUTFChars(env, jfilename, filename); + } + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_enableJs)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_enable_js(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_disableJs)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_disable_js(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_isJsSupported)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + jboolean supported = JNI_FALSE; + + if (!ctx || !pdf) return JNI_FALSE; + + fz_try(ctx) + supported = pdf_js_supported(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return supported; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_setJsEventListener)(JNIEnv *env, jobject self, jobject jlistener) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + + if (!ctx || !pdf) return; + if (!jlistener) jni_throw_arg_void(env, "listener must not be null"); + + jlistener = (*env)->NewGlobalRef(env, jlistener); + if (!jlistener) jni_throw_arg_void(env, "unable to get reference to listener"); + + fz_try(ctx) + pdf_set_doc_event_callback(ctx, pdf, event_cb, free_event_cb_data, jlistener); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_calculate)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + if (pdf->recalculate) + pdf_calculate_form(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_countVersions)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + int val = 0; + + if (!ctx || !pdf) return 0; + + fz_try(ctx) + val = pdf_count_versions(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return val; +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_countUnsavedVersions)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + int val = 0; + + if (!ctx || !pdf) return 0; + + fz_try(ctx) + val = pdf_count_unsaved_versions(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return val; +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_validateChangeHistory)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + int val = 0; + + if (!ctx || !pdf) return 0; + + fz_try(ctx) + val = pdf_validate_change_history(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return val; +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_wasPureXFA)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + jboolean val = JNI_FALSE; + + if (!ctx || !pdf) return JNI_FALSE; + + fz_try(ctx) + val = pdf_was_pure_xfa(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return val; +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_wasLinearized)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + jboolean val = JNI_FALSE; + + if (!ctx || !pdf) return JNI_FALSE; + + fz_try(ctx) + val = pdf_doc_was_linearized(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return val; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_graftPage)(JNIEnv *env, jobject self, jint pageTo, jobject jobj, jint pageFrom) +{ + fz_context *ctx = get_context(env); + pdf_document *src = from_PDFDocument(env, jobj); + pdf_document *dst = from_PDFDocument(env, self); + + if (!ctx || !dst) return; + if (!src) jni_throw_arg_void(env, "Source Document must not be null"); + + fz_try(ctx) + pdf_graft_page(ctx, dst, pageTo, src, pageFrom); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_enableJournal)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + pdf_enable_journal(ctx, pdf); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_saveJournalWithStream)(JNIEnv *env, jobject self, jobject jstream) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + SeekableStreamState *state = NULL; + jobject stream = NULL; + jbyteArray array = NULL; + fz_output *out = NULL; + + if (!ctx || !pdf) + return; + if (!jstream) + jni_throw_arg_void(env, "stream must not be null"); + + fz_var(state); + fz_var(out); + fz_var(stream); + fz_var(array); + + stream = (*env)->NewGlobalRef(env, jstream); + if (!stream) + jni_throw_run_void(env, "invalid stream"); + + array = (*env)->NewByteArray(env, sizeof state->buffer); + if ((*env)->ExceptionCheck(env)) + { + (*env)->DeleteGlobalRef(env, stream); + return; + } + if (!array) + { + (*env)->DeleteGlobalRef(env, stream); + jni_throw_run_void(env, "cannot create byte array"); + } + + array = (*env)->NewGlobalRef(env, array); + if (!array) + { + (*env)->DeleteGlobalRef(env, stream); + jni_throw_run_void(env, "cannot create global reference"); + } + + fz_try(ctx) + { + /* No exceptions can occur from here to stream owning state, so we must not free state. */ + state = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_state"); + state->stream = stream; + state->array = array; + + /* Ownership transferred to state. */ + stream = NULL; + array = NULL; + + /* Stream takes ownership of state. */ + out = fz_new_output(ctx, sizeof state->buffer, state, SeekableOutputStream_write, NULL, SeekableOutputStream_drop); + out->seek = SeekableOutputStream_seek; + out->tell = SeekableOutputStream_tell; + out->truncate = SeekableOutputStream_truncate; + out->as_stream = SeekableOutputStream_as_stream; + + /* these are now owned by 'out' */ + state = NULL; + + pdf_write_journal(ctx, pdf, out); + fz_close_output(ctx, out); + } + fz_always(ctx) + { + fz_drop_output(ctx, out); + } + fz_catch(ctx) + { + (*env)->DeleteGlobalRef(env, array); + (*env)->DeleteGlobalRef(env, stream); + jni_rethrow_void(env, ctx); + } +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_loadJournalWithStream)(JNIEnv *env, jobject self, jobject jstream) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + SeekableStreamState *state = NULL; + jobject stream = NULL; + jbyteArray array = NULL; + fz_stream *stm = NULL; + + if (!ctx || !pdf) + return; + if (!jstream) + jni_throw_arg_void(env, "stream must not be null"); + + fz_var(state); + fz_var(stm); + fz_var(stream); + fz_var(array); + + stream = (*env)->NewGlobalRef(env, jstream); + if (!stream) + jni_throw_run_void(env, "invalid stream"); + + array = (*env)->NewByteArray(env, sizeof state->buffer); + if ((*env)->ExceptionCheck(env)) + { + (*env)->DeleteGlobalRef(env, stream); + return; + } + if (!array) + { + (*env)->DeleteGlobalRef(env, stream); + jni_throw_run_void(env, "cannot create byte array"); + } + + array = (*env)->NewGlobalRef(env, array); + if (!array) + { + (*env)->DeleteGlobalRef(env, stream); + jni_throw_run_void(env, "cannot create global reference"); + } + + fz_try(ctx) + { + /* No exceptions can occur from here to stream owning state, so we must not free state. */ + state = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_state"); + state->stream = stream; + state->array = array; + + /* Ownership transferred to state. */ + stream = NULL; + array = NULL; + + /* Stream takes ownership of accstate. */ + stm = fz_new_stream(ctx, state, SeekableInputStream_next, SeekableInputStream_drop); + stm->seek = SeekableInputStream_seek; + + pdf_read_journal(ctx, pdf, stm); + } + fz_always(ctx) + { + fz_drop_stream(ctx, stm); + } + fz_catch(ctx) + { + (*env)->DeleteGlobalRef(env, array); + (*env)->DeleteGlobalRef(env, stream); + jni_rethrow_void(env, ctx); + } +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_saveJournal)(JNIEnv *env, jobject self, jstring jfilename) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + const char *filename = NULL; + + if (!ctx || !pdf) + return; + if (!jfilename) + jni_throw_arg_void(env, "filename must not be null"); + + filename = (*env)->GetStringUTFChars(env, jfilename, NULL); + if (!filename) + jni_throw_run_void(env, "cannot get characters in filename"); + + fz_try(ctx) + pdf_save_journal(ctx, pdf, filename); + fz_always(ctx) + (*env)->ReleaseStringUTFChars(env, jfilename, filename); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_loadJournal)(JNIEnv *env, jobject self, jstring jfilename) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + const char *filename = NULL; + + if (!ctx || !pdf) + return; + if (!jfilename) + jni_throw_arg_void(env, "filename must not be null"); + + filename = (*env)->GetStringUTFChars(env, jfilename, NULL); + if (!filename) + jni_throw_run_void(env, "cannot get characters in filename"); + + fz_try(ctx) + pdf_load_journal(ctx, pdf, filename); + fz_always(ctx) + (*env)->ReleaseStringUTFChars(env, jfilename, filename); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_undoRedoPosition)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + int steps; + + if (!ctx || !pdf) return 0; + + return pdf_undoredo_state(ctx, pdf, &steps); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_undoRedoSteps)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + int steps; + + if (!ctx || !pdf) return 0; + + (void)pdf_undoredo_state(ctx, pdf, &steps); + + return steps; +} + +JNIEXPORT jstring JNICALL +FUN(PDFDocument_undoRedoStep)(JNIEnv *env, jobject self, jint n) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + const char *step; + + if (!ctx || !pdf) return NULL; + + step = pdf_undoredo_step(ctx, pdf, n); + + return (*env)->NewStringUTF(env, step); +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_canUndo)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + jboolean can = JNI_FALSE; + + if (!ctx || !pdf) return JNI_FALSE; + + fz_try(ctx) + can = pdf_can_undo(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return can; +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_canRedo)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + jboolean can = JNI_FALSE; + + if (!ctx || !pdf) return JNI_FALSE; + + fz_try(ctx) + can = pdf_can_redo(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return can; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_undo)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_undo(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_redo)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_redo(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_beginOperation)(JNIEnv *env, jobject self, jstring joperation) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + const char *operation = NULL; + + if (!ctx || !pdf) return; + if (!joperation) jni_throw_arg_void(env, "operation must not be null"); + + operation = (*env)->GetStringUTFChars(env, joperation, NULL); + if (!operation) return; + + fz_try(ctx) + pdf_begin_operation(ctx, pdf, operation); + fz_always(ctx) + (*env)->ReleaseStringUTFChars(env, joperation, operation); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_beginImplicitOperation)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_begin_implicit_operation(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_endOperation)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_end_operation(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_abandonOperation)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_abandon_operation(ctx, pdf); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_isRedacted)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return JNI_FALSE; + return pdf->redacted; +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_getLanguage)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + int lang; + + if (!ctx || !pdf) return FZ_LANG_UNSET; + + fz_try(ctx) + lang = pdf_document_language(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return lang; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_setLanguage)(JNIEnv *env, jobject self, jint lang) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + + if (!ctx || !pdf) return; + + fz_try(ctx) + pdf_set_document_language(ctx, pdf, lang); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_countSignatures)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + jint val = -1; + + if (!ctx || !pdf) return -1; + + fz_try(ctx) + val = pdf_count_signatures(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return val; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_addEmbeddedFile)(JNIEnv *env, jobject self, jstring jfilename, jstring jmimetype, jobject jcontents, jlong created, jlong modified, jboolean addChecksum) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + const char *filename = NULL; + const char *mimetype = NULL; + fz_buffer *contents = from_Buffer(env, jcontents); + pdf_obj *fs = NULL; + + if (!ctx || !pdf) return NULL; + if (!jfilename) jni_throw_arg(env, "filename must not be null"); + + filename = (*env)->GetStringUTFChars(env, jfilename, NULL); + if (!filename) return NULL; + + if (jmimetype) + { + mimetype = (*env)->GetStringUTFChars(env, jmimetype, NULL); + if (!mimetype) + { + (*env)->ReleaseStringUTFChars(env, jfilename, filename); + return NULL; + } + } + + fz_try(ctx) + fs = pdf_add_embedded_file(ctx, pdf, filename, mimetype, contents, created, modified, addChecksum); + fz_always(ctx) + { + if (mimetype) + (*env)->ReleaseStringUTFChars(env, jmimetype, mimetype); + (*env)->ReleaseStringUTFChars(env, jfilename, filename); + } + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe(ctx, env, fs); +} + +JNIEXPORT jstring JNICALL +FUN(PDFDocument_getFilespecParams)(JNIEnv *env, jobject self, jobject jfs) +{ + fz_context *ctx = get_context(env); + pdf_obj *fs = from_PDFObject_safe(env, jfs); + pdf_filespec_params params; + jstring jfilename = NULL; + jstring jmimetype = NULL; + + fz_try(ctx) + pdf_get_filespec_params(ctx, fs, ¶ms); + fz_catch(ctx) + jni_rethrow(env, ctx); + + jfilename = (*env)->NewStringUTF(env, params.filename); + if (!jfilename || (*env)->ExceptionCheck(env)) + return NULL; + + jmimetype = (*env)->NewStringUTF(env, params.mimetype); + if (!jmimetype || (*env)->ExceptionCheck(env)) + return NULL; + + return (*env)->NewObject(env, cls_PDFDocument_PDFEmbeddedFileParams, mid_PDFDocument_PDFEmbeddedFileParams_init, + jfilename, jmimetype, params.size, params.created * 1000, params.modified * 1000); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_loadEmbeddedFileContents)(JNIEnv *env, jobject self, jobject jfs) +{ + fz_context *ctx = get_context(env); + pdf_obj *fs = from_PDFObject_safe(env, jfs); + fz_buffer *contents = NULL; + + fz_try(ctx) + contents = pdf_load_embedded_file_contents(ctx, fs); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_Buffer_safe(ctx, env, contents); +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_verifyEmbeddedFileChecksum)(JNIEnv *env, jobject self, jobject jfs) +{ + fz_context *ctx = get_context(env); + pdf_obj *fs = from_PDFObject_safe(env, jfs); + int valid = 0; + + fz_try(ctx) + valid = pdf_verify_embedded_file_checksum(ctx, fs); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return valid ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_isEmbeddedFile)(JNIEnv *env, jobject self, jobject jfs) +{ + fz_context *ctx = get_context(env); + pdf_obj *fs = from_PDFObject_safe(env, jfs); + int embedded = 0; + + fz_try(ctx) + embedded = pdf_is_embedded_file(ctx, fs); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return embedded ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_setPageLabels)(JNIEnv *env, jobject self, jint index, jint style, jstring jprefix, jint start) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + const char *prefix = NULL; + + if (jprefix) + { + prefix = (*env)->GetStringUTFChars(env, jprefix, NULL); + if (!prefix) return; + } + + fz_try(ctx) + { + pdf_set_page_labels(ctx, pdf, index, style, prefix, start); + } + fz_always(ctx) + { + if (jprefix) + (*env)->ReleaseStringUTFChars(env, jprefix, prefix); + } + fz_catch(ctx) + { + jni_rethrow_void(env, ctx); + } +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_deletePageLabels)(JNIEnv *env, jobject self, jint index) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument_safe(env, self); + fz_try(ctx) + pdf_delete_page_labels(ctx, pdf, index); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_getVersion)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + int version = 0; + + if (!ctx || !pdf) return 0; + + fz_try(ctx) + version = pdf_version(ctx, pdf); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return version; +} + +JNIEXPORT jstring JNICALL +FUN(PDFDocument_formatURIFromPathAndNamedDest)(JNIEnv *env, jclass cls, jstring jpath, jstring jname) +{ + fz_context *ctx = get_context(env); + char *uri = NULL; + jobject juri; + const char *path = NULL; + const char *name = NULL; + + if (jpath) + { + path = (*env)->GetStringUTFChars(env, jpath, NULL); + if (!path) return NULL; + } + if (jname) + { + name = (*env)->GetStringUTFChars(env, jname, NULL); + if (!name) return NULL; + } + + fz_try(ctx) + uri = pdf_new_uri_from_path_and_named_dest(ctx, path, name); + fz_always(ctx) + { + if (jname) + (*env)->ReleaseStringUTFChars(env, jname, name); + if (jpath) + (*env)->ReleaseStringUTFChars(env, jpath, path); + } + fz_catch(ctx) + jni_rethrow(env, ctx); + + juri = (*env)->NewStringUTF(env, uri); + fz_free(ctx, uri); + return juri; +} + +JNIEXPORT jstring JNICALL +FUN(PDFDocument_formatURIFromPathAndExplicitDest)(JNIEnv *env, jclass cls, jstring jpath, jobject jdest) +{ + fz_context *ctx = get_context(env); + fz_link_dest dest = from_LinkDestination(env, jdest); + char *uri = NULL; + jobject juri; + const char *path = NULL; + + if (jpath) + { + path = (*env)->GetStringUTFChars(env, jpath, NULL); + if (!path) return NULL; + } + + fz_try(ctx) + uri = pdf_new_uri_from_path_and_explicit_dest(ctx, path, dest); + fz_always(ctx) + { + if (jpath) + (*env)->ReleaseStringUTFChars(env, jpath, path); + } + fz_catch(ctx) + jni_rethrow(env, ctx); + + juri = (*env)->NewStringUTF(env, uri); + fz_free(ctx, uri); + return juri; +} + +JNIEXPORT jstring JNICALL +FUN(PDFDocument_appendNamedDestToURI)(JNIEnv *env, jclass cls, jstring jurl, jstring jname) +{ + fz_context *ctx = get_context(env); + char *uri = NULL; + jobject juri; + const char *url = NULL; + const char *name = NULL; + + if (jurl) + { + url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (!url) return NULL; + } + if (jname) + { + name = (*env)->GetStringUTFChars(env, jname, NULL); + if (!name) return NULL; + } + + fz_try(ctx) + uri = pdf_append_named_dest_to_uri(ctx, url, name); + fz_always(ctx) + { + if (jname) + (*env)->ReleaseStringUTFChars(env, jname, name); + if (jurl) + (*env)->ReleaseStringUTFChars(env, jurl, url); + } + fz_catch(ctx) + jni_rethrow(env, ctx); + + juri = (*env)->NewStringUTF(env, uri); + fz_free(ctx, uri); + return juri; +} + +JNIEXPORT jstring JNICALL +FUN(PDFDocument_appendExplicitDestToURI)(JNIEnv *env, jclass cls, jstring jurl, jobject jdest) +{ + fz_context *ctx = get_context(env); + fz_link_dest dest = from_LinkDestination(env, jdest); + char *uri = NULL; + jobject juri; + const char *url = NULL; + + if (jurl) + { + url = (*env)->GetStringUTFChars(env, jurl, NULL); + if (!url) return NULL; + } + + fz_try(ctx) + uri = pdf_append_explicit_dest_to_uri(ctx, url, dest); + fz_always(ctx) + { + if (jurl) + (*env)->ReleaseStringUTFChars(env, jurl, url); + } + fz_catch(ctx) + jni_rethrow(env, ctx); + + juri = (*env)->NewStringUTF(env, uri); + fz_free(ctx, uri); + return juri; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_rearrangePages)(JNIEnv *env, jobject self, jobject jpages) +{ + fz_context *ctx = get_context(env); + pdf_document *pdf = from_PDFDocument(env, self); + jsize len = 0; + int *pages = NULL; + + if (!ctx || !pdf) return; + + len = (*env)->GetArrayLength(env, jpages); + fz_try(ctx) + pages = fz_malloc_array(ctx, len, int); + fz_catch(ctx) + jni_rethrow_void(env, ctx); + + (*env)->GetIntArrayRegion(env, jpages, 0, len, pages); + if ((*env)->ExceptionCheck(env)) + { + fz_free(ctx, pages); + return; + } + + fz_try(ctx) + pdf_rearrange_pages(ctx, pdf, len, pages, PDF_CLEAN_STRUCTURE_DROP); + fz_always(ctx) + fz_free(ctx, pages); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_countAssociatedFiles)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + int n; + + if (!ctx) return 0; + + fz_try(ctx) + n = pdf_count_document_associated_files(ctx, doc); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return n; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_associatedFile)(JNIEnv *env, jobject self, jint idx) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + pdf_obj *af; + + if (!ctx) return NULL; + + fz_try(ctx) + af = pdf_document_associated_file(ctx, doc, idx); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, af); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_zugferdProfile)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + enum pdf_zugferd_profile p; + float version; + + if (!ctx) return 0; + + fz_try(ctx) + p = pdf_zugferd_profile(ctx, doc, &version); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return (int)p; +} + +JNIEXPORT jfloat JNICALL +FUN(PDFDocument_zugferdVersion)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + float version; + + if (!ctx) return 0; + + fz_try(ctx) + (void) pdf_zugferd_profile(ctx, doc, &version); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return (jfloat)version; +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_zugferdXML)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + fz_buffer *buf; + + if (!ctx) return NULL; + + fz_try(ctx) + buf = pdf_zugferd_xml(ctx, doc); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_Buffer_safe_own(ctx, env, buf); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_loadImage)(JNIEnv *env, jobject self, jobject jobj) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + pdf_obj *obj = from_PDFObject(env, jobj); + fz_image *img; + + if (!ctx) return NULL; + + fz_try(ctx) + img = pdf_load_image(ctx, doc, obj); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_Image_safe_own(ctx, env, img); +} + +JNIEXPORT jobject JNICALL +FUN(PDFDocument_lookupDest)(JNIEnv *env, jobject self, jobject jdest) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + pdf_obj *dest = from_PDFObject(env, jdest); + pdf_obj *obj = NULL; + + if (!ctx) return NULL; + + fz_try(ctx) + obj = pdf_lookup_dest(ctx, doc, dest); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return to_PDFObject_safe_own(ctx, env, obj); +} + +JNIEXPORT jint JNICALL +FUN(PDFDocument_countLayers)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + jint layers = 0; + + fz_try(ctx) + layers = pdf_count_layers(ctx, doc); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return layers; +} + +JNIEXPORT jboolean JNICALL +FUN(PDFDocument_isLayerVisible)(JNIEnv *env, jobject self, jint layer) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + jboolean visible = JNI_FALSE; + + fz_try(ctx) + visible = pdf_layer_is_enabled(ctx, doc, layer); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return visible; +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_setLayerVisible)(JNIEnv *env, jobject self, jint layer, jboolean visible) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + + fz_try(ctx) + pdf_enable_layer(ctx, doc, layer, visible); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT jstring JNICALL +FUN(PDFDocument_getLayerName)(JNIEnv *env, jobject self, jint layer) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + const char *name = NULL; + + fz_try(ctx) + name = pdf_layer_name(ctx, doc, layer); + fz_catch(ctx) + jni_rethrow(env, ctx); + + return (*env)->NewStringUTF(env, name); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_subsetFonts)(JNIEnv *env, jobject self) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + + fz_try(ctx) + pdf_subset_fonts(ctx, doc, 0, NULL); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +} + +JNIEXPORT void JNICALL +FUN(PDFDocument_bake)(JNIEnv *env, jobject self, jboolean bake_annots, jboolean bake_widgets) +{ + fz_context *ctx = get_context(env); + pdf_document *doc = from_PDFDocument(env, self); + + fz_try(ctx) + pdf_bake_document(ctx, doc, bake_annots, bake_widgets); + fz_catch(ctx) + jni_rethrow_void(env, ctx); +}
