summaryrefslogtreecommitdiff
path: root/demos
diff options
context:
space:
mode:
authorEthan Vrhel <ethanvrhel@gmail.com>2021-10-29 16:33:51 -0700
committerEthan Vrhel <ethanvrhel@gmail.com>2021-10-29 16:33:51 -0700
commitff1882c1e0915d2aad7689ba3c20adb3de64188e (patch)
tree2543bbc23c8840e201c6a93251920643d1ac7964 /demos
parentf609e5b7fce017cbafcbaa6c4a2651e287e5ddcb (diff)
downloadghostpdl-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.java21
-rw-r--r--demos/java/jni/gs_jni/callbacks.cpp313
-rw-r--r--demos/java/jni/gs_jni/callbacks.h34
-rw-r--r--demos/java/mtdemo/Main.java27
-rw-r--r--demos/java/mtdemo/Worker.java113
-rw-r--r--demos/java/mtdemo/build.bat5
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