summaryrefslogtreecommitdiffstats
path: root/src/libnr/nr-object.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/libnr/nr-object.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/libnr/nr-object.cpp')
-rw-r--r--src/libnr/nr-object.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/libnr/nr-object.cpp b/src/libnr/nr-object.cpp
new file mode 100644
index 000000000..b18685d11
--- /dev/null
+++ b/src/libnr/nr-object.cpp
@@ -0,0 +1,295 @@
+#define __NR_OBJECT_C__
+
+/*
+ * RGBA display list system for inkscape
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * MenTaLguY <mental@rydia.net>
+ *
+ * This code is in public domain
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <libnr/nr-macros.h>
+
+#include "nr-object.h"
+
+unsigned int nr_emit_fail_warning(const gchar *file, unsigned int line, const gchar *method, const gchar *expr)
+{
+ fprintf (stderr, "File %s line %d (%s): Assertion %s failed\n", file, line, method, expr);
+ return 1;
+}
+
+/* NRObject */
+
+static NRObjectClass **classes = NULL;
+static unsigned int classes_len = 0;
+static unsigned int classes_size = 0;
+
+NRType nr_type_is_a(NRType type, NRType test)
+{
+ nr_return_val_if_fail(type < classes_len, FALSE);
+ nr_return_val_if_fail(test < classes_len, FALSE);
+
+ NRObjectClass *c = classes[type];
+
+ while (c) {
+ if (c->type == test) {
+ return TRUE;
+ }
+ c = c->parent;
+ }
+
+ return FALSE;
+}
+
+void const *nr_object_check_instance_cast(void const *ip, NRType tc)
+{
+ nr_return_val_if_fail(ip != NULL, NULL);
+ nr_return_val_if_fail(nr_type_is_a(((NRObject const *) ip)->klass->type, tc), ip);
+ return ip;
+}
+
+unsigned int nr_object_check_instance_type(void const *ip, NRType tc)
+{
+ if (ip == NULL) {
+ return FALSE;
+ }
+
+ return nr_type_is_a(((NRObject const *) ip)->klass->type, tc);
+}
+
+NRType nr_object_register_type(NRType parent,
+ gchar const *name,
+ unsigned int csize,
+ unsigned int isize,
+ void (* cinit) (NRObjectClass *),
+ void (* iinit) (NRObject *))
+{
+ if (classes_len >= classes_size) {
+ classes_size += 32;
+ classes = nr_renew (classes, NRObjectClass *, classes_size);
+ if (classes_len == 0) {
+ classes[0] = NULL;
+ classes_len = 1;
+ }
+ }
+
+ NRType const type = classes_len;
+ classes_len += 1;
+
+ classes[type] = (NRObjectClass*) new char[csize];
+ NRObjectClass *c = classes[type];
+
+ /* FIXME: is this necessary? */
+ memset(c, 0, csize);
+
+ if (classes[parent]) {
+ memcpy(c, classes[parent], classes[parent]->csize);
+ }
+
+ c->type = type;
+ c->parent = classes[parent];
+ c->name = strdup(name);
+ c->csize = csize;
+ c->isize = isize;
+ c->cinit = cinit;
+ c->iinit = iinit;
+
+ c->cinit(c);
+
+ return type;
+}
+
+static void nr_object_class_init (NRObjectClass *klass);
+static void nr_object_init (NRObject *object);
+static void nr_object_finalize (NRObject *object);
+
+NRType nr_object_get_type()
+{
+ static NRType type = 0;
+
+ if (!type) {
+ type = nr_object_register_type (0,
+ "NRObject",
+ sizeof (NRObjectClass),
+ sizeof (NRObject),
+ (void (*) (NRObjectClass *)) nr_object_class_init,
+ (void (*) (NRObject *)) nr_object_init);
+ }
+
+ return type;
+}
+
+static void nr_object_class_init(NRObjectClass *c)
+{
+ c->finalize = nr_object_finalize;
+ c->cpp_ctor = NRObject::invoke_ctor<NRObject>;
+}
+
+static void nr_object_init (NRObject *object)
+{
+}
+
+static void nr_object_finalize (NRObject *object)
+{
+}
+
+/* Dynamic lifecycle */
+
+static void nr_class_tree_object_invoke_init(NRObjectClass *c, NRObject *object)
+{
+ if (c->parent) {
+ nr_class_tree_object_invoke_init(c->parent, object);
+ }
+ c->iinit (object);
+}
+
+namespace {
+
+void finalize_object(void *base, void *)
+{
+ NRObject *object = reinterpret_cast<NRObject *>(base);
+ object->klass->finalize(object);
+ object->~NRObject();
+}
+
+}
+
+NRObject *NRObject::alloc(NRType type)
+{
+ nr_return_val_if_fail (type < classes_len, NULL);
+
+ NRObjectClass *c = classes[type];
+
+ if ( c->parent && c->cpp_ctor == c->parent->cpp_ctor ) {
+ g_error("Cannot instantiate NRObject class %s which has not registered a C++ constructor\n", c->name);
+ }
+
+ NRObject *object = reinterpret_cast<NRObject *>(
+ ::operator new(c->isize, Inkscape::GC::SCANNED, Inkscape::GC::AUTO,
+ &finalize_object, NULL)
+ );
+ memset(object, 0xf0, c->isize);
+
+ object->klass = c;
+ c->cpp_ctor(object);
+ nr_class_tree_object_invoke_init (c, object);
+
+ return object;
+}
+
+/* NRActiveObject */
+
+static void nr_active_object_class_init(NRActiveObjectClass *c);
+static void nr_active_object_init(NRActiveObject *object);
+static void nr_active_object_finalize(NRObject *object);
+
+static NRObjectClass *parent_class;
+
+NRType nr_active_object_get_type()
+{
+ static NRType type = 0;
+ if (!type) {
+ type = nr_object_register_type (NR_TYPE_OBJECT,
+ "NRActiveObject",
+ sizeof (NRActiveObjectClass),
+ sizeof (NRActiveObject),
+ (void (*) (NRObjectClass *)) nr_active_object_class_init,
+ (void (*) (NRObject *)) nr_active_object_init);
+ }
+ return type;
+}
+
+static void nr_active_object_class_init(NRActiveObjectClass *c)
+{
+ NRObjectClass *object_class = (NRObjectClass *) c;
+
+ parent_class = object_class->parent;
+
+ object_class->finalize = nr_active_object_finalize;
+ object_class->cpp_ctor = NRObject::invoke_ctor<NRActiveObject>;
+}
+
+static void nr_active_object_init(NRActiveObject *object)
+{
+}
+
+static void nr_active_object_finalize(NRObject *object)
+{
+ NRActiveObject *aobject = (NRActiveObject *) object;
+
+ if (aobject->callbacks) {
+ for (unsigned int i = 0; i < aobject->callbacks->length; i++) {
+ NRObjectListener *listener = aobject->callbacks->listeners + i;
+ if ( listener->vector->dispose ) {
+ listener->vector->dispose(object, listener->data);
+ }
+ }
+ free (aobject->callbacks);
+ }
+
+ ((NRObjectClass *) (parent_class))->finalize(object);
+}
+
+void nr_active_object_add_listener(NRActiveObject *object,
+ const NRObjectEventVector *vector,
+ unsigned int size,
+ void *data)
+{
+ if (!object->callbacks) {
+ object->callbacks = (NRObjectCallbackBlock*) malloc(sizeof(NRObjectCallbackBlock));
+ object->callbacks->size = 1;
+ object->callbacks->length = 0;
+ }
+
+ if (object->callbacks->length >= object->callbacks->size) {
+ int newsize = object->callbacks->size << 1;
+ object->callbacks = (NRObjectCallbackBlock *)
+ realloc(object->callbacks, sizeof(NRObjectCallbackBlock) + (newsize - 1) * sizeof (NRObjectListener));
+ object->callbacks->size = newsize;
+ }
+
+ NRObjectListener *listener = object->callbacks->listeners + object->callbacks->length;
+ listener->vector = vector;
+ listener->size = size;
+ listener->data = data;
+ object->callbacks->length += 1;
+}
+
+void nr_active_object_remove_listener_by_data(NRActiveObject *object, void *data)
+{
+ if (object->callbacks == NULL) {
+ return;
+ }
+
+ for (unsigned i = 0; i < object->callbacks->length; i++) {
+ NRObjectListener *listener = object->callbacks->listeners + i;
+ if ( listener->data == data ) {
+ object->callbacks->length -= 1;
+ if ( object->callbacks->length < 1 ) {
+ free(object->callbacks);
+ object->callbacks = NULL;
+ } else if ( object->callbacks->length != i ) {
+ *listener = object->callbacks->listeners[object->callbacks->length];
+ }
+ return;
+ }
+ }
+}
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :