Code

Export. Fix PS/EPS export (Bug #698340, PS Level Restriction reversed.
[inkscape.git] / src / bind / dobinding.cpp
index 29da3c0a4882f093e7f655be080a61de1585d6d0..1ba708ed7c312bbcaa9209aadf062991ccf5cbc9 100644 (file)
@@ -1,16 +1,17 @@
 /**
- * This is a simple mechanism to bind Inkscape to Java, and thence
- * to all of the nice things that can be layered upon that. 
+ * @file
+ * @brief This is a simple mechanism to bind Inkscape to Java, and thence
+ * to all of the nice things that can be layered upon that.
  *
  * Authors:
  *   Bob Jamison
  *
- * Copyright (C) 2007 Bob Jamison
+ * Copyright (C) 2007-2008 Bob Jamison
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
  *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
+ *  version 3 of the License, or (at your option) any later version.
  *
  *  This library is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -54,24 +55,97 @@ using namespace org::w3c::dom;
  * This file can get quite large!
  */  
 
+/**
+ * This struct associates a class name with its native
+ * bindings.  Since C++ does not allow "flexible" arrays,
+ * we will separate each of the tables into a JNINativeMethod
+ * array, and a class with a name and a pointer to that array.  
+ */  
+typedef struct
+{
+    const char *className;
+    JNINativeMethod *methods;
+} NativeClass;
+
+/**
+ * Although I dislike macros, this one seems reasonable
+ */ 
+#define EXCEPTION (getExceptionString(env).c_str())
 
 //########################################################################
 //# BASE OBJECT
 //########################################################################
 
+static jmethodID _getPointer_id = NULL;
+
 static jlong getPointer(JNIEnv *env, jobject obj)
 {
-    jfieldID id = env->GetFieldID(env->GetObjectClass(obj), "_pointer", "J");
-    jlong val = env->GetLongField(obj, id);
+    if (!_getPointer_id)
+        {
+        _getPointer_id = env->GetMethodID(env->GetObjectClass(obj), "getPointer", "()J");
+        if (!_getPointer_id)
+            {
+            err("getPointer(): %s", EXCEPTION);
+            return 0;
+               }
+           }
+    jlong val = env->CallLongMethod(obj, _getPointer_id);
     return val;
 }
 
+
+static jmethodID _setPointer_id = NULL;
+
 static void setPointer(JNIEnv *env, jobject obj, jlong val)
 {
-    jfieldID id = env->GetFieldID(env->GetObjectClass(obj), "_pointer", "J");
-    env->SetLongField(obj, id, val);
+    if (!_setPointer_id)
+        {
+        _setPointer_id = env->GetMethodID(env->GetObjectClass(obj), "setPointer", "(J)V");
+        if (!_setPointer_id)
+            {
+            err("setPointer(): %s", EXCEPTION);
+            return;
+                   }
+               }
+    env->CallVoidMethod(obj, _setPointer_id, val);
+}
+
+
+static void JNICALL BaseObject_construct
+  (JNIEnv *env, jobject obj)
+{
+    setPointer(env, obj, 0L);
+}
+
+static void JNICALL BaseObject_destruct
+  (JNIEnv *env, jobject obj)
+{
+    BaseObject *ptr = (BaseObject *)getPointer(env, obj);
+    if (ptr)
+        {
+        delete ptr;
+        }
+    setPointer(env, obj, 0L);
 }
 
+
+static JNINativeMethod nm_BaseObject[] =
+{
+{ (char *)"construct", (char *)"()V", (void *)BaseObject_construct },
+{ (char *)"destruct",  (char *)"()V", (void *)BaseObject_destruct  },
+{ NULL,  NULL, NULL }
+};
+
+static NativeClass nc_BaseObject =
+{
+    "org/inkscape/cmn/BaseObject",
+    nm_BaseObject
+};
+
+//########################################################################
+//# BASE OBJECT
+//########################################################################
+
 static void JNICALL DOMBase_construct
   (JNIEnv *env, jobject obj)
 {
@@ -90,13 +164,20 @@ static void JNICALL DOMBase_destruct
 }
 
 
-static JNINativeMethod DOMBaseMethods[] =
+static JNINativeMethod nm_DOMBase[] =
 {
 { (char *)"construct", (char *)"()V", (void *)DOMBase_construct },
 { (char *)"destruct",  (char *)"()V", (void *)DOMBase_destruct  },
 { NULL,  NULL, NULL }
 };
 
+static NativeClass nc_DOMBase =
+{
+    "org/inkscape/dom/DOMBase",
+    nm_DOMBase
+};
+
+
 //########################################################################
 //# DOMImplementation
 //########################################################################
@@ -114,38 +195,45 @@ void JNICALL DOMImplementation_nCreateDocument
 
 
 
-static JNINativeMethod DOMImplementationMethods[] =
+static JNINativeMethod nm_DOMImplementation[] =
 {
 { (char *)"construct", (char *)"()V", (void *)DOMImplementation_nCreateDocument },
 { NULL,  NULL, NULL }
 };
 
+static NativeClass nc_DOMImplementation =
+{
+    "org/inkscape/dom/DOMImplementation",
+    nm_DOMImplementation
+};
+
 
 
 //########################################################################
 //# MAIN
 //########################################################################
-typedef struct
-{
-    const char *className;
-    JNINativeMethod *methods;
-} NativeEntry;
 
 
-static NativeEntry nativeEntries[] =
+/**
+ * This is a table-of-tables, matching a class name to its
+ * table of native methods.  We can probably think of a cleaner way
+ * of doing this
+ */   
+static NativeClass *allClasses[] =
 {
-    { "org/inkscape/dom/DOMBase",           DOMBaseMethods            },
-    { "org/inkscape/dom/DOMImplementation", DOMImplementationMethods  },
-    { NULL,                                 NULL                      }
+    &nc_BaseObject,
+    &nc_DOMBase,
+    &nc_DOMImplementation,
+    NULL
 };
 
 
 
 bool JavaBinderyImpl::doBinding()
 {
-    for (NativeEntry *ne = nativeEntries ; ne->className ; ne++)
+    for (NativeClass **nc = allClasses ; *nc ; nc++)
         {
-        bool ret = registerNatives(ne->className, ne->methods);
+        bool ret = registerNatives((*nc)->className, (*nc)->methods);
         if (!ret)
             {
             err("Could not bind native methods");