Thursday, December 10, 2009

Manipulate SVG 2D Graphics programmatically with GPAC

If you publish a scientific work based on GPAC thank you to mention in the article, mentioning "GPAC: open source multimedia framework" (DOI: 10.1145/1291233.1291452)


GPAC is a framework, focused on multimedia development, developed by Telecom ParisTech. GPAC is an Open Source project hosted on sourceforge.

GPAC has excellent SVG support. (look at the Show grid implementations of SVG).

This note is a start point for a series on the use of the GPAC library for manipulating SVG documents programmatically. The first note is about creating a SVG scene by C program and its backup as a file.

Create SVG

Create a scenegraph

Basically, a SceneGraph? is the object used by the Gpac library to manipulate a graphic scene. The same object is used for MPEG-4 BIFS, Laser, SVG.

Declaration:

GF_SceneGraph * sg;

Object creation:

sg = gf_sg_new ();

Now we are ready to put things in the sg object.

Create the root of the SVG document

SVG elements are handled in the GPAC type SVG_Element. We will create such an element, which we call root as the root SVG document.

Declaration

SVG_Element * root;

Creation:

root = (SVG_Element *)gf_node_new(sg, TAG_SVG_svg);

Here, we show that we create the element in the scene graph sg created earlier and that the element created must be of type TAG_SVG_svg. The constants used are defined in the file nodes_svg.h. The constants name is constructed with the prefix TAG_SVG_ followed by the name of the corresponding SVG element. For example, TAG_SVG_circle for the element circle, TAG_SVG_text for the text element.

The object is created. As it is the root of our SVG document, this particular role must be reported to GPAC by the following call:

gf_sg_set_root_node(sg, (GF_Node *)root);

In addition, each object created should be recorded at its parent (we shall see later that this is useful in the reuse of objects). As the root has no parent, we pass NULL as parameter. The call is:

gf_node_register ((GF_Node *) root, NULL);

Finally, the root element of an SVG document must have at least one attribute that associates the SVG namespace.

setAttributeNS(root, NULL, "xmlns", "http://www.w3.org/2000/svg");

This procedure is built on the DOM model. As we are not in an object language, we can not write root.setAttributeNS(...); we pass the object as first parameter of the procedure. The other parameters are similar to those of setAttributeNS DOM. The second is the namespace attribute, the third is the attribute name, the fourth is the attribute value. We will return later on the second parameter, the namespace; for the moment we use the default namespace by passing NULL.

Now, an empty SVG document is ready to receive content.

Add content into the document

We'll add a circle in the document.

For this, we declare a SVG_Element:

SVG_Element *circle;

then we create it:

circle = (SVG_Element *)gf_node_new(sg, TAG_SVG_circle);

like we created the element .

We must add it to the list of children of the root:

gf_node_list_add_child(&root->children, (GF_Node *)circle);

Then, as before, register it with its parent:

gf_node_register((GF_Node *)circle, (GF_Node *)root);

Finally, we create a set of attributes that will define the circle

setAttributeNS (circle, null, "cx", "200");
setAttributeNS(circle, NULL, "cy", "100"); setAttributeNS (circle, null, "cy", "100");
setAttributeNS(circle, NULL, "r", "50"); setAttributeNS (circle, NULL, "r", "50");

And here we have an SVG document with a circle.

Generate the corresponding file


To create the file, GPAC has a mechanism called dumper which produces an image of a scene graph.

We declare a dump object:

GF_SceneDumper *dumper;

Then we create the SVG dumper:

dumper = gf_sm_dumper_new(sg, "test", ' ', GF_SM_DUMP_SVG);

The first parameter is the SVG scene graph which we will dump. The second parameter is the name of file to generate. The third character is the character used for indentation. The fourth is the type of representation we want to generate, here we are concerned only with dump SVG specified by the constant GF_SM_DUMP_SVG.

Finally, we start writing the file:

gf_sm_dump_graph(dumper, 0, 0);

The first parameter is obviously the dump created just before. The other two parameters have no interest in the case of SVG backup.

Finish properly

Finally, we must free the memory occupied by the scene and objects within it. For this one call (provided that the objects be properly integrated into the scene):

gf_sg_del (sg);

To be continued

In the next few notes, we discuss the display of the created SVG document, the creation of more complex scenes with multiple levels of nested elements, then we'll create a scene with internal and external links.