summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEthan Vrhel <ethanvrhel@gmail.com>2020-08-16 16:28:44 -0700
committerevrhel <ethanvrhel@gmail.com>2020-09-24 15:23:43 -0700
commit9c9190192c1acdafbf4e9f277dba9e2079046cc7 (patch)
tree8b63a1a929bd137057eb01e09b6db7d298af6bbe
parentfbe9a961e7fef31c79cfd8ed857643ad00798af8 (diff)
downloadghostpdl-9c9190192c1acdafbf4e9f277dba9e2079046cc7.tar.gz
Fixed JNI bugs and began updating viewer to use one GS instance
Fixed JNI crashes when Ghostscript calls were made from different threads. Migrated loading low res and high res images from using multiple instances to using one global instance.
-rw-r--r--demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java2
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/Document.java137
-rw-r--r--demos/java/gsviewer/src/com/artifex/gsviewer/Page.java8
-rw-r--r--demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp12
-rw-r--r--demos/java/jni/gs_jni/jni_util.cpp4
5 files changed, 126 insertions, 37 deletions
diff --git a/demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java b/demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java
index 5a7b04dc0..38a34ac14 100644
--- a/demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java
+++ b/demos/java/gsjava/src/com/artifex/gsjava/util/Reference.java
@@ -40,6 +40,6 @@ public class Reference<T> {
@Override
public String toString() {
- return "Reference<" + (value == null ? "?" : value.getClass().getName()) + "> -> " + value.toString();
+ return "Reference<" + (value == null ? "?" : value.getClass().getName()) + "> -> " + value;
}
}
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/Document.java b/demos/java/gsviewer/src/com/artifex/gsviewer/Document.java
index 80e14333b..d147656ba 100644
--- a/demos/java/gsviewer/src/com/artifex/gsviewer/Document.java
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/Document.java
@@ -15,9 +15,11 @@ import java.util.Objects;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
+import com.artifex.gsjava.GSAPI;
import com.artifex.gsjava.GSInstance;
import com.artifex.gsjava.callbacks.DisplayCallback;
import com.artifex.gsjava.util.BytePointer;
+import com.artifex.gsjava.util.Reference;
import com.artifex.gsviewer.ImageUtil.ImageParams;
/**
@@ -297,32 +299,6 @@ public class Document implements List<Page> {
}
}
- /**
- * Initializes an instance of Ghostcript.
- *
- * @param instanceRef A reference to the instance of Ghostscript.
- * @throws IllegalStateException When any Ghostscript operation fails to execute.
- */
-// private static void initDocInstance(LongReference instanceRef) throws IllegalStateException {
-// int code = gsapi_new_instance(instanceRef, GS_NULL);
-// if (code != GS_ERROR_OK) {
-// gsapi_delete_instance(instanceRef.value);
-// throw new IllegalStateException("Failed to set stdio with handle (code = " + code + ")");
-// }
-//
-// code = gsapi_set_arg_encoding(instanceRef.value, 1);
-// if (code != GS_ERROR_OK) {
-// gsapi_delete_instance(instanceRef.value);
-// throw new IllegalArgumentException("Failed to set arg encoding (code = " + code + ")");
-// }
-//
-// code = gsapi_set_display_callback(instanceRef.value, documentLoader.reset());
-// if (code != GS_ERROR_OK) {
-// gsapi_delete_instance(instanceRef.value);
-// throw new IllegalStateException("Failed to set display callback code=" + code);
-// }
-// }
-
private static GSInstance initDocInstance() throws IllegalStateException {
GSInstance instance = new GSInstance();
@@ -339,6 +315,19 @@ public class Document implements List<Page> {
throw new IllegalStateException("Failed to set display callback (code = " + code + ")");
}
+ String[] gsargs = new String[] {
+ "gs",
+ "-dNOPAUSE", "-dSAFER", "-I%rom%Resource%/Init/", "-dBATCH",
+ "-sDEVICE=display",
+ "-dFirstPage=1",
+ "-dDisplayFormat=" + format
+ };
+ code = instance.init_with_args(gsargs);
+ if (code != GS_ERROR_OK) {
+ instance.delete_instance();
+ throw new IllegalStateException("Failed to init with args (code = " + code + ")");
+ }
+
return instance;
}
@@ -371,8 +360,15 @@ public class Document implements List<Page> {
}
@Override
+ public int onDisplayPresize(long handle, long device, int width, int height, int raster, int format) {
+ System.out.println("Presize");
+ return 0;
+ }
+
+ @Override
public int onDisplaySize(long handle, long device, int width, int height, int raster, int format,
BytePointer pimage) {
+ System.out.println("Size");
this.pageWidth = width;
this.pageHeight = height;
this.pageRaster = raster;
@@ -391,10 +387,16 @@ public class Document implements List<Page> {
return 0;
}
+
+ @Override
+ public void finalize() {
+ System.err.println("WARNING: The document loader has been freed by the Java VM");
+ }
}
private File file;
private List<Page> pages;
+ private GSInstance gsInstance;
/**
* Creates and loads a new document.
@@ -430,25 +432,46 @@ public class Document implements List<Page> {
startOperation();
- GSInstance instance = null;
try {
- instance = initDocInstance();
+ gsInstance = initDocInstance();
} catch (IllegalStateException e) {
operationDone();
}
- if (instance == null)
+ if (gsInstance == null) {
+ operationDone();
throw new IllegalStateException("Failed to initialize Ghostscript");
+ }
documentLoader.callback = loadCallback;
- int code = instance.init_with_args(gargs);
+ int code = gsInstance.set_param("HWResolution", Page.PAGE_LOW_DPI_STR, GS_SPT_PARSED);
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to set HWResolution (code = " + code + ")");
+ }
+
+ Reference<Integer> exitCode = new Reference<>();
+ code = gsInstance.run_file(file.getAbsolutePath(), 0, exitCode);
+
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to run file (code = " + code + ")");
+ }
+
+ gsInstance.set_param("TextAlphaBits", 4, GS_SPT_INT);
+ gsInstance.set_param("GraphicsAlphaBits", 4, GS_SPT_INT);
+
+ //gsInstance.exit();
+ //gsInstance.delete_instance();
+
+ /*int code = instance.init_with_args(gargs);
instance.exit();
instance.delete_instance();
if (code != GS_ERROR_OK) {
operationDone();
throw new IllegalStateException("Failed to gsapi_init_with_args code=" + code);
- }
+ }*/
this.pages = new ArrayList<>(documentLoader.images.size());
for (BufferedImage img : documentLoader.images) {
@@ -565,7 +588,7 @@ public class Document implements List<Page> {
"-dTextAlphaBits=4", "-dGraphicsAlphaBits=4",
"-f", file.getAbsolutePath() };
- GSInstance instance = null;
+ /*GSInstance instance = null;
try {
instance = initDocInstance();
} catch (IllegalStateException e) {
@@ -581,6 +604,36 @@ public class Document implements List<Page> {
if (code != GS_ERROR_OK) {
operationDone();
throw new IllegalStateException("Failed to gsapi_init_with_args code=" + code);
+ }*/
+ //gsInstance.set_display_callback(documentLoader.reset());
+ //documentLoader.reset();
+ documentLoader.images.clear();
+
+ this.setParams(Page.PAGE_HIGH_DPI, startPage, endPage);
+
+ for (GSInstance.GSParam<?> param : gsInstance) {
+ System.out.println(param);
+ }
+
+ Reference<Integer> ref = new Reference<>();
+ gsInstance.get_param_once("FirstPage", ref, GS_SPT_INT);
+ System.out.println(ref);
+ gsInstance.get_param_once("LastPage", ref, GS_SPT_INT);
+ System.out.println(ref);
+
+ Reference<Integer> exitCode = new Reference<>();
+ //gsInstance.set_display_callback(documentLoader.reset());
+ int code = gsInstance.run_file(file.getAbsolutePath(), 0, exitCode);
+
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to run file (code = " + code + ")");
+ }
+
+ if (documentLoader.images.size() != endPage - startPage + 1) {
+ operationDone();
+ throw new IllegalStateException("Page range mismatch (expected " +
+ (endPage - startPage) + ", got " + documentLoader.images.size() + ")");
}
int ind = startPage - 1;
@@ -847,6 +900,26 @@ public class Document implements List<Page> {
throw new IndexOutOfBoundsException("end < start");
}
+ private void setParams(int dpi, int startPage, int lastPage) {
+ int code = gsInstance.set_param("HWResolution", Page.toDPIString(dpi), GS_SPT_PARSED);
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to set HWResolution (code = " + code + ")");
+ }
+
+ code = gsInstance.set_param("FirstPage", startPage, GS_SPT_INT);
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to set dFirstPage (code = " + code + ")");
+ }
+
+ code = gsInstance.set_param("LastPage", lastPage, GS_SPT_INT);
+ if (code != GS_ERROR_OK) {
+ operationDone();
+ throw new IllegalStateException("Failed to set dEndPage (code = " + code + ")");
+ }
+ }
+
// Implementations of inherited methods from java.util.List.
@Override
diff --git a/demos/java/gsviewer/src/com/artifex/gsviewer/Page.java b/demos/java/gsviewer/src/com/artifex/gsviewer/Page.java
index dca755660..bdbcd04b0 100644
--- a/demos/java/gsviewer/src/com/artifex/gsviewer/Page.java
+++ b/demos/java/gsviewer/src/com/artifex/gsviewer/Page.java
@@ -21,11 +21,19 @@ public class Page {
*/
public static final int PAGE_HIGH_DPI = 72;
+ public static final String PAGE_HIGH_DPI_STR = toDPIString(PAGE_HIGH_DPI);
+
/**
* The low-resolution DPI to use.
*/
public static final int PAGE_LOW_DPI = 10;
+ public static final String PAGE_LOW_DPI_STR = toDPIString(PAGE_LOW_DPI);
+
+ public static String toDPIString(int dpi) {
+ return "[" + dpi + " " + dpi + "]";
+ }
+
private volatile BufferedImage lowRes;
private volatile BufferedImage highRes;
private volatile BufferedImage zoomed;
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 5c8acb83a..f3a568e77 100644
--- a/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp
+++ b/demos/java/jni/gs_jni/com_artifex_gsjava_GSAPI.cpp
@@ -159,6 +159,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1default_1device
if (list == NULL)
return throwNullPointerException(env, "list");
jboolean isCopy = false;
+ callbacks::setJNIEnv(env);
int code = gsapi_set_default_device_list((void *)instance,
(const char *)env->GetByteArrayElements(list, &isCopy), listlen);
return code;
@@ -191,6 +192,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1init_1with_1args
if (argv == NULL)
return throwNullPointerException(env, "argv");
char **cargv = jbyteArray2DToCharArray(env, argv);
+ callbacks::setJNIEnv(env);
int code = gsapi_init_with_args((void *)instance, argc, cargv);
delete2DByteArray(argc, cargv);
return code;
@@ -200,6 +202,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1begin
(JNIEnv *env, jclass, jlong instance, jint userErrors, jobject pExitCode)
{
int exitCode;
+ callbacks::setJNIEnv(env);
int code = gsapi_run_string_begin((void *)instance, userErrors, &exitCode);
if (pExitCode)
Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
@@ -214,6 +217,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1continu
jboolean copy = false;
int exitCode;
const char *cstring = (const char *)env->GetByteArrayElements(str, &copy);
+ callbacks::setJNIEnv(env);
int code = gsapi_run_string_continue((void *)instance, cstring, length, userErrors, &exitCode);
if (pExitCode)
Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
@@ -224,6 +228,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1end
(JNIEnv *env, jclass, jlong instance, jint userErrors, jobject pExitCode)
{
int exitCode;
+ callbacks::setJNIEnv(env);
int code = gsapi_run_string_end((void *)instance, userErrors, &exitCode);
if (pExitCode)
Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
@@ -238,6 +243,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string_1with_1l
jboolean copy = false;
int exitCode;
const char *cstring = (const char *)env->GetByteArrayElements(str, &copy);
+ callbacks::setJNIEnv(env);
int code = gsapi_run_string_with_length((void *)instance, cstring, length, userErrors, &exitCode);
if (pExitCode)
Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
@@ -252,6 +258,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1string
jboolean copy = false;
int exitCode;
const char *cstring = (const char *)env->GetByteArrayElements(str, &copy);
+ callbacks::setJNIEnv(env);
int code = gsapi_run_string((void *)instance, cstring, userErrors, &exitCode);
if (pExitCode)
Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
@@ -266,6 +273,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1run_1file
jboolean copy = false;
int exitCode;
const char *cstring = (const char *)env->GetByteArrayElements(fileName, &copy);
+ callbacks::setJNIEnv(env);
int code = gsapi_run_file((void *)instance, cstring, userErrors, &exitCode);
if (pExitCode)
Reference::setValueField(env, pExitCode, toWrapperType(env, (jint)exitCode));
@@ -300,6 +308,7 @@ JNIEXPORT jint JNICALL Java_com_artifex_gsjava_GSAPI_gsapi_1set_1param
int exitCode;
const char *cstring = (const char *)env->GetByteArrayElements(param, &copy);
+ callbacks::setJNIEnv(env);
int code = gsapi_set_param((void *)instance, cstring, data, type);
free(data);
@@ -526,7 +535,8 @@ void *getAsPointer(JNIEnv *env, jobject object, gs_set_param_type type, bool *su
cstring = (const char *)env->GetByteArrayElements(arr, &copy);
len = env->GetArrayLength(arr);
result = malloc(sizeof(char) * len);
- ((char *)result)[len - 1] = 0;
+ //((char *)result)[len - 1] = 0;
+ memcpy(result, cstring, len);
break;
case gs_spt_invalid:
default:
diff --git a/demos/java/jni/gs_jni/jni_util.cpp b/demos/java/jni/gs_jni/jni_util.cpp
index 0c1710bd8..df390a7f1 100644
--- a/demos/java/jni/gs_jni/jni_util.cpp
+++ b/demos/java/jni/gs_jni/jni_util.cpp
@@ -34,9 +34,7 @@ jmethodID util::getMethodID(JNIEnv *env, jobject object, const char *method, con
if (env == NULL || object == NULL || method == NULL || sig == NULL)
return NULL;
- jobject obj = env->NewLocalRef(object);
- jclass clazz = env->GetObjectClass(obj);
- env->DeleteLocalRef(obj);
+ jclass clazz = env->GetObjectClass(object);
jmethodID methodID = env->GetMethodID(clazz, method, sig);
if (methodID == NULL)