pdfwidget.c 20 KB

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