Thursday, June 11, 2009

Manipuler du graphique 2D SVG par programme avec GPAC

Si vous publiez un travail scientifique qui s'appuie sur GPAC, merci de mentionner GPAC en citant cet article "GPAC: open source multimedia framework" (DOI: 10.1145/1291233.1291452)

GPAC est un environnement de travail sur des développements multimédia porté par Telecom ParisTech. GPAC est un projet Open Source hébergé sur sourceforge.

GPAC a un excellent support de SVG. Voir la grille des implémentations de SVG.

Je démarre avec ce billet une série concernant l'utilisation de la librairie GPAC pour manipuler des documents SVG par programme. Ce premier billet porte sur la création par programme C d'une scène SVG et sa sauvegarde sous forme de fichier.

Créer un SVG



Créer un SceneGraph



A la base, l'objet manipulé par la librairie GPAC pour représenter une scène graphique est un SceneGraph. Ce même objet est utilisé pour du MPEG-4 BIFS, du Laser, du SVG.

La déclaration:
GF_SceneGraph *sg;

La création de l'objet:
sg = gf_sg_new();

Maintenant, nous sommes prêt pour mettre des choses dans l'objet sg.

Créer la racine du document SVG



Les éléments SVG manipulés dans GPAC sont de type SVG_Element. Nous allons créer un tel élément, que nous nommerons root, en tant que racine du document SVG.
La déclaration
SVG_Element *root;

La création:
root = (SVG_Element *)gf_node_new(sg, TAG_SVG_svg);

Ici, nous indiquons que nous créons l'élément dans la scène graphique sg créée précédemment et que l'élément créé doit être de type TAG_SVG_svg. Les constantes utilisées sont définies dans le fichier nodes_svg.h. Le nom des constantes est construit avec la racine TAG_SVG_ suivi du nom de l'élément SVG concerné. Par exemple, TAG_SVG_circle pour l'élément circle, TAG_SVG_text pour l'élément text.


L'objet est créé. Comme c'est la racine de notre document, ce rôle particulier doit être indiqué à GPAC par l'appel suivant:
gf_sg_set_root_node(sg, (GF_Node *)root);

En plus, chaque objet créé doit être comptabilisé au niveau de son parent (nous verrons plus tard que cela est utile dans des réutilisations d'objets). Comme la racine n'a pas de parent, on passe NULL comme paramètre. L'appel est donc: gf_node_register((GF_Node *)root, NULL);

Enfin, l'élément <svg> racine d'un document SVG doit posséder au moins un attribut qui lui associe le namespace SVG.
setAttributeNS(root, NULL, "xmlns", "http://www.w3.org/2000/svg");

Cette procédure est construite sur le modèle DOM. Comme nous ne sommes pas dans un langage objet, nous ne pouvons pas écrire root.setAttributeNS(...); nous passons l'objet comme premier paramètre de la procédure. Les autres paramètres sont similaires à ceux du setAttributeNS DOM. Le deuxième est le namespace de l'attribut, le troisième est le nom de l'attribut, le quatrième est la valeur de l'attribut. Nous reviendrons plus tard sur le deuxième paramètre, le namespace, pour l'instant nous utilisons le namespace par défaut en passant la valeur NULL.

Maintenant, un document SVG vide est prêt à recevoir du contenu.

Ajouter du contenu dans le document



Nous allons ajouter un cercle dans le document.
Pour cela, nous déclarons un SVG_Element:
SVG_Element *circle;

puis nous le créons:
circle = (SVG_Element *)gf_node_new(sg, TAG_SVG_circle);
à la façon dont nous avons créé l'élément <svg>.

Nous devons l'ajouter dans la liste des enfants de la racine:
gf_node_list_add_child(&root->children, (GF_Node *)circle);

Puis, comme précédemment, l'enregistrer auprès de son parent:
gf_node_register((GF_Node *)circle, (GF_Node *)root);

Enfin, nous créons un ensemble d'attribut qui vont définir le cercle: setAttributeNS(circle, NULL, "cx", "200");
setAttributeNS(circle, NULL, "cy", "100");
setAttributeNS(circle, NULL, "r", "50");

Et, voilà, nous avons un document SVG avec un cercle.

Générer le fichier correspondant



Pour créer le fichier, GPAC dispose d'un mécanisme nommé dumper qui permet de sauver une représentation d'une scène graphique.
Nous déclarons un objet dumper:
GF_SceneDumper *dumper;

Puis, nous créons l'objet:
dumper = gf_sm_dumper_new(sg, "test", ' ', GF_SM_DUMP_SVG);

Le premier paramètre est la scène pour laquelle nous créons un dumper. Le deuxième paramètre est le nom du fichier à générer. Le troisième caractère est le caractère utilisé pour l'indentation. Le quatrième est le type de représentation que nous souhaitons générer; ici, nous ne sommes concernés que par le dump SVG, spécifié par la constante GF_SM_DUMP_SVG.

Enfin, nous déclencons la sauvegarde proprement dite:
gf_sm_dump_graph(dumper, 0, 0);

Le premier paramètre est de façon évidente le dumper créé juste avant. Les deux autres paramètres n'ont pas d'intérêt pour le cas de la sauvegarde SVG.

Finir proprement



Enfin, nous devons libérer la mémoire occupée par la scène et les objets qui la composent. Pour cela, un appel suffit (pourvu que les objets aient correctement incorporés dans la scène):
gf_sg_del(sg);

A suivre



Dans les prochains billets, nous évoquerons l'affichage de la scène créée, la création de scènes plus complexe, avec plusieurs niveaux d'imbrication d'éléments, puis nous créerons une scène avec des liens internes et externes.

No comments: