summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/android/jni/Android.mk2
-rw-r--r--platform/android/jni/mupdf_native.c3473
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/AndroidDrawDevice.java19
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Annotation.java27
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/AwtDrawDevice.java12
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/CDevice.java49
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/ColorSpace.java34
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Context.java20
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Cookie.java30
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Device.java172
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/DisplayList.java32
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/DisplayListDevice.java14
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Document.java60
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Font.java22
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Image.java56
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Link.java27
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Matrix.java59
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Outline.java22
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Page.java37
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Path.java82
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/PathProcessor.java9
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Point.java29
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Rect.java79
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/RectI.java79
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Shade.java28
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/StrokeState.java64
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/Text.java46
-rw-r--r--platform/android/src/com/artifex/mupdf/fitz/TryLaterException.java9
-rw-r--r--platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java2
-rw-r--r--platform/win32/jni.vcproj441
-rw-r--r--platform/win32/mupdf.sln17
31 files changed, 5051 insertions, 1 deletions
diff --git a/platform/android/jni/Android.mk b/platform/android/jni/Android.mk
index 55cf593d..5c0b2294 100644
--- a/platform/android/jni/Android.mk
+++ b/platform/android/jni/Android.mk
@@ -19,7 +19,7 @@ LOCAL_C_INCLUDES := \
$(MUPDF_ROOT)/source/pdf
LOCAL_CFLAGS :=
LOCAL_MODULE := mupdf
-LOCAL_SRC_FILES := mupdf.c
+LOCAL_SRC_FILES := mupdf.c mupdf_native.c
LOCAL_STATIC_LIBRARIES := mupdfcore mupdfthirdparty
ifdef NDK_PROFILER
LOCAL_CFLAGS += -pg -DNDK_PROFILER
diff --git a/platform/android/jni/mupdf_native.c b/platform/android/jni/mupdf_native.c
new file mode 100644
index 00000000..b6ac0966
--- /dev/null
+++ b/platform/android/jni/mupdf_native.c
@@ -0,0 +1,3473 @@
+#include <jni.h>
+#include <time.h>
+#include <pthread.h>
+#include <android/log.h>
+#include <android/bitmap.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef NDK_PROFILER
+#include "prof.h"
+#endif
+
+#include "mupdf/fitz.h"
+#include "mupdf/pdf.h"
+
+#define MY_JNI_VERSION JNI_VERSION_1_6
+
+#define JNI_FN(A) Java_com_artifex_mupdf_fitz_ ## A
+#define PACKAGENAME "com.artifex.mupdf.fitz"
+#define PACKAGEPATH "com/artifex/mupdf/fitz/"
+
+#define LOG_TAG "libmupdf"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGT(...) __android_log_print(ANDROID_LOG_INFO,"alert",__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+/* Set to 1 to enable debug log traces. */
+#define DEBUG 0
+
+/* All the cached classes/mids/fids we need */
+
+static jclass annot_class;
+static jfieldID annot_fid;
+static jmethodID annot_const_mid;
+static jclass cdevice_class;
+static jfieldID cdevice_nativeresource_fid;
+static jfieldID cdevice_nativeinfo_fid;
+static jclass colorspace_class;
+static jfieldID colorspace_fid;
+static jmethodID colorspace_const_mid;
+static jclass cookie_class;
+static jfieldID cookie_fid;
+static jclass device_class;
+static jfieldID device_fid;
+static jmethodID device_begin_page_mid;
+static jmethodID device_end_page_mid;
+static jmethodID device_fill_path_mid;
+static jmethodID device_stroke_path_mid;
+static jmethodID device_clip_path_mid;
+static jmethodID device_clip_stroke_path_mid;
+static jmethodID device_fill_text_mid;
+static jmethodID device_stroke_text_mid;
+static jmethodID device_clip_text_mid;
+static jmethodID device_clip_stroke_text_mid;
+static jmethodID device_ignore_text_mid;
+static jmethodID device_fill_shade_mid;
+static jmethodID device_fill_image_mid;
+static jmethodID device_fill_image_mask_mid;
+static jmethodID device_clip_image_mask_mid;
+static jmethodID device_pop_clip_mid;
+static jmethodID device_begin_mask_mid;
+static jmethodID device_end_mask_mid;
+static jmethodID device_begin_group_mid;
+static jmethodID device_end_group_mid;
+static jmethodID device_begin_tile_mid;
+static jmethodID device_end_tile_mid;
+static jclass displaylist_class;
+static jfieldID displaylist_fid;
+static jclass document_class;
+static jfieldID document_fid;
+static jclass exception_class;
+static jclass font_class;
+static jfieldID font_fid;
+//static jfieldID font_isconst_fid;
+static jclass image_class;
+static jfieldID image_fid;
+static jmethodID image_const_mid;
+static jclass link_class;
+static jfieldID link_fid;
+static jclass matrix_class;
+static jfieldID matrix_a_fid;
+static jfieldID matrix_b_fid;
+static jfieldID matrix_c_fid;
+static jfieldID matrix_d_fid;
+static jfieldID matrix_e_fid;
+static jfieldID matrix_f_fid;
+static jmethodID matrix_const_mid;
+static jclass outline_class;
+static jfieldID outline_fid;
+static jmethodID outline_const_mid;
+static jclass page_class;
+static jfieldID page_fid;
+static jmethodID page_const_mid;
+static jfieldID page_document_fid;
+static jfieldID page_annots_fid;
+static jclass path_class;
+static jfieldID path_fid;
+static jmethodID path_const_mid;
+static jclass pathproc_class;
+static jmethodID pathproc_moveto_mid;
+static jmethodID pathproc_lineto_mid;
+static jmethodID pathproc_curveto_mid;
+static jmethodID pathproc_close_mid;
+static jclass point_class;
+static jfieldID point_fid;
+static jmethodID point_const_mid;
+static jclass rect_class;
+static jfieldID rect_x0_fid;
+static jfieldID rect_x1_fid;
+static jfieldID rect_y0_fid;
+static jfieldID rect_y1_fid;
+static jmethodID rect_const_mid;
+static jclass shade_class;
+static jfieldID shade_fid;
+static jmethodID shade_const_mid;
+static jclass stroke_class;
+static jfieldID stroke_fid;
+static jmethodID stroke_const_mid;
+static jclass text_class;
+static jfieldID text_fid;
+static jmethodID text_const_mid;
+static jclass trylaterexception_class;
+
+static pthread_key_t context_key;
+static fz_context *base_context;
+
+static void
+throwOutOfMemoryError(JNIEnv *env, const char *info)
+{
+ jclass oomCls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
+
+ if (oomCls == NULL)
+ return; /* Well, what hope have we got! */
+
+ (*env)->ExceptionClear(env);
+ (*env)->ThrowNew(env, oomCls, info);
+}
+
+static const char *last_class_obtained = NULL;
+
+static jclass
+get_class(int *failed, JNIEnv *env, const char *str)
+{
+ jclass local, global;
+
+ if (*failed)
+ return NULL;
+
+ last_class_obtained = str;
+ local = (*env)->FindClass(env, str);
+ if (local == NULL)
+ {
+ LOGI("Failed to find class %s", str);
+ *failed = 1;
+ return NULL;
+ }
+
+ global = (*env)->NewGlobalRef(env, local);
+ if (global == NULL)
+ {
+ LOGI("Failed to make global ref for %s", str);
+ *failed = 1;
+ return NULL;
+ }
+
+ (*env)->DeleteLocalRef(env, local);
+
+ return global;
+}
+
+static jfieldID
+get_field(int *failed, JNIEnv *env, jclass cla, const char *field, const char *sig)
+{
+ jfieldID fid;
+
+ if (*failed || cla == NULL)
+ return NULL;
+
+ fid = (*env)->GetFieldID(env, cla, field, sig);
+ if (fid == (jfieldID)0)
+ {
+ LOGI("Failed to get field for %s %s %s", last_class_obtained ? last_class_obtained : "<noclass>", field, sig);
+ *failed = 1;
+ }
+
+ return fid;
+}
+
+static jmethodID
+get_method(int *failed, JNIEnv *env, jclass cla, const char *method, const char *sig)
+{
+ jmethodID mid;
+
+ if (*failed || cla == NULL)
+ return NULL;
+
+ mid = (*env)->GetMethodID(env, cla, method, sig);
+ if (mid == (jmethodID)0)
+ {
+ LOGI("Failed to get method for %s %s %s", last_class_obtained ? last_class_obtained : "<noclass>", method, sig);
+ *failed = 1;
+ }
+
+ return mid;
+}
+
+static int find_fids(JNIEnv *env)
+{
+ int failed = 0;
+
+ annot_class = get_class(&failed, env, PACKAGEPATH"Annotation");
+ annot_fid = get_field(&failed, env, annot_class, "nativeAnnot", "J");
+ annot_const_mid = get_method(&failed, env, annot_class, "<init>", "(J)V");
+ cdevice_class = get_class(&failed, env, PACKAGEPATH"CDevice");
+ cdevice_nativeresource_fid = get_field(&failed, env, cdevice_class, "nativeResource", "Ljava.lang.Object;");
+ cdevice_nativeinfo_fid = get_field(&failed, env, cdevice_class, "nativeInfo", "J");
+ colorspace_class = get_class(&failed, env, PACKAGEPATH"ColorSpace");
+ colorspace_fid = get_field(&failed, env, colorspace_class, "nativeColorSpace", "J");
+ colorspace_const_mid = get_method(&failed, env, colorspace_class, "<init>", "(J)V");
+ cookie_class = get_class(&failed, env, PACKAGEPATH"Cookie");
+ cookie_fid = get_field(&failed, env, cookie_class, "nativeCookie", "J");
+ device_class = get_class(&failed, env, PACKAGEPATH"Device");
+ device_fid = get_field(&failed, env, device_class, "nativeDevice", "J");
+ device_begin_page_mid = get_method(&failed, env, device_class, "beginPage", "(L"PACKAGEPATH"Rect;L"PACKAGEPATH"Matrix;)V");
+ device_end_page_mid = get_method(&failed, env, device_class, "endPage", "()V");
+ device_fill_path_mid = get_method(&failed, env, device_class, "fillPath", "(L"PACKAGEPATH"Path;IL"PACKAGEPATH"Matrix;L"PACKAGEPATH"ColorSpace;[FF)V");
+ device_stroke_path_mid = get_method(&failed, env, device_class, "strokePath", "(JL"PACKAGEPATH"Path;L"PACKAGEPATH"StrokeState;L"PACKAGEPATH"Matrix;L"PACKAGEPATH"ColorSpace;[FF)V");
+ device_clip_path_mid = get_method(&failed, env, device_class, "clipPath", "(L"PACKAGEPATH"Path;L"PACKAGEPATH"Rect;IL"PACKAGEPATH"Matrix;)V");
+ device_clip_stroke_path_mid = get_method(&failed, env, device_class, "clipStrokePath", "(L"PACKAGEPATH"Path;L"PACKAGEPATH"Rect;L"PACKAGEPATH"StrokeState;L"PACKAGEPATH"Matrix;)V");
+ device_fill_text_mid = get_method(&failed, env, device_class, "fillText", "(L"PACKAGEPATH"Text;L"PACKAGEPATH"Matrix;L"PACKAGEPATH"ColorSpace;[FF)V");
+ device_stroke_text_mid = get_method(&failed, env, device_class, "strokeText", "(L"PACKAGEPATH"Text;L"PACKAGEPATH"StrokeState;L"PACKAGEPATH"Matrix;L"PACKAGEPATH"ColorSpace;[FF)V");
+ device_clip_text_mid = get_method(&failed, env, device_class, "clipText", "(L"PACKAGEPATH"Text;L"PACKAGEPATH"Matrix;)V");
+ device_clip_stroke_text_mid = get_method(&failed, env, device_class, "clipStrokeText", "(L"PACKAGEPATH"Text;L"PACKAGEPATH"StrokeState;L"PACKAGEPATH"Matrix;)V");
+ device_ignore_text_mid = get_method(&failed, env, device_class, "ignoreText", "(L"PACKAGEPATH"Text;L"PACKAGEPATH"Matrix;)V");
+ device_fill_shade_mid = get_method(&failed, env, device_class, "fillShade", "(L"PACKAGEPATH"Shade;L"PACKAGEPATH"Matrix;F)V");
+ device_fill_image_mid = get_method(&failed, env, device_class, "fillImage", "(L"PACKAGEPATH"Image;L"PACKAGEPATH"Matrix;F)V");
+ device_fill_image_mask_mid = get_method(&failed, env, device_class, "fillImageMask", "(L"PACKAGEPATH"Image;L"PACKAGEPATH"Matrix;L"PACKAGEPATH"ColorSpace;[FF)V");
+ device_clip_image_mask_mid = get_method(&failed, env, device_class, "clipImageMask", "(L"PACKAGEPATH"Image;L"PACKAGEPATH"Rect;L"PACKAGEPATH"Matrix;)V");
+ device_pop_clip_mid = get_method(&failed, env, device_class, "popClip", "()V");
+ device_begin_mask_mid = get_method(&failed, env, device_class, "beginMask", "(L"PACKAGEPATH"Rect;IL"PACKAGEPATH"ColorSpace;[F)V");
+ device_end_mask_mid = get_method(&failed, env, device_class, "endMask", "()V");
+ device_begin_group_mid = get_method(&failed, env, device_class, "beginGroup", "(L"PACKAGEPATH"Rect;IIIF)V");
+ device_end_group_mid = get_method(&failed, env, device_class, "endGroup", "()V");
+ device_begin_tile_mid = get_method(&failed, env, device_class, "beginTile", "(L"PACKAGEPATH"Rect;L"PACKAGEPATH"Rect;FFL"PACKAGEPATH"Matrix;I)I");
+ device_end_tile_mid = get_method(&failed, env, device_class, "endTile", "()V");
+ exception_class = get_class(&failed, env, "java/lang/Exception");
+ displaylist_class = get_class(&failed, env, PACKAGEPATH"DisplayList");
+ displaylist_fid = get_field(&failed, env, displaylist_class, "nativeDisplayList", "J");
+ document_class = get_class(&failed, env, PACKAGEPATH"Document");
+ document_fid = get_field(&failed, env, document_class, "nativeDocument", "J");
+ font_class = get_class(&failed, env, PACKAGEPATH"Font");
+ font_fid = get_field(&failed, env, font_class, "nativeFont", "J");
+ //font_isconst_fid = get_field(&failed, env, font_class, "isConst", "Z");
+ image_class = get_class(&failed, env, PACKAGEPATH"Image");
+ image_fid = get_field(&failed, env, image_class, "nativeImage", "J");
+ image_const_mid = get_method(&failed, env, image_class, "<init>", "(J)V");
+ link_class = get_class(&failed, env, PACKAGEPATH"Link");
+ link_fid = get_field(&failed, env, link_class, "nativeLink", "J");
+ matrix_class = get_class(&failed, env, PACKAGEPATH"Matrix");
+ matrix_a_fid = get_field(&failed, env, matrix_class, "a", "F");
+ matrix_b_fid = get_field(&failed, env, matrix_class, "b", "F");
+ matrix_c_fid = get_field(&failed, env, matrix_class, "c", "F");
+ matrix_d_fid = get_field(&failed, env, matrix_class, "d", "F");
+ matrix_e_fid = get_field(&failed, env, matrix_class, "e", "F");
+ matrix_f_fid = get_field(&failed, env, matrix_class, "f", "F");
+ matrix_const_mid = get_method(&failed, env, matrix_class, "<init>", "(FFFFFF)V");
+ outline_class = get_class(&failed, env, PACKAGEPATH"Outline");
+ outline_fid = get_field(&failed, env, outline_class, "nativeOutline", "J");
+ outline_const_mid = get_method(&failed, env, outline_class, "<init>", "(J)V");
+ page_class = get_class(&failed, env, PACKAGEPATH"Page");
+ page_fid = get_field(&failed, env, page_class, "nativePage", "J");
+ page_const_mid = get_method(&failed, env, page_class, "<init>", "(J)V");
+ page_annots_fid = get_field(&failed, env, page_class, "nativeAnnots", "[L"PACKAGEPATH"Annotation;");
+ path_class = get_class(&failed, env, PACKAGEPATH"Path");
+ path_fid = get_field(&failed, env, path_class, "nativePath", "J");
+ path_const_mid = get_method(&failed, env, path_class, "<init>", "(J)V");
+ point_class = get_class(&failed, env, PACKAGEPATH"Point");
+ point_const_mid = get_method(&failed, env, point_class, "<init>", "(FF)V");
+ pathproc_class = get_class(&failed, env, PACKAGEPATH"PathProcessor");
+ pathproc_moveto_mid = get_method(&failed, env, pathproc_class, "moveTo", "(FF)V");
+ pathproc_lineto_mid = get_method(&failed, env, pathproc_class, "lineTo", "(FF)V");
+ pathproc_curveto_mid = get_method(&failed, env, pathproc_class, "curveTo", "(FFFFFF)V");
+ pathproc_close_mid = get_method(&failed, env, pathproc_class, "close", "()V");
+ rect_class = get_class(&failed, env, PACKAGEPATH"Rect");
+ rect_x0_fid = get_field(&failed, env, rect_class, "x0", "F");
+ rect_x1_fid = get_field(&failed, env, rect_class, "x1", "F");
+ rect_y0_fid = get_field(&failed, env, rect_class, "y0", "F");
+ rect_y1_fid = get_field(&failed, env, rect_class, "y1", "F");
+ rect_const_mid = get_method(&failed, env, rect_class, "<init>", "(FFFF)V");
+ shade_class = get_class(&failed, env, PACKAGEPATH"Shade");
+ shade_fid = get_field(&failed, env, shade_class, "nativeShade", "J");
+ shade_const_mid = get_method(&failed, env, shade_class, "<init>", "(J)V");
+ stroke_class = get_class(&failed, env, PACKAGEPATH"StrokeState");
+ stroke_fid = get_field(&failed, env, stroke_class, "nativeStroke", "J");
+ stroke_const_mid = get_method(&failed, env, stroke_class, "<init>", "(J)V");
+ text_class = get_class(&failed, env, PACKAGEPATH"Text");
+ text_fid = get_field(&failed, env, text_class, "nativeText", "J");
+ text_const_mid = get_method(&failed, env, text_class, "<init>", "(J)V");
+ trylaterexception_class = get_class(&failed, env, PACKAGEPATH"TryLaterException");
+
+ return failed;
+}
+
+static void lose_fids(JNIEnv *env)
+{
+ (*env)->DeleteGlobalRef(env, annot_class);
+ (*env)->DeleteGlobalRef(env, cdevice_class);
+ (*env)->DeleteGlobalRef(env, colorspace_class);
+ (*env)->DeleteGlobalRef(env, cookie_class);
+ (*env)->DeleteGlobalRef(env, device_class);
+ (*env)->DeleteGlobalRef(env, displaylist_class);
+ (*env)->DeleteGlobalRef(env, document_class);
+ (*env)->DeleteGlobalRef(env, exception_class);
+ (*env)->DeleteGlobalRef(env, font_class);
+ (*env)->DeleteGlobalRef(env, image_class);
+ (*env)->DeleteGlobalRef(env, link_class);
+ (*env)->DeleteGlobalRef(env, matrix_class);
+ (*env)->DeleteGlobalRef(env, outline_class);
+ (*env)->DeleteGlobalRef(env, page_class);
+ (*env)->DeleteGlobalRef(env, path_class);
+ (*env)->DeleteGlobalRef(env, pathproc_class);
+ (*env)->DeleteGlobalRef(env, rect_class);
+ (*env)->DeleteGlobalRef(env, shade_class);
+ (*env)->DeleteGlobalRef(env, stroke_class);
+ (*env)->DeleteGlobalRef(env, text_class);
+ (*env)->DeleteGlobalRef(env, trylaterexception_class);
+}
+
+static pthread_mutex_t mutexes[FZ_LOCK_MAX];
+
+static void lock(void *user, int lock)
+{
+ (void)pthread_mutex_lock(&mutexes[lock]);
+}
+
+static void unlock(void *user, int lock)
+{
+ (void)pthread_mutex_unlock(&mutexes[lock]);
+}
+
+static const fz_locks_context locks =
+{
+ NULL, /* user */
+ lock,
+ unlock
+};
+
+static void fin_context(void *ctx)
+{
+ fz_drop_context((fz_context *)ctx);
+}
+
+static int fin_base_context(JNIEnv *env)
+{
+ int i;
+
+ for (i = 0; i < FZ_LOCK_MAX; i++)
+ (void)pthread_mutex_destroy(&mutexes[i]);
+
+ fz_drop_context(base_context);
+ base_context = NULL;
+}
+
+static int init_base_context(JNIEnv *env)
+{
+ int i;
+
+ for (i = 0; i < FZ_LOCK_MAX; i++)
+ (void)pthread_mutex_init(&mutexes[i], NULL);
+
+ base_context = fz_new_context(NULL, &locks, FZ_STORE_DEFAULT);
+ if (base_context == NULL)
+ return -1;
+
+ fz_register_document_handlers(base_context);
+
+ return 0;
+}
+
+static fz_context *get_context(JNIEnv *env)
+{
+ fz_context *ctx = (fz_context *)pthread_getspecific(context_key);
+
+ if (ctx != NULL)
+ return ctx;
+
+ ctx = fz_clone_context(base_context);
+ if (ctx == NULL)
+ {
+ throwOutOfMemoryError(env, "Failed to clone fz_context");
+ return NULL;
+ }
+ pthread_setspecific(context_key, ctx);
+ return ctx;
+}
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+
+ if ((*vm)->GetEnv(vm, (void **)&env, MY_JNI_VERSION) != JNI_OK)
+ return -1;
+
+ /* Must init the context before find_finds, because the act of
+ * finding the fids can cause classes to load. This causes
+ * statics to be setup, which can in turn call JNI code, which
+ * requires the context. (For example see ColorSpace) */
+ if (init_base_context(env) < 0)
+ return -1;
+
+ if (find_fids(env) != 0)
+ {
+ fin_base_context(env);
+ return -1;
+ }
+
+ return MY_JNI_VERSION;
+}
+
+void JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+
+ if ((*vm)->GetEnv(vm, (void **)&env, MY_JNI_VERSION) != JNI_OK)
+ return; /* If this fails, we're really in trouble! */
+
+ fz_drop_context(base_context);
+ base_context = NULL;
+ lose_fids(env);
+}
+
+// Do our best to avoid casting warnings.
+#define CAST(type, var) (type)pointer_cast(var)
+
+static inline void *pointer_cast(jlong l)
+{
+ return (void *)(intptr_t)l;
+}
+
+static inline jlong jlong_cast(const void *p)
+{
+ return (jlong)(intptr_t)p;
+}
+
+/* Conversion functions: C to Java */
+static inline jobject Annotation_from_fz_annot(fz_context *ctx, JNIEnv *env, fz_annot *annot)
+{
+ jobject jannot;
+
+ if (ctx == NULL)
+ return NULL;
+
+ (*env)->NewObject(env, annot_class, annot_const_mid, annot);
+ if (jannot == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Annotation creation failed");
+
+ return jannot;
+}
+
+static inline jobject ColorSpace_from_fz_colorspace(fz_context *ctx, JNIEnv *env, fz_colorspace *cs)
+{
+ jobject jobj;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jobj = (*env)->NewObject(env, colorspace_class, colorspace_const_mid, jlong_cast(cs));
+ if (jobj == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of ColorSpace failed");
+
+ fz_keep_colorspace(ctx, cs);
+
+ return jobj;
+}
+
+static inline jobject Image_from_fz_image(fz_context *ctx, JNIEnv *env, fz_image *img)
+{
+ jobject jobj;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jobj = (*env)->NewObject(env, image_class, image_const_mid, jlong_cast(img));
+ if (jobj == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Image failed");
+
+ fz_keep_image(ctx, img);
+
+ return jobj;
+}
+
+static inline jobject Matrix_from_fz_matrix(fz_context *ctx, JNIEnv *env, const fz_matrix *mat)
+{
+ jobject jobj;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jobj = (*env)->NewObject(env, matrix_class, matrix_const_mid, mat->a, mat->b, mat->c, mat->d, mat->e, mat->f);
+ if (jobj == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Matrix failed");
+
+ return jobj;
+}
+
+static inline jobject Outline_from_fz_outline(fz_context *ctx, JNIEnv *env, fz_outline *outline)
+{
+ jobject joutline;
+
+ if (ctx == NULL)
+ return NULL;
+
+ joutline = (*env)->NewObject(env, outline_class, outline_const_mid, jlong_cast(outline));
+ if (joutline == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "getOutline failed (3)");
+
+ return joutline;
+}
+
+static inline jobject Page_from_fz_page(fz_context *ctx, JNIEnv *env, fz_page *page)
+{
+ jobject jobj;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jobj = (*env)->NewObject(env, page_class, page_const_mid, jlong_cast(page));
+ if (jobj == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Page failed");
+
+ return jobj;
+}
+
+static inline jobject Path_from_fz_path(fz_context *ctx, JNIEnv *env, fz_path *path)
+{
+ jobject jobj;
+ fz_path *new_path;
+
+ if (ctx == NULL)
+ return NULL;
+
+ new_path = fz_clone_path(ctx, path);
+
+ jobj = (*env)->NewObject(env, path_class, path_const_mid, jlong_cast(new_path));
+ if (jobj == NULL)
+ {
+ fz_drop_path(ctx, new_path);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Path failed");
+ }
+
+ return jobj;
+}
+
+static inline jobject Point_from_fz_point(fz_context *ctx, JNIEnv *env, fz_point point)
+{
+ jobject jpoint;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jpoint = (*env)->NewObject(env, point_class, point_const_mid, point.x, point.y);
+ if (jpoint == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "currentPoint failed (3)");
+
+ return jpoint;
+}
+
+static inline jobject Rect_from_fz_rect(fz_context *ctx, JNIEnv *env, const fz_rect *rect)
+{
+ jobject jobj;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jobj = (*env)->NewObject(env, rect_class, rect_const_mid, rect->x0, rect->y0, rect->x1, rect->y1);
+ if (jobj == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Rect failed");
+
+ return jobj;
+}
+
+static inline jobject Shade_from_fz_shade(fz_context *ctx, JNIEnv *env, fz_shade *shade)
+{
+ jobject jobj;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jobj = (*env)->NewObject(env, shade_class, shade_const_mid, jlong_cast(shade));
+ if (jobj == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Shade failed");
+
+ fz_keep_shade(ctx, shade);
+
+ return jobj;
+}
+
+static inline jobject StrokeState_from_fz_stroke_state(fz_context *ctx, JNIEnv *env, fz_stroke_state *state)
+{
+ jobject jobj;
+
+ if (ctx == NULL)
+ return NULL;
+
+ jobj = (*env)->NewObject(env, stroke_class, stroke_const_mid, jlong_cast(state));
+ if (jobj == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of StrokeState failed");
+
+ fz_keep_stroke_state(ctx, state);
+
+ return jobj;
+}
+
+static inline jobject Text_from_fz_text(fz_context *ctx, JNIEnv *env, fz_text *text)
+{
+ jobject jobj;
+ fz_text *new_text;
+
+ if (ctx == NULL)
+ return NULL;
+
+ new_text = fz_clone_text(ctx, text);
+
+ jobj = (*env)->NewObject(env, text_class, text_const_mid, jlong_cast(new_text));
+ if (jobj == NULL)
+ {
+ fz_drop_text(ctx, new_text);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Text failed");
+ }
+
+ return jobj;
+}
+
+static inline jfloatArray jfloatArray_from_fz_color(fz_context *ctx, JNIEnv *env, float *color, int n)
+{
+ jfloatArray arr;
+
+ if (ctx == NULL)
+ return NULL;
+
+ arr = (*env)->NewFloatArray(env, n);
+ if (arr == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of floatArray failed");
+
+ (*env)->SetFloatArrayRegion(env, arr, 0, n, color);
+
+ return arr;
+}
+
+/* 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. The 'run' calls
+ * take care to lock/unlock for us.
+ * 3) Java -> C: The C device will have a java shim (a subclass of CDevice).
+ * All calls will go through the device methods in CDevice,
+ * which converts the java objects to C ones, and lock/unlock
+ * any underlying objects as required.
+ * 4) Java -> Java: No special worries.
+ */
+
+/* Our java device wrapping functions */
+
+typedef struct
+{
+ fz_device base;
+ JNIEnv *env;
+ jobject self;
+}
+fz_java_device;
+
+static void
+fz_java_device_begin_page(fz_context *ctx, fz_device *dev, const fz_rect *rect, const fz_matrix *ctm)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jrect = Rect_from_fz_rect(ctx, env, rect);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_begin_page_mid, jrect, jctm);
+}
+
+static void
+fz_java_device_end_page(fz_context *ctx, fz_device *dev)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+
+ (*env)->CallVoidMethod(env, jdev->self, device_end_page_mid);
+}
+
+static void
+fz_java_device_fill_path(fz_context *ctx, fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm, fz_colorspace *cs, float *color, float alpha)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jpath = Path_from_fz_path(ctx, env, path);
+ jobject jcs = ColorSpace_from_fz_colorspace(ctx, env, cs);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+ jfloatArray jcolor = jfloatArray_from_fz_color(ctx, env, color, cs ? cs->n : FZ_MAX_COLORS);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_fill_path_mid, jpath, even_odd, jctm, jcs, jcolor, alpha);
+}
+
+static void
+fz_java_device_stroke_path(fz_context *ctx, fz_device *dev, fz_path *path, fz_stroke_state *state, const fz_matrix *ctm, fz_colorspace *cs, float *color, float alpha)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jpath = Path_from_fz_path(ctx, env, path);
+ jobject jstate = StrokeState_from_fz_stroke_state(ctx, env, state);
+ jobject jcs = ColorSpace_from_fz_colorspace(ctx, env, cs);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+ jfloatArray jcolor = jfloatArray_from_fz_color(ctx, env, color, cs ? cs->n : FZ_MAX_COLORS);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_stroke_path_mid, jpath, jstate, jctm, jcs, jcolor, alpha);
+}
+
+static void
+fz_java_device_clip_path(fz_context *ctx, fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, const fz_matrix *ctm)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jpath = Path_from_fz_path(ctx, env, path);
+ jobject jrect = Rect_from_fz_rect(ctx, env, rect);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_clip_path_mid, jpath, jrect, even_odd, jctm);
+}
+
+static void
+fz_java_device_clip_stroke_path(fz_context *ctx, fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *state, const fz_matrix *ctm)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jpath = Path_from_fz_path(ctx, env, path);
+ jobject jrect = Rect_from_fz_rect(ctx, env, rect);
+ jobject jstate = StrokeState_from_fz_stroke_state(ctx, env, state);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_clip_stroke_path_mid, jpath, jrect, jstate, jctm);
+}
+
+static void
+fz_java_device_fill_text(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matrix *ctm, fz_colorspace *cs, float *color, float alpha)
+{
+ LOGI("fz_java_device_fill_text");
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jtext = Text_from_fz_text(ctx, env, text);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+ jobject jcs = ColorSpace_from_fz_colorspace(ctx, env, cs);
+ jfloatArray jcolor = jfloatArray_from_fz_color(ctx, env, color, cs ? cs->n : FZ_MAX_COLORS);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_fill_text_mid, jtext, jctm, jcs, jcolor, alpha);
+}
+
+static void
+fz_java_device_stroke_text(fz_context *ctx, fz_device *dev, fz_text *text, fz_stroke_state *state, const fz_matrix *ctm, fz_colorspace *cs, float *color, float alpha)
+{
+ LOGI("fz_java_device_stroke_text");
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jtext = Text_from_fz_text(ctx, env, text);
+ jobject jstate = StrokeState_from_fz_stroke_state(ctx, env, state);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+ jobject jcs = ColorSpace_from_fz_colorspace(ctx, env, cs);
+ jfloatArray jcolor = jfloatArray_from_fz_color(ctx, env, color, cs ? cs->n : FZ_MAX_COLORS);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_stroke_text_mid, jtext, jstate, jctm, jcs, jcolor, alpha);
+}
+
+static void
+fz_java_device_clip_text(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matrix *ctm)
+{
+ LOGI("fz_java_device_clip_text");
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jtext = Text_from_fz_text(ctx, env, text);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_clip_text_mid, jtext, jctm);
+}
+
+static void
+fz_java_device_clip_stroke_text(fz_context *ctx, fz_device *dev, fz_text *text, fz_stroke_state *state, const fz_matrix *ctm)
+{
+ LOGI("fz_java_device_clip_stroke_text");
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jtext = Text_from_fz_text(ctx, env, text);
+ jobject jstate = StrokeState_from_fz_stroke_state(ctx, env, state);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_clip_stroke_text_mid, jtext, jstate, jctm);
+}
+
+static void
+fz_java_device_ignore_text(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matrix *ctm)
+{
+ LOGI("fz_java_device_ignore_text");
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jtext = Text_from_fz_text(ctx, env, text);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_ignore_text_mid, jtext, jctm);
+}
+
+static void
+fz_java_device_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shd, const fz_matrix *ctm, float alpha)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jshd = Shade_from_fz_shade(ctx, env, shd);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_fill_shade_mid, jshd, jctm, alpha);
+}
+
+static void
+fz_java_device_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, float alpha)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jimg = Image_from_fz_image(ctx, env, img);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_fill_image_mid, jimg, jctm, alpha);
+}
+
+static void
+fz_java_device_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, fz_colorspace *cs, float *color, float alpha)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jimg = Image_from_fz_image(ctx, env, img);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+ jobject jcs = ColorSpace_from_fz_colorspace(ctx, env, cs);
+ jfloatArray jcolor = jfloatArray_from_fz_color(ctx, env, color, cs ? cs->n : FZ_MAX_COLORS);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_fill_image_mask_mid, jimg, jctm, jcs, jcolor, alpha);
+}
+
+static void
+fz_java_device_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, const fz_rect *rect, const fz_matrix *ctm)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jimg = Image_from_fz_image(ctx, env, img);
+ jobject jrect = Rect_from_fz_rect(ctx, env, rect);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_clip_image_mask_mid, jimg, jrect, jctm);
+}
+
+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, device_pop_clip_mid);
+}
+
+static void
+fz_java_device_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *cs, float *bc)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jrect = Rect_from_fz_rect(ctx, env, rect);
+ jobject jcs = ColorSpace_from_fz_colorspace(ctx, env, cs);
+ jfloatArray jbc = jfloatArray_from_fz_color(ctx, env, bc, cs ? cs->n : FZ_MAX_COLORS);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_begin_mask_mid, jrect, luminosity, jcs, jbc);
+}
+
+static void
+fz_java_device_end_mask(fz_context *ctx, fz_device *dev)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+
+ (*env)->CallVoidMethod(env, jdev->self, device_end_mask_mid);
+}
+
+static void
+fz_java_device_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jrect = Rect_from_fz_rect(ctx, env, rect);
+
+ (*env)->CallVoidMethod(env, jdev->self, device_begin_group_mid, jrect, isolated, knockout, blendmode, alpha);
+}
+
+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, device_end_group_mid);
+}
+
+static int
+fz_java_device_begin_tile(fz_context *ctx, fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+ JNIEnv *env = jdev->env;
+ jobject jarea = Rect_from_fz_rect(ctx, env, area);
+ jobject jview = Rect_from_fz_rect(ctx, env, view);
+ jobject jctm = Matrix_from_fz_matrix(ctx, env, ctm);
+ int res;
+
+ res = (*env)->CallIntMethod(env, jdev->self, device_begin_tile_mid, jarea, jview, xstep, ystep, jctm, id);
+
+ 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, device_end_tile_mid);
+}
+
+static void
+fz_java_device_drop_imp(fz_context *ctx, fz_device *dev)
+{
+ fz_java_device *jdev = (fz_java_device *)dev;
+
+ /* Nothing to do, currently */
+ jdev = jdev;
+}
+
+static fz_device *fz_new_java_device(JNIEnv *env, jobject self, fz_context *ctx)
+{
+ fz_device *dev = NULL;
+ fz_java_device *jdev = NULL;
+
+ fz_var(dev);
+ fz_var(jdev);
+
+ fz_try(ctx)
+ {
+ jdev = fz_new_device(ctx, sizeof(fz_java_device));
+ dev = &jdev->base;
+ jdev->env = env;
+ jdev->self = self;
+ dev->drop_imp = fz_java_device_drop_imp;
+
+ dev->fill_path = fz_java_device_fill_path;
+ dev->stroke_path = fz_java_device_stroke_path;
+ dev->clip_path = fz_java_device_clip_path;
+ dev->clip_stroke_path = fz_java_device_clip_stroke_path;
+
+ dev->fill_text = fz_java_device_fill_text;
+ dev->stroke_text = fz_java_device_stroke_text;
+ dev->clip_text = fz_java_device_clip_text;
+ dev->clip_stroke_text = fz_java_device_clip_stroke_text;
+
+ dev->fill_shade = fz_java_device_fill_shade;
+ dev->fill_image = fz_java_device_fill_image;
+ dev->fill_image_mask = fz_java_device_fill_image_mask;
+ dev->clip_image_mask = fz_java_device_clip_image_mask;
+
+ dev->pop_clip = fz_java_device_pop_clip;
+
+ dev->begin_mask = fz_java_device_begin_mask;
+ dev->end_mask = fz_java_device_end_mask;
+ dev->begin_group = fz_java_device_begin_group;
+ dev->end_group = fz_java_device_end_group;
+
+ dev->begin_tile = fz_java_device_begin_tile;
+ dev->end_tile = fz_java_device_end_tile;
+ }
+ fz_catch(ctx)
+ {
+ jclass exClass;
+
+ fz_free(ctx, jdev);
+ throwOutOfMemoryError(env, "Failed to create fz_java_device");
+ dev = NULL;
+ }
+ return dev;
+}
+
+/* Conversion functions: Java to C */
+static inline fz_colorspace *fz_colorspace_from_ColorSpace(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_colorspace *, (*env)->GetLongField(env, jobj, colorspace_fid));
+}
+
+
+static fz_device *fz_device_from_Device(JNIEnv *env, jobject self, fz_context *ctx)
+{
+ fz_device *dev = CAST(fz_device *, (*env)->GetLongField(env, self, device_fid));
+
+ if (dev == NULL)
+ {
+ /* This must be a Java device. Create a native shim. */
+ dev = fz_new_java_device(env, self, ctx);
+ (*env)->SetLongField(env, self, device_fid, jlong_cast(dev));
+ }
+ return dev;
+}
+
+static inline fz_image *fz_image_from_Image(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_image *, (*env)->GetLongField(env, jobj, image_fid));
+}
+
+static inline fz_matrix fz_matrix_from_Matrix(JNIEnv *env, jobject jmat)
+{
+ fz_matrix mat;
+
+ mat.a = (*env)->GetFloatField(env, jmat, matrix_a_fid);
+ mat.b = (*env)->GetFloatField(env, jmat, matrix_b_fid);
+ mat.c = (*env)->GetFloatField(env, jmat, matrix_c_fid);
+ mat.d = (*env)->GetFloatField(env, jmat, matrix_d_fid);
+ mat.e = (*env)->GetFloatField(env, jmat, matrix_e_fid);
+ mat.f = (*env)->GetFloatField(env, jmat, matrix_f_fid);
+
+ return mat;
+}
+
+static inline fz_path *fz_path_from_Path(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_path *, (*env)->GetLongField(env, jobj, path_fid));
+}
+
+static inline fz_rect fz_rect_from_Rect(JNIEnv *env, jobject jrect)
+{
+ fz_rect rect;
+
+ rect.x0 = (*env)->GetFloatField(env, jrect, rect_x0_fid);
+ rect.x1 = (*env)->GetFloatField(env, jrect, rect_x1_fid);
+ rect.y0 = (*env)->GetFloatField(env, jrect, rect_y0_fid);
+ rect.y1 = (*env)->GetFloatField(env, jrect, rect_y1_fid);
+
+ return rect;
+}
+
+static inline fz_shade *fz_shade_from_Shade(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_shade *, (*env)->GetLongField(env, jobj, shade_fid));
+}
+
+static inline fz_stroke_state *fz_stroke_state_from_StrokeState(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_stroke_state *, (*env)->GetLongField(env, jobj, stroke_fid));
+}
+
+static inline fz_text *fz_text_from_Text(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_text *, (*env)->GetLongField(env, jobj, text_fid));
+}
+
+static inline fz_font *fz_font_from_Font(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_font *, (*env)->GetLongField(env, jobj, font_fid));
+}
+
+static inline void fz_color_from_jfloatArray(JNIEnv *env, float *color, int n, jfloatArray jcolor)
+{
+ jsize len = (*env)->GetArrayLength(env, jcolor);
+ if (len > n)
+ len = n;
+ (*env)->GetFloatArrayRegion(env, jcolor, 0, len, color);
+ if (len < n)
+ memset(color+len, 0, (n-len)*sizeof(float));
+}
+
+static inline fz_cookie *fz_cookie_from_Cookie(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_cookie *, (*env)->GetLongField(env, jobj, cookie_fid));
+}
+
+static inline fz_display_list *fz_display_list_from_DisplayList(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_display_list *, (*env)->GetLongField(env, jobj, displaylist_fid));
+}
+
+static inline fz_page *fz_page_from_Page(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_page *, (*env)->GetLongField(env, jobj, page_fid));
+}
+
+static inline fz_document *fz_document_from_Document(JNIEnv *env, jobject jobj)
+{
+ jlong l;
+
+ l = (*env)->GetLongField(env, jobj, document_fid);
+ return CAST(fz_document *, l);
+}
+
+static inline fz_annot *fz_annot_from_Annotation(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_annot *, (*env)->GetLongField(env, jobj, annot_fid));
+}
+
+static inline fz_outline *fz_outline_from_Outline(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_outline *, (*env)->GetLongField(env, jobj, outline_fid));
+}
+
+static inline fz_link *fz_link_from_Link(JNIEnv *env, jobject jobj)
+{
+ return CAST(fz_link *, (*env)->GetLongField(env, jobj, link_fid));
+}
+
+/* Helper function for exception handling */
+
+static void jni_throw(JNIEnv *env, int type, const char *mess)
+{
+ const char *className;
+ int len;
+ jclass cla;
+
+ switch(type)
+ {
+ case FZ_ERROR_TRYLATER:
+ cla = trylaterexception_class;
+ break;
+ default:
+ case FZ_ERROR_GENERIC:
+ cla = exception_class;
+ break;
+ }
+
+ (void)(*env)->ThrowNew(env, cla, mess);
+}
+
+static void jni_rethrow(JNIEnv *env, fz_context *ctx)
+{
+ jni_throw(env, fz_caught(ctx), fz_caught_message(ctx));
+}
+
+/* ColorSpace Interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(ColorSpace_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, self);
+
+ if (ctx == NULL || cs == NULL)
+ return;
+
+ fz_drop_colorspace(ctx, cs);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(ColorSpace_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(ColorSpace_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, colorspace_fid, 0);
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(ColorSpace_getNumComponents)(JNIEnv * env, jobject self)
+{
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, self);
+
+ if (cs == NULL)
+ return 0;
+
+ return cs->n;
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(ColorSpace_newDeviceRGB)(JNIEnv * env, jobject self, jlong size)
+{
+ fz_context *ctx = get_context(env);
+
+ return jlong_cast(fz_device_rgb(ctx));
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(ColorSpace_newDeviceGray)(JNIEnv * env, jobject self, jlong size)
+{
+ fz_context *ctx = get_context(env);
+
+ return jlong_cast(fz_device_gray(ctx));
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(ColorSpace_newDeviceCMYK)(JNIEnv * env, jobject self, jlong size)
+{
+ fz_context *ctx = get_context(env);
+
+ return jlong_cast(fz_device_cmyk(ctx));
+}
+
+/* Device Interface */
+
+typedef struct CDeviceNativeInfo CDeviceNativeInfo;
+
+typedef void (CDeviceLockFn)(JNIEnv *env, CDeviceNativeInfo *info);
+typedef void (CDeviceUnlockFn)(JNIEnv *env, CDeviceNativeInfo *info);
+
+struct CDeviceNativeInfo
+{
+ /* Some devices (like the AndroidDrawDevice, or AwtDrawDevice) need
+ * to lock/unlock the java object around device calls. We have functions
+ * here to do that. Other devices (like the DisplayList device) need
+ * no such locking, so these are NULL. */
+ CDeviceLockFn *lock; /* Function to lock */
+ CDeviceUnlockFn *unlock; /* Function to unlock */
+ jobject object; /* The java object that needs to be locked. */
+
+ /* Conceptually, we support drawing onto a 'plane' of pixels.
+ * The plane is width/height in size. The page is positioned on this
+ * at pageX0,pageY0 -> pageX1,PageY1. We want to redraw the given patch
+ * of this.
+ *
+ * The samples pointer in pixmap is updated on every lock/unlock, to
+ * cope with the object moving in memory.
+ */
+ fz_pixmap *pixmap;
+ int pageX0;
+ int pageY0;
+ int width;
+};
+
+static CDeviceNativeInfo *lockCDevice(JNIEnv *env, jobject self)
+{
+ CDeviceNativeInfo *info;
+
+ info = CAST(CDeviceNativeInfo *, (*env)->GetLongField(env, self, cdevice_nativeinfo_fid));
+ if (info == NULL)
+ {
+ /* Some devices (like the Displaylist device) need no locking,
+ * so have no info. */
+ return NULL;
+ }
+ info->object = (*env)->GetObjectField(env, self, cdevice_nativeresource_fid);
+
+ info->lock(env, info);
+
+ return info;
+}
+
+static void unlockCDevice(JNIEnv *env, CDeviceNativeInfo *info)
+{
+ if (info != NULL)
+ info->unlock(env, info);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Device_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ fz_drop_device(ctx, dev);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Device_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Device_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, device_fid, 0);
+}
+
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_beginPage)(JNIEnv *env, jobject self, jobject jrect, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_rect rect = fz_rect_from_Rect(env, jrect);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_begin_page(ctx, dev, &rect, &ctm);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_endPage)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_end_page(ctx, dev);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_fillPath)(JNIEnv *env, jobject self, jobject jpath, int even_odd, jobject jctm, jobject jcs, jfloatArray jcolor, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_path *path = fz_path_from_Path(env, jpath);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, jcs);
+ float color[FZ_MAX_COLORS];
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_color_from_jfloatArray(env, color, cs ? cs->n : FZ_MAX_COLORS, jcolor);
+
+ fz_fill_path(ctx, dev, path, even_odd, &ctm, cs, color, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_strokePath)(JNIEnv *env, jobject self, jobject jpath, jobject jstroke, jobject jctm, jobject jcs, jfloatArray jcolor, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_path *path = fz_path_from_Path(env, jpath);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, jcs);
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, jstroke);
+ float color[FZ_MAX_COLORS];
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_color_from_jfloatArray(env, color, cs ? cs->n : FZ_MAX_COLORS, jcolor);
+
+ fz_stroke_path(ctx, dev, path, stroke, &ctm, cs, color, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_clipPath)(JNIEnv *env, jobject self, jobject jpath, jobject jrect, int even_odd, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_path *path = fz_path_from_Path(env, jpath);
+ fz_rect rect = fz_rect_from_Rect(env, jrect);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_clip_path(ctx, dev, path, &rect, even_odd, &ctm);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_clipStrokePath)(JNIEnv *env, jobject self, jobject jpath, jobject jrect, jobject jstroke, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_path *path = fz_path_from_Path(env, jpath);
+ fz_rect rect = fz_rect_from_Rect(env, jrect);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, jstroke);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_clip_stroke_path(ctx, dev, path, &rect, stroke, &ctm);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_fillText)(JNIEnv *env, jobject self, jobject jtext, jobject jctm, jobject jcs, jfloatArray jcolor, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_text *text = fz_text_from_Text(env, jtext);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, jcs);
+ float color[FZ_MAX_COLORS];
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_color_from_jfloatArray(env, color, cs ? cs->n : FZ_MAX_COLORS, jcolor);
+
+ fz_fill_text(ctx, dev, text, &ctm, cs, color, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_strokeText)(JNIEnv *env, jobject self, jobject jtext, jobject jstroke, jobject jctm, jobject jcs, jfloatArray jcolor, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_text *text = fz_text_from_Text(env, jtext);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, jcs);
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, jstroke);
+ float color[FZ_MAX_COLORS];
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_color_from_jfloatArray(env, color, cs ? cs->n : FZ_MAX_COLORS, jcolor);
+
+ fz_stroke_text(ctx, dev, text, stroke, &ctm, cs, color, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_clipText)(JNIEnv *env, jobject self, jobject jtext, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_text *text = fz_text_from_Text(env, jtext);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_clip_text(ctx, dev, text, &ctm);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_clipStrokeText)(JNIEnv *env, jobject self, jobject jtext, jobject jstroke, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_text *text = fz_text_from_Text(env, jtext);
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, jstroke);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_clip_stroke_text(ctx, dev, text, stroke, &ctm);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_ignoreText)(JNIEnv *env, jobject self, jobject jtext, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_text *text = fz_text_from_Text(env, jtext);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_ignore_text(ctx, dev, text, &ctm);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_fillShade)(JNIEnv *env, jobject self, jobject jshade, jobject jctm, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_shade *shade = fz_shade_from_Shade(env, jshade);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_fill_shade(ctx, dev, shade, &ctm, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_fillImage)(JNIEnv *env, jobject self, jobject jimg, jobject jctm, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_image *image = fz_image_from_Image(env, jimg);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_fill_image(ctx, dev, image, &ctm, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_fillImageMask)(JNIEnv *env, jobject self, jobject jimg, jobject jctm, jobject jcs, jfloatArray jcolor, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_image *image = fz_image_from_Image(env, jimg);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, jcs);
+ float color[FZ_MAX_COLORS];
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_color_from_jfloatArray(env, color, cs ? cs->n : FZ_MAX_COLORS, jcolor);
+
+ fz_fill_image_mask(ctx, dev, image, &ctm, cs, color, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_clipImageMask)(JNIEnv *env, jobject self, jobject jimg, jobject jrect, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_image *image = fz_image_from_Image(env, jimg);
+ fz_rect rect = fz_rect_from_Rect(env, jrect);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_clip_image_mask(ctx, dev, image, &rect, &ctm);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_popClip)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_pop_clip(ctx, dev);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_beginMask)(JNIEnv *env, jobject self, jobject jrect, int luminosity, jobject jcs, jfloatArray jcolor)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_rect rect = fz_rect_from_Rect(env, jrect);
+ fz_colorspace *cs = fz_colorspace_from_ColorSpace(env, jcs);
+ float color[FZ_MAX_COLORS];
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_color_from_jfloatArray(env, color, cs ? cs->n : FZ_MAX_COLORS, jcolor);
+
+ fz_begin_mask(ctx, dev, &rect, luminosity, cs, color);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_endMask)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_end_mask(ctx, dev);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_beginGroup)(JNIEnv *env, jobject self, jobject jrect, int isolated, int knockout, int blendmode, float alpha)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_rect rect = fz_rect_from_Rect(env, jrect);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_begin_group(ctx, dev, &rect, isolated, knockout, blendmode, alpha);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_endGroup)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_end_group(ctx, dev);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(CDevice_beginTile)(JNIEnv *env, jobject self, jobject jarea, jobject jview, float xstep, float ystep, jobject jctm, int id)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_rect area = fz_rect_from_Rect(env, jarea);
+ fz_rect view = fz_rect_from_Rect(env, jview);
+ int i;
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ i = fz_begin_tile_id(ctx, dev, &area, &view, xstep, ystep, &ctm, id);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+
+ return i;
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_endTile)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_device *dev = fz_device_from_Device(env, self, ctx);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || dev == NULL)
+ return;
+
+ info = lockCDevice(env, self);
+
+ fz_try(ctx)
+ {
+ fz_end_tile(ctx, dev);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+/* Draw Device interface */
+static jlong
+newCDevice(JNIEnv *env, jobject self, fz_context *ctx, jobject obj, jint width, jint height, CDeviceLockFn *lock, CDeviceUnlockFn *unlock, int pageX0, int pageY0, int pageX1, int pageY1, int patchX0, int patchY0, int patchX1, int patchY1)
+{
+ fz_device *device = NULL;
+ fz_pixmap *pixmap = NULL;
+ int ret;
+ unsigned char dummy;
+ CDeviceNativeInfo *ninfo = NULL;
+ fz_irect clip, pixbbox;
+
+ if (ctx == NULL)
+ return 0;
+
+ fz_var(pixmap);
+ fz_var(ninfo);
+
+ fz_try(ctx)
+ {
+ //LOGI("DrawDeviceNative: bitmap=%d,%d page=%d,%d->%d,%d patch=%d,%d->%d,%d", width, height, pageX0, pageY0, pageX1, pageY1, patchX0, patchY0, patchX1, patchY1);
+ /* Sanitise patch w.r.t page. */
+ if (patchX0 < pageX0)
+ patchX0 = pageX0;
+ if (patchY0 < pageY0)
+ patchY0 = pageY0;
+ if (patchX1 > pageX1)
+ patchX1 = pageX1;
+ if (patchY1 > pageY1)
+ patchY1 = pageY1;
+
+ clip.x0 = patchX0;
+ clip.y0 = patchY0;
+ clip.x1 = patchX1;
+ clip.y1 = patchY1;
+
+ /* Check for sanity. */
+ //LOGI("clip = %d,%d->%d,%d", clip.x0, clip.y0, clip.x1, clip.y1);
+ if (clip.x0 < 0 || clip.y0 < 0 || clip.x1 > width || clip.y1 > height)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "patch would draw out of bounds!");
+
+ clip.x0 -= pageX0;
+ clip.y0 -= pageY0;
+ clip.x1 -= pageX0;
+ clip.y1 -= pageY0;
+
+ /* pixmaps cannot handle right-edge padding, so the bbox must be expanded to
+ * match the pixels data */
+ pixbbox = clip;
+ pixbbox.x1 = pixbbox.x0 + width;
+ pixmap = fz_new_pixmap_with_bbox_and_data(ctx, fz_device_rgb(ctx), &pixbbox, &dummy);
+ ninfo = fz_malloc(ctx, sizeof(*ninfo));
+ ninfo->pixmap = pixmap;
+ ninfo->lock = lock;
+ ninfo->unlock = unlock;
+ ninfo->pageX0 = pageX0;
+ ninfo->pageY0 = pageY0;
+ ninfo->width = width;
+ ninfo->object = obj;
+ (*env)->SetLongField(env, self, cdevice_nativeinfo_fid, jlong_cast(ninfo));
+ (*env)->SetObjectField(env, self, cdevice_nativeresource_fid, obj);
+ lockCDevice(env,self);
+ fz_clear_pixmap_rect_with_value(ctx, pixmap, 0xff, &clip);
+ unlockCDevice(env,ninfo);
+ device = fz_new_draw_device_with_bbox(ctx, pixmap, &clip);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_pixmap(ctx, pixmap);
+ fz_free(ctx, ninfo);
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(device);
+}
+
+static void androidDrawDevice_lock(JNIEnv *env, CDeviceNativeInfo *info)
+{
+ uint8_t *pixels;
+
+ assert(info != NULL);
+ assert(info->object != NULL);
+
+ if (AndroidBitmap_lockPixels(env, info->object, (void **)&pixels) < 0)
+ {
+ jni_throw(env, FZ_ERROR_GENERIC, "Bitmap lock failed in DrawDevice call");
+ return;
+ }
+
+ /* Now offset pixels to allow for the page offsets */
+ //pixels += sizeof(int32_t) * (info->pageX0 + info->width * info->pageY0);
+
+ info->pixmap->samples = pixels;
+}
+
+static void androidDrawDevice_unlock(JNIEnv *env, CDeviceNativeInfo *info)
+{
+ assert(info != NULL);
+ assert(info->object != NULL);
+
+ if (AndroidBitmap_unlockPixels(env, info->object) < 0)
+ {
+ jni_throw(env, FZ_ERROR_GENERIC, "Bitmap unlock failed in DrawDevice call");
+ }
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(AndroidDrawDevice_newNative)(JNIEnv *env, jobject self, jobject jbitmap, int pageX0, int pageY0, int pageX1, int pageY1, int patchX0, int patchY0, int patchX1, int patchY1)
+{
+ fz_context *ctx = get_context(env);
+ AndroidBitmapInfo info;
+ jlong device = 0;
+ int ret;
+
+ fz_try(ctx)
+ {
+ if ((ret = AndroidBitmap_getInfo(env, jbitmap, &info)) < 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "new DrawDevice failed to get bitmap info");
+
+ if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "new DrawDevice failed as bitmap format is not RGBA_8888");
+
+ if (info.stride != info.width*4)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "new DrawDevice failed as bitmap width != stride");
+
+ device = newCDevice(env, self, ctx, jbitmap, info.width, info.height, androidDrawDevice_lock, androidDrawDevice_unlock, pageX0, pageY0, pageX1, pageY1, patchX0, patchY0, patchX1, patchY1);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return device;
+}
+
+static void awtDrawDevice_lock(JNIEnv *env, CDeviceNativeInfo *info)
+{
+ int8_t *pixels;
+
+ assert(info != NULL);
+ assert(info->object != NULL);
+ assert(info->pixmap != NULL);
+
+ //pixels = (unsigned char *)((*env)->GetIntArrayElements(env, info->object, 0));
+
+ /* Now offset pixels to allow for the page offsets */
+ pixels += sizeof(int32_t) * (info->pageX0 + info->width * info->pageY0);
+
+ info->pixmap->samples = pixels;
+}
+
+static void awtDrawDevice_unlock(JNIEnv *env, CDeviceNativeInfo *info)
+{
+ int8_t *pixels = info->pixmap->samples;
+
+ assert(info != NULL);
+ assert(info->object != NULL);
+ assert(info->pixmap != NULL);
+
+ /* Now offset pixels to allow for the page offsets */
+ //pixels -= sizeof(int32_t) * (info->pageX0 + info->width * info->pageY0);
+
+ (*env)->ReleaseIntArrayElements(env, info->object, (int *)(void *)pixels, 0);
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(AwtDrawDevice_newNative)(JNIEnv *env, jobject self, jobject rgba, jint w, jint h, int pageX0, int pageY0, int pageX1, int pageY1, int patchX0, int patchY0, int patchX1, int patchY1)
+{
+ fz_context *ctx = get_context(env);
+
+ return newCDevice(env, self, ctx, rgba, w, h, awtDrawDevice_lock, awtDrawDevice_unlock, pageX0, pageY0, pageX1, pageY1, patchX0, patchY0, patchX1, patchY1);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_finalize)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ CDeviceNativeInfo *ninfo;
+
+ ninfo = CAST(CDeviceNativeInfo *, (*env)->GetLongField(env, self, cdevice_nativeinfo_fid));
+ if (ninfo != NULL)
+ {
+ fz_drop_pixmap(ctx, ninfo->pixmap);
+ fz_free(ctx, ninfo);
+ }
+ (*env)->SetLongField(env, self, cdevice_nativeinfo_fid, 0);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(CDevice_destroy)(JNIEnv *env, jobject self)
+{
+ JNI_FN(CDevice_finalize)(env, self);
+ JNI_FN(Device_finalize)(env, self); /* Super class destroy */
+}
+
+/* Path Interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_drop_path(ctx, path);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Path_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, path_fid, 0);
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Path_newNative)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = NULL;
+
+ if (ctx == NULL)
+ return 0;
+
+ fz_try(ctx)
+ {
+ path = fz_new_path(ctx);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(path);
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Path_currentPoint)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+ fz_point point;
+ jmethodID cons;
+ jobject jpoint;
+
+ if (ctx == NULL || path == NULL)
+ return NULL;
+
+ fz_try(ctx)
+ {
+ point = fz_currentpoint(ctx, path);
+ jpoint = Point_from_fz_point(ctx, env, point);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jpoint;
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_moveTo)(JNIEnv * env, jobject self, float x, float y)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ fz_moveto(ctx, path, x, y);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_lineTo)(JNIEnv * env, jobject self, float x, float y)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ fz_lineto(ctx, path, x, y);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_curveTo)(JNIEnv * env, jobject self, float cx1, float cy1, float cx2, float cy2, float ex, float ey)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ fz_curveto(ctx, path, cx1, cy1, cx2, cy2, ex, ey);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_curveToV)(JNIEnv * env, jobject self, float cx, float cy, float ex, float ey)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ fz_curvetov(ctx, path, cx, cy, ex, ey);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_curveToY)(JNIEnv * env, jobject self, float cx, float cy, float ex, float ey)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ fz_curvetoy(ctx, path, cx, cy, ex, ey);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_close)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ fz_closepath(ctx, path);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Path_transform)(JNIEnv * env, jobject self, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+
+ if (ctx == NULL || path == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ fz_transform_path(ctx, path, &ctm);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Path_clone)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+ fz_path *path2 = NULL;
+
+ if (ctx == NULL || path == NULL)
+ return 0;
+
+ fz_try(ctx)
+ {
+ path2 = fz_clone_path(ctx, path);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(path2);
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Path_bound)(JNIEnv * env, jobject self, jobject jstroke, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+ jobject jrect;
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, jstroke);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_rect rect;
+
+ if (ctx == NULL || path == NULL)
+ return NULL;
+
+ fz_try(ctx)
+ {
+ fz_bound_path(ctx, path, stroke, &ctm, &rect);
+
+ jrect = Rect_from_fz_rect(ctx, env, &rect);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jrect;
+}
+
+typedef struct {
+ JNIEnv *env;
+ jobject jproc;
+} pproc_data;
+
+static void
+pathProcMoveTo(fz_context *ctx, void *arg, float x, float y)
+{
+ pproc_data *pproc = (pproc_data *)arg;
+
+ (*pproc->env)->CallVoidMethod(pproc->env, pproc->jproc, pathproc_moveto_mid, x, y);
+}
+
+static void
+pathProcLineTo(fz_context *ctx, void *arg, float x, float y)
+{
+ pproc_data *pproc = (pproc_data *)arg;
+
+ (*pproc->env)->CallVoidMethod(pproc->env, pproc->jproc, pathproc_lineto_mid, x, y);
+}
+
+static void
+pathProcCurveTo(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2, float x3, float y3)
+{
+ pproc_data *pproc = (pproc_data *)arg;
+
+ (*pproc->env)->CallVoidMethod(pproc->env, pproc->jproc, pathproc_curveto_mid, x1, y1, x2, y2, x3, y3);
+}
+
+static void
+pathProcClose(fz_context *ctx, void *arg)
+{
+ pproc_data *pproc = (pproc_data *) arg;
+
+ (*pproc->env)->CallVoidMethod(pproc->env, pproc->jproc, pathproc_close_mid);
+}
+
+static const fz_path_processor path_proc =
+{
+ pathProcMoveTo,
+ pathProcLineTo,
+ pathProcCurveTo,
+ pathProcClose
+};
+
+void JNICALL
+JNI_FN(Path_process)(JNIEnv * env, jobject self, jobject jproc)
+{
+ fz_context *ctx = get_context(env);
+ fz_path *path = fz_path_from_Path(env, self);
+ int i = 0, k = 0;
+ int n;
+ pproc_data data;
+
+ if (path == NULL || jproc == NULL)
+ return;
+
+ data.env = env;
+ data.jproc = jproc;
+
+ fz_process_path(ctx, &path_proc, &data, path);
+}
+
+
+/* StrokeState interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(StrokeState_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ if (ctx == NULL || stroke == NULL)
+ return;
+
+ fz_drop_stroke_state(ctx, stroke);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(StrokeState_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(StrokeState_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, stroke_fid, 0);
+}
+
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Path_newStrokeState)(JNIEnv * env, jobject self, int startCap, int dashCap, int endCap, int lineJoin, float lineWidth, float miterLimit, float dashPhase, jfloatArray dash)
+{
+ fz_context *ctx = get_context(env);
+ fz_stroke_state *stroke = NULL;
+ jsize len = (*env)->GetArrayLength(env, dash);
+
+ if (ctx == NULL)
+ return 0;
+
+ fz_var(stroke);
+
+ fz_try(ctx)
+ {
+ stroke = fz_new_stroke_state_with_dash_len(ctx, len);
+ stroke->start_cap = startCap;
+ stroke->dash_cap = dashCap;
+ stroke->end_cap = endCap;
+ stroke->linejoin = lineJoin;
+ stroke->linewidth = lineWidth;
+ stroke->miterlimit = miterLimit;
+ stroke->dash_phase = dashPhase;
+ stroke->dash_len = len;
+ (*env)->GetFloatArrayRegion(env, dash, 0, len, &stroke->dash_list[0]);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_stroke_state(ctx, stroke);
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(stroke);
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(StrokeState_getStartCap)(JNIEnv * env, jobject self)
+{
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ return stroke ? stroke->start_cap : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(StrokeState_getDashCap)(JNIEnv * env, jobject self)
+{
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ return stroke ? stroke->dash_cap : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(StrokeState_getEndCap)(JNIEnv * env, jobject self)
+{
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ return stroke ? stroke->end_cap : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(StrokeState_getLineJoin)(JNIEnv * env, jobject self)
+{
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ return stroke ? stroke->linejoin : 0;
+}
+
+JNIEXPORT float JNICALL
+JNI_FN(StrokeState_getLineWidth)(JNIEnv * env, jobject self)
+{
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ return stroke ? stroke->linewidth : 0;
+}
+
+JNIEXPORT float JNICALL
+JNI_FN(StrokeState_getMiterLimit)(JNIEnv * env, jobject self)
+{
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ return stroke ? stroke->miterlimit : 0;
+}
+
+JNIEXPORT float JNICALL
+JNI_FN(StrokeState_getDashPhase)(JNIEnv * env, jobject self)
+{
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+
+ return stroke ? stroke->dash_phase : 0;
+}
+
+JNIEXPORT jfloatArray JNICALL
+JNI_FN(StrokeState_getDashes)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, self);
+ jfloatArray arr;
+
+ if (stroke->dash_len == 0)
+ return NULL;
+
+ arr = (*env)->NewFloatArray(env, stroke->dash_len);
+ if (arr == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of floatArray failed");
+
+ (*env)->SetFloatArrayRegion(env, arr, 0, stroke->dash_len, &stroke->dash_list[0]);
+
+ return arr;
+}
+
+/* Text interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Text_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_text *text = fz_text_from_Text(env, self);
+
+ if (ctx == NULL || text == NULL)
+ return;
+
+ fz_drop_text(ctx, text);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Text_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Text_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, text_fid, 0);
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Text_clone)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_text *text = fz_text_from_Text(env, self);
+ fz_text *text2 = NULL;
+
+ if (ctx == NULL || text == NULL)
+ return 0;
+
+ fz_try(ctx)
+ {
+ text2 = fz_clone_text(ctx, text);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(text2);
+}
+
+//JNIEXPORT jlong JNICALL
+//JNI_FN(Text_newText)(JNIEnv * env, jobject self, jobject jfont, jobject jctm, int wmode)
+//{
+// fz_context *ctx = get_context(env);
+// fz_text *text = NULL;
+// fz_font *font = fz_font_from_Font(env, jfont);
+// fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+//
+// if (ctx == NULL)
+// return 0;
+//
+// fz_try(ctx)
+// {
+// text = fz_new_text(ctx, font, &ctm, wmode);
+// }
+// fz_catch(ctx)
+// {
+// jni_rethrow(env, ctx);
+// }
+// return jlong_cast(text);
+//}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Text_bound)(JNIEnv * env, jobject self, jobject jstroke, jobject jctm)
+{
+ fz_context *ctx = get_context(env);
+ fz_text *text = fz_text_from_Text(env, self);
+ fz_stroke_state *stroke = fz_stroke_state_from_StrokeState(env, jstroke);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ jobject jrect;
+ fz_rect rect;
+
+ if (ctx == NULL || text == NULL)
+ return NULL;
+
+ fz_try(ctx)
+ {
+ fz_bound_text(ctx, text, stroke, &ctm, &rect);
+
+ jrect = Rect_from_fz_rect(ctx, env, &rect);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jrect;
+}
+
+//JNIEXPORT void JNICALL
+//JNI_FN(Text_add)(JNIEnv * env, jobject self, int gid, int ucs, float x, float y)
+//{
+// fz_context *ctx = get_context(env);
+// fz_text *text = fz_text_from_Text(env, self);
+//
+// if (ctx == NULL || text == NULL)
+// return;
+//
+// fz_try(ctx)
+// {
+// fz_add_text(ctx, text, gid, ucs, x, y);
+// }
+// fz_catch(ctx)
+// {
+// jni_rethrow(env, ctx);
+// }
+//}
+
+/* Image interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Image_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_image *image = fz_image_from_Image(env, self);
+
+ if (ctx == NULL || image == NULL)
+ return;
+
+ fz_drop_image(ctx, image);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Image_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Image_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, image_fid, 0);
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Image_newImageFromBitmap)(JNIEnv * env, jobject self, jobject jbitmap, jlong jmask)
+{
+ fz_context *ctx = get_context(env);
+ fz_image *mask = CAST(fz_image *, jmask);
+ fz_image *image = NULL;
+ fz_pixmap *pixmap = NULL;
+ AndroidBitmapInfo info;
+ void *pixels;
+ int ret;
+
+ if (ctx == NULL)
+ return 0;
+
+ fz_var(pixmap);
+
+ fz_try(ctx)
+ {
+ if (mask && mask->mask)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "new Image failed as mask cannot be masked");
+
+ if ((ret = AndroidBitmap_getInfo(env, jbitmap, &info)) < 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "new Image failed to get bitmap info");
+
+ if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "new Image failed as bitmap format is not RGBA_8888");
+
+ if (info.stride != info.width)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "new Image failed as bitmap width != stride");
+
+ pixmap = fz_new_pixmap(ctx, fz_device_rgb(ctx), info.width, info.height);
+ if (AndroidBitmap_lockPixels(env, jbitmap, &pixels) < 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Bitmap lock failed in new Image");
+ memcpy(pixmap->samples, pixels, info.width * info.height * 4);
+ (void)AndroidBitmap_unlockPixels(env, jbitmap);
+
+ image = fz_new_image_from_pixmap(ctx, fz_keep_pixmap(ctx, pixmap), fz_keep_image(ctx, mask));
+ }
+ fz_always(ctx)
+ {
+ fz_drop_pixmap(ctx, pixmap);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(image);
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getWidth)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->w : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getHeight)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->h : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getNumComponents)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->n : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getBitsPerComponent)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->bpc : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getXResolution)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->xres : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getYResolution)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->yres : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getImageMask)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->imagemask : 0;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Image_getInterpolate)(JNIEnv * env, jobject self)
+{
+ fz_image *image = fz_image_from_Image(env, self);
+
+ return image ? image->interpolate : 0;
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Image_getMask)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_image *img = fz_image_from_Image(env, self);
+ jobject jobj;
+
+ if (img == NULL || img->mask == NULL)
+ return NULL;
+
+ jobj = Image_from_fz_image(ctx, env, img->mask);
+ if (jobj != NULL)
+ fz_keep_image(ctx, img->mask);
+
+ return jobj;
+
+died:
+ fz_throw(ctx, FZ_ERROR_GENERIC, "JNI creation of Image(Mask) failed");
+ return NULL;
+}
+
+/* Outline interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Outline_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_outline *outline = fz_outline_from_Outline(env, self);
+
+ if (ctx == NULL || outline == NULL)
+ return;
+
+ fz_drop_outline(ctx, outline);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Outline_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Outline_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, outline_fid, 0);
+}
+
+/* Annotation Interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Annotation_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_annot *annot = fz_annot_from_Annotation(env, self);
+
+ if (ctx == NULL || link == NULL)
+ return;
+
+ fz_drop_annot(ctx, annot);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Annotation_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Annotation_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, annot_fid, 0);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Annotation_run)(JNIEnv * env, jobject self, jobject jdev, jobject jctm, jobject jcookie)
+{
+ fz_context *ctx = get_context(env);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_cookie *cookie= fz_cookie_from_Cookie(env, jcookie);
+ fz_device *dev = fz_device_from_Device(env, jdev, ctx);
+ jobject jdoc;
+ fz_annot *annot = fz_annot_from_Annotation(env, self);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || self == NULL || jdev == NULL)
+ return;
+
+ fz_var(dev);
+
+ info = lockCDevice(env, jdev);
+
+ fz_try(ctx)
+ {
+ fz_run_annot(ctx, annot, dev, &ctm, cookie);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Annotation_advance)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_annot *annot;
+
+ if (ctx == NULL)
+ return;
+
+ fz_try(ctx)
+ {
+ annot = fz_annot_from_Annotation(env, self);
+
+ annot = fz_next_annot(ctx, annot);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(annot);
+}
+
+/* Link interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Link_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_link *link = fz_link_from_Link(env, self);
+
+ if (ctx == NULL || link == NULL)
+ return;
+
+ fz_drop_link(ctx, link);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Link_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Link_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, link_fid, 0);
+}
+
+/* Document interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Document_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *doc = fz_document_from_Document(env, self);
+
+ if (ctx == NULL || doc == NULL)
+ return;
+
+ fz_drop_document(ctx, doc);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Document_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Document_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, document_fid, 0);
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Document_newNative)(JNIEnv * env, jobject self, jstring jfilename)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = NULL;
+ const char *filename = NULL;
+
+ if (ctx == NULL || jfilename == NULL)
+ return 0;
+
+ fz_var(filename);
+
+ fz_try(ctx)
+ {
+ filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
+ if (filename == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to convert filename");
+ document = fz_open_document(ctx, filename);
+ }
+ fz_always(ctx)
+ {
+ (*env)->ReleaseStringUTFChars(env, jfilename, filename);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+
+ return jlong_cast(document);
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Document_needsPassword)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = fz_document_from_Document(env, self);
+ int ret;
+
+ if (ctx == NULL || document == NULL)
+ return 0;
+
+ fz_try(ctx)
+ {
+ ret = fz_needs_password(ctx, document);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ ret = 0;
+ }
+ return ret;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Document_authenticatePassword)(JNIEnv * env, jobject self, jstring jpassword)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = fz_document_from_Document(env, self);
+ int ret;
+ const char *password = NULL;
+
+ if (ctx == NULL || document == NULL)
+ return 0;
+
+ fz_var(password);
+
+ fz_try(ctx)
+ {
+ if (jpassword == NULL)
+ password = "";
+ else
+ {
+ password = (*env)->GetStringUTFChars(env, jpassword, NULL);
+ if (password == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to convert password");
+ }
+
+ ret = fz_authenticate_password(ctx, document, password);
+ }
+ fz_always(ctx)
+ {
+ if (jpassword != NULL)
+ (*env)->ReleaseStringUTFChars(env, jpassword, password);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ ret = 0;
+ }
+ return ret;
+}
+
+JNIEXPORT int JNICALL
+JNI_FN(Document_countPages)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = fz_document_from_Document(env, self);
+ int ret;
+
+ if (ctx == NULL || document == NULL)
+ return 0;
+
+ fz_try(ctx)
+ {
+ ret = fz_count_pages(ctx, document);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ ret = 0;
+ }
+ return ret;
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Document_getPage)(JNIEnv * env, jobject self, int n)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = fz_document_from_Document(env, self);
+ fz_page *page = NULL;
+ jobject jpage;
+
+ if (ctx == NULL || document == NULL)
+ return NULL;
+
+ fz_var(page);
+
+ fz_try(ctx)
+ {
+ page = fz_load_page(ctx, document, n);
+ if (page == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "getPage failed");
+
+ jpage = Page_from_fz_page(ctx, env, page);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_page(ctx, page);
+ jni_rethrow(env, ctx);
+ jpage = NULL;
+ }
+ return jpage;
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Document_getFileFormat)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = fz_document_from_Document(env, self);
+ char info[64];
+
+ if (ctx == NULL || document == NULL)
+ return NULL;
+
+ fz_lookup_metadata(ctx, document, FZ_META_FORMAT, info, sizeof(info));
+
+ return (*env)->NewStringUTF(env, info);
+}
+
+JNIEXPORT jboolean JNICALL
+JNI_FN(Document_isUnencryptedPDF)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = fz_document_from_Document(env, self);
+ pdf_document *idoc = pdf_specifics(ctx, document);
+ int cryptVer;
+
+ if (idoc == NULL)
+ return JNI_FALSE; // Not a PDF
+
+ cryptVer = pdf_crypt_version(ctx, idoc);
+ return (cryptVer == 0) ? JNI_TRUE : JNI_FALSE;
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Document_getOutline)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_document *document = fz_document_from_Document(env, self);
+ fz_outline *outline = NULL;
+ jobject joutline;
+
+ if (ctx == NULL || document == NULL)
+ return NULL;
+
+ fz_var(outline);
+
+ fz_try(ctx)
+ {
+ outline = fz_load_outline(ctx, document);
+ if (outline == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "getOutline failed");
+
+ joutline = Outline_from_fz_outline(ctx, env, outline);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_outline(ctx, outline);
+ jni_rethrow(env, ctx);
+ joutline = NULL;
+ }
+ return joutline;
+}
+
+/* Page interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Page_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_page *page = fz_page_from_Page(env, self);
+
+ if (ctx == NULL || page == NULL)
+ return;
+
+ fz_drop_page(ctx, page);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Page_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Page_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, page_fid, 0);
+ (*env)->SetLongField(env, self, page_annots_fid, 0);
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Page_bound)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_page *page = fz_page_from_Page(env, self);
+ jobject jrect;
+ fz_rect rect;
+
+ if (ctx == NULL || page == NULL)
+ return NULL;
+
+ fz_try(ctx)
+ {
+ fz_bound_page(ctx, page, &rect);
+
+ jrect = Rect_from_fz_rect(ctx, env, &rect);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jrect;
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Page_run)(JNIEnv * env, jobject self, jobject jdev, jobject jctm, jobject jcookie)
+{
+ fz_context *ctx = get_context(env);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_cookie *cookie = fz_cookie_from_Cookie(env, jcookie);
+ fz_device *dev = fz_device_from_Device(env, jdev, ctx);
+ fz_page *page = fz_page_from_Page(env, self);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL || self == NULL || jdev == NULL)
+ return;
+
+ info = lockCDevice(env, jdev);
+
+ fz_try(ctx)
+ {
+ fz_run_page(ctx, page, dev, &ctm, cookie);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Page_runPageContents)(JNIEnv * env, jobject self, jobject jdev, jobject jctm, jobject jcookie)
+{
+ fz_context *ctx = get_context(env);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_cookie *cookie = fz_cookie_from_Cookie(env, jcookie);
+ fz_device *dev = fz_device_from_Device(env, jdev, ctx);
+ fz_page *page = fz_page_from_Page(env, self);
+ CDeviceNativeInfo *info;
+
+ if (ctx == NULL)
+ return;
+
+ info = lockCDevice(env, jdev);
+
+ fz_try(ctx)
+ {
+ fz_run_page_contents(ctx, page, dev, &ctm, cookie);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT jobject JNICALL
+JNI_FN(Page_getAnnotations)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_page *page = fz_page_from_Page(env, self);
+ jobject jrect;
+ fz_rect rect;
+ fz_annot *annot = NULL;
+ fz_annot *first = NULL;
+ jobject jannots = NULL;
+ int ret;
+ int annot_count;
+ int i;
+
+ if (ctx == NULL || page == NULL)
+ return NULL;
+
+ fz_var(annot);
+ fz_var(jannots);
+
+ fz_try(ctx)
+ {
+ jannots = (*env)->GetObjectField(env, self, page_annots_fid);
+
+ first = fz_first_annot(ctx, page);
+
+ /* Count the annotations */
+ annot = first;
+ for (annot_count = 0; annot != NULL; annot_count++)
+ annot = fz_next_annot(ctx, annot);
+
+ if (annot_count == 0)
+ {
+ /* If no annotations, we don't want an annotation
+ * object stored in the page. */
+ if (jannots != NULL)
+ {
+ (*env)->SetObjectField(env, self, page_annots_fid, NULL);
+ }
+ break; /* No annotations! */
+ }
+
+ jannots = (*env)->NewObjectArray(env, annot_count, annot_class, NULL);
+ if (jannots == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "getAnnotations failed (1)");
+ (*env)->SetObjectField(env, self, page_annots_fid, jannots);
+
+ /* Now run through actually creating the annotation objects */
+ annot = first;
+ for (i = 0; annot != NULL && i < annot_count; i++)
+ {
+ jobject jannot = Annotation_from_fz_annot(ctx, env, annot);
+ (*env)->SetObjectArrayElement(env, jannots, i, jannot);
+ annot = fz_next_annot(ctx, annot);
+ }
+ if (annot != NULL || i != annot_count)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "getAnnotations failed (4)");
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jannots;
+}
+
+/* private native final Link[] getLinks(jlong ctx); */
+
+
+/* Cookie interface */
+
+JNIEXPORT void JNICALL
+JNI_FN(Cookie_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_cookie *cookie = fz_cookie_from_Cookie(env, self);
+
+ if (ctx == NULL || cookie == NULL)
+ return;
+
+ fz_free(ctx, cookie);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Cookie_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(Cookie_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, cookie_fid, 0);
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(Cookie_newNative)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+
+ return jlong_cast(fz_malloc_struct(ctx, fz_cookie));
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(Cookie_abort)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_cookie *cookie = fz_cookie_from_Cookie(env, self);
+
+ if (ctx == NULL || cookie == NULL)
+ return;
+
+ cookie->abort = 1;
+}
+
+/* DisplayList interface */
+JNIEXPORT jlong JNICALL
+JNI_FN(DisplayList_newNative)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+
+ return jlong_cast(fz_new_display_list(ctx));
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(DisplayList_run)(JNIEnv * env, jobject self, jobject jdev, jobject jctm, jobject jrect, jobject jcookie)
+{
+ fz_context *ctx = get_context(env);
+ fz_display_list *list = fz_display_list_from_DisplayList(env, self);
+ fz_matrix ctm = fz_matrix_from_Matrix(env, jctm);
+ fz_cookie *cookie = fz_cookie_from_Cookie(env, jcookie);
+ fz_device *dev = fz_device_from_Device(env, jdev, ctx);
+ CDeviceNativeInfo *info;
+ fz_rect local_rect;
+ fz_rect *rect;
+
+ if (ctx == NULL || self == NULL || jdev == NULL || list == NULL)
+ return;
+
+ /* Use a scissor rectangle if one is supplied */
+ if (jrect == NULL)
+ {
+ rect = NULL;
+ }
+ else
+ {
+ rect = &local_rect;
+ local_rect = fz_rect_from_Rect(env, jrect);
+ }
+
+ info = lockCDevice(env, jdev);
+
+ fz_try(ctx)
+ {
+ fz_run_display_list(ctx, list, dev, &ctm, rect, cookie);
+ }
+ fz_always(ctx)
+ {
+ unlockCDevice(env, info);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(DisplayList_finalize)(JNIEnv * env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ fz_display_list *list = fz_display_list_from_DisplayList(env, self);
+
+ if (ctx == NULL || list == NULL)
+ return;
+
+ fz_drop_display_list(ctx, list);
+}
+
+JNIEXPORT void JNICALL
+JNI_FN(DisplayList_destroy)(JNIEnv * env, jobject self)
+{
+ JNI_FN(DisplayList_finalize)(env, self);
+
+ (*env)->SetLongField(env, self, displaylist_fid, 0);
+}
+
+JNIEXPORT jlong JNICALL
+JNI_FN(DisplayListDevice_newNative)(JNIEnv *env, jobject self, jobject jlist)
+{
+ fz_context *ctx = get_context(env);
+ fz_display_list *list = fz_display_list_from_DisplayList(env, jlist);
+ fz_device *device = NULL;
+ int ret;
+ unsigned char dummy;
+
+ if (ctx == NULL || list == NULL)
+ return 0;
+
+ fz_try(ctx)
+ {
+ device = fz_new_list_device(ctx, list);
+ }
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ }
+ return jlong_cast(device);
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/AndroidDrawDevice.java b/platform/android/src/com/artifex/mupdf/fitz/AndroidDrawDevice.java
new file mode 100644
index 00000000..1537f62a
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/AndroidDrawDevice.java
@@ -0,0 +1,19 @@
+package com.artifex.mupdf.fitz;
+
+import android.graphics.Bitmap;
+
+public final class AndroidDrawDevice extends CDevice
+{
+ // Construction
+ public AndroidDrawDevice(Bitmap bitmap, int pageX0, int pageY0, int pageX1, int pageY1, int patchX0, int patchY0, int patchX1, int patchY1)
+ {
+ nativeDevice = newNative(bitmap, pageX0, pageY0, pageX1, pageY1, patchX0, patchY0, patchX1, patchY1);
+ }
+
+ public AndroidDrawDevice(Bitmap bitmap, RectI page, RectI patch)
+ {
+ nativeDevice = newNative(bitmap, page.x0, page.y0, page.x1, page.y1, patch.x0, patch.y0, patch.x1, patch.y1);
+ }
+
+ private native long newNative(Bitmap bitmap, int pageX0, int pageY0, int pageX1, int pageY1, int patchX0, int patchY0, int patchX1, int patchY1);
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Annotation.java b/platform/android/src/com/artifex/mupdf/fitz/Annotation.java
new file mode 100644
index 00000000..6e6dd1c1
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Annotation.java
@@ -0,0 +1,27 @@
+package com.artifex.mupdf.fitz;
+
+public class Annotation
+{
+ // Private data
+ private long nativeAnnot = 0;
+
+ // Construction
+ private Annotation(long ptr)
+ {
+ nativeAnnot = ptr;
+ }
+
+ // Operation
+ public native void run(Device dev, Matrix ctm, Cookie cookie);
+
+ // FIXME: Write accessors
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeAnnot = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/AwtDrawDevice.java b/platform/android/src/com/artifex/mupdf/fitz/AwtDrawDevice.java
new file mode 100644
index 00000000..4e6fb33d
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/AwtDrawDevice.java
@@ -0,0 +1,12 @@
+package com.artifex.mupdf.fitz;
+
+public final class AwtDrawDevice extends CDevice
+{
+ // Construction
+ public AwtDrawDevice(int rgba[], int width, int height)
+ {
+ nativeDevice = newNative(rgba, width, height);
+ }
+
+ private native long newNative(int rgba[], int width, int height);
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/CDevice.java b/platform/android/src/com/artifex/mupdf/fitz/CDevice.java
new file mode 100644
index 00000000..3bfe9c70
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/CDevice.java
@@ -0,0 +1,49 @@
+package com.artifex.mupdf.fitz;
+
+public abstract class CDevice extends Device
+{
+ // Private data
+ private Object nativeResource = null;
+ protected long nativeInfo = 0;
+
+ // Operation
+ public native final void beginPage(Rect rect, Matrix ctm);
+ public native final void endPage();
+
+ public native final void fillPath(Path path, int even_odd, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void strokePath(Path path, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void clipPath(Path path, Rect rect, int even_odd, Matrix ctm);
+ public native final void clipStrokePath(Path path, Rect rect, StrokeState stroke, Matrix ctm);
+
+ public native final void fillText(Text text, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void strokeText(Text text, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void clipText(Text text, Matrix ctm, int accumulate);
+ public native final void clipStrokeText(Text text, StrokeState stroke, Matrix ctm);
+ public native final void ignoreText(Text text, Matrix ctm);
+
+ public native final void fillShade(Shade shade, Matrix ctm, float alpha);
+ public native final void fillImage(Image img, Matrix ctm, float alpha);
+ public native final void fillImageMask(Image img, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void clipImageMask(Image img, Rect rect, Matrix ctm);
+
+ public native final void popClip();
+
+ public native final void beginMask(Rect rect, int luminosity, ColorSpace cs, float bc[]);
+ public native final void endMask();
+ public native final void beginGroup(Rect rect, int isolated, int knockout, int blendmode, float alpha);
+ public native final void endGroup();
+
+ public native final int beginTile(Rect area, Rect view, float xstep, float ystep, Matrix ctm, int id);
+ public native final void endTile();
+
+ // Destruction
+ public final void destroy()
+ {
+ finalize();
+ nativeDevice = 0;
+ nativeResource = null;
+ nativeInfo = 0;
+ }
+
+ protected native final void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/ColorSpace.java b/platform/android/src/com/artifex/mupdf/fitz/ColorSpace.java
new file mode 100644
index 00000000..cad952c0
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/ColorSpace.java
@@ -0,0 +1,34 @@
+package com.artifex.mupdf.fitz;
+
+public class ColorSpace
+{
+ // Private data
+ private long nativeColorSpace;
+
+ // Statics
+ public static ColorSpace DeviceGray = new ColorSpace(newDeviceGray());
+ public static ColorSpace DeviceRGB = new ColorSpace(newDeviceRGB());
+ public static ColorSpace DeviceCMYK = new ColorSpace(newDeviceCMYK());
+
+ private static native long newDeviceGray();
+ private static native long newDeviceRGB();
+ private static native long newDeviceCMYK();
+
+ // Construction
+ private ColorSpace(long l)
+ {
+ nativeColorSpace = l;
+ }
+
+ // Accessors
+ public native int getNumComponents();
+
+ // Destruction
+ public final void destroy()
+ {
+ finalize();
+ nativeColorSpace = 0;
+ }
+
+ protected final native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Context.java b/platform/android/src/com/artifex/mupdf/fitz/Context.java
new file mode 100644
index 00000000..1baafb01
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Context.java
@@ -0,0 +1,20 @@
+package com.artifex.mupdf.fitz;
+
+// This class handles the loading of the MuPDF shared library, together
+// with the ThreadLocal magic to get the required context.
+//
+// The only publicly accessible method here is Context.setStoreSize, which
+// sets the store size to use. This must be called before any other MuPDF
+// function.
+public class Context
+{
+ // Load our native library
+ static
+ {
+ System.loadLibrary("mupdf");
+ }
+
+ // FIXME: We should support the store size being changed dynamically.
+ // This requires changes within the MuPDF core.
+ //public native static void setStoreSize(long newSize);
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Cookie.java b/platform/android/src/com/artifex/mupdf/fitz/Cookie.java
new file mode 100644
index 00000000..a072e018
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Cookie.java
@@ -0,0 +1,30 @@
+package com.artifex.mupdf.fitz;
+
+public class Cookie
+{
+ // Private data
+ private long nativeCookie = 0;
+
+ // Construction
+ public Cookie()
+ {
+ nativeCookie = newNative();
+ }
+
+ private native long newNative();
+
+ // Operation
+ public native void abort();
+
+ //FIXME: Cookie accessors
+
+ // Destruction
+ protected native void finalize();
+
+ public void destroy()
+ {
+ finalize();
+ nativeCookie = 0;
+ }
+
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Device.java b/platform/android/src/com/artifex/mupdf/fitz/Device.java
new file mode 100644
index 00000000..366022e9
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Device.java
@@ -0,0 +1,172 @@
+package com.artifex.mupdf.fitz;
+
+public abstract class Device
+{
+ /* Flags */
+ public static final int FZ_DEVFLAG_MASK = 1;
+ public static final int FZ_DEVFLAG_COLOR = 2;
+ public static final int FZ_DEVFLAG_UNCACHEABLE = 4;
+ public static final int FZ_DEVFLAG_FILLCOLOR_UNDEFINED = 8;
+ public static final int FZ_DEVFLAG_STROKECOLOR_UNDEFINED = 16;
+ public static final int FZ_DEVFLAG_STARTCAP_UNDEFINED = 32;
+ public static final int FZ_DEVFLAG_DASHCAP_UNDEFINED = 64;
+ public static final int FZ_DEVFLAG_ENDCAP_UNDEFINED = 128;
+ public static final int FZ_DEVFLAG_LINEJOIN_UNDEFINED = 256;
+ public static final int FZ_DEVFLAG_MITERLIMIT_UNDEFINED = 512;
+ public static final int FZ_DEVFLAG_LINEWIDTH_UNDEFINED = 1024;
+
+ /* PDF 1.4 -- standard separable */
+ public static final int FZ_BLEND_NORMAL = 0;
+ public static final int FZ_BLEND_MULTIPLY = 1;
+ public static final int FZ_BLEND_SCREEN = 2;
+ public static final int FZ_BLEND_OVERLAY = 3;
+ public static final int FZ_BLEND_DARKEN = 4;
+ public static final int FZ_BLEND_LIGHTEN = 5;
+ public static final int FZ_BLEND_COLOR_DODGE = 6;
+ public static final int FZ_BLEND_COLOR_BURN = 7;
+ public static final int FZ_BLEND_HARD_LIGHT = 8;
+ public static final int FZ_BLEND_SOFT_LIGHT = 9;
+ public static final int FZ_BLEND_DIFFERENCE = 10;
+ public static final int FZ_BLEND_EXCLUSION = 11;
+
+ /* PDF 1.4 -- standard non-separable */
+ public static final int FZ_BLEND_HUE = 12;
+ public static final int FZ_BLEND_SATURATION = 13;
+ public static final int FZ_BLEND_COLOR = 14;
+ public static final int FZ_BLEND_LUMINOSITY = 15;
+
+ /* For packing purposes */
+ public static final int FZ_BLEND_MODEMASK = 15;
+ public static final int FZ_BLEND_ISOLATED = 16;
+ public static final int FZ_BLEND_KNOCKOUT = 32;
+
+ /* To implement your own device in Java, you should define your own
+ * class that extends this one, and override as many of the following
+ * functions as is appropriate. For example:
+ *
+ * class ImageTraceDevice extends Device
+ * {
+ * void fillImage(Image img, Matrix ctx, float alpha) {
+ * Debug.Log("Image!");
+ * }
+ * };
+ *
+ * There is no constructor here, as no one will ever construct a
+ * Device without subclassing.
+ */
+
+ /* Everything under here is private implementation details.
+ * Ideally we'd like to hide these from prying eyes, but Java doesn't
+ * allow that.
+ */
+
+ public static final int FZ_IGNORE_IMAGE = 1;
+ public static final int FZ_IGNORE_SHADE = 2;
+
+ /* None of our device functions do anything. Anyone interested will
+ * override them in a subclass either in Java, or (as a subclass of
+ * CDevice) in C.
+ */
+ public void beginPage(Rect rect, Matrix ctm)
+ {
+ }
+
+ public void endPage()
+ {
+ }
+
+ public void fillPath(Path path, int even_odd, Matrix ctm, ColorSpace cs, float color[], float alpha)
+ {
+ }
+
+ public void strokePath(long ctx, Path path, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha)
+ {
+ }
+
+ public void clipPath(Path path, Rect rect, int even_odd, Matrix ctm)
+ {
+ }
+
+ public void clipStrokePath(Path path, Rect rect, StrokeState stroke, Matrix ctm)
+ {
+ }
+
+ public void fillText(Text text, Matrix ctm, ColorSpace cs, float color[], float alpha)
+ {
+ }
+
+ public void strokeText(Text text, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha)
+ {
+ }
+
+ public void clipText(Text text, Matrix ctm)
+ {
+ }
+
+ public void clipStrokeText(Text text, StrokeState stroke, Matrix ctm)
+ {
+ }
+
+ public void ignoreText(Text text, Matrix ctm)
+ {
+ }
+
+ public void fillShade(Shade shade, Matrix ctm, float alpha)
+ {
+ }
+
+ public void fillImage(Image img, Matrix ctm, float alpha)
+ {
+ }
+
+ public void fillImageMask(Image img, Matrix ctm, ColorSpace cs, float color[], float alpha)
+ {
+ }
+
+ public void clipImageMask(Image img, Rect rect, Matrix ctm)
+ {
+ }
+
+ public void popClip()
+ {
+ }
+
+ public void beginMask(Rect rect, int luminosity, ColorSpace cs, float bc[])
+ {
+ }
+
+ public void endMask()
+ {
+ }
+
+ public void beginGroup(Rect rect, int isolated, int knockout, int blendmode, float alpha)
+ {
+ }
+
+ public void endGroup()
+ {
+ }
+
+ public int beginTile(Rect area, Rect view, float xstep, float ystep, Matrix ctm, int id)
+ {
+ return 0;
+ }
+
+ public void endTile()
+ {
+ }
+
+ /* An accessor for device hints */
+ final native int getHints();
+ final native void enableDeviceHints(int hints);
+ final native void disableDeviceHints(int hints);
+
+ // Destruction
+ public void destroy()
+ {
+ }
+
+ // Private data.
+ // All java devices MUST leave this as 0.
+ protected long nativeDevice;
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/DisplayList.java b/platform/android/src/com/artifex/mupdf/fitz/DisplayList.java
new file mode 100644
index 00000000..8a2515e4
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/DisplayList.java
@@ -0,0 +1,32 @@
+package com.artifex.mupdf.fitz;
+
+public class DisplayList
+{
+ // Private data
+ protected long nativeDisplayList;
+
+ // Constructions
+ public DisplayList()
+ {
+ nativeDisplayList = newNative();
+ }
+
+ private native long newNative();
+
+ // Operation
+ public native void run(Device device, Matrix ctm, Rect scissor, Cookie cookie);
+
+ public void run(Device device, Matrix ctm, Cookie cookie)
+ {
+ run(device, ctm, null, cookie);
+ }
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeDisplayList = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/DisplayListDevice.java b/platform/android/src/com/artifex/mupdf/fitz/DisplayListDevice.java
new file mode 100644
index 00000000..de3142dc
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/DisplayListDevice.java
@@ -0,0 +1,14 @@
+package com.artifex.mupdf.fitz;
+
+import android.graphics.Bitmap;
+
+public final class DisplayListDevice extends CDevice
+{
+ // Construction
+ public DisplayListDevice(DisplayList list)
+ {
+ nativeDevice = newNative(list);
+ }
+
+ private native long newNative(DisplayList list);
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Document.java b/platform/android/src/com/artifex/mupdf/fitz/Document.java
new file mode 100644
index 00000000..8c3136df
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Document.java
@@ -0,0 +1,60 @@
+package com.artifex.mupdf.fitz;
+
+import java.lang.ref.WeakReference;
+
+public class Document
+{
+ // Private data
+ private long nativeDocument = 0;
+
+ // Construction
+ public Document(String filename) throws Exception
+ {
+ nativeDocument = newNative(filename);
+ if (nativeDocument == 0)
+ throw(new Exception("Failed to load Document"));
+ }
+ private native final long newNative(String filename);
+
+ // FIXME: Should support opening java streams and from byte buffers etc.
+ // Streams would need to be seekable.
+ public Document(byte buffer[], String magic) throws Exception
+ {
+ nativeDocument = 0;//newFromBufferNative(buffer, magic);
+ if (nativeDocument == 0)
+ throw(new Exception("Failed to load Document"));
+ }
+ //private native final long newFromBufferNative(byte buffer[], String magic);
+
+ //public Document(SeekableStream stream, String magic) throws Exception
+ //{
+ // nativeDocument = newFromStreamNative(stream, magic);
+ // if (nativeDocument == 0)
+ // throw(new Exception("Failed to load Document"));
+ //}
+ //private native final long newFromBufferNative(SeekableStream stream, String magic);
+
+ // Operation
+ public native boolean needsPassword();
+
+ public native boolean authenticatePassword(String password);
+
+ public native int countPages();
+
+ public native Page getPage(int n);
+
+ public native String getFileFormat();
+
+ public native boolean isUnencryptedPDF();
+
+ public native Outline getOutline();
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeDocument = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Font.java b/platform/android/src/com/artifex/mupdf/fitz/Font.java
new file mode 100644
index 00000000..7630dfa5
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Font.java
@@ -0,0 +1,22 @@
+package com.artifex.mupdf.fitz;
+
+public class Font
+{
+ // Private data
+ private long nativeFont;
+
+ // Construction
+ private Font(long font)
+ {
+ nativeFont = font;
+ }
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeFont = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Image.java b/platform/android/src/com/artifex/mupdf/fitz/Image.java
new file mode 100644
index 00000000..a736ce5f
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Image.java
@@ -0,0 +1,56 @@
+package com.artifex.mupdf.fitz;
+import android.graphics.Bitmap;
+
+public class Image
+{
+ // Private data
+ private long nativeImage = 0;
+
+ // Construction
+ Image(Bitmap bm) throws Exception
+ {
+ if (bm == null)
+ throw new Exception("null Bitmap passed to Image");
+ nativeImage = newFromBitmapNative(bm, null);
+ }
+
+ Image(Bitmap bm, Image mask) throws Exception
+ {
+ if (bm == null)
+ throw new Exception("null Bitmap passed to Image");
+ nativeImage = newFromBitmapNative(bm, mask);
+ }
+
+ private native final long newFromBitmapNative(Bitmap bm, Image mask);
+
+ // Private constructor for the C to use. Any objects created by the
+ // C are done for purposes of calling back to a java device, and
+ // should therefore be considered const.
+ private Image(long l)
+ {
+ nativeImage = l;
+ }
+
+ // Accessors
+ public native int getWidth();
+ public native int getHeight();
+ public native int getNumComponents();
+ public native int getBitsPerComponent();
+ public native int getXResolution();
+ public native int getYResolution();
+ public native boolean getImageMask();
+ public native boolean getInterpolate();
+ public native Image getMask();
+
+ // FIXME: Get data back?
+ // FIXME: Create images from data or java streams?
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeImage = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Link.java b/platform/android/src/com/artifex/mupdf/fitz/Link.java
new file mode 100644
index 00000000..7c63fcf9
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Link.java
@@ -0,0 +1,27 @@
+package com.artifex.mupdf.fitz;
+
+public class Link
+{
+ // Private data
+ private long nativeLink = 0;
+
+ // Construction
+ private Link(long l)
+ {
+ nativeLink = l;
+ }
+
+ // Operation
+ public native Link getNext();
+
+ //FIXME: Accessors
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeLink = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Matrix.java b/platform/android/src/com/artifex/mupdf/fitz/Matrix.java
new file mode 100644
index 00000000..ede57ccc
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Matrix.java
@@ -0,0 +1,59 @@
+package com.artifex.mupdf.fitz;
+
+public class Matrix
+{
+ public float a;
+ public float b;
+ public float c;
+ public float d;
+ public float e;
+ public float f;
+
+ public Matrix(float a, float b, float c, float d, float e, float f)
+ {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.d = d;
+ this.e = e;
+ this.f = f;
+ }
+
+ public Matrix(float a, float d)
+ {
+ this.a = a;
+ this.b = 0;
+ this.c = 0;
+ this.d = d;
+ this.e = 0;
+ this.f = 0;
+ }
+
+ public Matrix(float a)
+ {
+ this.a = a;
+ this.b = 0;
+ this.c = 0;
+ this.d = a;
+ this.e = 0;
+ this.f = 0;
+ }
+
+ public Matrix concat(Matrix m)
+ {
+ float a = this.a * m.a + this.b * m.c;
+ float b = this.a * m.b + this.b * m.d;
+ float c = this.c * m.a + this.d * m.c;
+ float d = this.c * m.b + this.d * m.d;
+ float e = this.e * m.a + this.f * m.c + m.e;
+ this.f = this.e * m.b + this.f * m.d + m.f;
+
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.d = d;
+ this.e = e;
+
+ return this;
+ }
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Outline.java b/platform/android/src/com/artifex/mupdf/fitz/Outline.java
new file mode 100644
index 00000000..1b808d7f
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Outline.java
@@ -0,0 +1,22 @@
+package com.artifex.mupdf.fitz;
+
+public class Outline
+{
+ // Private data
+ private long nativeOutline = 0;
+
+ // Construction
+ private Outline(long out)
+ {
+ nativeOutline = out;
+ }
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeOutline = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Page.java b/platform/android/src/com/artifex/mupdf/fitz/Page.java
new file mode 100644
index 00000000..46d598ee
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Page.java
@@ -0,0 +1,37 @@
+package com.artifex.mupdf.fitz;
+
+public class Page
+{
+ // Private data
+ private long nativePage = 0;
+ private Annotation nativeAnnots[];
+
+ // Construction
+ private Page(long page)
+ {
+ nativePage = page;
+ nativeAnnots = null;
+ }
+
+ // Operation
+ public native Rect bound();
+ public native void run(Device dev, Matrix ctm, Cookie cookie);
+ public native void runPageContents(Device dev, Matrix ctm, Cookie cookie);
+ public native Annotation[] getAnnotations();
+
+ // FIXME: Later
+ public native Link[] getLinks();
+
+ // FIXME: Later. Much later.
+ //fz_transition *fz_page_presentation(fz_document *doc, fz_page *page, float *duration);
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativePage = 0;
+ nativeAnnots = null;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Path.java b/platform/android/src/com/artifex/mupdf/fitz/Path.java
new file mode 100644
index 00000000..17257f10
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Path.java
@@ -0,0 +1,82 @@
+package com.artifex.mupdf.fitz;
+
+public class Path implements PathProcessor
+{
+ // Private data
+ private long nativePath = 0;
+
+ // Construction
+ public Path()
+ {
+ nativePath = newNative();
+ }
+
+ private native long newNative();
+
+ private Path(long path)
+ {
+ nativePath = path;
+ }
+
+ public Path(Path old)
+ {
+ nativePath = clone(old);
+ }
+
+ private native long clone(Path old);
+
+ // Operation
+ public native Point currentPoint();
+
+ public void moveTo(Point xy)
+ {
+ moveTo(xy.x, xy.y);
+ }
+
+ public native void moveTo(float x, float y);
+
+ public void lineTo(Point xy)
+ {
+ lineTo(xy.x, xy.y);
+ }
+
+ public native void lineTo(float x, float y);
+
+ public void curveTo(Point c1, Point c2, Point e)
+ {
+ curveTo(c1.x, c1.y, c2.x, c2.y, e.x, e.y);
+ }
+
+ public native void curveTo(float cx1, float cy1, float cx2, float cy2, float ex, float ey);
+
+ public void curveToV(Point c, Point e)
+ {
+ curveToV(c.x, c.y, e.x, e.y);
+ }
+
+ public native void curveToV(float cx, float cy, float ex, float ey);
+
+ public void curveToY(Point c, Point e)
+ {
+ curveToY(c.x, c.y, e.x, e.y);
+ }
+
+ public native void curveToY(float cx, float cy, float ex, float ey);
+
+ public native void close();
+
+ public native void transform(Matrix mat);
+
+ public native Rect bound(StrokeState stroke, Matrix ctm);
+
+ public native void process(PathProcessor proc);
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativePath = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/PathProcessor.java b/platform/android/src/com/artifex/mupdf/fitz/PathProcessor.java
new file mode 100644
index 00000000..71d03c50
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/PathProcessor.java
@@ -0,0 +1,9 @@
+package com.artifex.mupdf.fitz;
+
+public interface PathProcessor
+{
+ public void moveTo(float x, float y);
+ public void lineTo(float x, float y);
+ public void curveTo(float cx1, float cy1, float cx2, float cy2, float ex, float ey);
+ public void close();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Point.java b/platform/android/src/com/artifex/mupdf/fitz/Point.java
new file mode 100644
index 00000000..08989dd7
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Point.java
@@ -0,0 +1,29 @@
+package com.artifex.mupdf.fitz;
+
+public class Point
+{
+ public float x;
+ public float y;
+
+ public Point(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public Point(Point p)
+ {
+ this.x = p.x;
+ this.y = p.y;
+ }
+
+ public Point transform(Matrix tm)
+ {
+ float old_x = this.x;
+
+ this.x = old_x * tm.a + y * tm.c + tm.e;
+ this.y = old_x * tm.b + y * tm.d + tm.f;
+
+ return this;
+ }
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Rect.java b/platform/android/src/com/artifex/mupdf/fitz/Rect.java
new file mode 100644
index 00000000..eb9138cf
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Rect.java
@@ -0,0 +1,79 @@
+package com.artifex.mupdf.fitz;
+
+public class Rect
+{
+ public float x0;
+ public float y0;
+ public float x1;
+ public float y1;
+
+ public Rect(float x0, float y0, float x1, float y1)
+ {
+ this.x0 = x0;
+ this.y0 = y0;
+ this.x1 = x1;
+ this.y1 = y1;
+ }
+
+ public Rect(Rect r)
+ {
+ this.x0 = r.x0;
+ this.y0 = r.y0;
+ this.x1 = r.x1;
+ this.y1 = r.y1;
+ }
+
+ public Rect transform(Matrix tm)
+ {
+ float ax0 = x0 * tm.a;
+ float ax1 = x1 * tm.a;
+
+ if (ax0 > ax1)
+ {
+ float t = ax0;
+ ax0 = ax1;
+ ax1 = t;
+ }
+
+ float cy0 = y0 * tm.c;
+ float cy1 = y1 * tm.c;
+
+ if (cy0 > cy1)
+ {
+ float t = cy0;
+ cy0 = cy1;
+ cy1 = t;
+ }
+ ax0 += cy0 + tm.e;
+ ax1 += cy1 + tm.e;
+
+ float bx0 = x0 * tm.b;
+ float bx1 = x1 * tm.b;
+
+ if (bx0 > bx1)
+ {
+ float t = bx0;
+ bx0 = bx1;
+ bx1 = t;
+ }
+
+ float dy0 = y0 * tm.d;
+ float dy1 = y1 * tm.d;
+
+ if (dy0 > dy1)
+ {
+ float t = dy0;
+ dy0 = dy1;
+ dy1 = t;
+ }
+ bx0 += dy0 + tm.f;
+ bx1 += dy1 + tm.f;
+
+ x0 = ax0;
+ x1 = ax1;
+ y0 = bx0;
+ y1 = bx1;
+
+ return this;
+ }
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/RectI.java b/platform/android/src/com/artifex/mupdf/fitz/RectI.java
new file mode 100644
index 00000000..1f91c778
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/RectI.java
@@ -0,0 +1,79 @@
+package com.artifex.mupdf.fitz;
+
+public class RectI
+{
+ public int x0;
+ public int y0;
+ public int x1;
+ public int y1;
+
+ public RectI(int x0, int y0, int x1, int y1)
+ {
+ this.x0 = x0;
+ this.y0 = y0;
+ this.x1 = x1;
+ this.y1 = y1;
+ }
+
+ public RectI(Rect r)
+ {
+ this.x0 = (int)Math.floor(r.x0);
+ this.y0 = (int)Math.ceil(r.y0);
+ this.x1 = (int)Math.floor(r.x1);
+ this.y1 = (int)Math.ceil(r.y1);
+ }
+
+ public RectI transform(Matrix tm)
+ {
+ float ax0 = x0 * tm.a;
+ float ax1 = x1 * tm.a;
+
+ if (ax0 > ax1)
+ {
+ float t = ax0;
+ ax0 = ax1;
+ ax1 = t;
+ }
+
+ float cy0 = y0 * tm.c;
+ float cy1 = y1 * tm.c;
+
+ if (cy0 > cy1)
+ {
+ float t = cy0;
+ cy0 = cy1;
+ cy1 = t;
+ }
+ ax0 += cy0 + tm.e;
+ ax1 += cy1 + tm.e;
+
+ float bx0 = x0 * tm.b;
+ float bx1 = x1 * tm.b;
+
+ if (bx0 > bx1)
+ {
+ float t = bx0;
+ bx0 = bx1;
+ bx1 = t;
+ }
+
+ float dy0 = y0 * tm.d;
+ float dy1 = y1 * tm.d;
+
+ if (dy0 > dy1)
+ {
+ float t = dy0;
+ dy0 = dy1;
+ dy1 = t;
+ }
+ bx0 += dy0 + tm.f;
+ bx1 += dy1 + tm.f;
+
+ x0 = (int)Math.floor(ax0);
+ x1 = (int)Math.ceil(ax1);
+ y0 = (int)Math.floor(bx0);
+ y1 = (int)Math.ceil(bx1);
+
+ return this;
+ }
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Shade.java b/platform/android/src/com/artifex/mupdf/fitz/Shade.java
new file mode 100644
index 00000000..bfadebc7
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Shade.java
@@ -0,0 +1,28 @@
+package com.artifex.mupdf.fitz;
+
+public class Shade
+{
+ // Private data
+ private long nativeShade = 0;
+
+ // Construction
+ // Private constructor for the C to use. Any objects created by the
+ // C are done for purposes of calling back to a java device, and
+ // should therefore be considered const.
+ private Shade(long l)
+ {
+ nativeShade = l;
+ }
+
+ // FIXME: Constructors for the different types of shade
+ // FIXME: Accessors for shade data
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeShade = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/StrokeState.java b/platform/android/src/com/artifex/mupdf/fitz/StrokeState.java
new file mode 100644
index 00000000..2f2fcf96
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/StrokeState.java
@@ -0,0 +1,64 @@
+package com.artifex.mupdf.fitz;
+
+import android.graphics.Rect;
+
+public class StrokeState
+{
+ public static final int FZ_LINECAP_BUTT = 0;
+ public static final int FZ_LINECAP_ROUND = 1;
+ public static final int FZ_LINECAP_SQUARE = 2;
+ public static final int FZ_LINECAP_TRIANGLE = 3;
+
+ public static final int FZ_LINEJOIN_MITER = 0;
+ public static final int FZ_LINEJOIN_ROUND = 1;
+ public static final int FZ_LINEJOIN_BEVEL = 2;
+ public static final int FZ_LINEJOIN_MITER_XPS = 3;
+
+ // Private data
+ private long nativeStroke;
+
+ // Construction
+ StrokeState(int startCap, int endCap, int lineJoin, float lineWidth, float miterLimit)
+ {
+ nativeStroke = newNative(startCap, 0, endCap, lineJoin, lineWidth, miterLimit, 0, null);
+ }
+
+ StrokeState(int startCap, int dashCap, int endCap, int lineJoin, float lineWidth, float miterLimit, float dashPhase, float dash[])
+ {
+ nativeStroke = newNative(startCap, dashCap, endCap, lineJoin, lineWidth, miterLimit, dashPhase, dash);
+ }
+
+ private native long newNative(int startCap, int dashCap, int endCap, int lineJoin, float lineWidth, float miterLimit, float dashPhase, float dash[]);
+
+ // Private constructor for the C to use. Any objects created by the
+ // C are done for purposes of calling back to a java device, and
+ // should therefore be considered const. This is fine as we don't
+ // currently provide mechanisms for changing individual elements
+ // of the StrokeState.
+ private StrokeState(long l)
+ {
+ nativeStroke = l;
+ }
+
+ // Operation
+ public native void adjustRectForStroke(Rect rect, Matrix ctm);
+
+ // Accessors
+ public native int getStartCap();
+ public native int getDashCap();
+ public native int getEndCap();
+ public native int getLineJoin();
+ public native float getLineWidth();
+ public native float getMiterLimit();
+ public native float getDashPhase();
+ public native float[] getDashes();
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeStroke = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/Text.java b/platform/android/src/com/artifex/mupdf/fitz/Text.java
new file mode 100644
index 00000000..eada4635
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/Text.java
@@ -0,0 +1,46 @@
+package com.artifex.mupdf.fitz;
+
+public class Text
+{
+ // Private data
+ private long nativeText = 0;
+ private boolean isConst = false;
+
+ // Cloning
+ public Text(Text old)
+ {
+ nativeText = cloneNative(old);
+ }
+
+ private native long cloneNative(Text old);
+
+ //public Text(Font font, Matrix trm, int wmode)
+ //{
+ // nativeText = newNative(font, trm, wmode);
+ //}
+
+ // Private method used for creating Text entries for a
+ // device implemented in java. These entries should be
+ // immutable.
+ private Text(long ptr)
+ {
+ nativeText = ptr;
+ isConst = true;
+ }
+
+ // Operation
+ public native Rect bound(StrokeState stroke, Matrix ctm);
+
+ //public native void add(int gid, int ucs, float x, float y);
+
+ // FIXME: Write accessors
+
+ // Destruction
+ public void destroy()
+ {
+ finalize();
+ nativeText = 0;
+ }
+
+ protected native void finalize();
+}
diff --git a/platform/android/src/com/artifex/mupdf/fitz/TryLaterException.java b/platform/android/src/com/artifex/mupdf/fitz/TryLaterException.java
new file mode 100644
index 00000000..644c6af1
--- /dev/null
+++ b/platform/android/src/com/artifex/mupdf/fitz/TryLaterException.java
@@ -0,0 +1,9 @@
+package com.artifex.mupdf.fitz;
+
+public class TryLaterException extends Exception
+{
+ TryLaterException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java b/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java
index de202b3c..da3c20cd 100644
--- a/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java
+++ b/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java
@@ -11,7 +11,9 @@ public class MuPDFCore
/* load our native library */
private static boolean gs_so_available = false;
static {
+ System.out.println("Loading dll");
System.loadLibrary("mupdf");
+ System.out.println("Loaded dll");
if (gprfSupportedInternal())
{
try {
diff --git a/platform/win32/jni.vcproj b/platform/win32/jni.vcproj
new file mode 100644
index 00000000..241fabb4
--- /dev/null
+++ b/platform/win32/jni.vcproj
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="jni"
+ ProjectGUID="{05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}"
+ RootNamespace="jni"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="java"
+ >
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\AndroidDrawDevice.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Annotation.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\AwtDrawDevice.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\CDevice.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\ColorSpace.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Context.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Cookie.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Device.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\DisplayList.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\DisplayListDevice.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Document.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\Font.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Image.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Link.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Matrix.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Outline.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Page.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Path.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\PathProcessor.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\Point.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\Rect.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\RectI.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Shade.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\StrokeState.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdf\fitz\Text.java"
+ >
+ </File>
+ <File
+ RelativePath="..\android\src\com\artifex\mupdf\fitz\TryLaterException.java"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="javaapp"
+ >
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\Annotation.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\ArrayDeque.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\AsyncTask.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\ChoosePDFActivity.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\ChoosePDFAdapter.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\ChoosePDFItem.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\Deque.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\FilePicker.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\LinkInfo.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\LinkInfoExternal.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\LinkInfoInternal.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\LinkInfoRemote.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\LinkInfoVisitor.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFActivity.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFAlert.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFAlertInternal.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFCore.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFPageAdapter.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFPageView.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFReaderView.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFReflowAdapter.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFReflowView.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\MuPDFView.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\OutlineActivity.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\OutlineActivityData.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\OutlineAdapter.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\OutlineItem.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\PageView.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\PrintDialogActivity.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\ReaderView.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\SafeAnimatorInflater.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\SearchTask.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\SearchTaskResult.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\TextChar.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\TextWord.java"
+ >
+ </File>
+ <File
+ RelativePath="..\..\platform\android\src\com\artifex\mupdfdemo\WidgetType.java"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\platform\android\jni\mupdf.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\platform\android\jni\mupdf_native.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/platform/win32/mupdf.sln b/platform/win32/mupdf.sln
index b614da1b..8894689d 100644
--- a/platform/win32/mupdf.sln
+++ b/platform/win32/mupdf.sln
@@ -52,6 +52,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdf-gl", "mupdf-gl.vcproj
{5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jni", "jni.vcproj", "{05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -286,6 +288,21 @@ Global
{CE3A76A8-A28F-4991-8FB9-C9453D922037}.ReleaseOpenssl|Win32.Build.0 = Release|Win32
{CE3A76A8-A28F-4991-8FB9-C9453D922037}.ReleaseOpenssl|x64.ActiveCfg = Release|x64
{CE3A76A8-A28F-4991-8FB9-C9453D922037}.ReleaseOpenssl|x64.Build.0 = Release|x64
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Debug|Win32.ActiveCfg = Debug|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Debug|Win32.Build.0 = Debug|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Debug|x64.ActiveCfg = Debug|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.DebugOpenssl|Win32.ActiveCfg = Debug|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.DebugOpenssl|Win32.Build.0 = Debug|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.DebugOpenssl|x64.ActiveCfg = Debug|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Memento|Win32.ActiveCfg = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Memento|Win32.Build.0 = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Memento|x64.ActiveCfg = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Release|Win32.ActiveCfg = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Release|Win32.Build.0 = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.Release|x64.ActiveCfg = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.ReleaseOpenssl|Win32.ActiveCfg = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.ReleaseOpenssl|Win32.Build.0 = Release|Win32
+ {05A1CA5B-9807-4B3A-9954-EFAB8ADE7757}.ReleaseOpenssl|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE