| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- // Copyright (C) 2004-2024 Artifex Software, Inc.
- //
- // This file is part of MuPDF.
- //
- // MuPDF is free software: you can redistribute it and/or modify it under the
- // terms of the GNU Affero General Public License as published by the Free
- // Software Foundation, either version 3 of the License, or (at your option)
- // any later version.
- //
- // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
- // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- // details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
- //
- // Alternative licensing terms are available from the licensor.
- // For commercial licensing, see <https://www.artifex.com/> or contact
- // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
- // CA 94129, USA, for further information.
- /* Device interface */
- /*
- Devices can either be implemented in C, or in Java.
- We therefore have to think about 4 possible call combinations.
- 1) C -> C:
- The standard mupdf case. No special worries here.
- 2) C -> Java:
- This can only happen when we call run on a page/annotation/
- displaylist. We need to ensure that the java Device has an
- appropriate fz_java_device generated for it, which is done by the
- Device constructor. The 'run' calls take care to lock/unlock for us.
- 3) Java -> C:
- The C device will have a java shim (a subclass of NativeDevice).
- All calls will go through the device methods in NativeDevice,
- which converts the java objects to C ones, and lock/unlock
- any underlying objects as required.
- 4) Java -> Java:
- No special worries.
- */
- typedef struct
- {
- fz_device super;
- JNIEnv *env;
- jobject self;
- }
- fz_java_device;
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jpath = to_Path(ctx, env, path);
- jobject jcs = to_ColorSpace(ctx, env, cs);
- jobject jctm = to_Matrix(ctx, env, ctm);
- jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
- int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillPath, jpath, (jboolean)even_odd, jctm, jcs, jcolor, alpha, jcp);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jpath = to_Path(ctx, env, path);
- jobject jstate = to_StrokeState(ctx, env, state);
- jobject jcs = to_ColorSpace(ctx, env, cs);
- jobject jctm = to_Matrix(ctx, env, ctm);
- jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
- int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokePath, jpath, jstate, jctm, jcs, jcolor, alpha, jcp);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jpath = to_Path(ctx, env, path);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipPath, jpath, (jboolean)even_odd, jctm);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jpath = to_Path(ctx, env, path);
- jobject jstate = to_StrokeState(ctx, env, state);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipStrokePath, jpath, jstate, jctm);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jtext = to_Text(ctx, env, text);
- jobject jctm = to_Matrix(ctx, env, ctm);
- jobject jcs = to_ColorSpace(ctx, env, cs);
- jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
- int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillText, jtext, jctm, jcs, jcolor, alpha, jcp);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jtext = to_Text(ctx, env, text);
- jobject jstate = to_StrokeState(ctx, env, state);
- jobject jctm = to_Matrix(ctx, env, ctm);
- jobject jcs = to_ColorSpace(ctx, env, cs);
- jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
- int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokeText, jtext, jstate, jctm, jcs, jcolor, alpha, jcp);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jtext = to_Text(ctx, env, text);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipText, jtext, jctm);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jtext = to_Text(ctx, env, text);
- jobject jstate = to_StrokeState(ctx, env, state);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipStrokeText, jtext, jstate, jctm);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jtext = to_Text(ctx, env, text);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_ignoreText, jtext, jctm);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shd, fz_matrix ctm, float alpha, fz_color_params color_params)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jshd = to_Shade(ctx, env, shd);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillShade, jshd, jctm, alpha);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, fz_matrix ctm, float alpha, fz_color_params color_params)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jimg = to_Image(ctx, env, img);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillImage, jimg, jctm, alpha);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jimg = to_Image(ctx, env, img);
- jobject jctm = to_Matrix(ctx, env, ctm);
- jobject jcs = to_ColorSpace(ctx, env, cs);
- jfloatArray jcolor = to_floatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
- int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillImageMask, jimg, jctm, jcs, jcolor, alpha, jcp);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, fz_matrix ctm, fz_rect scissor)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jimg = to_Image(ctx, env, img);
- jobject jctm = to_Matrix(ctx, env, ctm);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_clipImageMask, jimg, jctm);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_pop_clip(fz_context *ctx, fz_device *dev)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_popClip);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_begin_layer(fz_context *ctx, fz_device *dev, const char *name)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jstring jname;
- jname = (*env)->NewStringUTF(env, name);
- if (!jname || (*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginLayer, jname);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_end_layer(fz_context *ctx, fz_device *dev)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_endLayer);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jrect = to_Rect(ctx, env, rect);
- jobject jcs = to_ColorSpace(ctx, env, cs);
- jfloatArray jbc = to_floatArray(ctx, env, bc, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
- int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginMask, jrect, (jint)luminosity, jcs, jbc, jcp);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- // TODO: pass transfer function
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_endMask);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jrect = to_Rect(ctx, env, rect);
- jobject jcs = to_ColorSpace(ctx, env, cs);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginGroup, jrect, jcs, (jboolean)isolated, (jboolean)knockout, (jint)blendmode, alpha);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_end_group(fz_context *ctx, fz_device *dev)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_endGroup);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static int
- 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)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jarea = to_Rect(ctx, env, area);
- jobject jview = to_Rect(ctx, env, view);
- jobject jctm = to_Matrix(ctx, env, ctm);
- int res;
- res = (*env)->CallIntMethod(env, jdev->self, mid_Device_beginTile, jarea, jview, xstep, ystep, jctm, (jint)id);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- return res;
- }
- static void
- fz_java_device_end_tile(fz_context *ctx, fz_device *dev)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_endTile);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_renderFlags, set, clear);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *dcs)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jobject jdcs = to_DefaultColorSpaces(ctx, env, dcs);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_setDefaultColorSpaces, jdcs);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_begin_structure(fz_context *ctx, fz_device *dev, fz_structure standard, const char *raw, int idx)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jstring jraw;
- jraw = (*env)->NewStringUTF(env, raw);
- if (!jraw || (*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginStructure, standard, jraw, idx);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_end_structure(fz_context *ctx, fz_device *dev)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_endStructure);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *text)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- jstring jtext;
- jtext = (*env)->NewStringUTF(env, text);
- if (!jtext || (*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginMetatext, meta, jtext);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_end_metatext(fz_context *ctx, fz_device *dev)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_endMetatext);
- if ((*env)->ExceptionCheck(env))
- fz_throw_java(ctx, env);
- }
- static void
- fz_java_device_drop(fz_context *ctx, fz_device *dev)
- {
- fz_java_device *jdev = (fz_java_device *)dev;
- JNIEnv *env = jdev->env;
- (*env)->DeleteGlobalRef(env, jdev->self);
- }
- static fz_device *fz_new_java_device(fz_context *ctx, JNIEnv *env, jclass cls)
- {
- fz_java_device *dev = NULL;
- jobject jself;
- jself = (*env)->NewGlobalRef(env, cls);
- if (!jself) return NULL;
- fz_try(ctx)
- {
- dev = fz_new_derived_device(ctx, fz_java_device);
- dev->env = env;
- dev->self = jself;
- dev->super.drop_device = fz_java_device_drop;
- dev->super.fill_path = fz_java_device_fill_path;
- dev->super.stroke_path = fz_java_device_stroke_path;
- dev->super.clip_path = fz_java_device_clip_path;
- dev->super.clip_stroke_path = fz_java_device_clip_stroke_path;
- dev->super.fill_text = fz_java_device_fill_text;
- dev->super.stroke_text = fz_java_device_stroke_text;
- dev->super.clip_text = fz_java_device_clip_text;
- dev->super.clip_stroke_text = fz_java_device_clip_stroke_text;
- dev->super.ignore_text = fz_java_device_ignore_text;
- dev->super.fill_shade = fz_java_device_fill_shade;
- dev->super.fill_image = fz_java_device_fill_image;
- dev->super.fill_image_mask = fz_java_device_fill_image_mask;
- dev->super.clip_image_mask = fz_java_device_clip_image_mask;
- dev->super.pop_clip = fz_java_device_pop_clip;
- dev->super.begin_mask = fz_java_device_begin_mask;
- dev->super.end_mask = fz_java_device_end_mask;
- dev->super.begin_group = fz_java_device_begin_group;
- dev->super.end_group = fz_java_device_end_group;
- dev->super.begin_tile = fz_java_device_begin_tile;
- dev->super.end_tile = fz_java_device_end_tile;
- dev->super.render_flags = fz_java_device_render_flags;
- dev->super.set_default_colorspaces = fz_java_device_set_default_colorspaces;
- dev->super.begin_layer = fz_java_device_begin_layer;
- dev->super.end_layer = fz_java_device_end_layer;
- dev->super.begin_structure = fz_java_device_begin_structure;
- dev->super.end_structure = fz_java_device_end_structure;
- dev->super.begin_metatext = fz_java_device_begin_metatext;
- dev->super.end_metatext = fz_java_device_end_metatext;
- }
- fz_catch(ctx)
- {
- fz_drop_device(ctx, &dev->super);
- jni_rethrow(env, ctx);
- }
- return (fz_device *)dev;
- }
- JNIEXPORT jlong JNICALL
- FUN(Device_newNative)(JNIEnv *env, jclass cls)
- {
- fz_context *ctx = get_context(env);
- fz_device *dev = NULL;
- if (!ctx) return 0;
- fz_try(ctx)
- dev = fz_new_java_device(ctx, env, cls);
- fz_catch(ctx)
- jni_rethrow(env, ctx);
- return jlong_cast(dev);
- }
- JNIEXPORT void JNICALL
- FUN(Device_finalize)(JNIEnv *env, jobject self)
- {
- fz_context *ctx = get_context(env);
- fz_device *dev = from_Device_safe(env, self);
- if (!ctx || !dev) return;
- (*env)->SetLongField(env, self, fid_Device_pointer, 0);
- fz_drop_device(ctx, dev);
- }
|