summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-09-22 18:33:17 +0100
committerRobin Watts <robin.watts@artifex.com>2016-09-23 15:41:18 +0100
commiteef63823f5ced78205b7d0b04599759d5b4eff8e (patch)
tree9a0aa1bd8543720888ff93e594417ba42eb6c772 /platform
parent32131a60794d1bed3b7555b79aaf2caf69a88769 (diff)
downloadmupdf-eef63823f5ced78205b7d0b04599759d5b4eff8e.tar.xz
JNI: Rework conversion functions and nulls.
Java has a convention that 'toString' should return a printable version of an object. We cannot both support this, and support a sane naming of functions to interpret pdf objects that begins with 'to'. Instead use 'as'. This means we have 'asBoolean', 'asInteger', 'asString' which expect to work just on pdf objects of the required type. 'toString' continues to work on all types and gives a printable version. We split 'toByteString' into 2 separate functions, one for acting on strings (asByteString) and one for acting on names (asByteName) more nicely mirroring the C level functions (pdf_to_string and pdf_to_name). For simplicity of use, we add asString and asName functions that return using java Strings rather than byte arrays. There are potential encoding issues with these, but then there are throughout our string handling at the moment, so we will deal with those in a followup commit. We also update the internal workings of several functions so that they never return NULL pointers, but rather return the null object. To avoid repeatedly creating new null objects we introduce a global static PDFObject.Null object. This is important as we want get("SomethingNonexistent") to return a valid java object, so we can safely do things like: get("Foo").get("Bar").get("Baz").asInteger() without having to error check at every stage. Update DocViewActivity to call the new versions.
Diffstat (limited to 'platform')
-rw-r--r--platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java67
-rw-r--r--platform/java/mupdf_native.c154
-rw-r--r--platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java2
-rw-r--r--platform/java/src/com/artifex/mupdf/fitz/PDFObject.java18
4 files changed, 157 insertions, 84 deletions
diff --git a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java
index cbad6fa5..03739349 100644
--- a/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java
+++ b/platform/android/example/mupdf/src/main/java/com/artifex/mupdf/android/DocActivityView.java
@@ -770,72 +770,33 @@ public class DocActivityView extends FrameLayout implements TabHost.OnTabChangeL
private String getEmbeddedProfileName()
{
- PDFDocument doc = mDoc.toPDFDocument();
- if (doc == null)
- return null;
- PDFObject obj = doc.getTrailer();
- if (obj == null)
- return null;
- obj = obj.get("Root");
- if (obj == null)
- return null;
- PDFObject outputIntents = obj.get("OutputIntents");
+ PDFObject outputIntents = mDoc.toPDFDocument().getTrailer().get("Root").get("OutputIntents");
if (outputIntents == null)
return null;
int length = outputIntents.size();
int i;
- for (i = 0 ; i < length; i++)
- {
+ for (i = 0 ; i < length; i++) {
PDFObject intent = outputIntents.get(i);
- if (intent == null || !intent.isDictionary())
- continue;
-
- /* FIXME: Getting a name as a ByteString is horrible */
- obj = intent.get("S");
- if (obj == null)
- continue;
- byte name[] = obj.toByteString();
- if (name == null || name.length != 9)
- continue;
- if (name[0] != 'G' || name[1] != 'T' || name[2] != 'S' || name[3] != '_' ||
- name[4] != 'P' || name[5] != 'D' || name[6] != 'F' || name[7] != 'X' || name[8] != 0)
+ String name = intent.get("S").asName();
+ if (!name.equals("GTS_PDFX"))
continue;
/* We can't use the embedded profile if it's not CMYK based. */
- obj = intent.get("DestOutputProfile");
- if (obj == null)
- continue;
- obj = obj.get("N");
- if (obj == null)
- continue;
- if (obj.toInteger() != 4)
+ if (intent.get("DestOutputProfile").get("N").asInteger() != 4)
continue;
- String id;
- obj = intent.get("Info");
- if (obj != null)
- {
- id = obj.toString();
- if (id != null)
- return id;
- }
- obj = intent.get("OutputConditionIdentifier");
- if (obj != null)
- {
- id = obj.toString();
- if (id != null)
- return id;
- }
- obj = intent.get("OutputCondition");
- if (obj != null)
- {
- id = obj.toString();
- if (id != null)
- return id;
- }
+ PDFObject id = intent.get("Info");
+ if (id.isString())
+ return id.asString();
+ id = intent.get("OutputConditionIdentifier");
+ if (id.isString())
+ return id.asString();
+ id = intent.get("OutputCondition");
+ if (id.isString())
+ return id.asString();
}
return null;
}
diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c
index 4b9565c5..79a9e53f 100644
--- a/platform/java/mupdf_native.c
+++ b/platform/java/mupdf_native.c
@@ -117,6 +117,7 @@ static jfieldID fid_Path_pointer;
static jfieldID fid_PDFDocument_pointer;
static jfieldID fid_PDFGraftMap_pointer;
static jfieldID fid_PDFObject_pointer;
+static jfieldID fid_PDFObject_Null;
static jfieldID fid_Pixmap_pointer;
static jfieldID fid_Rect_x0;
static jfieldID fid_Rect_x1;
@@ -309,6 +310,22 @@ static jfieldID get_field(int *failed, JNIEnv *env, const char *field, const cha
return fid;
}
+static jfieldID get_static_field(int *failed, JNIEnv *env, const char *field, const char *sig)
+{
+ jfieldID fid;
+
+ if (*failed || !current_class) return NULL;
+
+ fid = (*env)->GetStaticFieldID(env, current_class, field, sig);
+ if (fid == 0)
+ {
+ LOGI("Failed to get static field for %s %s %s", current_class_name, field, sig);
+ *failed = 1;
+ }
+
+ return fid;
+}
+
static jmethodID get_method(int *failed, JNIEnv *env, const char *method, const char *sig)
{
jmethodID mid;
@@ -449,6 +466,7 @@ static int find_fids(JNIEnv *env)
cls_PDFObject = get_class(&err, env, PKG"PDFObject");
fid_PDFObject_pointer = get_field(&err, env, "pointer", "J");
+ fid_PDFObject_Null = get_static_field(&err, env, "Null", "L"PKG"PDFObject;");
mid_PDFObject_init = get_method(&err, env, "<init>", "(J)V");
cls_Pixmap = get_class(&err, env, PKG"Pixmap");
@@ -997,8 +1015,10 @@ static inline jobject to_PDFDocument_safe(fz_context *ctx, JNIEnv *env, pdf_docu
static inline jobject to_PDFObject_safe(fz_context *ctx, JNIEnv *env, jobject pdf, pdf_obj *obj)
{
- if (!ctx || !obj || !pdf) return NULL;
+ if (!ctx || !pdf) return NULL;
+ if (obj == NULL)
+ return (*env)->GetStaticObjectField(env, cls_PDFObject, fid_PDFObject_Null);
pdf_keep_obj(ctx, obj);
return (*env)->NewObject(env, cls_PDFObject, mid_PDFObject_init, jlong_cast(obj), pdf);
}
@@ -6254,6 +6274,17 @@ FUN(PDFObject_finalize)(JNIEnv *env, jobject self)
pdf_drop_obj(ctx, obj);
}
+JNIEXPORT jlong JNICALL
+FUN(PDFObject_newNull)(JNIEnv *env, jclass cls)
+{
+ fz_context *ctx = get_context(env);
+
+ if (!ctx) return 0;
+
+ /* Not nice to pass doc as NULL, but it is unused */
+ return jlong_cast(pdf_new_null(ctx, NULL));
+}
+
JNIEXPORT jint JNICALL
FUN(PDFObject_toIndirect)(JNIEnv *env, jobject self)
{
@@ -6705,7 +6736,6 @@ FUN(PDFObject_resolve)(JNIEnv *env, jobject self)
pdf_obj *ind = NULL;
if (!ctx || !obj) return NULL;
- if (!obj) { jni_throw_arg(env, "object must not be null"); return NULL; }
fz_try(ctx)
ind = pdf_resolve_indirect(ctx, obj);
@@ -6748,21 +6778,21 @@ FUN(PDFObject_getDictionary)(JNIEnv *env, jobject self, jstring jname)
pdf_obj *val = NULL;
if (!ctx || !dict) return NULL;
- if (jname)
- {
+
+ if (!jname)
name = (*env)->GetStringUTFChars(env, jname, NULL);
- if (!name) return NULL;
- }
- fz_try(ctx)
- val = pdf_dict_gets(ctx, dict, name);
- fz_always(ctx)
- if (name)
- (*env)->ReleaseStringUTFChars(env, jname, name);
- fz_catch(ctx)
+ if (name)
{
- jni_rethrow(env, ctx);
- return NULL;
+ fz_try(ctx)
+ val = pdf_dict_gets(ctx, dict, name);
+ fz_always(ctx)
+ (*env)->ReleaseStringUTFChars(env, jname, name);
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ return NULL;
+ }
}
return to_PDFObject_safe(ctx, env, self, val);
@@ -7232,7 +7262,7 @@ FUN(PDFObject_deleteDictionaryPDFObject)(JNIEnv *env, jobject self, jobject jnam
}
JNIEXPORT jboolean JNICALL
-FUN(PDFObject_toBoolean)(JNIEnv *env, jobject self)
+FUN(PDFObject_asBoolean)(JNIEnv *env, jobject self)
{
fz_context *ctx = get_context(env);
pdf_obj *obj = from_PDFObject(env, self);
@@ -7252,7 +7282,7 @@ FUN(PDFObject_toBoolean)(JNIEnv *env, jobject self)
}
JNIEXPORT jint JNICALL
-FUN(PDFObject_toInteger)(JNIEnv *env, jobject self)
+FUN(PDFObject_asInteger)(JNIEnv *env, jobject self)
{
fz_context *ctx = get_context(env);
pdf_obj *obj = from_PDFObject(env, self);
@@ -7272,7 +7302,7 @@ FUN(PDFObject_toInteger)(JNIEnv *env, jobject self)
}
JNIEXPORT jfloat JNICALL
-FUN(PDFObject_toFloat)(JNIEnv *env, jobject self)
+FUN(PDFObject_asFloat)(JNIEnv *env, jobject self)
{
fz_context *ctx = get_context(env);
pdf_obj *obj = from_PDFObject(env, self);
@@ -7291,34 +7321,108 @@ FUN(PDFObject_toFloat)(JNIEnv *env, jobject self)
return f;
}
+JNIEXPORT jstring JNICALL
+FUN(PDFObject_asString)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ pdf_obj *obj = from_PDFObject(env, self);
+ const char *str = NULL;
+
+ if (!ctx || !obj) return NULL;
+
+ fz_try(ctx)
+ str = pdf_to_str_buf(ctx, obj);
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ return NULL;
+ }
+
+ return (*env)->NewStringUTF(env, str);
+}
+
JNIEXPORT jobject JNICALL
-FUN(PDFObject_toByteString)(JNIEnv *env, jobject self)
+FUN(PDFObject_asByteString)(JNIEnv *env, jobject self)
{
fz_context *ctx = get_context(env);
pdf_obj *obj = from_PDFObject(env, self);
const char *str = NULL;
jobject jbs = NULL;
jbyte *bs = NULL;
+ int len;
if (!ctx || !obj) return NULL;
fz_try(ctx)
- if (pdf_is_name(ctx, obj))
- str = pdf_to_name(ctx, obj);
- else
- str = pdf_to_str_buf(ctx, obj);
+ {
+ str = pdf_to_str_buf(ctx, obj);
+ len = pdf_to_str_len(ctx, obj);
+ }
fz_catch(ctx)
{
jni_rethrow(env, ctx);
return NULL;
}
- jbs = (*env)->NewByteArray(env, strlen(str) + 1);
+ jbs = (*env)->NewByteArray(env, len);
if (!jbs) return NULL;
bs = (*env)->GetByteArrayElements(env, jbs, NULL);
if (!bs) return NULL;
- memcpy(bs, str, strlen(str) + 1);
+ memcpy(bs, str, len);
+
+ (*env)->ReleaseByteArrayElements(env, jbs, bs, 0);
+
+ return jbs;
+}
+
+JNIEXPORT jstring JNICALL
+FUN(PDFObject_asName)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ pdf_obj *obj = from_PDFObject(env, self);
+ const char *str = NULL;
+
+ if (!ctx || !obj) return NULL;
+
+ fz_try(ctx)
+ str = pdf_to_name(ctx, obj);
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ return NULL;
+ }
+
+ return (*env)->NewStringUTF(env, str);
+}
+
+JNIEXPORT jobject JNICALL
+FUN(PDFObject_asByteName)(JNIEnv *env, jobject self)
+{
+ fz_context *ctx = get_context(env);
+ pdf_obj *obj = from_PDFObject(env, self);
+ const char *str = NULL;
+ jobject jbs = NULL;
+ jbyte *bs = NULL;
+ int len;
+
+ if (!ctx || !obj) return NULL;
+
+ fz_try(ctx)
+ str = pdf_to_name(ctx, obj);
+ fz_catch(ctx)
+ {
+ jni_rethrow(env, ctx);
+ return NULL;
+ }
+
+ len = strlen(str);
+ jbs = (*env)->NewByteArray(env, len);
+ if (!jbs) return NULL;
+ bs = (*env)->GetByteArrayElements(env, jbs, NULL);
+ if (!bs) return NULL;
+
+ memcpy(bs, str, len);
(*env)->ReleaseByteArrayElements(env, jbs, bs, 0);
@@ -7460,7 +7564,7 @@ JNIEXPORT jstring JNICALL
FUN(PDFObject_toString)(JNIEnv *env, jobject self, jboolean tight)
{
fz_context *ctx = get_context(env);
- pdf_obj *obj = from_PDFObject(env, self);
+ pdf_obj *obj = from_PDFObject_safe(env, self);
jstring string = NULL;
char *s = NULL;
int n = 0;
diff --git a/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java b/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java
index 93fd5ebe..601919d7 100644
--- a/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java
+++ b/platform/java/src/com/artifex/mupdf/fitz/PDFDocument.java
@@ -42,7 +42,7 @@ public class PDFDocument
public native void deleteObject(int i);
public void deleteObject(PDFObject obj) {
- deleteObject(obj.toIndirect());
+ deleteObject(obj.asIndirect());
}
public native PDFGraftMap newPDFGraftMap();
diff --git a/platform/java/src/com/artifex/mupdf/fitz/PDFObject.java b/platform/java/src/com/artifex/mupdf/fitz/PDFObject.java
index 10a0e7a8..0f9741b5 100644
--- a/platform/java/src/com/artifex/mupdf/fitz/PDFObject.java
+++ b/platform/java/src/com/artifex/mupdf/fitz/PDFObject.java
@@ -19,6 +19,8 @@ public class PDFObject
pointer = p;
}
+ private static native long newNull();
+
public native boolean isIndirect();
public native boolean isNull();
public native boolean isBoolean();
@@ -31,11 +33,15 @@ public class PDFObject
public native boolean isDictionary();
public native boolean isStream();
- public native boolean toBoolean();
- public native int toInteger();
- public native float toFloat();
- public native byte[] toByteString();
- public native int toIndirect();
+ public native boolean asBoolean();
+ public native int asInteger();
+ public native float asFloat();
+ public native int asIndirect();
+ public native String asName();
+ public native byte[] asByteName();
+ public native String asString();
+ public native byte[] asByteString();
+
public native String toString(boolean tight);
public String toString() {
@@ -201,4 +207,6 @@ public class PDFObject
public void push(PDFObject obj) {
pushPDFObject(obj);
}
+
+ public static final PDFObject Null = new PDFObject(newNull());
}