Version 7, last updated by wycc at Aug 17 10:58 2010 UTC
The mb object t proposal
This document might not be updated. I create another MBAF Object page to be the design document.
Purpose of the mb_object_t
The MadButterfly will translate the SVG files into a C source file and header files. Each SVG elements will be translated into one of paint_t, shape_t or coord_t. However, these three are not in the same data type. The purpose of the mb_object_t is to encapsulate all three types together. Therefore, we can access objects without the prior knowledge of the content of the SVG file. This is very important for the DOM implementation.
In addition, for the DOM operation, we need to use a name to access the objects inside a SVG file. It means that we need to keep the name(ID) information as well. Currently, the name is translate into a c variable name. It means that the ID will be lost after compilation. Therefore, we need to add extra capability to enable the DOM. In this article, I will propose a design of mb_object_t for the above purposes.
Data structure
typedef struct _mb_class mb_class_t;
typedef struct _mb_object mb_object_t;
struct _mb_class {
struct _mb_object *(*new)(mb_rdman_t *rdman,bool_t DOM);
(*free)(struct _mb_object *obj);
};
struct _ob_object {
int type;
char *id;
mb_class_t *class;
union {
paint_t *paint;
shape_t *path;
coord_t *group;
} d;
dict_t dict;
}
The mb_objops provides interface to create/free/traverse an object which is generated by the SVG to C translator. In the future, if we implement the direct SVG support, we can still use the same interface. In that case, the name argument will become the reference to the SVG file.
For the SVG to C translator, we will generate the following file from the SVG
mb_class_t tank_Plugin = { tank_new, tank_free};
Therefore, we can use
mb_object_t *obj = tank_Plugin.new(rdman,1);
to acquire a new tank object. When the object is not used any more, ut can be freed by,
obj->class->free(obj);
In addition, a dict object is provided to access the object inside object by using the ID in the SVG file.
gun = object_find(obj, "gun");
to get the object gun from the tank object. If we need to traverse the whole object, we can use
ovject_foreach(obj, dump_obj,NULL);
to traverse every objects in the tank object. The object_find and object_foreach will use the dict field of the mb_object_t to find the appropriate object for the specified id.
How to generate the name in the C source file
In addition to the current codes, we need to generate extra information about the ID to object mapping. For example, if we have an element
<g id="abc" />
Currently, we generate it as
obj->abc = rdman_coord_new(rdman, obj->root_coord);
We need to generate the abc to obj->abc mapping as well. It will looks like.
dict_add(&obj->dict,"abc", obj->abc);
We should do this for every ID. In order to prevent the unnecessary overhead, we should implement the mapping in a sepearte function which will be called only when the DOM argument is true.
DOM operation
The DOM can be implemented by using the above interface. For example, we can implement rdman_get_root_object() to return the global root object and then use object_addChild to add a new object into it or use object_find to search for the objects. The object_find can not only find the direct child, but also the objects in the DOM tree. For example,
object_find(obj,"gun.trigger")
This call will access the gun object inside the obj and then get the trigger object inside the gun object. It will return NULL if any object can not be found in the dict.
Dynamic loading
By using the new structure, the dynamic loading can be implemented easily. We can choice to compile the C file as shared object so that it can be loaded by the dlopn. In this case, the loader will search for the xxx_Plugin symbol. For example,
mb_object_t *obj = mb_object_load("tank", 1);
will search for tank.so in the search path and then find the tank_Plugin symbol inside it. If the symbol is found, it will call the tank_Plugin.new to generate a new object.
The only limitation is that we can not use static method to access the object in this case since the object is loaded dynamically at the runtime. We need to use the DOM operation to access the objects inside the SVG file.
