Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/platform/java/jni/document.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 |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright (C) 2004-2024 Artifex Software, Inc. | |
| 2 // | |
| 3 // This file is part of MuPDF. | |
| 4 // | |
| 5 // MuPDF is free software: you can redistribute it and/or modify it under the | |
| 6 // terms of the GNU Affero General Public License as published by the Free | |
| 7 // Software Foundation, either version 3 of the License, or (at your option) | |
| 8 // any later version. | |
| 9 // | |
| 10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | |
| 13 // details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU Affero General Public License | |
| 16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> | |
| 17 // | |
| 18 // Alternative licensing terms are available from the licensor. | |
| 19 // For commercial licensing, see <https://www.artifex.com/> or contact | |
| 20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 21 // CA 94129, USA, for further information. | |
| 22 | |
| 23 /* Document interface */ | |
| 24 | |
| 25 /* Callbacks to implement fz_stream and fz_output using Java classes */ | |
| 26 | |
| 27 typedef struct | |
| 28 { | |
| 29 jobject stream; | |
| 30 jbyteArray array; | |
| 31 jbyte buffer[8192]; | |
| 32 } | |
| 33 SeekableStreamState; | |
| 34 | |
| 35 static int SeekableInputStream_next(fz_context *ctx, fz_stream *stm, size_t max) | |
| 36 { | |
| 37 SeekableStreamState *state = stm->state; | |
| 38 jboolean detach = JNI_FALSE; | |
| 39 JNIEnv *env; | |
| 40 int n, ch; | |
| 41 | |
| 42 env = jni_attach_thread(&detach); | |
| 43 if (env == NULL) | |
| 44 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in SeekableInputStream_next"); | |
| 45 | |
| 46 n = (*env)->CallIntMethod(env, state->stream, mid_SeekableInputStream_read, state->array); | |
| 47 if ((*env)->ExceptionCheck(env)) | |
| 48 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 49 | |
| 50 if (n > 0) | |
| 51 { | |
| 52 (*env)->GetByteArrayRegion(env, state->array, 0, n, state->buffer); | |
| 53 if ((*env)->ExceptionCheck(env)) | |
| 54 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 55 | |
| 56 /* update stm->pos so fz_tell knows the current position */ | |
| 57 stm->rp = (unsigned char *)state->buffer; | |
| 58 stm->wp = stm->rp + n; | |
| 59 stm->pos += n; | |
| 60 | |
| 61 ch = *stm->rp++; | |
| 62 } | |
| 63 else if (n < 0) | |
| 64 { | |
| 65 ch = EOF; | |
| 66 } | |
| 67 else | |
| 68 fz_throw_and_detach_thread(ctx, detach, FZ_ERROR_GENERIC, "no bytes read"); | |
| 69 | |
| 70 jni_detach_thread(detach); | |
| 71 return ch; | |
| 72 } | |
| 73 | |
| 74 static void SeekableInputStream_seek(fz_context *ctx, fz_stream *stm, int64_t offset, int whence) | |
| 75 { | |
| 76 SeekableStreamState *state = stm->state; | |
| 77 jboolean detach = JNI_FALSE; | |
| 78 JNIEnv *env; | |
| 79 int64_t pos; | |
| 80 | |
| 81 env = jni_attach_thread(&detach); | |
| 82 if (env == NULL) | |
| 83 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in SeekableInputStream_seek"); | |
| 84 | |
| 85 pos = (*env)->CallLongMethod(env, state->stream, mid_SeekableStream_seek, offset, whence); | |
| 86 if ((*env)->ExceptionCheck(env)) | |
| 87 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 88 | |
| 89 stm->pos = pos; | |
| 90 stm->rp = stm->wp = (unsigned char *)state->buffer; | |
| 91 | |
| 92 jni_detach_thread(detach); | |
| 93 } | |
| 94 | |
| 95 static void SeekableInputStream_drop(fz_context *ctx, void *streamState_) | |
| 96 { | |
| 97 SeekableStreamState *state = streamState_; | |
| 98 jboolean detach = JNI_FALSE; | |
| 99 JNIEnv *env; | |
| 100 | |
| 101 env = jni_attach_thread(&detach); | |
| 102 if (env == NULL) | |
| 103 { | |
| 104 fz_warn(ctx, "cannot attach to JVM in SeekableInputStream_drop; leaking input stream"); | |
| 105 return; | |
| 106 } | |
| 107 | |
| 108 (*env)->DeleteGlobalRef(env, state->stream); | |
| 109 (*env)->DeleteGlobalRef(env, state->array); | |
| 110 | |
| 111 fz_free(ctx, state); | |
| 112 | |
| 113 jni_detach_thread(detach); | |
| 114 } | |
| 115 | |
| 116 static void SeekableOutputStream_write(fz_context *ctx, void *streamState_, const void *buffer_, size_t count) | |
| 117 { | |
| 118 SeekableStreamState *state = streamState_; | |
| 119 const jbyte *buffer = buffer_; | |
| 120 jboolean detach = JNI_FALSE; | |
| 121 JNIEnv *env; | |
| 122 | |
| 123 env = jni_attach_thread(&detach); | |
| 124 if (env == NULL) | |
| 125 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in SeekableOutputStream_write"); | |
| 126 | |
| 127 while (count > 0) | |
| 128 { | |
| 129 size_t n = fz_minz(count, sizeof(state->buffer)); | |
| 130 | |
| 131 (*env)->SetByteArrayRegion(env, state->array, 0, n, buffer); | |
| 132 if ((*env)->ExceptionCheck(env)) | |
| 133 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 134 | |
| 135 buffer += n; | |
| 136 count -= n; | |
| 137 | |
| 138 (*env)->CallVoidMethod(env, state->stream, mid_SeekableOutputStream_write, state->array, 0, n); | |
| 139 if ((*env)->ExceptionCheck(env)) | |
| 140 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 141 } | |
| 142 | |
| 143 jni_detach_thread(detach); | |
| 144 } | |
| 145 | |
| 146 static int64_t SeekableOutputStream_tell(fz_context *ctx, void *streamState_) | |
| 147 { | |
| 148 SeekableStreamState *state = streamState_; | |
| 149 jboolean detach = JNI_FALSE; | |
| 150 int64_t pos = 0; | |
| 151 JNIEnv *env; | |
| 152 | |
| 153 env = jni_attach_thread(&detach); | |
| 154 if (env == NULL) | |
| 155 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in SeekableOutputStream_tell"); | |
| 156 | |
| 157 pos = (*env)->CallLongMethod(env, state->stream, mid_SeekableStream_position); | |
| 158 if ((*env)->ExceptionCheck(env)) | |
| 159 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 160 | |
| 161 jni_detach_thread(detach); | |
| 162 | |
| 163 return pos; | |
| 164 } | |
| 165 | |
| 166 static void SeekableOutputStream_truncate(fz_context *ctx, void *streamState_) | |
| 167 { | |
| 168 SeekableStreamState *state = streamState_; | |
| 169 jboolean detach = JNI_FALSE; | |
| 170 JNIEnv *env; | |
| 171 | |
| 172 env = jni_attach_thread(&detach); | |
| 173 if (env == NULL) | |
| 174 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in SeekableOutputStream_truncate"); | |
| 175 | |
| 176 (*env)->CallVoidMethod(env, state->stream, mid_SeekableOutputStream_truncate); | |
| 177 if ((*env)->ExceptionCheck(env)) | |
| 178 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 179 | |
| 180 jni_detach_thread(detach); | |
| 181 } | |
| 182 | |
| 183 static void SeekableOutputStream_seek(fz_context *ctx, void *streamState_, int64_t offset, int whence) | |
| 184 { | |
| 185 SeekableStreamState *state = streamState_; | |
| 186 jboolean detach = JNI_FALSE; | |
| 187 JNIEnv *env; | |
| 188 | |
| 189 env = jni_attach_thread(&detach); | |
| 190 if (env == NULL) | |
| 191 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot attach to JVM in SeekableOutputStream_seek"); | |
| 192 | |
| 193 (void) (*env)->CallLongMethod(env, state->stream, mid_SeekableStream_seek, offset, whence); | |
| 194 if ((*env)->ExceptionCheck(env)) | |
| 195 fz_throw_java_and_detach_thread(ctx, env, detach); | |
| 196 | |
| 197 jni_detach_thread(detach); | |
| 198 } | |
| 199 | |
| 200 static void SeekableOutputStream_drop(fz_context *ctx, void *streamState_) | |
| 201 { | |
| 202 SeekableStreamState *state = streamState_; | |
| 203 jboolean detach = JNI_FALSE; | |
| 204 JNIEnv *env; | |
| 205 | |
| 206 env = jni_attach_thread(&detach); | |
| 207 if (env == NULL) | |
| 208 { | |
| 209 fz_warn(ctx, "cannot attach to JVM in SeekableOutputStream_drop; leaking output stream"); | |
| 210 return; | |
| 211 } | |
| 212 | |
| 213 (*env)->DeleteGlobalRef(env, state->stream); | |
| 214 (*env)->DeleteGlobalRef(env, state->array); | |
| 215 | |
| 216 fz_free(ctx, state); | |
| 217 | |
| 218 jni_detach_thread(detach); | |
| 219 } | |
| 220 JNIEXPORT void JNICALL | |
| 221 FUN(Document_finalize)(JNIEnv *env, jobject self) | |
| 222 { | |
| 223 fz_context *ctx = get_context(env); | |
| 224 fz_document *doc = from_Document_safe(env, self); | |
| 225 if (!ctx || !doc) return; | |
| 226 (*env)->SetLongField(env, self, fid_Document_pointer, 0); | |
| 227 fz_drop_document(ctx, doc); | |
| 228 | |
| 229 /* This is a reasonable place to call Memento. */ | |
| 230 Memento_fin(); | |
| 231 } | |
| 232 | |
| 233 JNIEXPORT jobject JNICALL | |
| 234 FUN(Document_openNativeWithStream)(JNIEnv *env, jclass cls, jstring jmagic, jobject jdocument, jobject jaccelerator) | |
| 235 { | |
| 236 fz_context *ctx = get_context(env); | |
| 237 fz_document *doc = NULL; | |
| 238 fz_stream *docstream = NULL; | |
| 239 fz_stream *accstream = NULL; | |
| 240 jobject jdoc = NULL; | |
| 241 jobject jacc = NULL; | |
| 242 jbyteArray docarray = NULL; | |
| 243 jbyteArray accarray = NULL; | |
| 244 SeekableStreamState *docstate = NULL; | |
| 245 SeekableStreamState *accstate = NULL; | |
| 246 const char *magic = NULL; | |
| 247 | |
| 248 fz_var(jdoc); | |
| 249 fz_var(jacc); | |
| 250 fz_var(docarray); | |
| 251 fz_var(accarray); | |
| 252 fz_var(docstream); | |
| 253 fz_var(accstream); | |
| 254 | |
| 255 if (!ctx) return NULL; | |
| 256 if (jmagic) | |
| 257 { | |
| 258 magic = (*env)->GetStringUTFChars(env, jmagic, NULL); | |
| 259 if (!magic) jni_throw_run(env, "cannot get characters in magic string"); | |
| 260 } | |
| 261 if (jdocument) | |
| 262 { | |
| 263 jdoc = (*env)->NewGlobalRef(env, jdocument); | |
| 264 if (!jdoc) | |
| 265 { | |
| 266 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 267 jni_throw_run(env, "cannot get reference to document stream"); | |
| 268 } | |
| 269 } | |
| 270 if (jaccelerator) | |
| 271 { | |
| 272 jacc = (*env)->NewGlobalRef(env, jaccelerator); | |
| 273 if (!jacc) | |
| 274 { | |
| 275 (*env)->DeleteGlobalRef(env, jdoc); | |
| 276 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 277 jni_throw_run(env, "cannot get reference to accelerator stream"); | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 docarray = (*env)->NewByteArray(env, sizeof docstate->buffer); | |
| 282 if (docarray) | |
| 283 docarray = (*env)->NewGlobalRef(env, docarray); | |
| 284 if (!docarray) | |
| 285 { | |
| 286 (*env)->DeleteGlobalRef(env, jacc); | |
| 287 (*env)->DeleteGlobalRef(env, jdoc); | |
| 288 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 289 jni_throw_run(env, "cannot create internal buffer for document stream"); | |
| 290 } | |
| 291 | |
| 292 if (jacc) | |
| 293 { | |
| 294 accarray = (*env)->NewByteArray(env, sizeof accstate->buffer); | |
| 295 if (accarray) | |
| 296 accarray = (*env)->NewGlobalRef(env, accarray); | |
| 297 if (!accarray) | |
| 298 { | |
| 299 (*env)->DeleteGlobalRef(env, docarray); | |
| 300 (*env)->DeleteGlobalRef(env, jacc); | |
| 301 (*env)->DeleteGlobalRef(env, jdoc); | |
| 302 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 303 jni_throw_run(env, "cannot create internal buffer for accelerator stream"); | |
| 304 } | |
| 305 } | |
| 306 | |
| 307 fz_try(ctx) | |
| 308 { | |
| 309 if (jdoc) | |
| 310 { | |
| 311 /* No exceptions can occur from here to stream owning docstate, so we must not free docstate. */ | |
| 312 docstate = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_docstate"); | |
| 313 docstate->stream = jdoc; | |
| 314 docstate->array = docarray; | |
| 315 | |
| 316 /* Ownership transferred to docstate. */ | |
| 317 jdoc = NULL; | |
| 318 docarray = NULL; | |
| 319 | |
| 320 /* Stream takes ownership of docstate. */ | |
| 321 docstream = fz_new_stream(ctx, docstate, SeekableInputStream_next, SeekableInputStream_drop); | |
| 322 docstream->seek = SeekableInputStream_seek; | |
| 323 } | |
| 324 | |
| 325 if (jacc) | |
| 326 { | |
| 327 /* No exceptions can occur from here to stream owning accstate, so we must not free accstate. */ | |
| 328 accstate = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_accstate"); | |
| 329 accstate->stream = jacc; | |
| 330 accstate->array = accarray; | |
| 331 | |
| 332 /* Ownership transferred to accstate. */ | |
| 333 jacc = NULL; | |
| 334 accarray = NULL; | |
| 335 | |
| 336 /* Stream takes ownership of accstate. */ | |
| 337 accstream = fz_new_stream(ctx, accstate, SeekableInputStream_next, SeekableInputStream_drop); | |
| 338 accstream->seek = SeekableInputStream_seek; | |
| 339 } | |
| 340 | |
| 341 doc = fz_open_accelerated_document_with_stream(ctx, magic, docstream, accstream); | |
| 342 } | |
| 343 fz_always(ctx) | |
| 344 { | |
| 345 fz_drop_stream(ctx, accstream); | |
| 346 fz_drop_stream(ctx, docstream); | |
| 347 if (magic) | |
| 348 (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 349 } | |
| 350 fz_catch(ctx) | |
| 351 { | |
| 352 (*env)->DeleteGlobalRef(env, accarray); | |
| 353 (*env)->DeleteGlobalRef(env, docarray); | |
| 354 (*env)->DeleteGlobalRef(env, jacc); | |
| 355 (*env)->DeleteGlobalRef(env, jdoc); | |
| 356 jni_rethrow(env, ctx); | |
| 357 } | |
| 358 | |
| 359 return to_Document_safe_own(ctx, env, doc); | |
| 360 } | |
| 361 | |
| 362 JNIEXPORT jobject JNICALL | |
| 363 FUN(Document_openNativeWithPath)(JNIEnv *env, jclass cls, jstring jfilename, jstring jaccelerator) | |
| 364 { | |
| 365 fz_context *ctx = get_context(env); | |
| 366 fz_document *doc = NULL; | |
| 367 const char *filename = NULL; | |
| 368 const char *accelerator = NULL; | |
| 369 | |
| 370 if (!ctx) return NULL; | |
| 371 if (jfilename) | |
| 372 { | |
| 373 filename = (*env)->GetStringUTFChars(env, jfilename, NULL); | |
| 374 if (!filename) jni_throw_run(env, "cannot get characters in filename string"); | |
| 375 } | |
| 376 if (jaccelerator) | |
| 377 { | |
| 378 accelerator = (*env)->GetStringUTFChars(env, jaccelerator, NULL); | |
| 379 if (!accelerator) jni_throw_run(env, "cannot get characters in accelerator filename string"); | |
| 380 } | |
| 381 | |
| 382 fz_try(ctx) | |
| 383 doc = fz_open_accelerated_document(ctx, filename, accelerator); | |
| 384 fz_always(ctx) | |
| 385 { | |
| 386 if (accelerator) | |
| 387 (*env)->ReleaseStringUTFChars(env, jaccelerator, accelerator); | |
| 388 if (filename) | |
| 389 (*env)->ReleaseStringUTFChars(env, jfilename, filename); | |
| 390 } | |
| 391 fz_catch(ctx) | |
| 392 jni_rethrow(env, ctx); | |
| 393 | |
| 394 return to_Document_safe_own(ctx, env, doc); | |
| 395 } | |
| 396 | |
| 397 | |
| 398 JNIEXPORT jobject JNICALL | |
| 399 FUN(Document_openNativeWithPathAndStream)(JNIEnv *env, jclass cls, jstring jfilename, jobject jaccelerator) | |
| 400 { | |
| 401 fz_context *ctx = get_context(env); | |
| 402 fz_document *doc = NULL; | |
| 403 const char *filename = NULL; | |
| 404 fz_stream *docstream = NULL; | |
| 405 fz_stream *accstream = NULL; | |
| 406 jobject jacc = NULL; | |
| 407 jbyteArray accarray = NULL; | |
| 408 SeekableStreamState *accstate = NULL; | |
| 409 | |
| 410 fz_var(jacc); | |
| 411 fz_var(accarray); | |
| 412 fz_var(accstream); | |
| 413 fz_var(docstream); | |
| 414 | |
| 415 if (!ctx) return NULL; | |
| 416 if (jfilename) | |
| 417 { | |
| 418 filename = (*env)->GetStringUTFChars(env, jfilename, NULL); | |
| 419 if (!filename) jni_throw_run(env, "cannot get characters in filename string"); | |
| 420 } | |
| 421 if (jaccelerator) | |
| 422 { | |
| 423 jacc = (*env)->NewGlobalRef(env, jaccelerator); | |
| 424 if (!jacc) | |
| 425 { | |
| 426 if (jfilename) (*env)->ReleaseStringUTFChars(env, jfilename, filename); | |
| 427 jni_throw_run(env, "cannot get reference to accelerator stream"); | |
| 428 } | |
| 429 } | |
| 430 | |
| 431 accarray = (*env)->NewByteArray(env, sizeof accstate->buffer); | |
| 432 if (accarray) | |
| 433 accarray = (*env)->NewGlobalRef(env, accarray); | |
| 434 if (!accarray) | |
| 435 { | |
| 436 (*env)->DeleteGlobalRef(env, jacc); | |
| 437 if (jfilename) (*env)->ReleaseStringUTFChars(env, jfilename, filename); | |
| 438 jni_throw_run(env, "cannot get create internal buffer for accelerator stream"); | |
| 439 } | |
| 440 | |
| 441 fz_try(ctx) | |
| 442 { | |
| 443 if (filename) | |
| 444 docstream = fz_open_file(ctx, filename); | |
| 445 | |
| 446 if (jacc) | |
| 447 { | |
| 448 /* No exceptions can occur from here to stream owning accstate, so we must not free accstate. */ | |
| 449 accstate = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_accstate2"); | |
| 450 accstate->stream = jacc; | |
| 451 accstate->array = accarray; | |
| 452 | |
| 453 /* Ownership transferred to accstate. */ | |
| 454 jacc = NULL; | |
| 455 accarray = NULL; | |
| 456 | |
| 457 /* Stream takes ownership of accstate. */ | |
| 458 accstream = fz_new_stream(ctx, accstate, SeekableInputStream_next, SeekableInputStream_drop); | |
| 459 accstream->seek = SeekableInputStream_seek; | |
| 460 } | |
| 461 | |
| 462 doc = fz_open_accelerated_document_with_stream(ctx, filename, docstream, accstream); | |
| 463 } | |
| 464 fz_always(ctx) | |
| 465 { | |
| 466 fz_drop_stream(ctx, accstream); | |
| 467 fz_drop_stream(ctx, docstream); | |
| 468 if (filename) (*env)->ReleaseStringUTFChars(env, jfilename, filename); | |
| 469 } | |
| 470 fz_catch(ctx) | |
| 471 { | |
| 472 (*env)->DeleteGlobalRef(env, accarray); | |
| 473 (*env)->DeleteGlobalRef(env, jacc); | |
| 474 jni_rethrow(env, ctx); | |
| 475 } | |
| 476 | |
| 477 return to_Document_safe_own(ctx, env, doc); | |
| 478 } | |
| 479 | |
| 480 JNIEXPORT jobject JNICALL | |
| 481 FUN(Document_openNativeWithBuffer)(JNIEnv *env, jclass cls, jstring jmagic, jobject jbuffer, jobject jaccelerator) | |
| 482 { | |
| 483 fz_context *ctx = get_context(env); | |
| 484 fz_document *doc = NULL; | |
| 485 const char *magic = NULL; | |
| 486 fz_stream *docstream = NULL; | |
| 487 fz_stream *accstream = NULL; | |
| 488 fz_buffer *docbuf = NULL; | |
| 489 fz_buffer *accbuf = NULL; | |
| 490 jbyte *buffer = NULL; | |
| 491 jbyte *accelerator = NULL; | |
| 492 int n, m; | |
| 493 | |
| 494 fz_var(docbuf); | |
| 495 fz_var(accbuf); | |
| 496 fz_var(docstream); | |
| 497 fz_var(accstream); | |
| 498 | |
| 499 if (!ctx) return NULL; | |
| 500 if (jmagic) | |
| 501 { | |
| 502 magic = (*env)->GetStringUTFChars(env, jmagic, NULL); | |
| 503 if (!magic) | |
| 504 jni_throw_run(env, "cannot get characters in magic string"); | |
| 505 } | |
| 506 if (jbuffer) | |
| 507 { | |
| 508 n = (*env)->GetArrayLength(env, jbuffer); | |
| 509 | |
| 510 buffer = (*env)->GetByteArrayElements(env, jbuffer, NULL); | |
| 511 if (!buffer) | |
| 512 { | |
| 513 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 514 jni_throw_run(env, "cannot get document bytes to read"); | |
| 515 } | |
| 516 } | |
| 517 if (jaccelerator) | |
| 518 { | |
| 519 m = (*env)->GetArrayLength(env, jaccelerator); | |
| 520 | |
| 521 accelerator = (*env)->GetByteArrayElements(env, jaccelerator, NULL); | |
| 522 if (!accelerator) | |
| 523 { | |
| 524 if (buffer) (*env)->ReleaseByteArrayElements(env, jbuffer, buffer, 0); | |
| 525 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 526 jni_throw_run(env, "cannot get accelerator bytes to read"); | |
| 527 } | |
| 528 } | |
| 529 | |
| 530 fz_try(ctx) | |
| 531 { | |
| 532 if (buffer) | |
| 533 { | |
| 534 docbuf = fz_new_buffer(ctx, n); | |
| 535 fz_append_data(ctx, docbuf, buffer, n); | |
| 536 docstream = fz_open_buffer(ctx, docbuf); | |
| 537 } | |
| 538 | |
| 539 if (accelerator) | |
| 540 { | |
| 541 accbuf = fz_new_buffer(ctx, m); | |
| 542 fz_append_data(ctx, accbuf, accelerator, m); | |
| 543 accstream = fz_open_buffer(ctx, accbuf); | |
| 544 } | |
| 545 | |
| 546 doc = fz_open_accelerated_document_with_stream(ctx, magic, docstream, accstream); | |
| 547 } | |
| 548 fz_always(ctx) | |
| 549 { | |
| 550 fz_drop_stream(ctx, accstream); | |
| 551 fz_drop_buffer(ctx, accbuf); | |
| 552 fz_drop_stream(ctx, docstream); | |
| 553 fz_drop_buffer(ctx, docbuf); | |
| 554 if (accelerator) (*env)->ReleaseByteArrayElements(env, jaccelerator, accelerator, 0); | |
| 555 if (buffer) (*env)->ReleaseByteArrayElements(env, jbuffer, buffer, 0); | |
| 556 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 557 } | |
| 558 fz_catch(ctx) | |
| 559 { | |
| 560 jni_rethrow(env, ctx); | |
| 561 } | |
| 562 | |
| 563 return to_Document_safe_own(ctx, env, doc); | |
| 564 } | |
| 565 | |
| 566 JNIEXPORT jboolean JNICALL | |
| 567 FUN(Document_recognize)(JNIEnv *env, jclass cls, jstring jmagic) | |
| 568 { | |
| 569 fz_context *ctx = get_context(env); | |
| 570 const char *magic = NULL; | |
| 571 jboolean recognized = JNI_FALSE; | |
| 572 | |
| 573 if (!ctx) return JNI_FALSE; | |
| 574 if (jmagic) | |
| 575 { | |
| 576 magic = (*env)->GetStringUTFChars(env, jmagic, NULL); | |
| 577 if (!magic) return JNI_FALSE; | |
| 578 } | |
| 579 | |
| 580 fz_try(ctx) | |
| 581 recognized = fz_recognize_document(ctx, magic) != NULL; | |
| 582 fz_always(ctx) | |
| 583 if (magic) (*env)->ReleaseStringUTFChars(env, jmagic, magic); | |
| 584 fz_catch(ctx) | |
| 585 jni_rethrow(env, ctx); | |
| 586 | |
| 587 return recognized; | |
| 588 } | |
| 589 | |
| 590 JNIEXPORT jboolean JNICALL | |
| 591 FUN(Document_supportsAccelerator)(JNIEnv *env, jobject self) | |
| 592 { | |
| 593 fz_context *ctx = get_context(env); | |
| 594 fz_document *doc = from_Document(env, self); | |
| 595 jboolean support = JNI_FALSE; | |
| 596 | |
| 597 fz_try(ctx) | |
| 598 support = fz_document_supports_accelerator(ctx, doc); | |
| 599 fz_catch(ctx) | |
| 600 jni_rethrow(env, ctx); | |
| 601 | |
| 602 return support; | |
| 603 } | |
| 604 | |
| 605 JNIEXPORT void JNICALL | |
| 606 FUN(Document_saveAccelerator)(JNIEnv *env, jobject self, jstring jfilename) | |
| 607 { | |
| 608 fz_context *ctx = get_context(env); | |
| 609 fz_document *doc = from_Document(env, self); | |
| 610 const char *filename = "null"; | |
| 611 | |
| 612 if (!ctx || !doc) return; | |
| 613 if (!jfilename) jni_throw_arg_void(env, "filename must not be null"); | |
| 614 | |
| 615 filename = (*env)->GetStringUTFChars(env, jfilename, NULL); | |
| 616 if (!filename) return; | |
| 617 | |
| 618 fz_try(ctx) | |
| 619 fz_save_accelerator(ctx, doc, filename); | |
| 620 fz_always(ctx) | |
| 621 (*env)->ReleaseStringUTFChars(env, jfilename, filename); | |
| 622 fz_catch(ctx) | |
| 623 jni_rethrow_void(env, ctx); | |
| 624 } | |
| 625 | |
| 626 JNIEXPORT void JNICALL | |
| 627 FUN(Document_outputAccelerator)(JNIEnv *env, jobject self, jobject jstream) | |
| 628 { | |
| 629 fz_context *ctx = get_context(env); | |
| 630 fz_document *doc = from_Document(env, self); | |
| 631 SeekableStreamState *state = NULL; | |
| 632 jobject stream = NULL; | |
| 633 jbyteArray array = NULL; | |
| 634 fz_output *out; | |
| 635 | |
| 636 fz_var(state); | |
| 637 fz_var(out); | |
| 638 fz_var(stream); | |
| 639 fz_var(array); | |
| 640 | |
| 641 stream = (*env)->NewGlobalRef(env, jstream); | |
| 642 if (!stream) | |
| 643 return; | |
| 644 | |
| 645 array = (*env)->NewByteArray(env, sizeof state->buffer); | |
| 646 if (array) | |
| 647 array = (*env)->NewGlobalRef(env, array); | |
| 648 if (!array) | |
| 649 { | |
| 650 (*env)->DeleteGlobalRef(env, stream); | |
| 651 return; | |
| 652 } | |
| 653 | |
| 654 fz_try(ctx) | |
| 655 { | |
| 656 state = Memento_label(fz_malloc(ctx, sizeof(SeekableStreamState)), "SeekableStreamState_outputAccelerator"); | |
| 657 state->stream = stream; | |
| 658 state->array = array; | |
| 659 | |
| 660 out = fz_new_output(ctx, 8192, state, SeekableOutputStream_write, NULL, SeekableOutputStream_drop); | |
| 661 out->seek = SeekableOutputStream_seek; | |
| 662 out->tell = SeekableOutputStream_tell; | |
| 663 | |
| 664 /* these are now owned by 'out' */ | |
| 665 state = NULL; | |
| 666 stream = NULL; | |
| 667 array = NULL; | |
| 668 | |
| 669 fz_output_accelerator(ctx, doc, out); | |
| 670 fz_close_output(ctx, out); | |
| 671 } | |
| 672 fz_always(ctx) | |
| 673 { | |
| 674 fz_drop_output(ctx, out); | |
| 675 } | |
| 676 fz_catch(ctx) | |
| 677 { | |
| 678 (*env)->DeleteGlobalRef(env, stream); | |
| 679 (*env)->DeleteGlobalRef(env, array); | |
| 680 fz_free(ctx, state); | |
| 681 jni_rethrow_void(env, ctx); | |
| 682 } | |
| 683 } | |
| 684 | |
| 685 JNIEXPORT jboolean JNICALL | |
| 686 FUN(Document_needsPassword)(JNIEnv *env, jobject self) | |
| 687 { | |
| 688 fz_context *ctx = get_context(env); | |
| 689 fz_document *doc = from_Document(env, self); | |
| 690 int okay = 0; | |
| 691 | |
| 692 if (!ctx || !doc) return JNI_FALSE; | |
| 693 | |
| 694 fz_try(ctx) | |
| 695 okay = fz_needs_password(ctx, doc); | |
| 696 fz_catch(ctx) | |
| 697 jni_rethrow(env, ctx); | |
| 698 | |
| 699 return okay ? JNI_TRUE : JNI_FALSE; | |
| 700 } | |
| 701 | |
| 702 JNIEXPORT jboolean JNICALL | |
| 703 FUN(Document_authenticatePassword)(JNIEnv *env, jobject self, jstring jpassword) | |
| 704 { | |
| 705 fz_context *ctx = get_context(env); | |
| 706 fz_document *doc = from_Document(env, self); | |
| 707 const char *password = NULL; | |
| 708 int okay = 0; | |
| 709 | |
| 710 if (!ctx || !doc) return JNI_FALSE; | |
| 711 | |
| 712 if (jpassword) | |
| 713 { | |
| 714 password = (*env)->GetStringUTFChars(env, jpassword, NULL); | |
| 715 if (!password) return JNI_FALSE; | |
| 716 } | |
| 717 | |
| 718 fz_try(ctx) | |
| 719 okay = fz_authenticate_password(ctx, doc, password); | |
| 720 fz_always(ctx) | |
| 721 if (password) (*env)->ReleaseStringUTFChars(env, jpassword, password); | |
| 722 fz_catch(ctx) | |
| 723 jni_rethrow(env, ctx); | |
| 724 | |
| 725 return okay ? JNI_TRUE : JNI_FALSE; | |
| 726 } | |
| 727 | |
| 728 JNIEXPORT jint JNICALL | |
| 729 FUN(Document_countChapters)(JNIEnv *env, jobject self) | |
| 730 { | |
| 731 fz_context *ctx = get_context(env); | |
| 732 fz_document *doc = from_Document(env, self); | |
| 733 int count = 0; | |
| 734 | |
| 735 if (!ctx || !doc) return 0; | |
| 736 | |
| 737 fz_try(ctx) | |
| 738 count = fz_count_chapters(ctx, doc); | |
| 739 fz_catch(ctx) | |
| 740 jni_rethrow(env, ctx); | |
| 741 | |
| 742 return count; | |
| 743 } | |
| 744 | |
| 745 JNIEXPORT jint JNICALL | |
| 746 FUN(Document_countPages)(JNIEnv *env, jobject self, jint chapter) | |
| 747 { | |
| 748 fz_context *ctx = get_context(env); | |
| 749 fz_document *doc = from_Document(env, self); | |
| 750 int count = 0; | |
| 751 | |
| 752 if (!ctx || !doc) return 0; | |
| 753 | |
| 754 fz_try(ctx) | |
| 755 count = fz_count_chapter_pages(ctx, doc, chapter); | |
| 756 fz_catch(ctx) | |
| 757 jni_rethrow(env, ctx); | |
| 758 | |
| 759 return count; | |
| 760 } | |
| 761 | |
| 762 JNIEXPORT jboolean JNICALL | |
| 763 FUN(Document_isReflowable)(JNIEnv *env, jobject self) | |
| 764 { | |
| 765 fz_context *ctx = get_context(env); | |
| 766 fz_document *doc = from_Document(env, self); | |
| 767 int is_reflowable = 0; | |
| 768 | |
| 769 if (!ctx || !doc) return JNI_FALSE; | |
| 770 | |
| 771 fz_try(ctx) | |
| 772 is_reflowable = fz_is_document_reflowable(ctx, doc); | |
| 773 fz_catch(ctx) | |
| 774 jni_rethrow(env, ctx); | |
| 775 | |
| 776 return is_reflowable ? JNI_TRUE : JNI_FALSE; | |
| 777 } | |
| 778 | |
| 779 JNIEXPORT void JNICALL | |
| 780 FUN(Document_layout)(JNIEnv *env, jobject self, jfloat w, jfloat h, jfloat em) | |
| 781 { | |
| 782 fz_context *ctx = get_context(env); | |
| 783 fz_document *doc = from_Document(env, self); | |
| 784 | |
| 785 if (!ctx || !doc) return; | |
| 786 | |
| 787 fz_try(ctx) | |
| 788 fz_layout_document(ctx, doc, w, h, em); | |
| 789 fz_catch(ctx) | |
| 790 jni_rethrow_void(env, ctx); | |
| 791 } | |
| 792 | |
| 793 JNIEXPORT jobject JNICALL | |
| 794 FUN(Document_loadPage)(JNIEnv *env, jobject self, jint chapter, jint number) | |
| 795 { | |
| 796 fz_context *ctx = get_context(env); | |
| 797 fz_document *doc = from_Document(env, self); | |
| 798 fz_page *page = NULL; | |
| 799 | |
| 800 if (!ctx || !doc) return NULL; | |
| 801 | |
| 802 fz_try(ctx) | |
| 803 page = fz_load_chapter_page(ctx, doc, chapter, number); | |
| 804 fz_catch(ctx) | |
| 805 jni_rethrow(env, ctx); | |
| 806 | |
| 807 return to_Page_safe_own(ctx, env, page); | |
| 808 } | |
| 809 | |
| 810 JNIEXPORT jstring JNICALL | |
| 811 FUN(Document_getMetaData)(JNIEnv *env, jobject self, jstring jkey) | |
| 812 { | |
| 813 fz_context *ctx = get_context(env); | |
| 814 fz_document *doc = from_Document(env, self); | |
| 815 const char *key = NULL; | |
| 816 char info[256]; | |
| 817 | |
| 818 if (!ctx || !doc) return NULL; | |
| 819 if (!jkey) jni_throw_arg(env, "key must not be null"); | |
| 820 | |
| 821 key = (*env)->GetStringUTFChars(env, jkey, NULL); | |
| 822 if (!key) return 0; | |
| 823 | |
| 824 fz_try(ctx) | |
| 825 fz_lookup_metadata(ctx, doc, key, info, sizeof info); | |
| 826 fz_always(ctx) | |
| 827 if (key) | |
| 828 (*env)->ReleaseStringUTFChars(env, jkey, key); | |
| 829 fz_catch(ctx) | |
| 830 jni_rethrow(env, ctx); | |
| 831 | |
| 832 return (*env)->NewStringUTF(env, info); | |
| 833 } | |
| 834 | |
| 835 JNIEXPORT void JNICALL | |
| 836 FUN(Document_setMetaData)(JNIEnv *env, jobject self, jstring jkey, jstring jvalue) | |
| 837 { | |
| 838 fz_context *ctx = get_context(env); | |
| 839 fz_document *doc = from_Document(env, self); | |
| 840 const char *key = NULL; | |
| 841 const char *value = NULL; | |
| 842 | |
| 843 if (!ctx || !doc) return; | |
| 844 if (!jkey) jni_throw_arg_void(env, "key must not be null"); | |
| 845 if (!jvalue) jni_throw_arg_void(env, "value must not be null"); | |
| 846 | |
| 847 key = (*env)->GetStringUTFChars(env, jkey, NULL); | |
| 848 value = (*env)->GetStringUTFChars(env, jvalue, NULL); | |
| 849 if (!key || !value) | |
| 850 { | |
| 851 if (key) | |
| 852 (*env)->ReleaseStringUTFChars(env, jkey, key); | |
| 853 return; | |
| 854 } | |
| 855 | |
| 856 fz_try(ctx) | |
| 857 fz_set_metadata(ctx, doc, key, value); | |
| 858 fz_always(ctx) | |
| 859 { | |
| 860 (*env)->ReleaseStringUTFChars(env, jkey, key); | |
| 861 (*env)->ReleaseStringUTFChars(env, jvalue, value); | |
| 862 } | |
| 863 fz_catch(ctx) | |
| 864 jni_rethrow_void(env, ctx); | |
| 865 } | |
| 866 | |
| 867 JNIEXPORT jboolean JNICALL | |
| 868 FUN(Document_isUnencryptedPDF)(JNIEnv *env, jobject self) | |
| 869 { | |
| 870 fz_context *ctx = get_context(env); | |
| 871 fz_document *doc = from_Document(env, self); | |
| 872 pdf_document *idoc = pdf_specifics(ctx, doc); | |
| 873 int cryptVer; | |
| 874 | |
| 875 if (!ctx || !doc) return JNI_FALSE; | |
| 876 if (!idoc) | |
| 877 return JNI_FALSE; | |
| 878 | |
| 879 cryptVer = pdf_crypt_version(ctx, idoc->crypt); | |
| 880 return (cryptVer == 0) ? JNI_TRUE : JNI_FALSE; | |
| 881 } | |
| 882 | |
| 883 JNIEXPORT jobject JNICALL | |
| 884 FUN(Document_loadOutline)(JNIEnv *env, jobject self) | |
| 885 { | |
| 886 fz_context *ctx = get_context(env); | |
| 887 fz_document *doc = from_Document(env, self); | |
| 888 fz_outline *outline = NULL; | |
| 889 jobject joutline = NULL; | |
| 890 | |
| 891 if (!ctx || !doc) return NULL; | |
| 892 | |
| 893 fz_var(outline); | |
| 894 | |
| 895 fz_try(ctx) | |
| 896 { | |
| 897 outline = fz_load_outline(ctx, doc); | |
| 898 if (outline) | |
| 899 { | |
| 900 joutline = to_Outline_safe(ctx, env, doc, outline); | |
| 901 if (!joutline && !(*env)->ExceptionCheck(env)) | |
| 902 fz_throw(ctx, FZ_ERROR_GENERIC, "loadOutline failed"); | |
| 903 } | |
| 904 } | |
| 905 fz_always(ctx) | |
| 906 fz_drop_outline(ctx, outline); | |
| 907 fz_catch(ctx) | |
| 908 jni_rethrow(env, ctx); | |
| 909 | |
| 910 if ((*env)->ExceptionCheck(env)) | |
| 911 return NULL; | |
| 912 | |
| 913 return joutline; | |
| 914 } | |
| 915 | |
| 916 JNIEXPORT jobject JNICALL | |
| 917 FUN(Document_outlineIterator)(JNIEnv *env, jobject self) | |
| 918 { | |
| 919 fz_context *ctx = get_context(env); | |
| 920 fz_document *doc = from_Document(env, self); | |
| 921 fz_outline_iterator *iterator = NULL; | |
| 922 jobject jiterator = NULL; | |
| 923 | |
| 924 if (!ctx || !doc) return NULL; | |
| 925 | |
| 926 fz_var(iterator); | |
| 927 | |
| 928 fz_try(ctx) | |
| 929 { | |
| 930 iterator = fz_new_outline_iterator(ctx, doc); | |
| 931 if (iterator) | |
| 932 { | |
| 933 jiterator = to_OutlineIterator_safe(ctx, env, iterator); | |
| 934 if (!jiterator || (*env)->ExceptionCheck(env)) | |
| 935 fz_throw(ctx, FZ_ERROR_GENERIC, "outlineIterator failed"); | |
| 936 iterator = NULL; | |
| 937 } | |
| 938 } | |
| 939 fz_always(ctx) | |
| 940 fz_drop_outline_iterator(ctx, iterator); | |
| 941 fz_catch(ctx) | |
| 942 jni_rethrow(env, ctx); | |
| 943 | |
| 944 if ((*env)->ExceptionCheck(env)) | |
| 945 return NULL; | |
| 946 | |
| 947 return jiterator; | |
| 948 } | |
| 949 | |
| 950 JNIEXPORT jlong JNICALL | |
| 951 FUN(Document_makeBookmark)(JNIEnv *env, jobject self, jint chapter, jint page) | |
| 952 { | |
| 953 fz_context *ctx = get_context(env); | |
| 954 fz_document *doc = from_Document(env, self); | |
| 955 fz_bookmark mark = 0; | |
| 956 | |
| 957 fz_try(ctx) | |
| 958 mark = fz_make_bookmark(ctx, doc, fz_make_location(chapter, page)); | |
| 959 fz_catch(ctx) | |
| 960 jni_rethrow(env, ctx); | |
| 961 | |
| 962 return mark; | |
| 963 } | |
| 964 | |
| 965 JNIEXPORT jobject JNICALL | |
| 966 FUN(Document_findBookmark)(JNIEnv *env, jobject self, jlong mark) | |
| 967 { | |
| 968 fz_context *ctx = get_context(env); | |
| 969 fz_document *doc = from_Document(env, self); | |
| 970 fz_location loc = { -1, -1 }; | |
| 971 | |
| 972 fz_try(ctx) | |
| 973 loc = fz_lookup_bookmark(ctx, doc, mark); | |
| 974 fz_catch(ctx) | |
| 975 jni_rethrow(env, ctx); | |
| 976 | |
| 977 return (*env)->NewObject(env, cls_Location, mid_Location_init, loc.chapter, loc.page, 0, 0); | |
| 978 } | |
| 979 | |
| 980 JNIEXPORT jobject JNICALL | |
| 981 FUN(Document_resolveLink)(JNIEnv *env, jobject self, jstring juri) | |
| 982 { | |
| 983 fz_context *ctx = get_context(env); | |
| 984 fz_document *doc = from_Document(env, self); | |
| 985 fz_location loc = { -1, -1 }; | |
| 986 float x = 0, y = 0; | |
| 987 const char *uri = ""; | |
| 988 | |
| 989 if (juri) | |
| 990 { | |
| 991 uri = (*env)->GetStringUTFChars(env, juri, NULL); | |
| 992 if (!uri) | |
| 993 return NULL; | |
| 994 } | |
| 995 | |
| 996 fz_try(ctx) | |
| 997 loc = fz_resolve_link(ctx, doc, uri, &x, &y); | |
| 998 fz_always(ctx) | |
| 999 if (juri) | |
| 1000 (*env)->ReleaseStringUTFChars(env, juri, uri); | |
| 1001 fz_catch(ctx) | |
| 1002 jni_rethrow(env, ctx); | |
| 1003 | |
| 1004 return (*env)->NewObject(env, cls_Location, mid_Location_init, loc.chapter, loc.page, x, y); | |
| 1005 } | |
| 1006 | |
| 1007 JNIEXPORT jboolean JNICALL | |
| 1008 FUN(Document_hasPermission)(JNIEnv *env, jobject self, jint permission) | |
| 1009 { | |
| 1010 fz_context *ctx = get_context(env); | |
| 1011 fz_document *doc = from_Document(env, self); | |
| 1012 jboolean result = JNI_FALSE; | |
| 1013 | |
| 1014 fz_try(ctx) | |
| 1015 result = fz_has_permission(ctx, doc, permission); | |
| 1016 fz_catch(ctx) | |
| 1017 jni_rethrow(env, ctx); | |
| 1018 | |
| 1019 return result; | |
| 1020 } | |
| 1021 | |
| 1022 JNIEXPORT jobject JNICALL | |
| 1023 FUN(Document_search)(JNIEnv *env, jobject self, jint chapter, jint page, jstring jneedle) | |
| 1024 { | |
| 1025 fz_context *ctx = get_context(env); | |
| 1026 fz_document *doc = from_Document(env, self); | |
| 1027 const char *needle = NULL; | |
| 1028 search_state state = { env, NULL, 0 }; | |
| 1029 | |
| 1030 if (!ctx || !doc) return NULL; | |
| 1031 if (!jneedle) jni_throw_arg(env, "needle must not be null"); | |
| 1032 | |
| 1033 needle = (*env)->GetStringUTFChars(env, jneedle, NULL); | |
| 1034 if (!needle) return NULL; | |
| 1035 | |
| 1036 state.hits = (*env)->NewObject(env, cls_ArrayList, mid_ArrayList_init); | |
| 1037 if (!state.hits || (*env)->ExceptionCheck(env)) return NULL; | |
| 1038 | |
| 1039 fz_try(ctx) | |
| 1040 fz_search_chapter_page_number_cb(ctx, doc, chapter, page, needle, hit_callback, &state); | |
| 1041 fz_always(ctx) | |
| 1042 { | |
| 1043 (*env)->ReleaseStringUTFChars(env, jneedle, needle); | |
| 1044 } | |
| 1045 fz_catch(ctx) | |
| 1046 jni_rethrow(env, ctx); | |
| 1047 | |
| 1048 if (state.error) | |
| 1049 return NULL; | |
| 1050 | |
| 1051 return (*env)->CallObjectMethod(env, state.hits, mid_ArrayList_toArray); | |
| 1052 } | |
| 1053 | |
| 1054 JNIEXPORT jobject JNICALL | |
| 1055 FUN(Document_resolveLinkDestination)(JNIEnv *env, jobject self, jstring juri) | |
| 1056 { | |
| 1057 fz_context *ctx = get_context(env); | |
| 1058 fz_document *doc = from_Document(env, self); | |
| 1059 const char *uri = ""; | |
| 1060 fz_link_dest dest; | |
| 1061 jobject jdestination; | |
| 1062 | |
| 1063 if (!ctx || !doc) return NULL; | |
| 1064 | |
| 1065 if (juri) | |
| 1066 { | |
| 1067 uri = (*env)->GetStringUTFChars(env, juri, NULL); | |
| 1068 if (!uri) | |
| 1069 return NULL; | |
| 1070 } | |
| 1071 | |
| 1072 fz_try(ctx) | |
| 1073 dest = fz_resolve_link_dest(ctx, doc, uri); | |
| 1074 fz_always(ctx) | |
| 1075 if (juri) | |
| 1076 (*env)->ReleaseStringUTFChars(env, juri, uri); | |
| 1077 fz_catch(ctx) | |
| 1078 jni_rethrow(env, ctx); | |
| 1079 | |
| 1080 jdestination = (*env)->NewObject(env, cls_LinkDestination, mid_LinkDestination_init, | |
| 1081 dest.loc.chapter, dest.loc.page, dest.type, dest.x, dest.y, dest.w, dest.h, dest.zoom); | |
| 1082 if (!jdestination || (*env)->ExceptionCheck(env)) | |
| 1083 return NULL; | |
| 1084 | |
| 1085 return jdestination; | |
| 1086 } | |
| 1087 | |
| 1088 JNIEXPORT jstring JNICALL | |
| 1089 FUN(Document_formatLinkURI)(JNIEnv *env, jobject self, jobject jdest) | |
| 1090 { | |
| 1091 fz_context *ctx = get_context(env); | |
| 1092 fz_document *doc = from_Document(env, self); | |
| 1093 fz_link_dest dest = from_LinkDestination(env, jdest); | |
| 1094 char *uri = NULL; | |
| 1095 jobject juri; | |
| 1096 | |
| 1097 fz_try(ctx) | |
| 1098 uri = fz_format_link_uri(ctx, doc, dest); | |
| 1099 fz_catch(ctx) | |
| 1100 jni_rethrow(env, ctx); | |
| 1101 | |
| 1102 juri = (*env)->NewStringUTF(env, uri); | |
| 1103 fz_free(ctx, uri); | |
| 1104 if (juri == NULL || (*env)->ExceptionCheck(env)) | |
| 1105 return NULL; | |
| 1106 | |
| 1107 return juri; | |
| 1108 } | |
| 1109 | |
| 1110 JNIEXPORT jobject JNICALL | |
| 1111 FUN(Document_asPDF)(JNIEnv *env, jobject self) | |
| 1112 { | |
| 1113 fz_context *ctx = get_context(env); | |
| 1114 fz_document *doc = from_Document(env, self); | |
| 1115 pdf_document *pdf; | |
| 1116 | |
| 1117 fz_try(ctx) | |
| 1118 pdf = fz_new_pdf_document_from_fz_document(ctx, doc); | |
| 1119 fz_catch(ctx) | |
| 1120 jni_rethrow(env, ctx); | |
| 1121 | |
| 1122 if (!pdf) | |
| 1123 return NULL; | |
| 1124 | |
| 1125 return to_PDFDocument_safe_own(ctx, env, pdf); | |
| 1126 } |
