comparison mupdf-source/platform/java/jni/pdfwidget.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-2025 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 /* PDFWidget interface */
24
25 JNIEXPORT jstring JNICALL
26 FUN(PDFWidget_getValue)(JNIEnv *env, jobject self)
27 {
28 fz_context *ctx = get_context(env);
29 pdf_annot *widget = from_PDFWidget_safe(env, self);
30 const char *text = NULL;
31
32 if (!ctx || !widget) return NULL;
33
34 fz_try(ctx)
35 text = pdf_field_value(ctx, pdf_annot_obj(ctx, widget));
36 fz_catch(ctx)
37 jni_rethrow(env, ctx);
38
39 return (*env)->NewStringUTF(env, text);
40 }
41
42 JNIEXPORT jboolean JNICALL
43 FUN(PDFWidget_setTextValue)(JNIEnv *env, jobject self, jstring jval)
44 {
45 fz_context *ctx = get_context(env);
46 pdf_annot *widget = from_PDFWidget_safe(env, self);
47 const char *val = NULL;
48 jboolean accepted = JNI_FALSE;
49
50 if (!ctx || !widget) return JNI_FALSE;
51
52 if (jval)
53 val = (*env)->GetStringUTFChars(env, jval, NULL);
54
55 fz_var(accepted);
56 fz_try(ctx)
57 accepted = pdf_set_text_field_value(ctx, widget, val);
58 fz_always(ctx)
59 if (jval)
60 (*env)->ReleaseStringUTFChars(env, jval, val);
61 fz_catch(ctx)
62 jni_rethrow(env, ctx);
63
64 return accepted;
65 }
66
67 JNIEXPORT jboolean JNICALL
68 FUN(PDFWidget_setChoiceValue)(JNIEnv *env, jobject self, jstring jval)
69 {
70 fz_context *ctx = get_context(env);
71 pdf_annot *widget = from_PDFWidget_safe(env, self);
72 const char *val = NULL;
73 jboolean accepted = JNI_FALSE;
74
75 if (!ctx || !widget) return JNI_FALSE;
76
77 if (jval)
78 val = (*env)->GetStringUTFChars(env, jval, NULL);
79
80 fz_var(accepted);
81 fz_try(ctx)
82 accepted = pdf_set_choice_field_value(ctx, widget, val);
83 fz_always(ctx)
84 if (jval)
85 (*env)->ReleaseStringUTFChars(env, jval, val);
86 fz_catch(ctx)
87 jni_rethrow(env, ctx);
88
89 return accepted;
90 }
91
92 JNIEXPORT jboolean JNICALL
93 FUN(PDFWidget_setValue)(JNIEnv *env, jobject self, jstring jval)
94 {
95 fz_context *ctx = get_context(env);
96 pdf_annot *widget = from_PDFWidget_safe(env, self);
97 const char *val = NULL;
98 jboolean accepted = JNI_FALSE;
99
100 if (!ctx || !widget) return JNI_FALSE;
101
102 if (jval)
103 val = (*env)->GetStringUTFChars(env, jval, NULL);
104
105 fz_var(accepted);
106 fz_try(ctx)
107 accepted = pdf_set_field_value(ctx, pdf_annot_page(ctx, widget)->doc, pdf_annot_obj(ctx, widget), (char *)val, pdf_get_widget_editing_state(ctx, widget));
108 fz_always(ctx)
109 if (jval)
110 (*env)->ReleaseStringUTFChars(env, jval, val);
111 fz_catch(ctx)
112 jni_rethrow(env, ctx);
113
114 return accepted;
115 }
116
117 JNIEXPORT jboolean JNICALL
118 FUN(PDFWidget_toggle)(JNIEnv *env, jobject self)
119 {
120 fz_context *ctx = get_context(env);
121 pdf_annot *widget = from_PDFWidget_safe(env, self);
122 jboolean accepted = JNI_FALSE;
123
124 if (!ctx || !widget) return JNI_FALSE;
125
126 fz_var(accepted);
127 fz_try(ctx)
128 accepted = pdf_toggle_widget(ctx, widget);
129 fz_catch(ctx)
130 jni_rethrow(env, ctx);
131
132 return accepted;
133 }
134
135 JNIEXPORT void JNICALL
136 FUN(PDFWidget_setEditing)(JNIEnv *env, jobject self, jboolean val)
137 {
138 fz_context *ctx = get_context(env);
139 pdf_annot *widget = from_PDFWidget_safe(env, self);
140
141 if (!ctx || !widget) return;
142
143 fz_try(ctx)
144 pdf_set_widget_editing_state(ctx, widget, val);
145 fz_catch(ctx)
146 jni_rethrow_void(env, ctx);
147 }
148
149 JNIEXPORT jboolean JNICALL
150 FUN(PDFWidget_isEditing)(JNIEnv *env, jobject self)
151 {
152 fz_context *ctx = get_context(env);
153 pdf_annot *widget = from_PDFWidget_safe(env, self);
154 jboolean state = JNI_FALSE;
155
156 if (!ctx || !widget) return JNI_FALSE;
157
158 fz_var(state);
159 fz_try(ctx)
160 state = pdf_get_widget_editing_state(ctx, widget);
161 fz_catch(ctx)
162 jni_rethrow(env, ctx);
163
164 return state;
165 }
166
167 JNIEXPORT jobject JNICALL
168 FUN(PDFWidget_textQuads)(JNIEnv *env, jobject self)
169 {
170 fz_context *ctx = get_context(env);
171 pdf_annot *widget = from_PDFWidget_safe(env, self);
172 jobject jquad;
173 jobjectArray array;
174 int i, nchars;
175 fz_stext_page *stext = NULL;
176
177 if (!ctx || !widget) return NULL;
178
179 fz_try(ctx)
180 {
181 fz_stext_options opts = { 0 };
182 opts.flags = FZ_STEXT_INHIBIT_SPACES;
183 stext = pdf_new_stext_page_from_annot(ctx, widget, &opts);
184 }
185 fz_catch(ctx)
186 jni_rethrow(env, ctx);
187
188 nchars = 0;
189 for (fz_stext_block *block = stext->first_block; block; block = block->next)
190 {
191 if (block->type == FZ_STEXT_BLOCK_TEXT)
192 {
193 for (fz_stext_line *line = block->u.t.first_line; line; line = line->next)
194 {
195 for (fz_stext_char *ch = line->first_char; ch; ch = ch->next)
196 {
197 nchars++;
198 }
199 }
200 }
201 }
202
203 array = (*env)->NewObjectArray(env, nchars, cls_Quad, NULL);
204 if (!array || (*env)->ExceptionCheck(env))
205 {
206 fz_drop_stext_page(ctx, stext);
207 return NULL;
208 }
209
210 i = 0;
211 for (fz_stext_block *block = stext->first_block; block; block = block->next)
212 {
213 if (block->type == FZ_STEXT_BLOCK_TEXT)
214 {
215 for (fz_stext_line *line = block->u.t.first_line; line; line = line->next)
216 {
217 for (fz_stext_char *ch = line->first_char; ch; ch = ch->next)
218 {
219 jquad = to_Quad_safe(ctx, env, ch->quad);
220 if (!jquad)
221 {
222 fz_drop_stext_page(ctx, stext);
223 return NULL;
224 }
225
226 (*env)->SetObjectArrayElement(env, array, i, jquad);
227 if ((*env)->ExceptionCheck(env))
228 {
229 fz_drop_stext_page(ctx, stext);
230 return NULL;
231 }
232
233 (*env)->DeleteLocalRef(env, jquad);
234 i++;
235 }
236 }
237 }
238 }
239
240 fz_drop_stext_page(ctx, stext);
241 return array;
242 }
243
244 JNIEXPORT jint JNICALL
245 FUN(PDFWidget_validateSignature)(JNIEnv *env, jobject self)
246 {
247 fz_context *ctx = get_context(env);
248 pdf_annot *widget = from_PDFWidget_safe(env, self);
249 int val = 0;
250
251 if (!ctx || !widget) return 0;
252
253 fz_try(ctx)
254 val = pdf_validate_signature(ctx, widget);
255 fz_catch(ctx)
256 jni_rethrow(env, ctx);
257
258 return val;
259 }
260
261 JNIEXPORT void JNICALL
262 FUN(PDFWidget_clearSignature)(JNIEnv *env, jobject self)
263 {
264 fz_context *ctx = get_context(env);
265 pdf_annot *widget = from_PDFWidget_safe(env, self);
266
267 if (!ctx || !widget) return;
268
269 fz_try(ctx)
270 pdf_clear_signature(ctx, widget);
271 fz_catch(ctx)
272 jni_rethrow_void(env, ctx);
273 }
274
275 JNIEXPORT jboolean JNICALL
276 FUN(PDFWidget_isSigned)(JNIEnv *env, jobject self)
277 {
278 fz_context *ctx = get_context(env);
279 pdf_annot *widget = from_PDFWidget_safe(env, self);
280 jboolean val = JNI_FALSE;
281
282 if (!ctx || !widget) return JNI_FALSE;
283
284 fz_try(ctx)
285 val = !!pdf_widget_is_signed(ctx, widget);
286 fz_catch(ctx)
287 jni_rethrow(env, ctx);
288
289 return val;
290 }
291
292 JNIEXPORT jint JNICALL
293 FUN(PDFWidget_checkCertificate)(JNIEnv *env, jobject self, jobject jverifier)
294 {
295 fz_context *ctx = get_context(env);
296 pdf_annot *widget = from_PDFWidget_safe(env, self);
297 pdf_document *pdf = pdf_annot_page(ctx, widget)->doc;
298 java_pkcs7_verifier *verifier = from_PKCS7Verifier_safe(env, jverifier);
299 pdf_signature_error ret = PDF_SIGNATURE_ERROR_UNKNOWN;
300
301 if (!ctx || !widget || !pdf) return PDF_SIGNATURE_ERROR_UNKNOWN;
302 if (!verifier) jni_throw_arg(env, "verifier must not be null");
303
304 fz_try(ctx)
305 ret = pdf_check_certificate(ctx, &verifier->base, pdf, pdf_annot_obj(ctx, widget));
306 fz_catch(ctx)
307 jni_rethrow(env, ctx);
308
309 return ret;
310 }
311
312 JNIEXPORT jint JNICALL
313 FUN(PDFWidget_checkDigest)(JNIEnv *env, jobject self, jobject jverifier)
314 {
315 fz_context *ctx = get_context(env);
316 pdf_annot *widget = from_PDFWidget_safe(env, self);
317 java_pkcs7_verifier *verifier = from_PKCS7Verifier_safe(env, jverifier);
318 pdf_signature_error ret = PDF_SIGNATURE_ERROR_UNKNOWN;
319
320 if (!ctx || !widget) return PDF_SIGNATURE_ERROR_UNKNOWN;
321 if (!verifier) jni_throw_arg(env, "verifier must not be null");
322
323 fz_try(ctx)
324 ret = pdf_check_widget_digest(ctx, &verifier->base, widget);
325 fz_catch(ctx)
326 jni_rethrow(env, ctx);
327
328 return ret;
329 }
330
331 JNIEXPORT jboolean JNICALL
332 FUN(PDFWidget_incrementalChangeSinceSigning)(JNIEnv *env, jobject self)
333 {
334 fz_context *ctx = get_context(env);
335 pdf_annot *widget = from_PDFWidget_safe(env, self);
336 jboolean change = JNI_FALSE;
337
338 if (!ctx || !widget) return JNI_FALSE;
339
340 fz_try(ctx)
341 change = pdf_incremental_change_since_signing_widget(ctx, widget);
342 fz_catch(ctx)
343 jni_rethrow(env, ctx);
344
345 return change;
346 }
347
348 JNIEXPORT jobject JNICALL
349 FUN(PDFWidget_getDistinguishedName)(JNIEnv *env, jobject self, jobject jverifier)
350 {
351 fz_context *ctx = get_context(env);
352 pdf_annot *widget = from_PDFWidget_safe(env, self);
353 java_pkcs7_verifier *verifier = from_PKCS7Verifier_safe(env, jverifier);
354 pdf_document *pdf = pdf_annot_page(ctx, widget)->doc;
355 jobject jcn, jo, jou, jemail, jc;
356 pdf_pkcs7_distinguished_name *name;
357 jobject jname;
358
359 if (!ctx || !widget || !pdf) return NULL;
360 if (!verifier) jni_throw_arg(env, "verifier must not be null");
361
362 jname = (*env)->NewObject(env, cls_PKCS7DistinguishedName, mid_PKCS7DistinguishedName_init);
363 if ((*env)->ExceptionCheck(env)) return NULL;
364 if (!jname) jni_throw_run(env, "cannot create distinguished name object");
365
366 fz_try(ctx)
367 {
368 name = pdf_signature_get_widget_signatory(ctx, &verifier->base, widget);
369
370 jcn = (*env)->NewStringUTF(env, name->cn);
371 if (!jcn)
372 jni_throw_run(env, "cannot create common name string");
373 if ((*env)->ExceptionCheck(env))
374 fz_throw_java(ctx, env);
375 jo = (*env)->NewStringUTF(env, name->o);
376 if (!jo)
377 jni_throw_run(env, "cannot create organization string");
378 if ((*env)->ExceptionCheck(env))
379 fz_throw_java(ctx, env);
380 jou = (*env)->NewStringUTF(env, name->ou);
381 if (!jou)
382 jni_throw_run(env, "cannot create organizational unit string");
383 if ((*env)->ExceptionCheck(env))
384 fz_throw_java(ctx, env);
385 jemail = (*env)->NewStringUTF(env, name->email);
386 if (!jemail)
387 jni_throw_run(env, "cannot create email string");
388 if ((*env)->ExceptionCheck(env))
389 fz_throw_java(ctx, env);
390 jc = (*env)->NewStringUTF(env, name->c);
391 if (!jc)
392 jni_throw_run(env, "cannot create country string");
393 if ((*env)->ExceptionCheck(env))
394 fz_throw_java(ctx, env);
395 }
396 fz_always(ctx)
397 pdf_signature_drop_distinguished_name(ctx, name);
398 fz_catch(ctx)
399 jni_rethrow(env, ctx);
400
401 (*env)->SetObjectField(env, jname, fid_PKCS7DistinguishedName_cn, jcn);
402 (*env)->SetObjectField(env, jname, fid_PKCS7DistinguishedName_o, jo);
403 (*env)->SetObjectField(env, jname, fid_PKCS7DistinguishedName_ou, jou);
404 (*env)->SetObjectField(env, jname, fid_PKCS7DistinguishedName_email, jemail);
405 (*env)->SetObjectField(env, jname, fid_PKCS7DistinguishedName_c, jc);
406
407 return jname;
408 }
409
410 JNIEXPORT jstring JNICALL
411 FUN(PDFWidget_getSignatory)(JNIEnv *env, jobject self, jobject jverifier)
412 {
413 fz_context *ctx = get_context(env);
414 pdf_annot *widget = from_PDFWidget_safe(env, self);
415 java_pkcs7_verifier *verifier = from_PKCS7Verifier_safe(env, jverifier);
416 pdf_document *pdf = pdf_annot_page(ctx, widget)->doc;
417 pdf_pkcs7_distinguished_name *name;
418 char *s = NULL;
419 char buf[800];
420
421 if (!ctx || !widget || !pdf) return NULL;
422 if (!verifier) jni_throw_arg(env, "verifier must not be null");
423
424 fz_var(s);
425
426 fz_try(ctx)
427 {
428 name = pdf_signature_get_widget_signatory(ctx, &verifier->base, widget);
429 if (name)
430 {
431 s = pdf_signature_format_distinguished_name(ctx, name);
432 fz_strlcpy(buf, s, sizeof buf);
433 fz_free(ctx, s);
434 }
435 else
436 {
437 fz_strlcpy(buf, "Signature information missing.", sizeof buf);
438 }
439 }
440 fz_always(ctx)
441 pdf_signature_drop_distinguished_name(ctx, name);
442 fz_catch(ctx)
443 jni_rethrow(env, ctx);
444
445 return to_String_safe(ctx, env, &buf[0]);
446 }
447
448 JNIEXPORT jboolean JNICALL
449 FUN(PDFWidget_signNative)(JNIEnv *env, jobject self, jobject jsigner, jint flags, jobject jimage, jstring jreason, jstring jlocation)
450 {
451 fz_context *ctx = get_context(env);
452 pdf_annot *widget = from_PDFWidget_safe(env, self);
453 pdf_document *pdf = pdf_annot_page(ctx, widget)->doc;
454 pdf_pkcs7_signer *signer = from_PKCS7Signer_safe(env, jsigner);
455 fz_image *image = from_Image_safe(env, jimage);
456 const char *reason = NULL;
457 const char *location = NULL;
458
459 if (!ctx || !widget || !pdf) return JNI_FALSE;
460 if (!signer) jni_throw_arg(env, "signer must not be null");
461
462 if (jreason)
463 reason = (*env)->GetStringUTFChars(env, jreason, NULL);
464 if (jlocation)
465 location = (*env)->GetStringUTFChars(env, jlocation, NULL);
466
467 fz_try(ctx)
468 pdf_sign_signature(ctx, widget, signer, flags, image, reason, location);
469 fz_always(ctx)
470 {
471 if (jreason)
472 (*env)->ReleaseStringUTFChars(env, jreason, reason);
473 if (jlocation)
474 (*env)->ReleaseStringUTFChars(env, jlocation, location);
475 }
476 fz_catch(ctx)
477 jni_rethrow(env, ctx);
478
479 return JNI_TRUE;
480 }
481
482 JNIEXPORT jobject JNICALL
483 FUN(PDFWidget_previewSignatureNative)(JNIEnv *env, jclass cls, jint width, jint height, jint lang, jobject jsigner, jint flags, jobject jimage, jstring jreason, jstring jlocation)
484 {
485 fz_context *ctx = get_context(env);
486 pdf_pkcs7_signer *signer = from_PKCS7Signer_safe(env, jsigner);
487 fz_image *image = from_Image_safe(env, jimage);
488 const char *reason = NULL;
489 const char *location = NULL;
490 fz_pixmap *pixmap = NULL;
491
492 if (!ctx) return JNI_FALSE;
493 if (!signer) jni_throw_arg(env, "signer must not be null");
494
495 if (jreason)
496 reason = (*env)->GetStringUTFChars(env, jreason, NULL);
497 if (jlocation)
498 location = (*env)->GetStringUTFChars(env, jlocation, NULL);
499
500 fz_var(pixmap);
501
502 fz_try(ctx)
503 pixmap = pdf_preview_signature_as_pixmap(ctx,
504 width, height, lang,
505 signer, flags, image,
506 reason, location);
507 fz_always(ctx)
508 {
509 if (jreason)
510 (*env)->ReleaseStringUTFChars(env, jreason, reason);
511 if (jlocation)
512 (*env)->ReleaseStringUTFChars(env, jlocation, location);
513 }
514 fz_catch(ctx)
515 jni_rethrow(env, ctx);
516
517 return to_Pixmap_safe_own(ctx, env, pixmap);
518 }
519
520 JNIEXPORT jobject JNICALL
521 FUN(PDFWidget_layoutTextWidget)(JNIEnv *env, jobject self)
522 {
523 fz_context *ctx = get_context(env);
524 pdf_annot *widget = from_PDFWidget_safe(env, self);
525 fz_layout_block *layout = NULL;
526 fz_layout_line *line = NULL;
527 fz_layout_char *chr = NULL;
528 jobject jlayout, jlines, jmatrix, jinvmatrix;
529 fz_rect bounds;
530 fz_matrix mat;
531 const char *s;
532 int nlines = 0;
533 int i;
534
535 if (!ctx || !widget) return NULL;
536
537 jlayout = (*env)->NewObject(env, cls_TextWidgetLayout, mid_TextWidgetLayout_init, self);
538 if ((*env)->ExceptionCheck(env)) return NULL;
539 if (!jlayout) jni_throw_run(env, "cannot create text widget layout object");
540
541 fz_try(ctx)
542 {
543 bounds = pdf_bound_widget(ctx, widget);
544 layout = pdf_layout_text_widget(ctx, widget);
545 mat = fz_concat(layout->inv_matrix, fz_translate(-bounds.x0, -bounds.y0));
546 }
547 fz_catch(ctx)
548 jni_rethrow(env, ctx);
549
550 jmatrix = to_Matrix_safe(ctx, env, layout->matrix);
551 if ((*env)->ExceptionCheck(env))
552 {
553 fz_drop_layout(ctx, layout);
554 return NULL;
555 }
556 if (!jmatrix)
557 {
558 fz_drop_layout(ctx, layout);
559 jni_throw_run(env, "cannot create text widget layout matrix object");
560 }
561 (*env)->SetObjectField(env, jlayout, fid_TextWidgetLayout_matrix, jmatrix);
562
563 jinvmatrix = to_Matrix_safe(ctx, env, layout->inv_matrix);
564 if ((*env)->ExceptionCheck(env))
565 {
566 fz_drop_layout(ctx, layout);
567 return NULL;
568 }
569 if (!jinvmatrix)
570 {
571 fz_drop_layout(ctx, layout);
572 jni_throw_run(env, "cannot create text widget layout inverted matrix object");
573 }
574 (*env)->SetObjectField(env, jlayout, fid_TextWidgetLayout_invMatrix, jinvmatrix);
575
576 for (line = layout->head; line; line = line->next)
577 nlines++;
578
579 jlines = (*env)->NewObjectArray(env, nlines, cls_TextWidgetLineLayout, NULL);
580 if ((*env)->ExceptionCheck(env))
581 {
582 fz_drop_layout(ctx, layout);
583 return NULL;
584 }
585 if (!jlines)
586 {
587 fz_drop_layout(ctx, layout);
588 jni_throw_run(env, "cannot create text widget line layout object");
589 }
590 (*env)->SetObjectField(env, jlayout, fid_TextWidgetLayout_lines, jlines);
591
592 s = layout->head->p;
593
594 i = 0;
595 for (line = layout->head; line; line = line->next)
596 {
597 jobject jlinelayout, jchars, jlrect;
598 float y = line->y - line->font_size * 0.2f;
599 float b = line->y + line->font_size;
600 fz_rect lrect = fz_make_rect(line->x, y, line->x, b);
601 lrect = fz_transform_rect(lrect, mat);
602 int nchars = 0;
603 int k;
604
605 jlinelayout = (*env)->NewObject(env, cls_TextWidgetLineLayout, mid_TextWidgetLineLayout_init, self);
606 if ((*env)->ExceptionCheck(env))
607 {
608 fz_drop_layout(ctx, layout);
609 return NULL;
610 }
611 if (!jlinelayout)
612 {
613 fz_drop_layout(ctx, layout);
614 jni_throw_run(env, "cannot create text widget line layout object");
615 }
616
617 (*env)->SetObjectArrayElement(env, jlines, i, jlinelayout);
618 if ((*env)->ExceptionCheck(env))
619 {
620 fz_drop_layout(ctx, layout);
621 return NULL;
622 }
623 i++;
624
625 (*env)->SetFloatField(env, jlinelayout, fid_TextWidgetLineLayout_x, line->x);
626 (*env)->SetFloatField(env, jlinelayout, fid_TextWidgetLineLayout_y, line->y);
627 (*env)->SetFloatField(env, jlinelayout, fid_TextWidgetLineLayout_fontSize, line->font_size);
628 (*env)->SetIntField(env, jlinelayout, fid_TextWidgetLineLayout_index, fz_runeidx(s, line->p));
629
630 for (chr = line->text; chr; chr = chr->next)
631 nchars++;
632
633 jchars = (*env)->NewObjectArray(env, nchars, cls_TextWidgetCharLayout, NULL);
634 if (!jchars || (*env)->ExceptionCheck(env))
635 {
636 fz_drop_layout(ctx, layout);
637 return NULL;
638 }
639 (*env)->SetObjectField(env, jlinelayout, fid_TextWidgetLineLayout_chars, jchars);
640
641 k = 0;
642 for (chr = line->text; chr; chr = chr->next)
643 {
644 jobject jcharlayout, jcrect;
645 fz_rect crect = fz_make_rect(chr->x, y, chr->x + chr->advance, b);
646 crect = fz_transform_rect(crect, mat);
647 lrect = fz_union_rect(lrect, crect);
648
649 jcharlayout = (*env)->NewObject(env, cls_TextWidgetCharLayout, mid_TextWidgetCharLayout_init, self);
650 if ((*env)->ExceptionCheck(env))
651 {
652 fz_drop_layout(ctx, layout);
653 return NULL;
654 }
655 if (!jcharlayout)
656 {
657 fz_drop_layout(ctx, layout);
658 jni_throw_run(env, "cannot create text widget character layout object");
659 }
660
661 (*env)->SetObjectArrayElement(env, jchars, k, jcharlayout);
662 if ((*env)->ExceptionCheck(env))
663 {
664 fz_drop_layout(ctx, layout);
665 return NULL;
666 }
667 k++;
668
669 jcrect = to_Rect_safe(ctx, env, crect);
670 (*env)->SetObjectField(env, jcharlayout, fid_TextWidgetCharLayout_rect, jcrect);
671 (*env)->SetFloatField(env, jcharlayout, fid_TextWidgetCharLayout_x, chr->x);
672 (*env)->SetFloatField(env, jcharlayout, fid_TextWidgetCharLayout_advance, chr->advance);
673 (*env)->SetIntField(env, jcharlayout, fid_TextWidgetCharLayout_index, fz_runeidx(s, chr->p));
674
675 (*env)->DeleteLocalRef(env, jcrect);
676 (*env)->DeleteLocalRef(env, jcharlayout);
677 }
678
679 jlrect = to_Rect_safe(ctx, env, lrect);
680 (*env)->SetObjectField(env, jlinelayout, fid_TextWidgetLineLayout_rect, jlrect);
681
682 (*env)->DeleteLocalRef(env, jlrect);
683 (*env)->DeleteLocalRef(env, jchars);
684 (*env)->DeleteLocalRef(env, jlinelayout);
685 }
686
687 fz_drop_layout(ctx, layout);
688
689 return jlayout;
690 }
691
692 JNIEXPORT jstring JNICALL
693 FUN(PDFWidget_getLabel)(JNIEnv *env, jobject self)
694 {
695 fz_context *ctx = get_context(env);
696 pdf_annot *widget = from_PDFWidget_safe(env, self);
697 const char *text = NULL;
698
699 if (!ctx || !widget) return NULL;
700
701 fz_try(ctx)
702 text = pdf_annot_field_label(ctx, widget);
703 fz_catch(ctx)
704 jni_rethrow(env, ctx);
705
706 return (*env)->NewStringUTF(env, text);
707 }
708
709 JNIEXPORT jstring JNICALL
710 FUN(PDFWidget_getName)(JNIEnv *env, jobject self)
711 {
712 fz_context *ctx = get_context(env);
713 pdf_annot *widget = from_PDFWidget_safe(env, self);
714 char *name = NULL;
715 jstring jname;
716
717 if (!ctx || !widget) return NULL;
718
719 fz_try(ctx)
720 name = pdf_load_field_name(ctx, pdf_annot_obj(ctx, widget));
721 fz_catch(ctx)
722 jni_rethrow(env, ctx);
723
724 jname = (*env)->NewStringUTF(env, name);
725 fz_free(ctx, name);
726 if (!jname || (*env)->ExceptionCheck(env))
727 jni_throw_run(env, "cannot create widget name string");
728 return jname;
729 }
730
731 JNIEXPORT jboolean JNICALL
732 FUN(PDFWidget_getEditingState)(JNIEnv *env, jobject self)
733 {
734 fz_context *ctx = get_context(env);
735 pdf_annot *widget = from_PDFWidget_safe(env, self);
736 jboolean editing = JNI_FALSE;
737
738 if (!ctx || !widget) return JNI_FALSE;
739
740 fz_try(ctx)
741 editing = pdf_get_widget_editing_state(ctx, widget);
742 fz_catch(ctx)
743 jni_rethrow(env, ctx);
744
745 return editing;
746 }
747
748 JNIEXPORT void JNICALL
749 FUN(PDFWidget_setEditingState)(JNIEnv *env, jobject self, jboolean editing)
750 {
751 fz_context *ctx = get_context(env);
752 pdf_annot *widget = from_PDFWidget_safe(env, self);
753
754 if (!ctx || !widget) return;
755
756 fz_try(ctx)
757 pdf_set_widget_editing_state(ctx, widget, editing);
758 fz_catch(ctx)
759 jni_rethrow_void(env, ctx);
760 }