From 7db1ae4245a2ec37ae256f11b96e50ebb2dc9f45 Mon Sep 17 00:00:00 2001 From: Ethan Vrhel Date: Fri, 12 Nov 2021 15:45:55 -0800 Subject: Fixed an assertion failure in display callbacks --- demos/java/README.txt | 9 ++++ demos/java/jni/gs_jni/build_darwin.sh | 11 +++++ demos/java/jni/gs_jni/callbacks.cpp | 24 +++++----- demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp | 54 +++++++++++++++++++++- demos/java/jni/gs_jni/instance_data.h | 3 ++ 5 files changed, 89 insertions(+), 12 deletions(-) (limited to 'demos') diff --git a/demos/java/README.txt b/demos/java/README.txt index 4781bb099..3e94a920c 100644 --- a/demos/java/README.txt +++ b/demos/java/README.txt @@ -6,3 +6,12 @@ variable. This exposes command line programs to build Java applications. On Linux and Mac, OpenJDK 8 is used. + +What's in this directory: + +./gsjava The Java project which provides the bindings to Ghostscript. +./gstest An old project used for testing gsjava +./gsviewer A demo Java PDF viewer made using the Java bindings +./jni Contains the C++ project which backs the Java bindings to Ghostscript +./mtdemo A demo project used to demonstrate how multithreading can be used with + the Java bindings \ No newline at end of file diff --git a/demos/java/jni/gs_jni/build_darwin.sh b/demos/java/jni/gs_jni/build_darwin.sh index 81b10c019..18e12caeb 100644 --- a/demos/java/jni/gs_jni/build_darwin.sh +++ b/demos/java/jni/gs_jni/build_darwin.sh @@ -46,6 +46,16 @@ g++ -c -Wall -O3 -fPIC \ "jni_util.cpp" \ -o "obin/jni_util.o" +echo "Compile instance_data.cpp" +g++ -c -Wall -O3 -fPIC \ + -std=c++14 \ + -I./include \ + -I./include/darwin \ + -I./../../../../psi \ + -I./../../../../devices \ + "instance_data.cpp" \ + -o "obin/instance_data.o" + echo "Link" g++ -dynamiclib -fPIC \ -Wl \ @@ -54,4 +64,5 @@ g++ -dynamiclib -fPIC \ "obin/com_artifex_gsjava_GSAPI.o" \ "obin/com_artifex_gsjava_util_NativePointer.o" \ "obin/jni_util.o" \ + "obin/instance_data.o" \ "../../../../sobin/libgpdl.dylib" \ No newline at end of file diff --git a/demos/java/jni/gs_jni/callbacks.cpp b/demos/java/jni/gs_jni/callbacks.cpp index fa2f54b75..2d0da54ed 100644 --- a/demos/java/jni/gs_jni/callbacks.cpp +++ b/demos/java/jni/gs_jni/callbacks.cpp @@ -175,6 +175,8 @@ int callbacks::calloutFunction(void *instance, void *handle, const char *deviceN jsize len = (jsize)strlen(deviceName); jbyteArray array = gsdata->env->NewByteArray(len); gsdata->env->SetByteArrayRegion(array, 0, len, (const jbyte *)deviceName); + + // TODO: gsdata->callerHandle is not consistent with the specification for a callout code = callIntMethod(gsdata->env, gsdata->callout, "onCallout", "(JJ[BIIJ)I", (jlong)instance, (jlong)gsdata->callerHandle, array, id, size, (jlong)data); } return code; @@ -192,7 +194,7 @@ int callbacks::display::displayOpenFunction(void *handle, void *device) jclass clazz = gsdata->env->GetObjectClass(gsdata->displayCallback); const char *name = getClassName(gsdata->env, clazz); freeClassName(name); - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayOpen", DISPLAY_OPEN_SIG, (jlong)gsdata->callerHandle, (jlong)device); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayOpen", DISPLAY_OPEN_SIG, (jlong)gsdata->displayHandle, (jlong)device); CHECK_AND_RETURN(gsdata->env); } return code; @@ -207,7 +209,7 @@ int callbacks::display::displayPrecloseFunction(void *handle, void *device) if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPreclose", DISPLAY_PRECLOSE_SIG, (jlong)gsdata->callerHandle, (jlong)device); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPreclose", DISPLAY_PRECLOSE_SIG, (jlong)gsdata->displayHandle, (jlong)device); CHECK_AND_RETURN(gsdata->env); } return code; @@ -222,7 +224,7 @@ int callbacks::display::displayCloseFunction(void *handle, void *device) if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayClose", DISPLAY_CLOSE_SIG, (jlong)gsdata->callerHandle, (jlong)device); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayClose", DISPLAY_CLOSE_SIG, (jlong)gsdata->displayHandle, (jlong)device); CHECK_AND_RETURN(gsdata->env); } return code; @@ -237,7 +239,7 @@ int callbacks::display::displayPresizeFunction(void *handle, void *device, int w if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPresize", DISPLAY_PRESIZE_SIG, (jlong)gsdata->callerHandle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPresize", DISPLAY_PRESIZE_SIG, (jlong)gsdata->displayHandle, (jlong)device, width, height, raster, (jint)format); CHECK_AND_RETURN(gsdata->env); } @@ -300,7 +302,7 @@ int callbacks::display::displaySizeFunction(void *handle, void *device, int widt gsdata->env->SetLongField(bytePointer, dataPtrID, (jlong)pimage); gsdata->env->SetLongField(bytePointer, lengthID, len); - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySize", DISPLAY_SIZE_SIG, (jlong)gsdata->callerHandle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySize", DISPLAY_SIZE_SIG, (jlong)gsdata->displayHandle, (jlong)device, width, height, raster, (jint)format, bytePointer); CHECK_AND_RETURN(gsdata->env); } @@ -316,7 +318,7 @@ int callbacks::display::displaySyncFunction(void *handle, void *device) if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySync", DISPLAY_SYNC_SIG, (jlong)gsdata->callerHandle, (jlong)device); + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySync", DISPLAY_SYNC_SIG, (jlong)gsdata->displayHandle, (jlong)device); CHECK_AND_RETURN(gsdata->env); } return code; @@ -331,7 +333,7 @@ int callbacks::display::displayPageFunction(void *handle, void *device, int copi if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPage", DISPLAY_PAGE_SIG, (jlong)gsdata->callerHandle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayPage", DISPLAY_PAGE_SIG, (jlong)gsdata->displayHandle, (jlong)device, copies, flush); CHECK_AND_RETURN(gsdata->env); } @@ -347,7 +349,7 @@ int callbacks::display::displayUpdateFunction(void *handle, void *device, int x, if (gsdata->env && gsdata->displayCallback) { - code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayUpdate", DISPLAY_UPDATE_SIG, (jlong)gsdata->callerHandle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayUpdate", DISPLAY_UPDATE_SIG, (jlong)gsdata->displayHandle, (jlong)device, x, y, w, h); CHECK_AND_RETURN(gsdata->env); } @@ -367,7 +369,7 @@ int callbacks::display::displaySeparationFunction(void *handle, void *device, in jsize len = (jsize)strlen(componentName); 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)gsdata->callerHandle, + code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplaySeparation", DISPLAY_SEPARATION_SIG, (jlong)gsdata->displayHandle, (jlong)device, component, byteArray, c, m, y, k); CHECK_AND_RETURN(gsdata->env); } @@ -384,7 +386,7 @@ int callbacks::display::displayAdjustBandHeightFunction(void *handle, void *devi if (gsdata->env && gsdata->displayCallback) { code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayAdjustBandHeght", DISPLAY_ADJUST_BAND_HEIGHT_SIG, - (jlong)gsdata->callerHandle, (jlong)device, bandHeight); + (jlong)gsdata->displayHandle, (jlong)device, bandHeight); CHECK_AND_RETURN(gsdata->env); } return code; @@ -411,7 +413,7 @@ int callbacks::display::displayRectangleRequestFunction(void *handle, void *devi Reference hRef = Reference(gsdata->env, toWrapperType(gsdata->env, (jint)*h)); code = callIntMethod(gsdata->env, gsdata->displayCallback, "onDisplayRectangleRequest", DISPLAY_RECTANGLE_REQUEST, - (jlong)gsdata->callerHandle, + (jlong)gsdata->displayHandle, (jlong)device, memoryRef.object(), oxRef.object(), diff --git a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp index c5b809481..1a045b948 100644 --- a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp +++ b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "jni_util.h" #include "callbacks.h" @@ -14,6 +15,8 @@ using namespace util; static void *getAsPointer(JNIEnv *env, jobject object, gs_set_param_type type, bool *success); +static void storeDispalyHandle(GSInstanceData *idata); + JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1revision (JNIEnv *env, jclass, jobject revision, jint len) { @@ -40,7 +43,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1new_1instance GSInstanceData *idata = new GSInstanceData(); idata->callerHandle = (void *)callerHandle; - void *gsInstance; + void *gsInstance = NULL; int code = gsapi_new_instance(&gsInstance, idata); if (code == 0) Reference::setValueField(env, instance, toWrapperType(env, (jlong)gsInstance)); @@ -79,6 +82,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio_1with_1ha callbacks::setJNIEnv(idata, env); callbacks::setIOCallbacks(idata, stdIn, stdOut, stdErr); } + return code; } @@ -97,6 +101,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1stdio callbacks::setJNIEnv(idata, env); callbacks::setIOCallbacks(idata, stdIn, stdOut, stdErr); } + return code; } @@ -136,6 +141,9 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1display_1callba GSInstanceData *idata = findDataFromInstance((void *)instance); assert(idata); + if (idata->hasinit && idata->displayCallback) + storeDispalyHandle(idata); + display_callback *cb = new display_callback; cb->size = sizeof(display_callback); cb->version_major = DISPLAY_VERSION_MAJOR; @@ -241,6 +249,9 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1init_1with_1args callbacks::setJNIEnv(idata, env); int code = gsapi_init_with_args((void *)instance, argc, cargv); delete2DByteArray(argc, cargv); + + idata->hasinit = true; + storeDispalyHandle(idata); return code; } @@ -654,3 +665,44 @@ void *getAsPointer(JNIEnv *env, jobject object, gs_set_param_type type, bool *su } return result; } + +void storeDispalyHandle(GSInstanceData *idata) +{ + static const char PARAM_NAME[] = "DisplayHandle"; + + char *param = NULL; + int bytes = gsapi_get_param(idata->instance, PARAM_NAME, NULL, gs_spt_string); + if (bytes == com_artifex_gsjava_GSAPI_GS_ERROR_UNDEFINED) + idata->displayCallback = NULL; + else + { + // Parse the DisplayHandle string again + + param = new char[bytes]; + gsapi_get_param(idata->instance, PARAM_NAME, param, gs_spt_string); + + char *toparse = param; + + int radix = 10; // default base 10 + + // If there is a # character, we need to change the radix + char *rend = strchr(param, '#'); + if (rend) + { + *rend = 0; + radix = atoi(param); + toparse = rend + 1; + } + + char *end; + long long val = std::strtoll(toparse, &end, radix); + + idata->displayHandle = (void *)val; + + delete[] param; + } + + char buf[20]; // 16#[16 hex digits][null terminator] + sprintf_s(buf, "16#%llx", (long long)idata); + gsapi_set_param(idata->instance, PARAM_NAME, buf, gs_spt_string); +} diff --git a/demos/java/jni/gs_jni/instance_data.h b/demos/java/jni/gs_jni/instance_data.h index 94422a672..2b2afe2e6 100644 --- a/demos/java/jni/gs_jni/instance_data.h +++ b/demos/java/jni/gs_jni/instance_data.h @@ -13,6 +13,7 @@ public: void *instance = NULL; // The Ghostscript instance void *callerHandle = NULL; // The caller handle passed to gsapi_new_instance void *stdioHandle = NULL; // The caller handle passed to gsapi_set_stdio_with_handle + void *displayHandle = NULL; // The handle passed to display callbacks JNIEnv *env = NULL; // The JNIEnv which should be used for JNI API calls @@ -25,6 +26,8 @@ public: jobject displayCallback = NULL; // The user DisplayCallback class jobject callout = NULL; // The user ICalloutFunction class + + bool hasinit = false; // Whether the user has called init_with_args }; GSInstanceData *putInstanceData(GSInstanceData *data); -- cgit v1.2.1