device.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  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. /* Device interface */
  23. /*
  24. Devices can either be implemented in C, or in Java.
  25. We therefore have to think about 4 possible call combinations.
  26. 1) C -> C:
  27. The standard mupdf case. No special worries here.
  28. 2) C -> Java:
  29. This can only happen when we call run on a page/annotation/
  30. displaylist. We need to ensure that the java Device has an
  31. appropriate fz_java_device generated for it, which is done by the
  32. Device constructor. The 'run' calls take care to lock/unlock for us.
  33. 3) Java -> C:
  34. The C device will have a java shim (a subclass of NativeDevice).
  35. All calls will go through the device methods in NativeDevice,
  36. which converts the java objects to C ones, and lock/unlock
  37. any underlying objects as required.
  38. 4) Java -> Java:
  39. No special worries.
  40. */
  41. typedef struct
  42. {
  43. fz_device super;
  44. JNIEnv *env;
  45. jobject self;
  46. }
  47. fz_java_device;
  48. static void
  49. fz_java_device_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *cs, const float *color, float alpha, fz_color_params cs_params)
  50. {
  51. fz_java_device *jdev = (fz_java_device *)dev;
  52. JNIEnv *env = jdev->env;
  53. jobject jpath = to_Path(ctx, env, path);
  54. jobject jcs = to_ColorSpace(ctx, env, cs);
  55. jobject jctm = to_Matrix(ctx, env, ctm);
  56. jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
  57. int jcp = to_ColorParams_safe(ctx, env, cs_params);
  58. (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillPath, jpath, (jboolean)even_odd, jctm, jcs, jcolor, alpha, jcp);
  59. if ((*env)->ExceptionCheck(env))
  60. fz_throw_java(ctx, env);
  61. }
  62. static void
  63. fz_java_device_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *state, fz_matrix ctm, fz_colorspace *cs, const float *color, float alpha, fz_color_params cs_params)
  64. {
  65. fz_java_device *jdev = (fz_java_device *)dev;
  66. JNIEnv *env = jdev->env;
  67. jobject jpath = to_Path(ctx, env, path);
  68. jobject jstate = to_StrokeState(ctx, env, state);
  69. jobject jcs = to_ColorSpace(ctx, env, cs);
  70. jobject jctm = to_Matrix(ctx, env, ctm);
  71. jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
  72. int jcp = to_ColorParams_safe(ctx, env, cs_params);
  73. (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokePath, jpath, jstate, jctm, jcs, jcolor, alpha, jcp);
  74. if ((*env)->ExceptionCheck(env))
  75. fz_throw_java(ctx, env);
  76. }
  77. static void
  78. fz_java_device_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
  79. {
  80. fz_java_device *jdev = (fz_java_device *)dev;
  81. JNIEnv *env = jdev->env;
  82. jobject jpath = to_Path(ctx, env, path);
  83. jobject jctm = to_Matrix(ctx, env, ctm);
  84. (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipPath, jpath, (jboolean)even_odd, jctm);
  85. if ((*env)->ExceptionCheck(env))
  86. fz_throw_java(ctx, env);
  87. }
  88. static void
  89. fz_java_device_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *state, fz_matrix ctm, fz_rect scissor)
  90. {
  91. fz_java_device *jdev = (fz_java_device *)dev;
  92. JNIEnv *env = jdev->env;
  93. jobject jpath = to_Path(ctx, env, path);
  94. jobject jstate = to_StrokeState(ctx, env, state);
  95. jobject jctm = to_Matrix(ctx, env, ctm);
  96. (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipStrokePath, jpath, jstate, jctm);
  97. if ((*env)->ExceptionCheck(env))
  98. fz_throw_java(ctx, env);
  99. }
  100. static void
  101. fz_java_device_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_colorspace *cs, const float *color, float alpha, fz_color_params cs_params)
  102. {
  103. fz_java_device *jdev = (fz_java_device *)dev;
  104. JNIEnv *env = jdev->env;
  105. jobject jtext = to_Text(ctx, env, text);
  106. jobject jctm = to_Matrix(ctx, env, ctm);
  107. jobject jcs = to_ColorSpace(ctx, env, cs);
  108. jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
  109. int jcp = to_ColorParams_safe(ctx, env, cs_params);
  110. (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillText, jtext, jctm, jcs, jcolor, alpha, jcp);
  111. if ((*env)->ExceptionCheck(env))
  112. fz_throw_java(ctx, env);
  113. }
  114. static void
  115. fz_java_device_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *state, fz_matrix ctm, fz_colorspace *cs, const float *color, float alpha, fz_color_params cs_params)
  116. {
  117. fz_java_device *jdev = (fz_java_device *)dev;
  118. JNIEnv *env = jdev->env;
  119. jobject jtext = to_Text(ctx, env, text);
  120. jobject jstate = to_StrokeState(ctx, env, state);
  121. jobject jctm = to_Matrix(ctx, env, ctm);
  122. jobject jcs = to_ColorSpace(ctx, env, cs);
  123. jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
  124. int jcp = to_ColorParams_safe(ctx, env, cs_params);
  125. (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokeText, jtext, jstate, jctm, jcs, jcolor, alpha, jcp);
  126. if ((*env)->ExceptionCheck(env))
  127. fz_throw_java(ctx, env);
  128. }
  129. static void
  130. fz_java_device_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
  131. {
  132. fz_java_device *jdev = (fz_java_device *)dev;
  133. JNIEnv *env = jdev->env;
  134. jobject jtext = to_Text(ctx, env, text);
  135. jobject jctm = to_Matrix(ctx, env, ctm);
  136. (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipText, jtext, jctm);
  137. if ((*env)->ExceptionCheck(env))
  138. fz_throw_java(ctx, env);
  139. }
  140. static void
  141. fz_java_device_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *state, fz_matrix ctm, fz_rect scissor)
  142. {
  143. fz_java_device *jdev = (fz_java_device *)dev;
  144. JNIEnv *env = jdev->env;
  145. jobject jtext = to_Text(ctx, env, text);
  146. jobject jstate = to_StrokeState(ctx, env, state);
  147. jobject jctm = to_Matrix(ctx, env, ctm);
  148. (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipStrokeText, jtext, jstate, jctm);
  149. if ((*env)->ExceptionCheck(env))
  150. fz_throw_java(ctx, env);
  151. }
  152. static void
  153. fz_java_device_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
  154. {
  155. fz_java_device *jdev = (fz_java_device *)dev;
  156. JNIEnv *env = jdev->env;
  157. jobject jtext = to_Text(ctx, env, text);
  158. jobject jctm = to_Matrix(ctx, env, ctm);
  159. (*env)->CallVoidMethod(env, jdev->self, mid_Device_ignoreText, jtext, jctm);
  160. if ((*env)->ExceptionCheck(env))
  161. fz_throw_java(ctx, env);
  162. }
  163. static void
  164. fz_java_device_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shd, fz_matrix ctm, float alpha, fz_color_params color_params)
  165. {
  166. fz_java_device *jdev = (fz_java_device *)dev;
  167. JNIEnv *env = jdev->env;
  168. jobject jshd = to_Shade(ctx, env, shd);
  169. jobject jctm = to_Matrix(ctx, env, ctm);
  170. (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillShade, jshd, jctm, alpha);
  171. if ((*env)->ExceptionCheck(env))
  172. fz_throw_java(ctx, env);
  173. }
  174. static void
  175. fz_java_device_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, fz_matrix ctm, float alpha, fz_color_params color_params)
  176. {
  177. fz_java_device *jdev = (fz_java_device *)dev;
  178. JNIEnv *env = jdev->env;
  179. jobject jimg = to_Image(ctx, env, img);
  180. jobject jctm = to_Matrix(ctx, env, ctm);
  181. (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillImage, jimg, jctm, alpha);
  182. if ((*env)->ExceptionCheck(env))
  183. fz_throw_java(ctx, env);
  184. }
  185. static void
  186. fz_java_device_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, fz_matrix ctm, fz_colorspace *cs, const float *color, float alpha, fz_color_params cs_params)
  187. {
  188. fz_java_device *jdev = (fz_java_device *)dev;
  189. JNIEnv *env = jdev->env;
  190. jobject jimg = to_Image(ctx, env, img);
  191. jobject jctm = to_Matrix(ctx, env, ctm);
  192. jobject jcs = to_ColorSpace(ctx, env, cs);
  193. jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
  194. int jcp = to_ColorParams_safe(ctx, env, cs_params);
  195. (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillImageMask, jimg, jctm, jcs, jcolor, alpha, jcp);
  196. if ((*env)->ExceptionCheck(env))
  197. fz_throw_java(ctx, env);
  198. }
  199. static void
  200. fz_java_device_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, fz_matrix ctm, fz_rect scissor)
  201. {
  202. fz_java_device *jdev = (fz_java_device *)dev;
  203. JNIEnv *env = jdev->env;
  204. jobject jimg = to_Image(ctx, env, img);
  205. jobject jctm = to_Matrix(ctx, env, ctm);
  206. (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipImageMask, jimg, jctm);
  207. if ((*env)->ExceptionCheck(env))
  208. fz_throw_java(ctx, env);
  209. }
  210. static void
  211. fz_java_device_pop_clip(fz_context *ctx, fz_device *dev)
  212. {
  213. fz_java_device *jdev = (fz_java_device *)dev;
  214. JNIEnv *env = jdev->env;
  215. (*env)->CallVoidMethod(env, jdev->self, mid_Device_popClip);
  216. if ((*env)->ExceptionCheck(env))
  217. fz_throw_java(ctx, env);
  218. }
  219. static void
  220. fz_java_device_begin_layer(fz_context *ctx, fz_device *dev, const char *name)
  221. {
  222. fz_java_device *jdev = (fz_java_device *)dev;
  223. JNIEnv *env = jdev->env;
  224. jstring jname;
  225. jname = (*env)->NewStringUTF(env, name);
  226. if (!jname || (*env)->ExceptionCheck(env))
  227. fz_throw_java(ctx, env);
  228. (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginLayer, jname);
  229. if ((*env)->ExceptionCheck(env))
  230. fz_throw_java(ctx, env);
  231. }
  232. static void
  233. fz_java_device_end_layer(fz_context *ctx, fz_device *dev)
  234. {
  235. fz_java_device *jdev = (fz_java_device *)dev;
  236. JNIEnv *env = jdev->env;
  237. (*env)->CallVoidMethod(env, jdev->self, mid_Device_endLayer);
  238. if ((*env)->ExceptionCheck(env))
  239. fz_throw_java(ctx, env);
  240. }
  241. static void
  242. fz_java_device_begin_mask(fz_context *ctx, fz_device *dev, fz_rect rect, int luminosity, fz_colorspace *cs, const float *bc, fz_color_params cs_params)
  243. {
  244. fz_java_device *jdev = (fz_java_device *)dev;
  245. JNIEnv *env = jdev->env;
  246. jobject jrect = to_Rect(ctx, env, rect);
  247. jobject jcs = to_ColorSpace(ctx, env, cs);
  248. jfloatArray jbc = to_floatArray(ctx, env, bc, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
  249. int jcp = to_ColorParams_safe(ctx, env, cs_params);
  250. (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginMask, jrect, (jint)luminosity, jcs, jbc, jcp);
  251. if ((*env)->ExceptionCheck(env))
  252. fz_throw_java(ctx, env);
  253. }
  254. static void
  255. fz_java_device_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
  256. {
  257. fz_java_device *jdev = (fz_java_device *)dev;
  258. JNIEnv *env = jdev->env;
  259. // TODO: pass transfer function
  260. (*env)->CallVoidMethod(env, jdev->self, mid_Device_endMask);
  261. if ((*env)->ExceptionCheck(env))
  262. fz_throw_java(ctx, env);
  263. }
  264. static void
  265. fz_java_device_begin_group(fz_context *ctx, fz_device *dev, fz_rect rect, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
  266. {
  267. fz_java_device *jdev = (fz_java_device *)dev;
  268. JNIEnv *env = jdev->env;
  269. jobject jrect = to_Rect(ctx, env, rect);
  270. jobject jcs = to_ColorSpace(ctx, env, cs);
  271. (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginGroup, jrect, jcs, (jboolean)isolated, (jboolean)knockout, (jint)blendmode, alpha);
  272. if ((*env)->ExceptionCheck(env))
  273. fz_throw_java(ctx, env);
  274. }
  275. static void
  276. fz_java_device_end_group(fz_context *ctx, fz_device *dev)
  277. {
  278. fz_java_device *jdev = (fz_java_device *)dev;
  279. JNIEnv *env = jdev->env;
  280. (*env)->CallVoidMethod(env, jdev->self, mid_Device_endGroup);
  281. if ((*env)->ExceptionCheck(env))
  282. fz_throw_java(ctx, env);
  283. }
  284. static int
  285. fz_java_device_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id)
  286. {
  287. fz_java_device *jdev = (fz_java_device *)dev;
  288. JNIEnv *env = jdev->env;
  289. jobject jarea = to_Rect(ctx, env, area);
  290. jobject jview = to_Rect(ctx, env, view);
  291. jobject jctm = to_Matrix(ctx, env, ctm);
  292. int res;
  293. res = (*env)->CallIntMethod(env, jdev->self, mid_Device_beginTile, jarea, jview, xstep, ystep, jctm, (jint)id);
  294. if ((*env)->ExceptionCheck(env))
  295. fz_throw_java(ctx, env);
  296. return res;
  297. }
  298. static void
  299. fz_java_device_end_tile(fz_context *ctx, fz_device *dev)
  300. {
  301. fz_java_device *jdev = (fz_java_device *)dev;
  302. JNIEnv *env = jdev->env;
  303. (*env)->CallVoidMethod(env, jdev->self, mid_Device_endTile);
  304. if ((*env)->ExceptionCheck(env))
  305. fz_throw_java(ctx, env);
  306. }
  307. static void
  308. fz_java_device_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
  309. {
  310. fz_java_device *jdev = (fz_java_device *)dev;
  311. JNIEnv *env = jdev->env;
  312. (*env)->CallVoidMethod(env, jdev->self, mid_Device_renderFlags, set, clear);
  313. if ((*env)->ExceptionCheck(env))
  314. fz_throw_java(ctx, env);
  315. }
  316. static void
  317. fz_java_device_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *dcs)
  318. {
  319. fz_java_device *jdev = (fz_java_device *)dev;
  320. JNIEnv *env = jdev->env;
  321. jobject jdcs = to_DefaultColorSpaces(ctx, env, dcs);
  322. (*env)->CallVoidMethod(env, jdev->self, mid_Device_setDefaultColorSpaces, jdcs);
  323. if ((*env)->ExceptionCheck(env))
  324. fz_throw_java(ctx, env);
  325. }
  326. static void
  327. fz_java_device_begin_structure(fz_context *ctx, fz_device *dev, fz_structure standard, const char *raw, int idx)
  328. {
  329. fz_java_device *jdev = (fz_java_device *)dev;
  330. JNIEnv *env = jdev->env;
  331. jstring jraw;
  332. jraw = (*env)->NewStringUTF(env, raw);
  333. if (!jraw || (*env)->ExceptionCheck(env))
  334. fz_throw_java(ctx, env);
  335. (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginStructure, standard, jraw, idx);
  336. if ((*env)->ExceptionCheck(env))
  337. fz_throw_java(ctx, env);
  338. }
  339. static void
  340. fz_java_device_end_structure(fz_context *ctx, fz_device *dev)
  341. {
  342. fz_java_device *jdev = (fz_java_device *)dev;
  343. JNIEnv *env = jdev->env;
  344. (*env)->CallVoidMethod(env, jdev->self, mid_Device_endStructure);
  345. if ((*env)->ExceptionCheck(env))
  346. fz_throw_java(ctx, env);
  347. }
  348. static void
  349. fz_java_device_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *text)
  350. {
  351. fz_java_device *jdev = (fz_java_device *)dev;
  352. JNIEnv *env = jdev->env;
  353. jstring jtext;
  354. jtext = (*env)->NewStringUTF(env, text);
  355. if (!jtext || (*env)->ExceptionCheck(env))
  356. fz_throw_java(ctx, env);
  357. (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginMetatext, meta, jtext);
  358. if ((*env)->ExceptionCheck(env))
  359. fz_throw_java(ctx, env);
  360. }
  361. static void
  362. fz_java_device_end_metatext(fz_context *ctx, fz_device *dev)
  363. {
  364. fz_java_device *jdev = (fz_java_device *)dev;
  365. JNIEnv *env = jdev->env;
  366. (*env)->CallVoidMethod(env, jdev->self, mid_Device_endMetatext);
  367. if ((*env)->ExceptionCheck(env))
  368. fz_throw_java(ctx, env);
  369. }
  370. static void
  371. fz_java_device_drop(fz_context *ctx, fz_device *dev)
  372. {
  373. fz_java_device *jdev = (fz_java_device *)dev;
  374. JNIEnv *env = jdev->env;
  375. (*env)->DeleteGlobalRef(env, jdev->self);
  376. }
  377. static fz_device *fz_new_java_device(fz_context *ctx, JNIEnv *env, jclass cls)
  378. {
  379. fz_java_device *dev = NULL;
  380. jobject jself;
  381. jself = (*env)->NewGlobalRef(env, cls);
  382. if (!jself) return NULL;
  383. fz_try(ctx)
  384. {
  385. dev = fz_new_derived_device(ctx, fz_java_device);
  386. dev->env = env;
  387. dev->self = jself;
  388. dev->super.drop_device = fz_java_device_drop;
  389. dev->super.fill_path = fz_java_device_fill_path;
  390. dev->super.stroke_path = fz_java_device_stroke_path;
  391. dev->super.clip_path = fz_java_device_clip_path;
  392. dev->super.clip_stroke_path = fz_java_device_clip_stroke_path;
  393. dev->super.fill_text = fz_java_device_fill_text;
  394. dev->super.stroke_text = fz_java_device_stroke_text;
  395. dev->super.clip_text = fz_java_device_clip_text;
  396. dev->super.clip_stroke_text = fz_java_device_clip_stroke_text;
  397. dev->super.ignore_text = fz_java_device_ignore_text;
  398. dev->super.fill_shade = fz_java_device_fill_shade;
  399. dev->super.fill_image = fz_java_device_fill_image;
  400. dev->super.fill_image_mask = fz_java_device_fill_image_mask;
  401. dev->super.clip_image_mask = fz_java_device_clip_image_mask;
  402. dev->super.pop_clip = fz_java_device_pop_clip;
  403. dev->super.begin_mask = fz_java_device_begin_mask;
  404. dev->super.end_mask = fz_java_device_end_mask;
  405. dev->super.begin_group = fz_java_device_begin_group;
  406. dev->super.end_group = fz_java_device_end_group;
  407. dev->super.begin_tile = fz_java_device_begin_tile;
  408. dev->super.end_tile = fz_java_device_end_tile;
  409. dev->super.render_flags = fz_java_device_render_flags;
  410. dev->super.set_default_colorspaces = fz_java_device_set_default_colorspaces;
  411. dev->super.begin_layer = fz_java_device_begin_layer;
  412. dev->super.end_layer = fz_java_device_end_layer;
  413. dev->super.begin_structure = fz_java_device_begin_structure;
  414. dev->super.end_structure = fz_java_device_end_structure;
  415. dev->super.begin_metatext = fz_java_device_begin_metatext;
  416. dev->super.end_metatext = fz_java_device_end_metatext;
  417. }
  418. fz_catch(ctx)
  419. {
  420. fz_drop_device(ctx, &dev->super);
  421. jni_rethrow(env, ctx);
  422. }
  423. return (fz_device *)dev;
  424. }
  425. JNIEXPORT jlong JNICALL
  426. FUN(Device_newNative)(JNIEnv *env, jclass cls)
  427. {
  428. fz_context *ctx = get_context(env);
  429. fz_device *dev = NULL;
  430. if (!ctx) return 0;
  431. fz_try(ctx)
  432. dev = fz_new_java_device(ctx, env, cls);
  433. fz_catch(ctx)
  434. jni_rethrow(env, ctx);
  435. return jlong_cast(dev);
  436. }
  437. JNIEXPORT void JNICALL
  438. FUN(Device_finalize)(JNIEnv *env, jobject self)
  439. {
  440. fz_context *ctx = get_context(env);
  441. fz_device *dev = from_Device_safe(env, self);
  442. if (!ctx || !dev) return;
  443. (*env)->SetLongField(env, self, fid_Device_pointer, 0);
  444. fz_drop_device(ctx, dev);
  445. }