| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- // 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.
- /* DocumentWriter interface */
- JNIEXPORT void JNICALL
- FUN(DocumentWriter_finalize)(JNIEnv *env, jobject self)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = from_DocumentWriter_safe(env, self);
- jobject ref;
- if (!ctx || !wri) return;
- ref = (jobject)(*env)->GetLongField(env, self, fid_DocumentWriter_ocrlistener);
- if (ref)
- {
- (*env)->DeleteGlobalRef(env, ref);
- (*env)->SetLongField(env, self, fid_DocumentWriter_ocrlistener, 0);
- }
- (*env)->SetLongField(env, self, fid_DocumentWriter_pointer, 0);
- fz_drop_document_writer(ctx, wri);
- }
- JNIEXPORT jlong JNICALL
- FUN(DocumentWriter_newNativeDocumentWriter)(JNIEnv *env, jclass cls, jstring jfilename, jstring jformat, jstring joptions)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = NULL;
- const char *filename = NULL;
- const char *format = NULL;
- const char *options = NULL;
- if (!ctx) return 0;
- if (!jfilename) jni_throw_arg(env, "filename must not be null");
- filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
- if (!filename) return 0;
- if (jformat)
- {
- format = (*env)->GetStringUTFChars(env, jformat, NULL);
- if (!format)
- {
- (*env)->ReleaseStringUTFChars(env, jfilename, filename);
- return 0;
- }
- }
- if (joptions)
- {
- options = (*env)->GetStringUTFChars(env, joptions, NULL);
- if (!options)
- {
- if (format)
- (*env)->ReleaseStringUTFChars(env, jformat, format);
- (*env)->ReleaseStringUTFChars(env, jfilename, filename);
- return 0;
- }
- }
- fz_try(ctx)
- wri = fz_new_document_writer(ctx, filename, format, options);
- fz_always(ctx)
- {
- if (options)
- (*env)->ReleaseStringUTFChars(env, joptions, options);
- if (format)
- (*env)->ReleaseStringUTFChars(env, jformat, format);
- (*env)->ReleaseStringUTFChars(env, jfilename, filename);
- }
- fz_catch(ctx)
- jni_rethrow(env, ctx);
- return jlong_cast(wri);
- }
- JNIEXPORT jlong JNICALL
- FUN(DocumentWriter_newNativeDocumentWriterWithSeekableOutputStream)(JNIEnv *env, jclass cls, jobject jstream, jstring jformat, jstring joptions)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = NULL;
- SeekableStreamState *state = NULL;
- jobject stream = NULL;
- const char *format = NULL;
- const char *options = NULL;
- jbyteArray array = NULL;
- fz_output *out;
- if (!ctx) return 0;
- if (!jstream) jni_throw_arg(env, "output stream must not be null");
- stream = (*env)->NewGlobalRef(env, jstream);
- if (!stream)
- return 0;
- array = (*env)->NewByteArray(env, sizeof state->buffer);
- if (array)
- array = (*env)->NewGlobalRef(env, array);
- if (!array)
- {
- (*env)->DeleteGlobalRef(env, stream);
- return 0;
- }
- if (jformat)
- {
- format = (*env)->GetStringUTFChars(env, jformat, NULL);
- if (!format)
- return 0;
- }
- if (joptions)
- {
- options = (*env)->GetStringUTFChars(env, joptions, NULL);
- if (!options)
- {
- if (format)
- (*env)->ReleaseStringUTFChars(env, jformat, format);
- return 0;
- }
- }
- fz_var(state);
- fz_var(out);
- fz_var(stream);
- fz_var(array);
- fz_try(ctx)
- {
- fz_output *out_temp;
- state = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_newNativeDocumentWriterWithSeekableOutputStream");
- state->stream = stream;
- state->array = array;
- out = fz_new_output(ctx, 8192, state, SeekableOutputStream_write, NULL, SeekableOutputStream_drop);
- out->seek = SeekableOutputStream_seek;
- out->tell = SeekableOutputStream_tell;
- /* these are now owned by 'out' */
- state = NULL;
- stream = NULL;
- array = NULL;
- /* out becomes owned by 'wri' as soon as we call, even if it throws. */
- out_temp = out;
- out = NULL;
- wri = fz_new_document_writer_with_output(ctx, out_temp, format, options);
- }
- fz_always(ctx)
- {
- fz_drop_output(ctx, out);
- if (options)
- (*env)->ReleaseStringUTFChars(env, joptions, options);
- if (format)
- (*env)->ReleaseStringUTFChars(env, jformat, format);
- }
- fz_catch(ctx)
- jni_rethrow(env, ctx);
- return jlong_cast(wri);
- }
- JNIEXPORT jlong JNICALL
- FUN(DocumentWriter_newNativeDocumentWriterWithBuffer)(JNIEnv *env, jclass cls, jobject jbuffer, jstring jformat, jstring joptions)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = NULL;
- fz_buffer *buffer = from_Buffer_safe(env, jbuffer);
- const char *format = NULL;
- const char *options = NULL;
- if (!ctx) return 0;
- if (!buffer) jni_throw_arg(env, "output buffer must not be null");
- if (jformat)
- {
- format = (*env)->GetStringUTFChars(env, jformat, NULL);
- if (!format)
- return 0;
- }
- if (joptions)
- {
- options = (*env)->GetStringUTFChars(env, joptions, NULL);
- if (!options)
- {
- if (format)
- (*env)->ReleaseStringUTFChars(env, jformat, format);
- return 0;
- }
- }
- fz_try(ctx)
- wri = fz_new_document_writer_with_buffer(ctx, buffer, format, options);
- fz_always(ctx)
- {
- if (options)
- (*env)->ReleaseStringUTFChars(env, joptions, options);
- if (format)
- (*env)->ReleaseStringUTFChars(env, jformat, format);
- }
- fz_catch(ctx)
- jni_rethrow(env, ctx);
- return jlong_cast(wri);
- }
- JNIEXPORT jobject JNICALL
- FUN(DocumentWriter_beginPage)(JNIEnv *env, jobject self, jobject jmediabox)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = from_DocumentWriter(env, self);
- fz_rect mediabox = from_Rect(env, jmediabox);
- fz_device *device = NULL;
- if (!ctx || !wri) return NULL;
- fz_try(ctx)
- device = fz_begin_page(ctx, wri, mediabox);
- fz_catch(ctx)
- jni_rethrow(env, ctx);
- return to_NativeDevice_safe_own(ctx, env, fz_keep_device(ctx, device));
- }
- JNIEXPORT void JNICALL
- FUN(DocumentWriter_endPage)(JNIEnv *env, jobject self)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = from_DocumentWriter(env, self);
- if (!ctx || !wri) return;
- fz_try(ctx)
- fz_end_page(ctx, wri);
- fz_catch(ctx)
- jni_rethrow_void(env, ctx);
- }
- JNIEXPORT void JNICALL
- FUN(DocumentWriter_close)(JNIEnv *env, jobject self)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = from_DocumentWriter(env, self);
- if (!ctx || !wri) return;
- fz_try(ctx)
- fz_close_document_writer(ctx, wri);
- fz_catch(ctx)
- jni_rethrow_void(env, ctx);
- }
- static int
- jni_ocr_progress(fz_context *ctx, void *arg, int page, int percent)
- {
- jobject ref = (jobject)arg;
- jboolean cancel;
- JNIEnv *env = NULL;
- jboolean detach = JNI_FALSE;
- if (ref == NULL)
- return JNI_FALSE;
- env = jni_attach_thread(&detach);
- if (env == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in jni_ocr_progress");
- cancel = (*env)->CallBooleanMethod(env, ref, mid_DocumentWriter_OCRListener_progress, page, percent);
- if ((*env)->ExceptionCheck(env))
- cancel = 1;
- jni_detach_thread(detach);
- return !!cancel;
- }
- JNIEXPORT void JNICALL
- FUN(DocumentWriter_addOCRListener)(JNIEnv *env, jobject self, jobject jlistener)
- {
- fz_context *ctx = get_context(env);
- fz_document_writer *wri = from_DocumentWriter(env, self);
- jobject ref;
- if (!ctx || !wri) return;
- /* Delete any old OCRListener if there is one. */
- ref = (jobject)(*env)->GetLongField(env, self, fid_DocumentWriter_ocrlistener);
- if (ref != NULL)
- {
- (*env)->DeleteGlobalRef(env, ref);
- (*env)->SetLongField(env, self, fid_DocumentWriter_ocrlistener, 0);
- }
- /* Take a ref and store it for the callback to use */
- ref = (*env)->NewGlobalRef(env, jlistener);
- if (!ref)
- jni_throw_run_void(env, "cannot take reference to listener");
- (*env)->SetLongField(env, self, fid_DocumentWriter_ocrlistener, jlong_cast(ref));
- fz_try(ctx)
- fz_pdfocr_writer_set_progress(ctx, wri, jni_ocr_progress, ref);
- fz_catch(ctx)
- {
- (*env)->DeleteGlobalRef(env, ref);
- (*env)->SetLongField(env, self, fid_DocumentWriter_ocrlistener, 0);
- jni_rethrow_void(env, ctx);
- }
- }
|