root/applications/generators/SVG/main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. NewSVGGenAttribute
  2. deleteSVGGenAttribute
  3. NewSVGGenAttrGrp
  4. NewSVGGenElement
  5. deleteSVGGenElement
  6. sortElements
  7. sortAttrGrp
  8. sortAttr
  9. svgNameToImplementationName
  10. isGenericAttributesGroup
  11. setGenericAttributesFlags
  12. flattenAttributeGroups
  13. flattenAttributeGroup
  14. findAttribute
  15. countAttributesAllInGroup
  16. findNodes
  17. setAttributeType
  18. getAttributeType
  19. getRealAttributes
  20. getOneGlobalAttrGrp
  21. getAllGlobalAttrGrp
  22. getElements
  23. BeginFile
  24. EndFile
  25. generateAttributes
  26. replaceIncludes
  27. main

/*
 *                      GPAC - Multimedia Framework C SDK
 *
 *                      Authors: Cyril Concolato
 *                      Copyright (c) Telecom ParisTech 2004-2012
 *                                      All rights reserved
 *
 *  This file is part of GPAC / SVG Scene Graph Generator sub-project
 *
 *  GPAC 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, or (at your option)
 *  any later version.
 *
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include "svggen.h"

SVGGenAttribute *NewSVGGenAttribute()
{
        SVGGenAttribute *att;
        GF_SAFEALLOC(att, SVGGenAttribute)
        return att;
}

void deleteSVGGenAttribute(SVGGenAttribute **p)
{
        xmlFree((*p)->svg_name);
        xmlFree((*p)->svg_type);
        gf_free(*p);
        *p = NULL;
}

SVGGenAttrGrp *NewSVGGenAttrGrp()
{
        SVGGenAttrGrp *tmp;
        GF_SAFEALLOC(tmp, SVGGenAttrGrp)
        tmp->attrs = gf_list_new();
        tmp->attrgrps = gf_list_new();
        return tmp;
}

SVGGenElement *NewSVGGenElement()
{
        SVGGenElement *elt;
        GF_SAFEALLOC(elt, SVGGenElement);
        if (elt) {
                elt->attributes = gf_list_new();
                elt->generic_attributes = gf_list_new();
        }
        return elt;
}

void deleteSVGGenElement(SVGGenElement **p)
{
        u32 i;
        xmlFree((*p)->svg_name);
        for (i = 0; i < gf_list_count((*p)->attributes); i++) {
                SVGGenAttribute *a = gf_list_get((*p)->attributes, i);
                deleteSVGGenAttribute(&a);
        }
        gf_list_del((*p)->attributes);
        gf_free(*p);
        *p = NULL;
}

static GF_List *sortElements(GF_List *elements)
{
        u32 i, j;
        GF_List *sorted_elements = gf_list_new();

        for (i = 0; i< gf_list_count(elements); i++) {
                u8 is_added = 0;
                SVGGenElement *elt = gf_list_get(elements, i);
                for (j = 0; j < gf_list_count(sorted_elements); j++) {
                        SVGGenElement *selt = gf_list_get(sorted_elements, j);
                        if (strcmp(elt->svg_name, selt->svg_name) < 0) {
                                gf_list_insert(sorted_elements, elt, j);
                                is_added = 1;
                                break;
                        }
                }
                if (!is_added) gf_list_add(sorted_elements, elt);
        }

        gf_list_del(elements);
        return sorted_elements;
}

static GF_List *sortAttrGrp(GF_List *attgrps)
{
        u32 i, j;
        GF_List *sorted_attgrps = gf_list_new();

        for (i = 0; i< gf_list_count(attgrps); i++) {
                u8 is_added = 0;
                SVGGenAttrGrp *grp = gf_list_get(attgrps, i);
                for (j = 0; j < gf_list_count(sorted_attgrps); j++) {
                        SVGGenAttrGrp *sgrp = gf_list_get(sorted_attgrps, j);
                        if (strcmp(grp->name, sgrp->name) < 0) {
                                gf_list_insert(sorted_attgrps, grp, j);
                                is_added = 1;
                                break;
                        }
                }
                if (!is_added) gf_list_add(sorted_attgrps, grp);
        }

        gf_list_del(attgrps);
        return sorted_attgrps;
}

static GF_List *sortAttr(GF_List *atts)
{
        u32 i, j;
        GF_List *sorted_atts = gf_list_new();

        for (i = 0; i< gf_list_count(atts); i++) {
                u8 is_added = 0;
                SVGGenAttribute *att = gf_list_get(atts, i);
                for (j = 0; j < gf_list_count(sorted_atts); j++) {
                        SVGGenAttribute *satt = gf_list_get(sorted_atts, j);
                        if (strcmp(att->svg_name, satt->svg_name) < 0) {
                                gf_list_insert(sorted_atts, att, j);
                                is_added = 1;
                                break;
                        }
                }
                if (!is_added) gf_list_add(sorted_atts, att);
        }

        gf_list_del(atts);
        return sorted_atts;
}

void svgNameToImplementationName(xmlChar *svg_name, char implementation_name[50]) {
        char *tmp;
        strcpy(implementation_name, svg_name);
        tmp = implementation_name;
        while ( (tmp = strchr(tmp, '.')) ) {
                *tmp='_';
                tmp++;
        }
        tmp = implementation_name;
        while ( (tmp = strchr(tmp, '-')) ) {
                *tmp='_';
                tmp++;
        }
        tmp = implementation_name;
        while ( (tmp = strchr(tmp, ':')) ) {
                *tmp='_';
                tmp++;
        }
}

static Bool isGenericAttributesGroup(char *name)
{
        if (!strcmp(name, "svg.Core.attr") ||
                !strcmp(name, "svg.CorePreserve.attr") ||
                !strcmp(name, "svg.External.attr") ||
                !strcmp(name, "svg.Properties.attr") ||
                !strcmp(name, "svg.Media.attr") ||
                !strcmp(name, "svg.MediaClip.attr") ||
                !strcmp(name, "svg.Opacity.attr") ||
                !strcmp(name, "svg.FocusHighlight.attr") ||
                !strcmp(name, "svg.Focus.attr") ||
                !strcmp(name, "svg.AnimateCommon.attr") ||
                !strcmp(name, "svg.XLinkEmbed.attr") ||
                !strcmp(name, "svg.XLinkRequired.attr") ||
                !strcmp(name, "svg.XLinkReplace.attr") ||
//              !strcmp(name, "svg.ContentType.attr") ||
                !strcmp(name, "svg.AnimateTiming.attr") ||
                !strcmp(name, "svg.AnimateTimingNoMinMax.attr") ||
                !strcmp(name, "svg.AnimateBegin.attr") ||
                !strcmp(name, "svg.AnimateTimingNoFillNoMinMax.attr") ||
                !strcmp(name, "svg.AnimateSync.attr") ||
                !strcmp(name, "svg.AnimateSyncDefault.attr") ||
                !strcmp(name, "svg.AnimateAttributeCommon.attr") ||
                !strcmp(name, "svg.AnimateToCommon.attr") ||
                !strcmp(name, "svg.AnimateValueCommon.attr") ||
                !strcmp(name, "svg.AnimateAdditionCommon.attr") ||
                !strcmp(name, "svg.AnimateTypeCommon.attr") ||
                !strcmp(name, "svg.Conditional.attr") ||
//              !strcmp(name, "svg.XY.attr") ||
                !strcmp(name, "svg.Transform.attr")) {
                return 1;
        } else {
                return 0;
        }
}

static Bool setGenericAttributesFlags(char *name, SVGGenElement *e)
{
        Bool ret = 1;
        if (!strcmp(name, "svg.Core.attr") ||
                !strcmp(name, "svg.CorePreserve.attr") ||
                !strcmp(name, "svg.External.attr")) {
                e->has_svg_generic = 1;
                e->has_xml_generic = 1;
        } else if (!strcmp(name, "svg.Properties.attr")) {
                e->has_properties = 1;
                e->has_media_properties = 1;
        } else if (!strcmp(name, "svg.Media.attr")) {
                e->has_media_properties = 1;
        } else if (!strcmp(name, "svg.Opacity.attr")) {
                e->has_opacity_properties = 1;
        } else if (!strcmp(name, "svg.FocusHighlight.attr") ||
                   !strcmp(name, "svg.Focus.attr")) {
                e->has_focus = 1;
        } else if (!strcmp(name, "svg.AnimateCommon.attr") ||
                   !strcmp(name, "svg.XLinkEmbed.attr") ||
                   !strcmp(name, "svg.XLinkRequired.attr") ||
                   !strcmp(name, "svg.XLinkReplace.attr")) { //||
//                         !strcmp(name, "svg.ContentType.attr")) {
                e->has_xlink = 1;
        } else if (!strcmp(name, "svg.AnimateTiming.attr") ||
                   !strcmp(name, "svg.AnimateTimingNoMinMax.attr") ||
                   !strcmp(name, "svg.AnimateBegin.attr") ||
                   !strcmp(name, "svg.AnimateTimingNoFillNoMinMax.attr")) {
                e->has_timing = 1;
        } else if (!strcmp(name, "svg.AnimateSync.attr") ||
                   !strcmp(name, "svg.AnimateSyncDefault.attr")) {
                e->has_sync= 1;
        } else if (!strcmp(name, "svg.AnimateAttributeCommon.attr") ||
                   !strcmp(name, "svg.AnimateToCommon.attr") ||
                   !strcmp(name, "svg.AnimateValueCommon.attr") ||
                   !strcmp(name, "svg.AnimateAdditionCommon.attr") ||
                   !strcmp(name, "svg.AnimateTypeCommon.attr")) {
                e->has_animation = 1;
        } else if (!strcmp(name, "svg.Conditional.attr")) {
                e->has_conditional = 1;
        } else if (!strcmp(name, "svg.Transform.attr")) {
                e->has_transform = 1;
        } else if (!strcmp(name, "svg.XY.attr")) {
                e->has_xy = 1;
        } else {
                ret = 0;
        }
        return ret;
}

static void flattenAttributeGroup(SVGGenAttrGrp attgrp, SVGGenElement *e, Bool all);

static void flattenAttributeGroups(GF_List *attrgrps, SVGGenElement *e, Bool all)
{
        u32 i;
        for (i = 0; i < gf_list_count(attrgrps); i ++) {
                SVGGenAttrGrp *ag = gf_list_get(attrgrps, i);
                flattenAttributeGroup(*ag, e, all);
        }
}

static void flattenAttributeGroup(SVGGenAttrGrp attgrp, SVGGenElement *e, Bool all)
{
        u32 i;

        if (isGenericAttributesGroup(attgrp.name) && !all) {
                setGenericAttributesFlags(attgrp.name, e);
                flattenAttributeGroups(attgrp.attrgrps, e, 1);
                for (i = 0; i < gf_list_count(attgrp.attrs); i++) {
                        gf_list_add(e->generic_attributes, gf_list_get(attgrp.attrs, i));
                }
        } else {
                flattenAttributeGroups(attgrp.attrgrps, e, all);
                for (i = 0; i < gf_list_count(attgrp.attrs); i++) {
                        if (all)
                                gf_list_add(e->generic_attributes, gf_list_get(attgrp.attrs, i));
                        else
                                gf_list_add(e->attributes, gf_list_get(attgrp.attrs, i));
                }
        }
}

SVGGenAttribute *findAttribute(SVGGenElement *e, char *name)
{
        u32 i;
        for (i = 0; i < gf_list_count(e->attributes); i++) {
                SVGGenAttribute *a = gf_list_get(e->attributes, i);
                if (!strcmp(a->svg_name, name)) return a;
        }
        for (i = 0; i < gf_list_count(e->generic_attributes); i++) {
                SVGGenAttribute *a = gf_list_get(e->generic_attributes, i);
                if (!strcmp(a->svg_name, name)) return a;
        }
        return NULL;
}

static u32 countAttributesAllInGroup(SVGGenAttrGrp *ag)
{
        u32 i, ret = 0;
        for (i = 0; i < gf_list_count(ag->attrgrps); i ++) {
                SVGGenAttrGrp *agtmp = gf_list_get(ag->attrgrps, i);
                ret += countAttributesAllInGroup(agtmp);
        }
        ret += gf_list_count(ag->attrs);
        return ret;
}

/* XML related functions */
xmlNodeSetPtr findNodes( xmlXPathContextPtr ctxt, xmlChar * path )
{
        xmlXPathObjectPtr res = NULL;

        if ( ctxt->node != NULL && path != NULL ) {
                xmlXPathCompExprPtr comp;

                xmlDocPtr tdoc = NULL;
                xmlNodePtr froot = ctxt->node;

                comp = xmlXPathCompile( path );
                if ( comp == NULL ) {
                        return NULL;
                }

                if ( ctxt->node->doc == NULL ) {
                        /* if one XPaths a node from a fragment, libxml2 will
                           refuse the lookup. this is not very usefull for XML
                           scripters. thus we need to create a temporary document
                           to make libxml2 do it's job correctly.
                         */
                        tdoc = xmlNewDoc( NULL );

                        /* find refnode's root node */
                        while ( froot != NULL ) {
                                if ( froot->parent == NULL ) {
                                        break;
                                }
                                froot = froot->parent;
                        }
                        xmlAddChild((xmlNodePtr)tdoc, froot);

                        ctxt->node->doc = tdoc;
                }

                res = xmlXPathCompiledEval(comp, ctxt);

                xmlXPathFreeCompExpr(comp);

                if ( tdoc != NULL ) {
                        /* after looking through a fragment, we need to drop the
                           fake document again */
                        xmlSetTreeDoc(froot,NULL);
                        froot->doc = NULL;
                        tdoc->children = NULL;
                        tdoc->last     = NULL;
                        froot->parent  = NULL;
                        ctxt->node->doc = NULL;

                        xmlFreeDoc( tdoc );
                }
        }
        if (res && res->type == XPATH_NODESET)
                return res->nodesetval;
        else
                return NULL;
}


/* definition of GPAC groups of SVG attributes */

void setAttributeType(SVGGenAttribute *att)
{
        if (!att->svg_type) { /* if the type is not given in the RNG, we explicitely set it */
                if (!strcmp(att->svg_name, "textContent")) {
                        strcpy(att->impl_type, "SVG_TextContent");
                } else if (!strcmp(att->svg_name, "class")) {
                        strcpy(att->implementation_name, "_class");
                        strcpy(att->impl_type, "SVG_String");
                } else if (!strcmp(att->svg_name, "visibility")) {
                        strcpy(att->impl_type, "SVG_Visibility");
                } else if (!strcmp(att->svg_name, "display")) {
                        strcpy(att->impl_type, "SVG_Display");
                } else if (!strcmp(att->svg_name, "stroke-linecap")) {
                        strcpy(att->impl_type, "SVG_StrokeLineCap");
                } else if (!strcmp(att->svg_name, "stroke-dasharray")) {
                        strcpy(att->impl_type, "SVG_StrokeDashArray");
                } else if (!strcmp(att->svg_name, "stroke-linejoin")) {
                        strcpy(att->impl_type, "SVG_StrokeLineJoin");
                } else if (!strcmp(att->svg_name, "font-style")) {
                        strcpy(att->impl_type, "SVG_FontStyle");
                } else if (!strcmp(att->svg_name, "font-weight")) {
                        strcpy(att->impl_type, "SVG_FontWeight");
                } else if (!strcmp(att->svg_name, "text-anchor")) {
                        strcpy(att->impl_type, "SVG_TextAnchor");
                } else if (!strcmp(att->svg_name, "fill")) {
                        strcpy(att->impl_type, "SMIL_Fill");
                } else if (!strcmp(att->svg_name, "fill-rule")) {
                        strcpy(att->impl_type, "SVG_FillRule");
                } else if (!strcmp(att->svg_name, "font-family")) {
                        strcpy(att->impl_type, "SVG_FontFamily");
                } else if (!strcmp(att->svg_name, "calcMode")) {
                        strcpy(att->impl_type, "SMIL_CalcMode");
                } else if (!strcmp(att->svg_name, "values")) {
                        strcpy(att->impl_type, "SMIL_AnimateValues");
                } else if (!strcmp(att->svg_name, "keyTimes")) {
                        strcpy(att->impl_type, "SMIL_KeyTimes");
                } else if (!strcmp(att->svg_name, "keySplines")) {
                        strcpy(att->impl_type, "SMIL_KeySplines");
                } else if (!strcmp(att->svg_name, "keyPoints")) {
                        strcpy(att->impl_type, "SMIL_KeyPoints");
                } else if (!strcmp(att->svg_name, "from") ||
                           !strcmp(att->svg_name, "to") ||
                           !strcmp(att->svg_name, "by")) {
                        strcpy(att->impl_type, "SMIL_AnimateValue");
                } else if (!strcmp(att->svg_name, "additive")) {
                        strcpy(att->impl_type, "SMIL_Additive");
                } else if (!strcmp(att->svg_name, "accumulate")) {
                        strcpy(att->impl_type, "SMIL_Accumulate");
                } else if (!strcmp(att->svg_name, "begin") ||
                           !strcmp(att->svg_name, "end")
                          ) {
                        strcpy(att->impl_type, "SMIL_Times");
                } else if (!strcmp(att->svg_name, "clipBegin") ||
                           !strcmp(att->svg_name, "clipEnd")
                          ) {
                        strcpy(att->impl_type, "SVG_Clock");
                } else if (!strcmp(att->svg_name, "min") ||
                           !strcmp(att->svg_name, "max") ||
                           !strcmp(att->svg_name, "dur") ||
                           !strcmp(att->svg_name, "repeatDur")
                          ) {
                        strcpy(att->impl_type, "SMIL_Duration");
                } else if (!strcmp(att->svg_name, "repeat")) {
                        strcpy(att->impl_type, "SMIL_Repeat");
                } else if (!strcmp(att->svg_name, "restart")) {
                        strcpy(att->impl_type, "SMIL_Restart");
                } else if (!strcmp(att->svg_name, "repeatCount")) {
                        strcpy(att->impl_type, "SMIL_RepeatCount");
                } else if (!strcmp(att->svg_name, "attributeName")) {
                        strcpy(att->impl_type, "SMIL_AttributeName");
                } else if (!strcmp(att->svg_name, "type")) {
                        strcpy(att->impl_type, "SVG_TransformType");
                } else if (!strcmp(att->svg_name, "font-size")) {
                        strcpy(att->impl_type, "SVG_FontSize");
                } else if (!strcmp(att->svg_name, "viewBox")) {
                        strcpy(att->impl_type, "SVG_ViewBox");
                } else if (!strcmp(att->svg_name, "preserveAspectRatio")) {
                        strcpy(att->impl_type, "SVG_PreserveAspectRatio");
                } else if (!strcmp(att->svg_name, "zoomAndPan")) {
                        strcpy(att->impl_type, "SVG_ZoomAndPan");
                } else if (!strcmp(att->svg_name, "path")) {
                        strcpy(att->impl_type, "SVG_PathData");
                } else if (!strcmp(att->svg_name, "image-rendering")) {
                        strcpy(att->impl_type, "SVG_RenderingHint");
                } else if (!strcmp(att->svg_name, "color-rendering")) {
                        strcpy(att->impl_type, "SVG_RenderingHint");
                } else if (!strcmp(att->svg_name, "text-rendering")) {
                        strcpy(att->impl_type, "SVG_RenderingHint");
                } else if (!strcmp(att->svg_name, "shape-rendering")) {
                        strcpy(att->impl_type, "SVG_RenderingHint");
                } else if (!strcmp(att->svg_name, "pointer-events")) {
                        strcpy(att->impl_type, "SVG_PointerEvents");
                } else if (!strcmp(att->svg_name, "vector-effect")) {
                        strcpy(att->impl_type, "SVG_VectorEffect");
                } else if (!strcmp(att->svg_name, "vector-effect")) {
                        strcpy(att->impl_type, "SVG_VectorEffect");
                } else if (!strcmp(att->svg_name, "display-align")) {
                        strcpy(att->impl_type, "SVG_DisplayAlign");
                } else if (!strcmp(att->svg_name, "text-align")) {
                        strcpy(att->impl_type, "SVG_TextAlign");
                } else if (!strcmp(att->svg_name, "propagate")) {
                        strcpy(att->impl_type, "XMLEV_Propagate");
                } else if (!strcmp(att->svg_name, "defaultAction")) {
                        strcpy(att->impl_type, "XMLEV_DefaultAction");
                } else if (!strcmp(att->svg_name, "phase")) {
                        strcpy(att->impl_type, "XMLEV_Phase");
                } else if (!strcmp(att->svg_name, "syncBehavior")) {
                        strcpy(att->impl_type, "SMIL_SyncBehavior");
                } else if (!strcmp(att->svg_name, "syncBehaviorDefault")) {
                        strcpy(att->impl_type, "SMIL_SyncBehavior");
                } else if (!strcmp(att->svg_name, "attributeType")) {
                        strcpy(att->impl_type, "SMIL_AttributeType");
                } else if (!strcmp(att->svg_name, "playbackOrder")) {
                        strcpy(att->impl_type, "SVG_PlaybackOrder");
                } else if (!strcmp(att->svg_name, "timelineBegin")) {
                        strcpy(att->impl_type, "SVG_TimelineBegin");
                } else if (!strcmp(att->svg_name, "xml:space")) {
                        strcpy(att->impl_type, "XML_Space");
                } else if (!strcmp(att->svg_name, "snapshotTime")) {
                        strcpy(att->impl_type, "SVG_Clock");
                } else if (!strcmp(att->svg_name, "version")) {
                        strcpy(att->impl_type, "SVG_String");
                } else if (!strcmp(att->svg_name, "gradientUnits")) {
                        strcpy(att->impl_type, "SVG_GradientUnit");
                } else if (!strcmp(att->svg_name, "baseProfile")) {
                        strcpy(att->impl_type, "SVG_String");
                } else if (!strcmp(att->svg_name, "focusHighlight")) {
                        strcpy(att->impl_type, "SVG_FocusHighlight");
                } else if (!strcmp(att->svg_name, "initialVisibility")) {
                        strcpy(att->impl_type, "SVG_InitialVisibility");
                } else if (!strcmp(att->svg_name, "overlay")) {
                        strcpy(att->impl_type, "SVG_Overlay");
                } else if (!strcmp(att->svg_name, "transformBehavior")) {
                        strcpy(att->impl_type, "SVG_TransformBehavior");
                } else if (!strcmp(att->svg_name, "rotate")) {
                        strcpy(att->impl_type, "SVG_Rotate");
                } else if (!strcmp(att->svg_name, "font-variant")) {
                        strcpy(att->impl_type, "SVG_FontVariant");
                } else if (!strcmp(att->svg_name, "lsr:enabled")) {
                        strcpy(att->impl_type, "SVG_Boolean");
                } else if (!strcmp(att->svg_name, "spreadMethod")) {
                        strcpy(att->impl_type, "SVG_SpreadMethod");
                } else if (!strcmp(att->svg_name, "gradientTransform")) {
                        strcpy(att->impl_type, "SVG_Transform_Full");
                } else if (!strcmp(att->svg_name, "editable")) {
                        strcpy(att->impl_type, "SVG_Boolean");
                } else if (!strcmp(att->svg_name, "choice")) {
                        strcpy(att->impl_type, "LASeR_Choice");
                } else if (!strcmp(att->svg_name, "size") ||
                           !strcmp(att->svg_name, "delta")) {
                        strcpy(att->impl_type, "LASeR_Size");
                } else if (!strcmp(att->svg_name, "syncReference")) {
                        strcpy(att->impl_type, "XMLRI");
                } else {
                        /* For all other attributes, we use String as default type */
                        strcpy(att->impl_type, "SVG_String");
                        fprintf(stdout, "Warning: using type SVG_String for attribute %s.\n", att->svg_name);
                }
        } else { /* for some attributes, the type given in the RNG needs to be overriden */
                if (!strcmp(att->svg_name, "color")) {
                        strcpy(att->impl_type, "SVG_Paint");
                } else if (!strcmp(att->svg_name, "viewport-fill")) {
                        strcpy(att->impl_type, "SVG_Paint");
                } else if (!strcmp(att->svg_name, "syncTolerance")) {
                        strcpy(att->impl_type, "SMIL_SyncTolerance");
                } else if (!strcmp(att->svg_name, "syncToleranceDefault")) {
                        strcpy(att->impl_type, "SMIL_SyncTolerance");
                } else if (!strcmp(att->svg_name, "transform")) {
                        strcpy(att->impl_type, "SVG_Transform");
                } else if (!strcmp(att->svg_name, "gradientTransform")) {
                        strcpy(att->impl_type, "SVG_Transform");
                } else if (!strcmp(att->svg_name, "focusable")) {
                        strcpy(att->impl_type, "SVG_Focusable");
                } else if (!strcmp(att->svg_name, "event") || !strcmp(att->svg_name, "ev:event")) {
                        strcpy(att->impl_type, "XMLEV_Event");
                } else if (!strcmp(att->svg_type, "IRI.datatype")) {
                        strcpy(att->impl_type, "XMLRI");
                } else if (!strcmp(att->svg_type, "IDREF.datatype")) {
                        strcpy(att->impl_type, "XML_IDREF");
                } else if (strstr(att->svg_type, "datatype")) {
                        char *tmp;
                        sprintf(att->impl_type, "SVG_%s", att->svg_type);
                        tmp = att->impl_type;
                        while ( (tmp = strstr(tmp, "-")) ) {
                                *tmp='_';
                                tmp++;
                        }
                        tmp = att->impl_type;
                        while ( (tmp = strstr(tmp, ".")) ) {
                                *tmp='_';
                                tmp++;
                        }
                        tmp = att->impl_type;;
                        if ( (tmp = strstr(tmp, "datatype")) ) {
                                tmp--;
                                *tmp = 0;
                        }
                }
        }
}

void getAttributeType(xmlDocPtr doc, xmlXPathContextPtr xpathCtx,
                      xmlNodePtr attributeNode, SVGGenAttribute *a)
{

        xmlNodeSetPtr refNodes;
        xpathCtx->node = attributeNode;
        refNodes = findNodes(xpathCtx, ".//rng:ref");
        if (refNodes->nodeNr == 0) {
                //a->svg_type = xmlStrdup("0_ref_type");
        } else if (refNodes->nodeNr == 1) {
                xmlNodePtr ref = refNodes->nodeTab[0];
                a->svg_type = xmlStrdup(xmlGetProp(ref, "name"));
        } else {
                //a->svg_type = xmlStrdup("N_ref_type");
        }
}

void getRealAttributes(xmlDocPtr doc, xmlXPathContextPtr xpathCtx, xmlNodePtr newCtxNode,
                       GF_List *attributes)
{
        xmlNodeSetPtr attributeNodes;
        int k;
        u32 j;

        xpathCtx->node = newCtxNode;
        attributeNodes = findNodes(xpathCtx, ".//rng:attribute");
        for (k = 0; k < attributeNodes->nodeNr; k++)    {
                Bool already_exists = 0;
                xmlNodePtr attributeNode = attributeNodes->nodeTab[k];
                if (attributeNode->type == XML_ELEMENT_NODE) {
                        SVGGenAttribute *a = NewSVGGenAttribute();
                        a->svg_name = xmlGetProp(attributeNode, "name");
                        a->optional = xmlStrEqual(attributeNode->parent->name, "optional");
                        svgNameToImplementationName(a->svg_name, a->implementation_name);
                        getAttributeType(doc, xpathCtx, attributeNode, a);
                        setAttributeType(a);
                        for (j=0; j<gf_list_count(attributes); j++) {
                                SVGGenAttribute *ta = gf_list_get(attributes, j);
                                if (xmlStrEqual(ta->svg_name, a->svg_name)) {
                                        already_exists = 1;
                                        break;
                                }
                        }
                        if (already_exists) {
                                deleteSVGGenAttribute(&a);
                        } else {
                                //fprintf(stdout, "Adding attribute %s to element %s\n",a->svg_name, e->svg_name);
                                gf_list_add(attributes, a);
                        }
                }
        }
}

SVGGenAttrGrp *getOneGlobalAttrGrp(xmlDocPtr doc, xmlXPathContextPtr xpathCtx, xmlChar *name)
{
        SVGGenAttrGrp *attgrp = NULL;
        xmlNodeSetPtr attrGrpDefNodes;
        xmlChar *expr;
        u32 j;
        int i, l;

        /* attributes group already resolved */
        for (j = 0; j < gf_list_count(globalAttrGrp); j++) {
                SVGGenAttrGrp *attgrp = gf_list_get(globalAttrGrp, j);
                if (!strcmp(attgrp->name, name)) {
                        return attgrp;
                }
        }

        /* new attributes group */
        expr = xmlStrdup("//rng:define[@name=\"");
        expr = xmlStrcat(expr, name);
        expr = xmlStrcat(expr, "\" and not(rng:empty) and not(rng:notAllowed)]");
        attrGrpDefNodes = findNodes(xpathCtx, expr);
        if (!attrGrpDefNodes->nodeNr) {
                fprintf(stdout, "Warning: found 0 non-empty or allowed definition for the Group of Attributes: %s\n", name);
                return NULL;
        }
        attgrp = NewSVGGenAttrGrp();
        attgrp->name = gf_strdup(name);
        svgNameToImplementationName(attgrp->name, attgrp->imp_name);
        gf_list_add(globalAttrGrp, attgrp);

        for (i = 0; i < attrGrpDefNodes->nodeNr; i++) {
                xmlNodePtr attrGrp = attrGrpDefNodes->nodeTab[i];
                getRealAttributes(doc, xpathCtx, attrGrp, attgrp->attrs);

                {
                        xmlNodeSetPtr refNodes;
                        xpathCtx->node = attrGrp;
                        refNodes = findNodes(xpathCtx, ".//rng:ref");
                        for (l = 0; l < refNodes->nodeNr; l++) {
                                xmlNodePtr ref = refNodes->nodeTab[l];
                                xmlChar *rname = xmlGetProp(ref, "name");
                                if (xmlStrstr(rname, ".attr")) {
                                        SVGGenAttrGrp *g2 = getOneGlobalAttrGrp(doc, xpathCtx, rname);
                                        if (g2) {
                                                gf_list_add(attgrp->attrgrps, g2);
                                        }
                                }
                        }
                }
        }
        return attgrp;
}

void getAllGlobalAttrGrp(xmlDocPtr doc, xmlXPathContextPtr xpathCtx)
{
        xmlNodeSetPtr elementNodes = findNodes(xpathCtx, "//rng:define");
        int k;
        for (k = 0; k < elementNodes->nodeNr; k++)      {
                xmlNodePtr elementNode = elementNodes->nodeTab[k];
                if (elementNode->type == XML_ELEMENT_NODE) {
                        xmlChar *name = NULL;
                        name = xmlGetProp(elementNode, "name");
                        if (xmlStrstr(name, ".attr")) {
                                getOneGlobalAttrGrp(doc, xpathCtx, name);
                        }
                }
        }
}

GF_List *getElements(xmlDocPtr doc, xmlXPathContextPtr xpathCtx)
{
        xmlChar *expr;
        GF_List *elements = gf_list_new();
        xmlNodeSetPtr ATNodes;
        xmlNodeSetPtr refNodes, elementNodes = findNodes(xpathCtx, "//rng:element");
        int k, j;
        u32 i;

        for (k = 0; k < elementNodes->nodeNr; k++)      {
                xmlNodePtr elementNode = elementNodes->nodeTab[k];
                if (elementNode->type == XML_ELEMENT_NODE) {
                        SVGGenElement *e = NewSVGGenElement();
                        e->svg_name = xmlStrdup(xmlGetProp(elementNode, "name"));
                        //fprintf(stdout, "\n\tElement %s\n", e->svg_name);

                        svgNameToImplementationName(e->svg_name, e->implementation_name);

                        /* getting the <define name="element.AT"/> */
                        expr = xmlStrdup("//rng:define[@name=\"");
                        if (!xmlStrcmp(e->svg_name, "polygon") || !xmlStrcmp(e->svg_name, "polyline")) {
                                expr = xmlStrcat(expr, "polyCommon");
                        } else {
                                expr = xmlStrcat(expr, e->svg_name);
                        }
                        expr = xmlStrcat(expr, ".AT\"]");
                        ATNodes = findNodes(xpathCtx, expr);
                        if (ATNodes->nodeNr) {

                                /* dealing with attributes defined in groups of attributes */
                                xpathCtx->node = ATNodes->nodeTab[0];
                                refNodes = findNodes(xpathCtx, ".//rng:ref");
                                for (j = 0; j <refNodes->nodeNr; j++) {
                                        xmlNodePtr refNode = refNodes->nodeTab[j];
                                        char *name = xmlGetProp(refNode, "name");
                                        for (i = 0; i < gf_list_count(globalAttrGrp); i++) {
                                                SVGGenAttrGrp *a = gf_list_get(globalAttrGrp, i);
                                                if (!strcmp(a->name, name)) {
                                                        if (isGenericAttributesGroup(a->name)) {
                                                                setGenericAttributesFlags(a->name, e);
                                                                flattenAttributeGroup(*a, e, 1);
                                                        } else {
                                                                flattenAttributeGroup(*a, e, 0);
                                                        }
                                                        break;
                                                }
                                        }
                                }

                                /* dealing with attributes defined directly here */
                                getRealAttributes(doc, xpathCtx, ATNodes->nodeTab[0], e->attributes);
                        }

                        /* checking if this element is already present in the list of possible elements
                           and if not, adding it */
                        {
                                Bool found = 0;
                                for (i=0; i<gf_list_count(elements); i++) {
                                        SVGGenElement *etmp = gf_list_get(elements, i);
                                        if (!strcmp(etmp->svg_name, e->svg_name)) {
                                                found = 1;
                                                break;
                                        }
                                }
                                if (!found) gf_list_add(elements, e);
                        }
                }
        }
        return elements;
}

/*type: 0: header, 1: source*/
FILE *BeginFile(u32 type)
{
        FILE *f;

        char sPath[GF_MAX_PATH];

        if (!type) {
#ifdef LOCAL_SVG_NODES
                sprintf(sPath, "nodes_svg.h", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
#else
                if (generation_mode == 1)
                        sprintf(sPath, "..%c..%c..%c..%cinclude%cgpac%cnodes_svg_sa.h", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
                else if (generation_mode == 2)
                        sprintf(sPath, "..%c..%c..%c..%cinclude%cgpac%cnodes_svg_sani.h", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
                else if (generation_mode == 3)
                        sprintf(sPath, "..%c..%c..%c..%cinclude%cgpac%cnodes_svg_da.h", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);

#endif
        } else if (type==1) {
#ifdef LOCAL_SVG_NODES
                sprintf(sPath, "svg_nodes.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
#else
                if (generation_mode == 1)
                        sprintf(sPath, "..%c..%c..%c..%csrc%cscenegraph%csvg_nodes_sa.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
                else if (generation_mode == 2)
                        sprintf(sPath, "..%c..%c..%c..%csrc%cscenegraph%csvg_nodes_sani.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
                else if (generation_mode == 3)
                        sprintf(sPath, "..%c..%c..%c..%csrc%cscenegraph%csvg_nodes_da.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
#endif
        } else {
#ifdef LOCAL_SVG_NODES
                sprintf(sPath, "lsr_tables.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
#else
                if (generation_mode == 1)
                        sprintf(sPath, "..%c..%c..%c..%csrc%claser%clsr_tables_sa.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
                else if (generation_mode == 2)
                        sprintf(sPath, "..%c..%c..%c..%csrc%claser%clsr_tables_sani.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
                else if (generation_mode == 3)
                        sprintf(sPath, "..%c..%c..%c..%csrc%claser%clsr_tables.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);

#endif
        }

        f = gf_fopen(sPath, "wt");
        fprintf(f, "%s\n", COPYRIGHT);

        {
                time_t rawtime;
                time(&rawtime);
                fprintf(f, "\n/*\n\tDO NOT MOFIFY - File generated on GMT %s\n\tBY SVGGen for GPAC Version %s\n*/\n\n", asctime(gmtime(&rawtime)), GPAC_VERSION);
        }

        if (!type) {
                if (generation_mode == 1) {
                        fprintf(f, "#ifndef _GF_SVG_SA_NODES_H\n");
                        fprintf(f, "#define _GF_SVG_SA_NODES_H\n\n");
                } else if (generation_mode == 2) {
                        fprintf(f, "#ifndef _GF_SVG_SANI_NODES_H\n");
                        fprintf(f, "#define _GF_SVG_SANI_NODES_H\n\n");
                } else if (generation_mode == 3) {
                        fprintf(f, "#ifndef _GF_SVG_NODES_H\n");
                        fprintf(f, "#define _GF_SVG_NODES_H\n\n");
                }
                fprintf(f, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");
        }
        return f;
}

void EndFile(FILE *f, u32 type)
{
        if (!type) {
                fprintf(f, "#ifdef __cplusplus\n}\n#endif\n\n");
                if (generation_mode == 1) fprintf(f, "\n\n#endif\t\t/*_GF_SVG_SA_NODES_H*/\n\n");
                if (generation_mode == 2) fprintf(f, "\n\n#endif\t\t/*_GF_SVG_SANI_NODES_H*/\n\n");
                if (generation_mode == 3) fprintf(f, "\n\n#endif\t\t/*_GF_SVG_NODES_H*/\n\n");
        } else {
                fprintf(f, "\n");
        }
        gf_fclose(f);
}

void generateAttributes(FILE *output, GF_List *attributes, Bool inDefine)
{
        u32 i;
        for (i = 0; i<gf_list_count(attributes); i++) {
                SVGGenAttribute *att = (SVGGenAttribute *)gf_list_get(attributes, i);
                if (inDefine)
                        if (i == gf_list_count(attributes) -1)
                                fprintf(output, "\t%s %s;\n", att->impl_type, att->implementation_name);
                        else
                                fprintf(output, "\t%s %s; \\\n", att->impl_type, att->implementation_name);
                else
                        fprintf(output, "\t%s %s;\n", att->impl_type, att->implementation_name);
        }
}

/*
u32 generateAttributesGroupInfo(FILE *output, char * elt_imp_name, SVGGenAttrGrp *attgrp, u32 i)
{
        u32 att_index = i;
        u32 k;
        for (k=0; k<gf_list_count(attgrp->attrgrps); k++) {
                SVGGenAttrGrp *ag = gf_list_get(attgrp->attrgrps, k);
                att_index = generateAttributesGroupInfo(output, elt_imp_name, ag, att_index);
        }
        for (k=0; k<gf_list_count(attgrp->attrs); k++) {
                SVGGenAttribute *at = gf_list_get(attgrp->attrs, k);
                generateAttributeInfo(output, elt_imp_name, at, att_index++);
        }
        return att_index;
}
*/

void replaceIncludes(xmlDocPtr doc, xmlXPathContextPtr xpathCtx)
{
        int k;
        xmlNodeSetPtr nodes;
        xmlXPathObjectPtr xpathObj;

        /* Get all the RNG elements */
        xpathObj = xmlXPathEvalExpression("//rng:include", xpathCtx);
        if(xpathObj == NULL || xpathObj->type != XPATH_NODESET) return;

        nodes = xpathObj->nodesetval;

        for (k = 0; k < nodes->nodeNr; k++)     {
                xmlNodePtr node = nodes->nodeTab[k];
                if (node->type == XML_ELEMENT_NODE) {
                        xmlChar *href;
                        xmlDocPtr sub_doc;

                        href = xmlGetNoNsProp(node, "href");
                        sub_doc = xmlParseFile(href);
                        xmlReplaceNode(nodes->nodeTab[k], xmlDocGetRootElement(sub_doc));
                }
        }
        xmlXPathFreeObject(xpathObj);
}

int main(int argc, char **argv)
{
        xmlDocPtr doc = NULL;
        xmlXPathContextPtr xpathCtx = NULL;
        GF_List *svg_elements = NULL;

        xmlInitParser();
        LIBXML_TEST_VERSION

        doc = xmlParseFile(argv[1]);
        if (!doc) {
                printf("error: could not parse file %s\n", argv[1]);
                return -1;
        }

        xpathCtx = xmlXPathNewContext(doc);
        if(xpathCtx == NULL) {
                fprintf(stderr,"Error: unable to create new XPath context\n");
                xmlFreeDoc(doc);
                return(-1);
        }
        xmlXPathRegisterNs(xpathCtx, RNG_PREFIX, RNG_NS);
        xmlXPathRegisterNs(xpathCtx, RNGA_PREFIX, RNGA_NS);
        xmlXPathRegisterNs(xpathCtx, SVGA_PREFIX, SVGA_NS);

        replaceIncludes(doc, xpathCtx);
        xmlSaveFile("completerng_props.xml", doc);

        globalAttrGrp = gf_list_new();
        getAllGlobalAttrGrp(doc, xpathCtx);

        svg_elements = getElements(doc, xpathCtx);
        svg_elements = sortElements(svg_elements);

        if (argv[2] && !strcmp(argv[2], "-html")) {
                generate_table(svg_elements);
        } else {
                if (generation_mode == 1) generateSVGCode_V1(svg_elements);
                if (generation_mode == 2) generateSVGCode_V2(svg_elements);
                if (generation_mode == 3) generateSVGCode_V3(svg_elements);
        }

        xmlXPathFreeContext(xpathCtx);
        //xmlFreeDoc(doc);

        xmlCleanupParser();
        return 0;
}



/* [<][>][^][v][top][bottom][index][help] */