diff options
author | Ethan Vrhel <ethanvrhel@gmail.com> | 2021-10-29 16:33:51 -0700 |
---|---|---|
committer | Ethan Vrhel <ethanvrhel@gmail.com> | 2021-10-29 16:33:51 -0700 |
commit | ff1882c1e0915d2aad7689ba3c20adb3de64188e (patch) | |
tree | 2543bbc23c8840e201c6a93251920643d1ac7964 /demos | |
parent | f609e5b7fce017cbafcbaa6c4a2651e287e5ddcb (diff) | |
download | ghostpdl-ff1882c1e0915d2aad7689ba3c20adb3de64188e.tar.gz |
Making gsjava work with multiple Ghostscript instances
Diffstat (limited to 'demos')
-rw-r--r-- | demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java | 21 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/callbacks.cpp | 313 | ||||
-rw-r--r-- | demos/java/jni/gs_jni/callbacks.h | 34 | ||||
-rw-r--r-- | demos/java/mtdemo/Main.java | 27 | ||||
-rw-r--r-- | demos/java/mtdemo/Worker.java | 113 | ||||
-rw-r--r-- | demos/java/mtdemo/build.bat | 5 |
6 files changed, 363 insertions, 150 deletions
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java b/demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java index e5e713c71..0059e2cca 100644 --- a/demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java +++ b/demos/java/gsjava/src/com/artifex/gsjava/GSInstance.java @@ -75,13 +75,22 @@ public class GSInstance implements Iterable<GSInstance.GSParam<?>> { } } - private static volatile boolean instanceExists = false; + private static boolean ALLOW_MULTITHREADING = false; + private static volatile int INSTANCES = 0; + + public static void setAllowMultithreading(boolean state) { + ALLOW_MULTITHREADING = state; + } + + public static int getInstanceCount() { + return INSTANCES; + } private long instance; private long callerHandle; public GSInstance(long callerHandle) throws IllegalStateException { - if (instanceExists) + if (!ALLOW_MULTITHREADING && INSTANCES > 0) throw new IllegalStateException("An instance already exists"); Reference<Long> ref = new Reference<>(); int ret = gsapi_new_instance(ref, callerHandle); @@ -89,7 +98,7 @@ public class GSInstance implements Iterable<GSInstance.GSParam<?>> { throw new IllegalStateException("Failed to create new instance: " + ret); this.instance = ref.getValue(); this.callerHandle = callerHandle; - instanceExists = true; + INSTANCES++; } public GSInstance() throws IllegalStateException { @@ -99,8 +108,10 @@ public class GSInstance implements Iterable<GSInstance.GSParam<?>> { public void delete_instance() { if (instance != GS_NULL) gsapi_delete_instance(instance); - instance = GS_NULL; - instanceExists = false; + if (instance != GS_NULL) { + instance = GS_NULL; + INSTANCES--; + } } public int set_stdio(IStdInFunction stdin, IStdOutFunction stdout, IStdErrFunction stderr) { diff --git a/demos/java/jni/gs_jni/callbacks.cpp b/demos/java/jni/gs_jni/callbacks.cpp index 7826b3289..f54678318 100644 --- a/demos/java/jni/gs_jni/callbacks.cpp +++ b/demos/java/jni/gs_jni/callbacks.cpp @@ -3,6 +3,7 @@ #include "jni_util.h" #include <string.h> +#include <unordered_map> #define STDIN_SIG "(J[BI)I" #define STDOUT_SIG "(J[BI)I" @@ -31,50 +32,73 @@ Lcom/artifex/gsjava/IntReference;)I" using namespace util; -static JNIEnv *g_env = NULL; +class GSInstanceData +{ +public: + JNIEnv *env; + + jobject stdIn = NULL; + jobject stdOut = NULL; + jobject stdErr = NULL; + + jobject poll = NULL; -static jobject g_stdIn = NULL; -static jobject g_stdOut = NULL; -static jobject g_stdErr = NULL; + jobject displayCallback = NULL; -static jobject g_poll = NULL; + jobject callout = NULL; +}; + +static std::unordered_map<void *, GSInstanceData> g_instanceData; + +static inline GSInstanceData *getInstanceData(void *instance) +{ + GSInstanceData *gsdata; -static jobject g_displayCallback = NULL; + auto it = g_instanceData.find(instance); + if (it == g_instanceData.end()) + gsdata = &(g_instanceData[instance] = GSInstanceData()); + else + gsdata = &it->second; -static jobject g_callout = NULL; + return gsdata; +} -void callbacks::setJNIEnv(JNIEnv *env) +void callbacks::setJNIEnv(void *instance, JNIEnv *env) { - g_env = env; + GSInstanceData *gsdata = getInstanceData(instance); + gsdata->env = env; } -void callbacks::setIOCallbacks(jobject stdIn, jobject stdOut, jobject stdErr) +void callbacks::setIOCallbacks(void *instance, jobject stdIn, jobject stdOut, jobject stdErr) { - if (g_env) + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env) { - if (g_stdIn) - g_env->DeleteGlobalRef(g_stdIn); + if (gsdata->stdIn) + gsdata->env->DeleteGlobalRef(gsdata->stdIn); - if (g_stdOut) - g_env->DeleteGlobalRef(g_stdOut); + if (gsdata->stdOut) + gsdata->env->DeleteGlobalRef(gsdata->stdOut); - if (g_stdErr) - g_env->DeleteGlobalRef(g_stdErr); + if (gsdata->stdErr) + gsdata->env->DeleteGlobalRef(gsdata->stdErr); - g_stdIn = g_env->NewGlobalRef(stdIn); - g_stdOut = g_env->NewGlobalRef(stdOut); - g_stdErr = g_env->NewGlobalRef(stdErr); + gsdata->stdIn = gsdata->env->NewGlobalRef(stdIn); + gsdata->stdOut = gsdata->env->NewGlobalRef(stdOut); + gsdata->stdErr = gsdata->env->NewGlobalRef(stdErr); } } int callbacks::stdInFunction(void *callerHandle, char *buf, int len) { int code = 0; - if (g_env && g_stdIn) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->stdIn) { - jbyteArray byteArray = g_env->NewByteArray(len); - g_env->SetByteArrayRegion(byteArray, 0, len, (jbyte *)buf); - code = callIntMethod(g_env, g_stdIn, "onStdIn", STDIN_SIG, (jlong)callerHandle, byteArray, (jint)len); + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (jbyte *)buf); + code = callIntMethod(gsdata->env, gsdata->stdIn, "onStdIn", STDIN_SIG, (jlong)callerHandle, byteArray, (jint)len); } return code; } @@ -82,11 +106,13 @@ int callbacks::stdInFunction(void *callerHandle, char *buf, int len) int callbacks::stdOutFunction(void *callerHandle, const char *str, int len) { int code = 0; - if (g_env && g_stdOut) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->stdOut) { - jbyteArray byteArray = g_env->NewByteArray(len); - g_env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); - code = callIntMethod(g_env, g_stdOut, "onStdOut", STDOUT_SIG, (jlong)callerHandle, byteArray, (jint)len); + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); + code = callIntMethod(gsdata->env, gsdata->stdOut, "onStdOut", STDOUT_SIG, (jlong)callerHandle, byteArray, (jint)len); } return code; } @@ -94,262 +120,293 @@ int callbacks::stdOutFunction(void *callerHandle, const char *str, int len) int callbacks::stdErrFunction(void *callerHandle, const char *str, int len) { int code = 0; - if (g_env && g_stdErr) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->stdErr) { - jbyteArray byteArray = g_env->NewByteArray(len); - g_env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); - code = callIntMethod(g_env, g_stdErr, "onStdErr", STDERR_SIG, (jlong)callerHandle, byteArray, (jint)len); + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)str); + code = callIntMethod(gsdata->env, gsdata->stdErr, "onStdErr", STDERR_SIG, (jlong)callerHandle, byteArray, (jint)len); } return code; } -void callbacks::setPollCallback(jobject poll) +void callbacks::setPollCallback(void *instance, jobject poll) { - if (g_env) + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env) { - if (g_poll) - g_env->DeleteGlobalRef(g_poll); + if (gsdata->poll) + gsdata->env->DeleteGlobalRef(gsdata->poll); - g_poll = g_env->NewGlobalRef(poll); + gsdata->poll = gsdata->env->NewGlobalRef(poll); } } -int callbacks::pollFunction(void *callerHandle) +int callbacks::pollFunction(void *instance, void *callerHandle) { int code = 0; - if (g_env && g_poll) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->poll) { - code = callIntMethod(g_env, g_poll, "onPoll", POLL_SIG, (jlong)callerHandle); + code = callIntMethod(gsdata->env, gsdata->poll, "onPoll", POLL_SIG, (jlong)callerHandle); } return code; } -void callbacks::setDisplayCallback(jobject displayCallback) +void callbacks::setDisplayCallback(void *instance, jobject displayCallback) { - if (g_env) + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env) { - if (g_displayCallback) + if (gsdata->displayCallback) { - g_env->DeleteGlobalRef(g_displayCallback); - g_displayCallback = NULL; + gsdata->env->DeleteGlobalRef(gsdata->displayCallback); + gsdata->displayCallback = NULL; } - g_displayCallback = g_env->NewGlobalRef(displayCallback); + gsdata->displayCallback = gsdata->env->NewGlobalRef(displayCallback); //g_displayCallback = displayCallback; } } -void callbacks::setCalloutCallback(jobject callout) +void callbacks::setCalloutCallback(void *instance, jobject callout) { - if (g_env) + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env) { - if (g_callout) - g_env->DeleteGlobalRef(g_callout); + if (gsdata->callout) + gsdata->env->DeleteGlobalRef(gsdata->callout); - g_callout = g_env->NewGlobalRef(callout); + gsdata->callout = gsdata->env->NewGlobalRef(callout); } } int callbacks::calloutFunction(void *instance, void *handle, const char *deviceName, int id, int size, void *data) { int code = 0; - if (g_env && g_callout) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->callout) { jsize len = strlen(deviceName); - jbyteArray array = g_env->NewByteArray(len); - g_env->SetByteArrayRegion(array, 0, len, (const jbyte *)deviceName); - code = callIntMethod(g_env, g_callout, "onCallout", "(JJ[BIIJ)I", (jlong)instance, (jlong)handle, array, id, size, (jlong)data); + jbyteArray array = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(array, 0, len, (const jbyte *)deviceName); + code = callIntMethod(gsdata->env, gsdata->callout, "onCallout", "(JJ[BIIJ)I", (jlong)instance, (jlong)handle, array, id, size, (jlong)data); } return code; } -int callbacks::display::displayOpenFunction(void *handle, void *device) +int callbacks::display::displayOpenFunction(void *instance, void *handle, void *device) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - jclass clazz = g_env->GetObjectClass(g_displayCallback); - const char *name = getClassName(g_env, clazz); + jclass clazz = gsdata->env->GetObjectClass(gsdata->displayCallback); + const char *name = getClassName(gsdata->env, clazz); freeClassName(name); - code = callIntMethod(g_env, g_displayCallback, "onDisplayOpen", DISPLAY_OPEN_SIG, (jlong)handle, (jlong)device); - CHECK_AND_RETURN(g_env); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayOpen", DISPLAY_OPEN_SIG, (jlong)handle, (jlong)device); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displayPrecloseFunction(void *handle, void *device) +int callbacks::display::displayPrecloseFunction(void *instance, void *handle, void *device) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(g_env, g_displayCallback, "onDisplayPreclose", DISPLAY_PRECLOSE_SIG, (jlong)handle, (jlong)device); - CHECK_AND_RETURN(g_env); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPreclose", DISPLAY_PRECLOSE_SIG, (jlong)handle, (jlong)device); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displayCloseFunction(void *handle, void *device) +int callbacks::display::displayCloseFunction(void *instance, void *handle, void *device) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(g_env, g_displayCallback, "onDisplayClose", DISPLAY_CLOSE_SIG, (jlong)handle, (jlong)device); - CHECK_AND_RETURN(g_env); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayClose", DISPLAY_CLOSE_SIG, (jlong)handle, (jlong)device); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displayPresizeFunction(void *handle, void *device, int width, int height, int raster, unsigned int format) +int callbacks::display::displayPresizeFunction(void *instance, void *handle, void *device, int width, int height, int raster, unsigned int format) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(g_env, g_displayCallback, "onDisplayPresize", DISPLAY_PRESIZE_SIG, (jlong)handle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPresize", DISPLAY_PRESIZE_SIG, (jlong)handle, (jlong)device, width, height, raster, (jint)format); - CHECK_AND_RETURN(g_env); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displaySizeFunction(void *handle, void *device, int width, int height, int raster, +int callbacks::display::displaySizeFunction(void *instance, void *handle, void *device, int width, int height, int raster, unsigned int format, unsigned char *pimage) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { jsize len = height * raster; - jbyteArray byteArray = g_env->NewByteArray(len); - g_env->SetByteArrayRegion(byteArray, 0, len, (signed char *)pimage); + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (signed char *)pimage); static const char *const bytePointerClassName = "com/artifex/gsjava/util/BytePointer"; static const char *const nativePointerClassName = "com/artifex/gsjava/util/NativePointer"; - jclass bytePointerClass = g_env->FindClass(bytePointerClassName); + jclass bytePointerClass = gsdata->env->FindClass(bytePointerClassName); if (bytePointerClass == NULL) { - throwNoClassDefError(g_env, bytePointerClassName); + throwNoClassDefError(gsdata->env, bytePointerClassName); return -21; } - jclass nativePointerClass = g_env->FindClass(nativePointerClassName); + jclass nativePointerClass = gsdata->env->FindClass(nativePointerClassName); if (nativePointerClass == NULL) { - throwNoClassDefError(g_env, nativePointerClassName); + throwNoClassDefError(gsdata->env, nativePointerClassName); return -21; } - jmethodID constructor = g_env->GetMethodID(bytePointerClass, "<init>", "()V"); + jmethodID constructor = gsdata->env->GetMethodID(bytePointerClass, "<init>", "()V"); if (constructor == NULL) { - throwNoSuchMethodError(g_env, "com.artifex.gsjava.util.BytePointer.<init>()V"); + throwNoSuchMethodError(gsdata->env, "com.artifex.gsjava.util.BytePointer.<init>()V"); return -21; } - jobject bytePointer = g_env->NewObject(bytePointerClass, constructor); + jobject bytePointer = gsdata->env->NewObject(bytePointerClass, constructor); - jfieldID dataPtrID = g_env->GetFieldID(nativePointerClass, "address", "J"); + jfieldID dataPtrID = gsdata->env->GetFieldID(nativePointerClass, "address", "J"); if (dataPtrID == NULL) { - throwNoSuchFieldError(g_env, "address"); + throwNoSuchFieldError(gsdata->env, "address"); return -21; } - jfieldID lengthID = g_env->GetFieldID(bytePointerClass, "length", "J"); + jfieldID lengthID = gsdata->env->GetFieldID(bytePointerClass, "length", "J"); if (lengthID == NULL) { - throwNoSuchFieldError(g_env, "length"); + throwNoSuchFieldError(gsdata->env, "length"); return -21; } - g_env->SetLongField(bytePointer, dataPtrID, (jlong)pimage); - g_env->SetLongField(bytePointer, lengthID, len); + gsdata->env->SetLongField(bytePointer, dataPtrID, (jlong)pimage); + gsdata->env->SetLongField(bytePointer, lengthID, len); - code = callIntMethod(g_env, g_displayCallback, "onDisplaySize", DISPLAY_SIZE_SIG, (jlong)handle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySize", DISPLAY_SIZE_SIG, (jlong)handle, (jlong)device, width, height, raster, (jint)format, bytePointer); - CHECK_AND_RETURN(g_env); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displaySyncFunction(void *handle, void *device) +int callbacks::display::displaySyncFunction(void *instance, void *handle, void *device) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(g_env, g_displayCallback, "onDisplaySync", DISPLAY_SYNC_SIG, (jlong)handle, (jlong)device); - CHECK_AND_RETURN(g_env); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySync", DISPLAY_SYNC_SIG, (jlong)handle, (jlong)device); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displayPageFunction(void *handle, void *device, int copies, int flush) +int callbacks::display::displayPageFunction(void *instance, void *handle, void *device, int copies, int flush) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(g_env, g_displayCallback, "onDisplayPage", DISPLAY_PAGE_SIG, (jlong)handle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPage", DISPLAY_PAGE_SIG, (jlong)handle, (jlong)device, copies, flush); - CHECK_AND_RETURN(g_env); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displayUpdateFunction(void *handle, void *device, int x, int y, int w, int h) +int callbacks::display::displayUpdateFunction(void *instance, void *handle, void *device, int x, int y, int w, int h) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(g_env, g_displayCallback, "onDisplayUpdate", DISPLAY_UPDATE_SIG, (jlong)handle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayUpdate", DISPLAY_UPDATE_SIG, (jlong)handle, (jlong)device, x, y, w, h); - CHECK_AND_RETURN(g_env); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displaySeparationFunction(void *handle, void *device, int component, const char *componentName, +int callbacks::display::displaySeparationFunction(void *instance, void *handle, void *device, int component, const char *componentName, unsigned short c, unsigned short m, unsigned short y, unsigned short k) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { jsize len = strlen(componentName); - jbyteArray byteArray = g_env->NewByteArray(len); - g_env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)componentName); - code = callIntMethod(g_env, g_displayCallback, "onDisplaySeparation", DISPLAY_SEPARATION_SIG, (jlong)handle, + jbyteArray byteArray = gsdata->env->NewByteArray(len); + gsdata->env->SetByteArrayRegion(byteArray, 0, len, (const jbyte *)componentName); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySeparation", DISPLAY_SEPARATION_SIG, (jlong)handle, (jlong)device, component, byteArray, c, m, y, k); - CHECK_AND_RETURN(g_env); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displayAdjustBandHeightFunction(void *handle, void *device, int bandHeight) +int callbacks::display::displayAdjustBandHeightFunction(void *instance, void *handle, void *device, int bandHeight) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(g_env, g_displayCallback, "onDisplayAdjustBandHeght", DISPLAY_ADJUST_BAND_HEIGHT_SIG, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayAdjustBandHeght", DISPLAY_ADJUST_BAND_HEIGHT_SIG, (jlong)handle, (jlong)device, bandHeight); - CHECK_AND_RETURN(g_env); + CHECK_AND_RETURN(gsdata->env); } return code; } -int callbacks::display::displayRectangleRequestFunction(void *handle, void *device, void **memory, int *ox, int *oy, +int callbacks::display::displayRectangleRequestFunction(void *instance, void *handle, void *device, void **memory, int *ox, int *oy, int *raster, int *plane_raster, int *x, int *y, int *w, int *h) { int code = 0; - if (g_env && g_displayCallback) + + GSInstanceData *gsdata = getInstanceData(instance); + if (gsdata->env && gsdata->displayCallback) { - Reference memoryRef = Reference(g_env, toWrapperType(g_env, (jlong)*memory)); - Reference oxRef = Reference(g_env, toWrapperType(g_env, (jint)*ox)); - Reference oyRef = Reference(g_env, toWrapperType(g_env, (jint)*oy)); - Reference rasterRef = Reference(g_env, toWrapperType(g_env, (jint)*raster)); - Reference planeRasterRef = Reference(g_env, toWrapperType(g_env, (jint)*plane_raster)); - Reference xRef = Reference(g_env, toWrapperType(g_env, (jint)*x)); - Reference yRef = Reference(g_env, toWrapperType(g_env, (jint)*y)); - Reference wRef = Reference(g_env, toWrapperType(g_env, (jint)*w)); - Reference hRef = Reference(g_env, toWrapperType(g_env, (jint)*h)); - - code = callIntMethod(g_env, g_displayCallback, "onDisplayRectangleRequest", DISPLAY_RECTANGLE_REQUEST, + Reference memoryRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jlong)*memory)); + Reference oxRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*ox)); + Reference oyRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*oy)); + Reference rasterRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*raster)); + Reference planeRasterRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*plane_raster)); + Reference xRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*x)); + Reference yRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*y)); + Reference wRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*w)); + Reference hRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*h)); + + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayRectangleRequest", DISPLAY_RECTANGLE_REQUEST, (jlong)handle, (jlong)device, memoryRef.object(), @@ -373,7 +430,7 @@ int callbacks::display::displayRectangleRequestFunction(void *handle, void *devi *w = wRef.intValue(); *h = hRef.intValue(); - CHECK_AND_RETURN(g_env); + CHECK_AND_RETURN(gsdata->env); } return code; } diff --git a/demos/java/jni/gs_jni/callbacks.h b/demos/java/jni/gs_jni/callbacks.h index 55508f2b2..93a3c5f3f 100644 --- a/demos/java/jni/gs_jni/callbacks.h +++ b/demos/java/jni/gs_jni/callbacks.h @@ -10,45 +10,45 @@ namespace callbacks @param env A JNIEnv. */ - void setJNIEnv(JNIEnv *env); + void setJNIEnv(void *instance, JNIEnv *env); - void setIOCallbacks(jobject stdIn, jobject stdOut, jobject stdErr); + void setIOCallbacks(void *instance, jobject stdIn, jobject stdOut, jobject stdErr); int stdInFunction(void *callerHandle, char *buf, int len); int stdOutFunction(void *callerHandle, const char *str, int len); int stdErrFunction(void *callerHandle, const char *str, int len); - void setPollCallback(jobject poll); - int pollFunction(void *callerHandle); + void setPollCallback(void *instance, jobject poll); + int pollFunction(void *instance, void *callerHandle); - void setDisplayCallback(jobject displayCallback); + void setDisplayCallback(void *instance, jobject displayCallback); namespace display { - int displayOpenFunction(void *handle, void *device); - int displayPrecloseFunction(void *handle, void *device); - int displayCloseFunction(void *handle, void *device); - int displayPresizeFunction(void *handle, void *device, int width, + int displayOpenFunction(void *instance, void *handle, void *device); + int displayPrecloseFunction(void *instance, void *handle, void *device); + int displayCloseFunction(void *instance, void *handle, void *device); + int displayPresizeFunction(void *instance, void *handle, void *device, int width, int height, int raster, unsigned int format); - int displaySizeFunction(void *handle, void *device, int width, + int displaySizeFunction(void *instance, void *handle, void *device, int width, int height, int raster, unsigned int format, unsigned char *pimage); - int displaySyncFunction(void *handle, void *device); - int displayPageFunction(void *handle, void *device, int copies, + int displaySyncFunction(void *instance, void *handle, void *device); + int displayPageFunction(void *instance, void *handle, void *device, int copies, int flush); - int displayUpdateFunction(void *handle, void *device, int x, + int displayUpdateFunction(void *instance, void *handle, void *device, int x, int y, int w, int h); // display_memalloc omitted // display_memfree omitted - int displaySeparationFunction(void *handle, void *device, + int displaySeparationFunction(void *instance, void *handle, void *device, int component, const char *componentName, unsigned short c, unsigned short m, unsigned short y, unsigned short k); - int displayAdjustBandHeightFunction(void *handle, void *device, + int displayAdjustBandHeightFunction(void *instance, void *handle, void *device, int bandHeight); - int displayRectangleRequestFunction(void *handle, void *device, + int displayRectangleRequestFunction(void *instance, void *handle, void *device, void **memory, int *ox, int *oy, int *raster, int *plane_raster, int *x, int *y, int *w, int *h); } - void setCalloutCallback(jobject calout); + void setCalloutCallback(void *instance, jobject calout); int calloutFunction(void *instance, void *handle, const char *deviceName, int id, int size, void *data); }
\ No newline at end of file diff --git a/demos/java/mtdemo/Main.java b/demos/java/mtdemo/Main.java new file mode 100644 index 000000000..a8c2232a6 --- /dev/null +++ b/demos/java/mtdemo/Main.java @@ -0,0 +1,27 @@ +import com.artifex.gsjava.GSInstance; + +public class Main { + + public static void main(String[] args) { + GSInstance.setAllowMultithreading(true); + + int workerCount = 10; + if (args.length > 0) { + try { + workerCount = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { } + } + + Worker[] workers = new Worker[workerCount]; + + for (int i = 0; i < workers.length; i++) { + workers[i] = new Worker("../../../examples/tiger.eps", "pdfout/out" + i + ".pdf"); + } + + System.out.println("Starting workers..."); + for (int i = 0; i < workers.length; i++) { + workers[i].start(); + } + System.out.println("Workers dispatched"); + } +}
\ No newline at end of file diff --git a/demos/java/mtdemo/Worker.java b/demos/java/mtdemo/Worker.java new file mode 100644 index 000000000..c6ed6f44a --- /dev/null +++ b/demos/java/mtdemo/Worker.java @@ -0,0 +1,113 @@ +import java.io.File; + +import com.artifex.gsjava.GSInstance; +import com.artifex.gsjava.callbacks.DisplayCallback; +import com.artifex.gsjava.util.*; +import com.artifex.gsjava.callbacks.*; + +import java.io.IOException; + +import static com.artifex.gsjava.GSAPI.*; + +public class Worker implements Runnable { + + public static final boolean USE_STDOUT = false; + + private static int ID = 0; + + private final File inPS, outPDF; + private final Thread thread; + + /** + * Create a worker thread to convert a postscript file + * to a pdf file. + * + * @param inPS The postscript file. + * @param outPDF The output PDF file. + */ + public Worker(String inPS, String outPDF) { + this.inPS = new File(inPS); + this.outPDF = new File(outPDF); + this.thread = new Thread(this); + this.thread.setName("Worker-" + ID++); + } + + public void start() { + System.out.println("Start: " + thread.getName()); + thread.start(); + } + + @Override + public void run() { + System.out.println("Started worker: " + thread.getName()); + + GSInstance gsInstance = null; + try { + gsInstance = createGSInstance(); + + StdIO io = new StdIO(); + gsInstance.set_stdio(io, null, null); + + if (!outPDF.exists()) + outPDF.createNewFile(); + + final int FORMAT = GS_COLORS_RGB | GS_DISPLAY_DEPTH_8 | GS_DISPLAY_BIGENDIAN; + String[] args = { + "gs", + "-sDEVICE=pdfwrite", + //"dFirstPage=1", + //"dDisplayFormat=" + FORMAT, + "-o", outPDF.getAbsolutePath(), + "-f", inPS.getAbsolutePath() + }; + + int code = gsInstance.init_with_args(args); + if (code != GS_ERROR_OK) { + gsInstance.delete_instance(); + throw new IllegalStateException("Failed to init with args (code = " + code + ")"); + } + + System.out.println("Worker " + thread.getName() + " completed."); + } catch (Exception e) { + System.err.println("Worker " + thread.getName() + " threw exception: " + e); + } finally { + if (gsInstance != null) + gsInstance.delete_instance(); + } + } + + private GSInstance createGSInstance() { + GSInstance gsInstance = new GSInstance(); + + int code; + code = gsInstance.set_arg_encoding(1); + if (code != GS_ERROR_OK) { + gsInstance.delete_instance(); + throw new IllegalStateException("Failed to set arg encoding (code = " + code + ")"); + } + + return gsInstance; + } + + private static class StdIO implements IStdOutFunction, IStdErrFunction, IStdInFunction { + + public int onStdOut(long callerHandle, byte[] str, int len) { + //if (USE_STDOUT) + System.out.println(new String(str)); + return len; + } + + public int onStdErr(long callerHandle, byte[] str, int len) { + System.err.println(new String(str)); + return len; + } + + public int onStdIn(long callerHandle, byte[] buf, int len) { + try { + return System.in.read(buf, 0, len); + } catch (IOException e) { + return 0; + } + } + } +}
\ No newline at end of file diff --git a/demos/java/mtdemo/build.bat b/demos/java/mtdemo/build.bat new file mode 100644 index 000000000..5dd5f34b8 --- /dev/null +++ b/demos/java/mtdemo/build.bat @@ -0,0 +1,5 @@ +@echo off + +echo Build... +javac -cp ../gsjava/bin;. Main.java Worker.java +echo Done.
\ No newline at end of file |