LCOV - code coverage report
Current view: top level - scenegraph - xml_ns.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 203 357 56.9 %
Date: 2021-04-29 23:48:07 Functions: 20 23 87.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre - Cyril Concolato
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / SVG Scene Graph sub-project
       9             :  *
      10             :  *  GPAC is free software, TYPE, 0 }, you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation, TYPE, 0 }, either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY, TYPE, 0 }, without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library, TYPE, 0 }, see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : #include <gpac/internal/scenegraph_dev.h>
      28             : 
      29             : #ifndef GPAC_DISABLE_SVG
      30             : 
      31             : #include <gpac/nodes_svg.h>
      32             : 
      33             : enum
      34             : {
      35             :         /*no specific criteria*/
      36             :         GF_SVG_ATTOPT_NONE = 0,
      37             :         /*attribute only valid for SMIL anims*/
      38             :         GF_SVG_ATTOPT_SMIL = 1,
      39             :         /*attribute only valid for TEXT*/
      40             :         GF_SVG_ATTOPT_TEXT = 2,
      41             :         /*attribute only valid for cursor*/
      42             :         GF_SVG_ATTOPT_CURSOR = 3,
      43             :         /*attribute only valid for listener*/
      44             :         GF_SVG_ATTOPT_LISTENER = 4,
      45             :         /*attribute only valid for filters*/
      46             :         GF_SVG_ATTOPT_FILTER = 5,
      47             : } GF_SVGAttOption;
      48             : 
      49             : /* unused XBL tags (deprecated)
      50             : 
      51             :         TAG_XBL_ATT_RANGE_FIRST = TAG_SVG_ATT_RANGE_FIRST + 256,
      52             :         TAG_XBL_ATT_id = TAG_XBL_ATT_RANGE_FIRST,
      53             :         TAG_XBL_ATT_extends,
      54             :         TAG_XBL_ATT_display,
      55             :         TAG_XBL_ATT_inheritstyle,
      56             :         TAG_XBL_ATT_includes,
      57             :         TAG_XBL_ATT_name,
      58             :         TAG_XBL_ATT_implements,
      59             :         TAG_XBL_ATT_type,
      60             :         TAG_XBL_ATT_readonly,
      61             :         TAG_XBL_ATT_onget,
      62             :         TAG_XBL_ATT_onset,
      63             :         TAG_XBL_ATT_event,
      64             :         TAG_XBL_ATT_action,
      65             :         TAG_XBL_ATT_phase,
      66             :         TAG_XBL_ATT_button,
      67             :         TAG_XBL_ATT_modifiers,
      68             :         TAG_XBL_ATT_keycode,
      69             :         TAG_XBL_ATT_key,
      70             :         TAG_XBL_ATT_charcode,
      71             :         TAG_XBL_ATT_clickcount,
      72             :         TAG_XBL_ATT_command,
      73             :         TAG_XBL_ATT_preventdefault,
      74             :         TAG_XBL_ATT_src,
      75             : */
      76             : static const struct xml_att_def {
      77             :         const char *name;
      78             :         u32 tag;
      79             :         u32 type;
      80             :         u32 opts;
      81             :         u32 xmlns;
      82             : } xml_attributes [] =
      83             : {
      84             :         /*XML base*/
      85             :         { "id", TAG_XML_ATT_id, SVG_ID_datatype, 0, GF_XMLNS_XML } ,
      86             :         { "base", TAG_XML_ATT_base, XMLRI_datatype, 0, GF_XMLNS_XML } ,
      87             :         { "lang", TAG_XML_ATT_lang, SVG_LanguageID_datatype, 0, GF_XMLNS_XML } ,
      88             :         { "space", TAG_XML_ATT_space, XML_Space_datatype, 0, GF_XMLNS_XML } ,
      89             : 
      90             :         /*XLINK*/
      91             :         { "type", TAG_XLINK_ATT_type, DOM_String_datatype, 0, GF_XMLNS_XLINK },
      92             :         { "role", TAG_XLINK_ATT_role, XMLRI_datatype, 0, GF_XMLNS_XLINK },
      93             :         { "arcrole", TAG_XLINK_ATT_arcrole, XMLRI_datatype, 0, GF_XMLNS_XLINK },
      94             :         { "title", TAG_XLINK_ATT_title, DOM_String_datatype, 0, GF_XMLNS_XLINK },
      95             :         { "href", TAG_XLINK_ATT_href, XMLRI_datatype, 0, GF_XMLNS_XLINK },
      96             :         { "show", TAG_XLINK_ATT_show, DOM_String_datatype, 0, GF_XMLNS_XLINK },
      97             :         { "actuate", TAG_XLINK_ATT_actuate, DOM_String_datatype, 0, GF_XMLNS_XLINK },
      98             : 
      99             :         /*XML Events*/
     100             :         { "event", TAG_XMLEV_ATT_event, XMLEV_Event_datatype, 0, GF_XMLNS_XMLEV },
     101             :         { "phase", TAG_XMLEV_ATT_phase, XMLEV_Phase_datatype, 0, GF_XMLNS_XMLEV },
     102             :         { "propagate", TAG_XMLEV_ATT_propagate, XMLEV_Propagate_datatype, 0, GF_XMLNS_XMLEV },
     103             :         { "defaultAction", TAG_XMLEV_ATT_defaultAction, XMLEV_DefaultAction_datatype, 0, GF_XMLNS_XMLEV },
     104             :         { "observer", TAG_XMLEV_ATT_observer, XML_IDREF_datatype, 0, GF_XMLNS_XMLEV },
     105             :         { "target", TAG_XMLEV_ATT_target, XML_IDREF_datatype, 0, GF_XMLNS_XMLEV },
     106             :         { "handler", TAG_XMLEV_ATT_handler, XMLRI_datatype, 0, GF_XMLNS_XMLEV },
     107             : 
     108             : 
     109             :         { "id", TAG_SVG_ATT_id, SVG_ID_datatype, 0, GF_XMLNS_SVG } ,
     110             :         { "class", TAG_SVG_ATT__class, DOM_String_datatype, 0, GF_XMLNS_SVG },
     111             :         { "requiredFeatures", TAG_SVG_ATT_requiredFeatures, XMLRI_List_datatype, 0, GF_XMLNS_SVG },
     112             :         { "requiredExtensions", TAG_SVG_ATT_requiredExtensions, XMLRI_List_datatype, 0, GF_XMLNS_SVG },
     113             :         { "requiredFormats", TAG_SVG_ATT_requiredFormats, DOM_StringList_datatype, 0, GF_XMLNS_SVG },
     114             :         { "requiredFonts", TAG_SVG_ATT_requiredFonts, DOM_StringList_datatype, 0, GF_XMLNS_SVG },
     115             :         { "systemLanguage", TAG_SVG_ATT_systemLanguage, DOM_StringList_datatype, 0, GF_XMLNS_SVG },
     116             :         { "display", TAG_SVG_ATT_display, SVG_Display_datatype, 0, GF_XMLNS_SVG },
     117             :         { "visibility", TAG_SVG_ATT_visibility, SVG_Visibility_datatype, 0, GF_XMLNS_SVG },
     118             :         { "image-rendering", TAG_SVG_ATT_image_rendering, SVG_RenderingHint_datatype, 0, GF_XMLNS_SVG },
     119             :         { "pointer-events", TAG_SVG_ATT_pointer_events, SVG_PointerEvents_datatype, 0, GF_XMLNS_SVG },
     120             :         { "shape-rendering", TAG_SVG_ATT_shape_rendering, SVG_RenderingHint_datatype, 0, GF_XMLNS_SVG },
     121             :         { "text-rendering", TAG_SVG_ATT_text_rendering, SVG_RenderingHint_datatype, 0, GF_XMLNS_SVG },
     122             :         { "audio-level", TAG_SVG_ATT_audio_level, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     123             :         { "viewport-fill", TAG_SVG_ATT_viewport_fill, SVG_Paint_datatype, 0, GF_XMLNS_SVG },
     124             :         { "viewport-fill-opacity", TAG_SVG_ATT_viewport_fill_opacity, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     125             :         { "overflow", TAG_SVG_ATT_overflow, DOM_String_datatype, 0, GF_XMLNS_SVG },
     126             :         { "fill-opacity", TAG_SVG_ATT_fill_opacity, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     127             :         { "stroke-opacity", TAG_SVG_ATT_stroke_opacity, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     128             :         { "fill-rule", TAG_SVG_ATT_fill_rule, SVG_FillRule_datatype, 0, GF_XMLNS_SVG },
     129             :         { "stroke", TAG_SVG_ATT_stroke, SVG_Paint_datatype, 0, GF_XMLNS_SVG },
     130             :         { "stroke-dasharray", TAG_SVG_ATT_stroke_dasharray, SVG_StrokeDashArray_datatype, 0, GF_XMLNS_SVG },
     131             :         { "stroke-dashoffset", TAG_SVG_ATT_stroke_dashoffset, SVG_Length_datatype, 0, GF_XMLNS_SVG },
     132             :         { "stroke-linecap", TAG_SVG_ATT_stroke_linecap, SVG_StrokeLineCap_datatype, 0, GF_XMLNS_SVG },
     133             :         { "stroke-linejoin", TAG_SVG_ATT_stroke_linejoin, SVG_StrokeLineJoin_datatype, 0, GF_XMLNS_SVG },
     134             :         { "stroke-miterlimit", TAG_SVG_ATT_stroke_miterlimit, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     135             :         { "stroke-width", TAG_SVG_ATT_stroke_width, SVG_Length_datatype, 0, GF_XMLNS_SVG },
     136             :         { "color", TAG_SVG_ATT_color, SVG_Paint_datatype, 0, GF_XMLNS_SVG },
     137             :         { "color-rendering", TAG_SVG_ATT_color_rendering, SVG_RenderingHint_datatype, 0, GF_XMLNS_SVG },
     138             :         { "vector-effect", TAG_SVG_ATT_vector_effect, SVG_VectorEffect_datatype, 0, GF_XMLNS_SVG },
     139             :         { "solid-color", TAG_SVG_ATT_solid_color, SVG_Paint_datatype, 0, GF_XMLNS_SVG },
     140             :         { "solid-opacity", TAG_SVG_ATT_solid_opacity, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     141             :         { "display-align", TAG_SVG_ATT_display_align, SVG_DisplayAlign_datatype, 0, GF_XMLNS_SVG },
     142             :         { "line-increment", TAG_SVG_ATT_line_increment, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     143             :         { "stop-color", TAG_SVG_ATT_stop_color, SVG_Paint_datatype, 0, GF_XMLNS_SVG },
     144             :         { "stop-opacity", TAG_SVG_ATT_stop_opacity, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     145             :         { "font-family", TAG_SVG_ATT_font_family, SVG_FontFamily_datatype, 0, GF_XMLNS_SVG },
     146             :         { "font-size", TAG_SVG_ATT_font_size, SVG_FontSize_datatype, 0, GF_XMLNS_SVG },
     147             :         { "font-style", TAG_SVG_ATT_font_style, SVG_FontStyle_datatype, 0, GF_XMLNS_SVG },
     148             :         { "font-variant", TAG_SVG_ATT_font_variant, SVG_FontVariant_datatype, 0, GF_XMLNS_SVG },
     149             :         { "font-weight", TAG_SVG_ATT_font_weight, SVG_FontWeight_datatype, 0, GF_XMLNS_SVG },
     150             :         { "text-anchor", TAG_SVG_ATT_text_anchor, SVG_TextAnchor_datatype, 0, GF_XMLNS_SVG },
     151             :         { "text-align", TAG_SVG_ATT_text_align, SVG_TextAlign_datatype, 0, GF_XMLNS_SVG },
     152             :         { "text-decoration", TAG_SVG_ATT_text_decoration, DOM_String_datatype, 0, GF_XMLNS_SVG },
     153             :         { "focusHighlight", TAG_SVG_ATT_focusHighlight, SVG_FocusHighlight_datatype, 0, GF_XMLNS_SVG },
     154             :         { "externalResourcesRequired", TAG_SVG_ATT_externalResourcesRequired, SVG_Boolean_datatype, 0, GF_XMLNS_SVG },
     155             :         { "focusable", TAG_SVG_ATT_focusable, SVG_Focusable_datatype, 0, GF_XMLNS_SVG },
     156             :         { "nav-next", TAG_SVG_ATT_nav_next, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     157             :         { "nav-prev", TAG_SVG_ATT_nav_prev, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     158             :         { "nav-up", TAG_SVG_ATT_nav_up, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     159             :         { "nav-up-right", TAG_SVG_ATT_nav_up_right, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     160             :         { "nav-right", TAG_SVG_ATT_nav_right, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     161             :         { "nav-down-right", TAG_SVG_ATT_nav_down_right, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     162             :         { "nav-down", TAG_SVG_ATT_nav_down, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     163             :         { "nav-down-left", TAG_SVG_ATT_nav_down_left, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     164             :         { "nav-left", TAG_SVG_ATT_nav_left, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     165             :         { "nav-up-left", TAG_SVG_ATT_nav_up_left, SVG_Focus_datatype, 0, GF_XMLNS_SVG },
     166             :         { "transform", TAG_SVG_ATT_transform, SVG_Transform_datatype, 0, GF_XMLNS_SVG },
     167             :         { "target", TAG_SVG_ATT_target, DOM_String_datatype, 0, GF_XMLNS_SVG },
     168             :         { "attributeName", TAG_SVG_ATT_attributeName, SMIL_AttributeName_datatype, 0, GF_XMLNS_SVG },
     169             :         { "attributeType", TAG_SVG_ATT_attributeType, SMIL_AttributeType_datatype, 0, GF_XMLNS_SVG },
     170             :         { "begin", TAG_SVG_ATT_begin, SMIL_Times_datatype, 0, GF_XMLNS_SVG },
     171             :         { "dur", TAG_SVG_ATT_dur, SMIL_Duration_datatype, 0, GF_XMLNS_SVG },
     172             :         { "end", TAG_SVG_ATT_end, SMIL_Times_datatype, 0, GF_XMLNS_SVG },
     173             :         { "repeatCount", TAG_SVG_ATT_repeatCount, SMIL_RepeatCount_datatype, 0, GF_XMLNS_SVG },
     174             :         { "repeatDur", TAG_SVG_ATT_repeatDur, SMIL_Duration_datatype, 0, GF_XMLNS_SVG },
     175             :         { "restart", TAG_SVG_ATT_restart, SMIL_Restart_datatype, 0, GF_XMLNS_SVG },
     176             :         { "min", TAG_SVG_ATT_min, SMIL_Duration_datatype, 0, GF_XMLNS_SVG },
     177             :         { "max", TAG_SVG_ATT_max, SMIL_Duration_datatype, 0, GF_XMLNS_SVG },
     178             :         { "to", TAG_SVG_ATT_to, SMIL_AnimateValue_datatype, 0, GF_XMLNS_SVG },
     179             :         { "calcMode", TAG_SVG_ATT_calcMode, SMIL_CalcMode_datatype, 0, GF_XMLNS_SVG },
     180             :         { "values", TAG_SVG_ATT_values, SMIL_AnimateValues_datatype, 0, GF_XMLNS_SVG },
     181             :         { "keyTimes", TAG_SVG_ATT_keyTimes, SMIL_KeyTimes_datatype, 0, GF_XMLNS_SVG },
     182             :         { "keySplines", TAG_SVG_ATT_keySplines, SMIL_KeySplines_datatype, 0, GF_XMLNS_SVG },
     183             :         { "from", TAG_SVG_ATT_from, SMIL_AnimateValue_datatype, 0, GF_XMLNS_SVG },
     184             :         { "by", TAG_SVG_ATT_by, SMIL_AnimateValue_datatype, 0, GF_XMLNS_SVG },
     185             :         { "additive", TAG_SVG_ATT_additive, SMIL_Additive_datatype, 0, GF_XMLNS_SVG },
     186             :         { "accumulate", TAG_SVG_ATT_accumulate, SMIL_Accumulate_datatype, 0, GF_XMLNS_SVG },
     187             :         { "path", TAG_SVG_ATT_path, SVG_PathData_datatype, 0, GF_XMLNS_SVG },
     188             :         { "keyPoints", TAG_SVG_ATT_keyPoints, SMIL_KeyPoints_datatype, 0, GF_XMLNS_SVG },
     189             :         { "origin", TAG_SVG_ATT_origin, DOM_String_datatype, 0, GF_XMLNS_SVG },
     190             :         { "clipBegin", TAG_SVG_ATT_clipBegin, SVG_Clock_datatype, 0, GF_XMLNS_SVG },
     191             :         { "clipEnd", TAG_SVG_ATT_clipEnd, SVG_Clock_datatype, 0, GF_XMLNS_SVG },
     192             :         { "syncBehavior", TAG_SVG_ATT_syncBehavior, SMIL_SyncBehavior_datatype, 0, GF_XMLNS_SVG },
     193             :         { "syncTolerance", TAG_SVG_ATT_syncTolerance, SMIL_SyncTolerance_datatype, 0, GF_XMLNS_SVG },
     194             :         { "syncMaster", TAG_SVG_ATT_syncMaster, SVG_Boolean_datatype, 0, GF_XMLNS_SVG },
     195             :         { "syncReference", TAG_SVG_ATT_syncReference, XMLRI_datatype, 0, GF_XMLNS_SVG },
     196             :         { "width", TAG_SVG_ATT_width, SVG_Length_datatype, 0, GF_XMLNS_SVG },
     197             :         { "height", TAG_SVG_ATT_height, SVG_Length_datatype, 0, GF_XMLNS_SVG },
     198             :         { "preserveAspectRatio", TAG_SVG_ATT_preserveAspectRatio, SVG_PreserveAspectRatio_datatype, 0, GF_XMLNS_SVG },
     199             :         { "initialVisibility", TAG_SVG_ATT_initialVisibility, SVG_InitialVisibility_datatype, 0, GF_XMLNS_SVG },
     200             :         { "cx", TAG_SVG_ATT_cx, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     201             :         { "cy", TAG_SVG_ATT_cy, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     202             :         { "r", TAG_SVG_ATT_r, SVG_Length_datatype, 0, GF_XMLNS_SVG },
     203             :         { "rx", TAG_SVG_ATT_rx, SVG_Length_datatype, 0, GF_XMLNS_SVG },
     204             :         { "ry", TAG_SVG_ATT_ry, SVG_Length_datatype, 0, GF_XMLNS_SVG },
     205             :         { "horiz-adv-x", TAG_SVG_ATT_horiz_adv_x, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     206             :         { "horiz-origin-x", TAG_SVG_ATT_horiz_origin_x, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     207             :         { "font-stretch", TAG_SVG_ATT_font_stretch, DOM_String_datatype, 0, GF_XMLNS_SVG },
     208             :         { "unicode-range", TAG_SVG_ATT_unicode_range, DOM_String_datatype, 0, GF_XMLNS_SVG },
     209             :         { "panose-1", TAG_SVG_ATT_panose_1, DOM_String_datatype, 0, GF_XMLNS_SVG },
     210             :         { "widths", TAG_SVG_ATT_widths, DOM_String_datatype, 0, GF_XMLNS_SVG },
     211             :         { "bbox", TAG_SVG_ATT_bbox, DOM_String_datatype, 0, GF_XMLNS_SVG },
     212             :         { "units-per-em", TAG_SVG_ATT_units_per_em, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     213             :         { "stemv", TAG_SVG_ATT_stemv, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     214             :         { "stemh", TAG_SVG_ATT_stemh, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     215             :         { "slope", TAG_SVG_ATT_slope, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     216             :         { "cap-height", TAG_SVG_ATT_cap_height, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     217             :         { "x-height", TAG_SVG_ATT_x_height, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     218             :         { "accent-height", TAG_SVG_ATT_accent_height, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     219             :         { "ascent", TAG_SVG_ATT_ascent, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     220             :         { "descent", TAG_SVG_ATT_descent, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     221             :         { "ideographic", TAG_SVG_ATT_ideographic, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     222             :         { "alphabetic", TAG_SVG_ATT_alphabetic, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     223             :         { "mathematical", TAG_SVG_ATT_mathematical, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     224             :         { "hanging", TAG_SVG_ATT_hanging, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     225             :         { "underline-position", TAG_SVG_ATT_underline_position, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     226             :         { "underline-thickness", TAG_SVG_ATT_underline_thickness, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     227             :         { "strikethrough-position", TAG_SVG_ATT_strikethrough_position, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     228             :         { "strikethrough-thickness", TAG_SVG_ATT_strikethrough_thickness, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     229             :         { "overline-position", TAG_SVG_ATT_overline_position, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     230             :         { "overline-thickness", TAG_SVG_ATT_overline_thickness, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     231             :         { "d", TAG_SVG_ATT_d, SVG_PathData_datatype, 0, GF_XMLNS_SVG },
     232             :         { "unicode", TAG_SVG_ATT_unicode, DOM_String_datatype, 0, GF_XMLNS_SVG },
     233             :         { "glyph-name", TAG_SVG_ATT_glyph_name, DOM_String_datatype, 0, GF_XMLNS_SVG },
     234             :         { "arabic-form", TAG_SVG_ATT_arabic_form, DOM_String_datatype, 0, GF_XMLNS_SVG },
     235             :         { "lang", TAG_SVG_ATT_lang, DOM_StringList_datatype, 0, GF_XMLNS_SVG },
     236             :         { "u1", TAG_SVG_ATT_u1, DOM_String_datatype, 0, GF_XMLNS_SVG },
     237             :         { "g1", TAG_SVG_ATT_g1, DOM_String_datatype, 0, GF_XMLNS_SVG },
     238             :         { "u2", TAG_SVG_ATT_u2, DOM_String_datatype, 0, GF_XMLNS_SVG },
     239             :         { "g2", TAG_SVG_ATT_g2, DOM_String_datatype, 0, GF_XMLNS_SVG },
     240             :         { "k", TAG_SVG_ATT_k, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     241             :         { "opacity", TAG_SVG_ATT_opacity, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     242             :         { "x1", TAG_SVG_ATT_x1, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     243             :         { "y1", TAG_SVG_ATT_y1, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     244             :         { "x2", TAG_SVG_ATT_x2, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     245             :         { "y2", TAG_SVG_ATT_y2, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     246             :         { "gradientUnits", TAG_SVG_ATT_gradientUnits, SVG_GradientUnit_datatype, 0, GF_XMLNS_SVG },
     247             :         { "filterUnits", TAG_SVG_ATT_filterUnits, SVG_GradientUnit_datatype, 0, GF_XMLNS_SVG },
     248             :         { "spreadMethod", TAG_SVG_ATT_spreadMethod, SVG_SpreadMethod_datatype, 0, GF_XMLNS_SVG },
     249             :         { "gradientTransform", TAG_SVG_ATT_gradientTransform, SVG_Transform_datatype, 0, GF_XMLNS_SVG },
     250             :         { "pathLength", TAG_SVG_ATT_pathLength, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     251             :         { "points", TAG_SVG_ATT_points, SVG_Points_datatype, 0, GF_XMLNS_SVG },
     252             :         { "mediaSize", TAG_SVG_ATT_mediaSize, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     253             :         { "mediaTime", TAG_SVG_ATT_mediaTime, DOM_String_datatype, 0, GF_XMLNS_SVG },
     254             :         { "mediaCharacterEncoding", TAG_SVG_ATT_mediaCharacterEncoding, DOM_String_datatype, 0, GF_XMLNS_SVG },
     255             :         { "mediaContentEncodings", TAG_SVG_ATT_mediaContentEncodings, DOM_String_datatype, 0, GF_XMLNS_SVG },
     256             :         { "bandwidth", TAG_SVG_ATT_bandwidth, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     257             :         { "fx", TAG_SVG_ATT_fx, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     258             :         { "fy", TAG_SVG_ATT_fy, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     259             :         { "size", TAG_SVG_ATT_size, LASeR_Size_datatype, 0, GF_XMLNS_SVG },
     260             :         { "choice", TAG_SVG_ATT_choice, LASeR_Choice_datatype, 0, GF_XMLNS_LASER },
     261             :         { "delta", TAG_SVG_ATT_delta, LASeR_Size_datatype, 0, GF_XMLNS_LASER },
     262             :         { "offset", TAG_SVG_ATT_offset, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     263             :         { "syncBehaviorDefault", TAG_SVG_ATT_syncBehaviorDefault, SMIL_SyncBehavior_datatype, 0, GF_XMLNS_SVG },
     264             :         { "syncToleranceDefault", TAG_SVG_ATT_syncToleranceDefault, SMIL_SyncTolerance_datatype, 0, GF_XMLNS_SVG },
     265             :         { "viewBox", TAG_SVG_ATT_viewBox, SVG_ViewBox_datatype, 0, GF_XMLNS_SVG },
     266             :         { "zoomAndPan", TAG_SVG_ATT_zoomAndPan, SVG_ZoomAndPan_datatype, 0, GF_XMLNS_SVG },
     267             :         { "version", TAG_SVG_ATT_version, DOM_String_datatype, 0, GF_XMLNS_SVG },
     268             :         { "baseProfile", TAG_SVG_ATT_baseProfile, DOM_String_datatype, 0, GF_XMLNS_SVG },
     269             :         { "snapshotTime", TAG_SVG_ATT_snapshotTime, SVG_Clock_datatype, 0, GF_XMLNS_SVG },
     270             :         { "timelineBegin", TAG_SVG_ATT_timelineBegin, SVG_TimelineBegin_datatype, 0, GF_XMLNS_SVG },
     271             :         { "playbackOrder", TAG_SVG_ATT_playbackOrder, SVG_PlaybackOrder_datatype, 0, GF_XMLNS_SVG },
     272             :         { "editable", TAG_SVG_ATT_editable, SVG_Boolean_datatype, 0, GF_XMLNS_SVG },
     273             :         { "transformBehavior", TAG_SVG_ATT_transformBehavior, SVG_TransformBehavior_datatype, 0, GF_XMLNS_SVG },
     274             :         { "overlay", TAG_SVG_ATT_overlay, SVG_Overlay_datatype, 0, GF_XMLNS_SVG },
     275             :         { "fullscreen", TAG_SVG_ATT_fullscreen, SVG_Boolean_datatype, 0, GF_XMLNS_SVG },
     276             :         { "motionTransform", TAG_SVG_ATT_motionTransform, SVG_Motion_datatype, 0, GF_XMLNS_SVG },
     277             :         /*SMIL anim fill*/
     278             :         { "fill", TAG_SVG_ATT_smil_fill, SMIL_Fill_datatype, GF_SVG_ATTOPT_SMIL, GF_XMLNS_SVG },
     279             :         /*regular paint fill*/
     280             :         { "fill", TAG_SVG_ATT_fill, SVG_Paint_datatype, 0, GF_XMLNS_SVG },
     281             :         /*filter*/
     282             :         { "filter", TAG_SVG_ATT_filter, SVG_Paint_datatype, 0, GF_XMLNS_SVG },
     283             :         /*text rotate*/
     284             :         { "rotate", TAG_SVG_ATT_text_rotate, SVG_Numbers_datatype, GF_SVG_ATTOPT_TEXT, GF_XMLNS_SVG },
     285             :         /*regular matrix rotate*/
     286             :         { "rotate", TAG_SVG_ATT_rotate, SVG_Rotate_datatype, 0, GF_XMLNS_SVG },
     287             :         /*SMIL anim type*/
     288             :         { "type", TAG_SVG_ATT_transform_type, SVG_TransformType_datatype, GF_SVG_ATTOPT_SMIL, GF_XMLNS_SVG },
     289             :         /*Filter componentTransfer type*/
     290             :         { "type", TAG_SVG_ATT_filter_transfer_type, SVG_Filter_TransferType_datatype, GF_SVG_ATTOPT_FILTER, GF_XMLNS_SVG },
     291             :         /*regular content type*/
     292             :         { "type", TAG_SVG_ATT_type, SVG_ContentType_datatype, 0, GF_XMLNS_SVG },
     293             :         /*text x*/
     294             :         { "x", TAG_SVG_ATT_text_x, SVG_Coordinates_datatype, GF_SVG_ATTOPT_TEXT, GF_XMLNS_SVG },
     295             :         /*regular x position*/
     296             :         { "x", TAG_SVG_ATT_x, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     297             :         /*text y*/
     298             :         { "y", TAG_SVG_ATT_text_y, SVG_Coordinates_datatype, GF_SVG_ATTOPT_TEXT, GF_XMLNS_SVG },
     299             :         /*regular y position*/
     300             :         { "y", TAG_SVG_ATT_y, SVG_Coordinate_datatype, 0, GF_XMLNS_SVG },
     301             : 
     302             :         /*filters*/
     303             :         { "tableValues", TAG_SVG_ATT_filter_table_values, SVG_Numbers_datatype, 0, GF_XMLNS_SVG },
     304             :         { "intercept", TAG_SVG_ATT_filter_intercept, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     305             :         { "amplitude", TAG_SVG_ATT_filter_amplitude, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     306             :         { "exponent", TAG_SVG_ATT_filter_exponent, SVG_Number_datatype, 0, GF_XMLNS_SVG },
     307             : 
     308             :         /*LASeR*/
     309             :         { "enabled", TAG_LSR_ATT_enabled, SVG_Boolean_datatype, 0, GF_XMLNS_LASER },
     310             :         /*cursor x*/
     311             :         { "x", TAG_SVG_ATT_cursorManager_x, SVG_Length_datatype, GF_SVG_ATTOPT_CURSOR, GF_XMLNS_LASER },
     312             :         /*cursor y*/
     313             :         { "y", TAG_SVG_ATT_cursorManager_y, SVG_Length_datatype, GF_SVG_ATTOPT_CURSOR, GF_XMLNS_LASER },
     314             : 
     315             :         /*XBL*/
     316             : #if 0
     317             :         { "id", TAG_XBL_ATT_id, DOM_String_datatype, 0, GF_XMLNS_XBL },
     318             :         { "extends", TAG_XBL_ATT_extends, DOM_String_datatype, 0, GF_XMLNS_XBL },
     319             :         { "display", TAG_XBL_ATT_display, DOM_String_datatype, 0, GF_XMLNS_XBL },
     320             :         { "inheritstyle", TAG_XBL_ATT_inheritstyle, DOM_String_datatype, 0, GF_XMLNS_XBL },
     321             :         { "includes", TAG_XBL_ATT_includes, DOM_String_datatype, 0, GF_XMLNS_XBL },
     322             :         { "name", TAG_XBL_ATT_name, DOM_String_datatype, 0, GF_XMLNS_XBL },
     323             :         { "implements", TAG_XBL_ATT_implements, DOM_String_datatype, 0, GF_XMLNS_XBL },
     324             :         { "type", TAG_XBL_ATT_type, DOM_String_datatype, 0, GF_XMLNS_XBL },
     325             :         { "readonly", TAG_XBL_ATT_readonly, DOM_String_datatype, 0, GF_XMLNS_XBL },
     326             :         { "onget", TAG_XBL_ATT_onget, DOM_String_datatype, 0, GF_XMLNS_XBL },
     327             :         { "onset", TAG_XBL_ATT_onset, DOM_String_datatype, 0, GF_XMLNS_XBL },
     328             :         { "event", TAG_XBL_ATT_event, DOM_String_datatype, 0, GF_XMLNS_XBL },
     329             :         { "action", TAG_XBL_ATT_action, DOM_String_datatype, 0, GF_XMLNS_XBL },
     330             :         { "phase", TAG_XBL_ATT_phase, DOM_String_datatype, 0, GF_XMLNS_XBL },
     331             :         { "button", TAG_XBL_ATT_button, DOM_String_datatype, 0, GF_XMLNS_XBL },
     332             :         { "modifiers", TAG_XBL_ATT_modifiers, DOM_String_datatype, 0, GF_XMLNS_XBL },
     333             :         { "keycode", TAG_XBL_ATT_keycode, DOM_String_datatype, 0, GF_XMLNS_XBL },
     334             :         { "key", TAG_XBL_ATT_key, DOM_String_datatype, 0, GF_XMLNS_XBL },
     335             :         { "charcode", TAG_XBL_ATT_charcode, DOM_String_datatype, 0, GF_XMLNS_XBL },
     336             :         { "clickcount", TAG_XBL_ATT_clickcount, DOM_String_datatype, 0, GF_XMLNS_XBL },
     337             :         { "command", TAG_XBL_ATT_command, DOM_String_datatype, 0, GF_XMLNS_XBL },
     338             :         { "preventdefault", TAG_XBL_ATT_preventdefault, DOM_String_datatype, 0, GF_XMLNS_XBL },
     339             :         { "src", TAG_XBL_ATT_src, DOM_String_datatype, 0, GF_XMLNS_XBL },
     340             : #endif
     341             :         /*GPAC SVG Extensions*/
     342             :         { "use-as-primary", TAG_GSVG_ATT_useAsPrimary, SVG_Boolean_datatype, 0, GF_XMLNS_SVG_GPAC_EXTENSION},
     343             :         { "depthOffset", TAG_GSVG_ATT_depthOffset, SVG_Number_datatype, 0, GF_XMLNS_SVG_GPAC_EXTENSION},
     344             :         { "depthGain", TAG_GSVG_ATT_depthGain, SVG_Number_datatype, 0, GF_XMLNS_SVG_GPAC_EXTENSION},
     345             : 
     346             : };
     347             : 
     348         354 : void gf_xml_push_namespaces(GF_DOMNode *elt)
     349             : {
     350         354 :         GF_DOMAttribute *att = elt->attributes;
     351        1966 :         while (att) {
     352        1258 :                 if (att->tag==TAG_DOM_ATT_any) {
     353             :                         GF_DOMFullAttribute *datt = (GF_DOMFullAttribute*)att;
     354           0 :                         if (datt->name && !strncmp(datt->name, "xmlns", 5)) {
     355             :                                 char *qname = datt->name+5;
     356           0 :                                 gf_sg_add_namespace(elt->sgprivate->scenegraph, *(DOM_String *) datt->data, qname[0] ? qname+1 : NULL);
     357             :                         }
     358             :                 }
     359        1258 :                 att = att->next;
     360             :         }
     361         354 : }
     362             : 
     363         168 : void gf_xml_pop_namespaces(GF_DOMNode *elt)
     364             : {
     365         168 :         GF_DOMAttribute *att = elt->attributes;
     366        1389 :         while (att) {
     367        1053 :                 if (att->tag==TAG_DOM_ATT_any) {
     368             :                         GF_DOMFullAttribute *datt = (GF_DOMFullAttribute*)att;
     369         397 :                         if (datt->name && !strncmp(datt->name, "xmlns", 5)) {
     370             :                                 char *qname = datt->name+5;
     371         198 :                                 gf_sg_remove_namespace(elt->sgprivate->scenegraph, *(DOM_String *) datt->data, qname[0] ? qname+1 : NULL);
     372             :                         }
     373             :                 }
     374        1053 :                 att = att->next;
     375             :         }
     376         168 : }
     377             : 
     378             : 
     379           0 : static u32 gf_xml_get_namespace(GF_DOMNode *elt, const char *attribute_name)
     380             : {
     381           0 :         GF_DOMAttribute *att = elt->attributes;
     382           0 :         while (att) {
     383           0 :                 if (att->tag==TAG_DOM_ATT_any) {
     384             :                         GF_DOMFullAttribute *datt = (GF_DOMFullAttribute*)att;
     385           0 :                         if (datt->name && !strncmp(datt->name, "xmlns", 5) && !strcmp(datt->name+6, attribute_name)) {
     386           0 :                                 return gf_xml_get_namespace_id(*(DOM_String *)  datt->data);
     387             :                         }
     388             :                 }
     389           0 :                 att = att->next;
     390             :         }
     391           0 :         if (!elt->sgprivate->parents) return 0;
     392           0 :         return gf_xml_get_namespace((GF_DOMNode*)elt->sgprivate->parents->node, attribute_name);
     393             : }
     394             : 
     395         148 : static char *gf_xml_get_namespace_qname(GF_DOMNode *elt, u32 ns)
     396             : {
     397         344 :         GF_DOMAttribute *att = elt->attributes;
     398        3148 :         while (att) {
     399        2804 :                 if (att->tag==TAG_DOM_ATT_any) {
     400             :                         GF_DOMFullAttribute *datt = (GF_DOMFullAttribute*)att;
     401           0 :                         if (datt->name && !strncmp(datt->name, "xmlns", 5) && (gf_xml_get_namespace_id(*(DOM_String *)  datt->data)==ns)) {
     402           0 :                                 if (datt->name[5]) return datt->name+6;
     403             :                                 return NULL;
     404             :                         }
     405             :                 }
     406        2804 :                 att = att->next;
     407             :         }
     408         344 :         if (!elt->sgprivate->parents) return NULL;
     409         196 :         return gf_xml_get_namespace_qname((GF_DOMNode*)elt->sgprivate->parents->node, ns);
     410             : }
     411             : 
     412       10295 : u32 gf_xml_get_attribute_tag(GF_Node *elt, char *attribute_name, GF_NamespaceType ns)
     413             : {
     414             :         u32 i, count;
     415             :         count = sizeof(xml_attributes) / sizeof(struct xml_att_def);
     416             : 
     417       10295 :         if (!ns) {
     418          67 :                 char *ns_sep = strchr(attribute_name, ':');
     419          67 :                 if (ns_sep) {
     420           0 :                         ns_sep[0] = 0;
     421           0 :                         ns = gf_sg_get_namespace_code(elt->sgprivate->scenegraph, attribute_name);
     422           0 :                         if (ns==GF_XMLNS_UNDEFINED) ns = gf_xml_get_namespace((GF_DOMNode*)elt, attribute_name);
     423           0 :                         ns_sep[0] = ':';
     424           0 :                         attribute_name = ++ns_sep;
     425             :                 } else {
     426             :                         ns = gf_xml_get_element_namespace(elt);
     427          67 :                         if (!ns) ns = gf_sg_get_namespace_code(elt->sgprivate->scenegraph, NULL);
     428             :                 }
     429             :         }
     430             : 
     431     1108528 :         for (i=0; i<count; i++) {
     432     1107855 :                 if (strcmp(xml_attributes[i].name, attribute_name)) continue;
     433       13651 :                 if (xml_attributes[i].xmlns != ns) continue;
     434             : 
     435       11458 :                 switch (xml_attributes[i].opts) {
     436        1465 :                 case GF_SVG_ATTOPT_SMIL:
     437        1465 :                         switch (elt->sgprivate->tag) {
     438          56 :                         case TAG_SVG_animate:
     439             :                         case TAG_SVG_animateColor:
     440             :                         case TAG_SVG_animateMotion:
     441             :                         case TAG_SVG_animateTransform:
     442             :                         case TAG_SVG_animation:
     443             :                         case TAG_SVG_audio:
     444             :                         case TAG_SVG_video:
     445             :                         case TAG_SVG_set:
     446          56 :                                 return xml_attributes[i].tag;
     447             :                         default:
     448             :                                 break;
     449             :                         }
     450             :                         break;
     451        1015 :                 case GF_SVG_ATTOPT_TEXT:
     452        1015 :                         if (elt->sgprivate->tag == TAG_SVG_text)
     453         594 :                                 return xml_attributes[i].tag;
     454             :                         break;
     455           0 :                 case GF_SVG_ATTOPT_CURSOR:
     456           0 :                         if (elt->sgprivate->tag == TAG_LSR_cursorManager)
     457           0 :                                 return xml_attributes[i].tag;
     458             :                         break;
     459           0 :                 case GF_SVG_ATTOPT_LISTENER:
     460           0 :                         if (elt->sgprivate->tag == TAG_SVG_listener)
     461           0 :                                 return xml_attributes[i].tag;
     462             :                         break;
     463          12 :                 case GF_SVG_ATTOPT_FILTER:
     464          12 :                         switch (elt->sgprivate->tag) {
     465           6 :                         case TAG_SVG_filter:
     466             :                         case TAG_SVG_feDistantLight:
     467             :                         case TAG_SVG_fePointLight:
     468             :                         case TAG_SVG_feSpotLight:
     469             :                         case TAG_SVG_feBlend:
     470             :                         case TAG_SVG_feColorMatrix:
     471             :                         case TAG_SVG_feComponentTransfer:
     472             :                         case TAG_SVG_feFuncR:
     473             :                         case TAG_SVG_feFuncG:
     474             :                         case TAG_SVG_feFuncB:
     475             :                         case TAG_SVG_feFuncA:
     476             :                         case TAG_SVG_feComposite:
     477             :                         case TAG_SVG_feConvolveMatrix:
     478             :                         case TAG_SVG_feDiffuseLighting:
     479             :                         case TAG_SVG_feDisplacementMap:
     480             :                         case TAG_SVG_feFlood:
     481             :                         case TAG_SVG_feGaussianBlur:
     482             :                         case TAG_SVG_feImage:
     483             :                         case TAG_SVG_feMerge:
     484             :                         case TAG_SVG_feMorphology:
     485             :                         case TAG_SVG_feOffset:
     486             :                         case TAG_SVG_feSpecularLighting:
     487             :                         case TAG_SVG_feTile:
     488             :                         case TAG_SVG_feTurbulence:
     489           6 :                                 return xml_attributes[i].tag;
     490             :                         default:
     491             :                                 break;
     492             :                         }
     493             :                         break;
     494        8966 :                 default:
     495        8966 :                         return xml_attributes[i].tag;
     496             :                 }
     497             :         }
     498             :         return TAG_DOM_ATT_any;
     499             : }
     500             : 
     501         182 : u32 gf_xml_get_attribute_type(u32 tag)
     502             : {
     503             :         u32 i, count;
     504             :         count = sizeof(xml_attributes) / sizeof(struct xml_att_def);
     505     1177352 :         for (i=0; i<count; i++) {
     506     1189608 :                 if (xml_attributes[i].tag==tag) return xml_attributes[i].type;
     507             :         }
     508             :         return DOM_String_datatype;
     509             : }
     510             : 
     511        1386 : const char*gf_svg_get_attribute_name(GF_Node *node, u32 tag)
     512             : {
     513             :         u32 i, count, ns;
     514             : 
     515             :         //ns = gf_sg_get_namespace_code(node->sgprivate->scenegraph, NULL);
     516             :         ns = gf_xml_get_element_namespace(node);
     517             :         count = sizeof(xml_attributes) / sizeof(struct xml_att_def);
     518      131258 :         for (i=0; i<count; i++) {
     519      131258 :                 if (xml_attributes[i].tag==tag) {
     520             :                         char *xmlns;
     521        1386 :                         if (ns == xml_attributes[i].xmlns)
     522        1238 :                                 return xml_attributes[i].name;
     523             : 
     524         148 :                         xmlns = (char *) gf_xml_get_namespace_qname((GF_DOMNode*)node, xml_attributes[i].xmlns);
     525         148 :                         if (xmlns) {
     526           0 :                                 sprintf(node->sgprivate->scenegraph->szNameBuffer, "%s:%s", xmlns, xml_attributes[i].name);
     527           0 :                                 return node->sgprivate->scenegraph->szNameBuffer;
     528             :                         }
     529         148 :                         return xml_attributes[i].name;
     530             :                 }
     531             :         }
     532             :         return 0;
     533             : }
     534           0 : GF_DOMAttribute *gf_xml_create_attribute(GF_Node *node, u32 tag)
     535             : {
     536             :         u32 type = gf_xml_get_attribute_type(tag);
     537       12260 :         return gf_node_create_attribute_from_datatype(type, tag);
     538             : }
     539             : 
     540             : static const struct xml_elt_def {
     541             :         const char *name;
     542             :         u32 tag;
     543             :         u32 xmlns;
     544             : } xml_elements [] =
     545             : {
     546             :         { "listener", TAG_SVG_listener, GF_XMLNS_XMLEV},
     547             :         /*SVG*/
     548             :         { "a", TAG_SVG_a, GF_XMLNS_SVG },
     549             :         { "animate", TAG_SVG_animate, GF_XMLNS_SVG },
     550             :         { "animateColor", TAG_SVG_animateColor, GF_XMLNS_SVG },
     551             :         { "animateMotion", TAG_SVG_animateMotion, GF_XMLNS_SVG },
     552             :         { "animateTransform", TAG_SVG_animateTransform, GF_XMLNS_SVG },
     553             :         { "animation", TAG_SVG_animation, GF_XMLNS_SVG },
     554             :         { "audio", TAG_SVG_audio, GF_XMLNS_SVG },
     555             :         { "circle", TAG_SVG_circle, GF_XMLNS_SVG },
     556             :         { "defs", TAG_SVG_defs, GF_XMLNS_SVG },
     557             :         { "desc", TAG_SVG_desc, GF_XMLNS_SVG },
     558             :         { "discard", TAG_SVG_discard, GF_XMLNS_SVG },
     559             :         { "ellipse", TAG_SVG_ellipse, GF_XMLNS_SVG },
     560             :         { "font", TAG_SVG_font, GF_XMLNS_SVG },
     561             :         { "font-face", TAG_SVG_font_face, GF_XMLNS_SVG },
     562             :         { "font-face-src", TAG_SVG_font_face_src, GF_XMLNS_SVG },
     563             :         { "font-face-uri", TAG_SVG_font_face_uri, GF_XMLNS_SVG },
     564             :         { "foreignObject", TAG_SVG_foreignObject, GF_XMLNS_SVG },
     565             :         { "g", TAG_SVG_g, GF_XMLNS_SVG },
     566             :         { "glyph", TAG_SVG_glyph, GF_XMLNS_SVG },
     567             :         { "handler", TAG_SVG_handler, GF_XMLNS_SVG },
     568             :         { "hkern", TAG_SVG_hkern, GF_XMLNS_SVG },
     569             :         { "image", TAG_SVG_image, GF_XMLNS_SVG },
     570             :         { "line", TAG_SVG_line, GF_XMLNS_SVG },
     571             :         { "linearGradient", TAG_SVG_linearGradient, GF_XMLNS_SVG },
     572             :         { "metadata", TAG_SVG_metadata, GF_XMLNS_SVG },
     573             :         { "missing-glyph", TAG_SVG_missing_glyph, GF_XMLNS_SVG },
     574             :         { "mpath", TAG_SVG_mpath, GF_XMLNS_SVG },
     575             :         { "path", TAG_SVG_path, GF_XMLNS_SVG },
     576             :         { "polygon", TAG_SVG_polygon, GF_XMLNS_SVG },
     577             :         { "polyline", TAG_SVG_polyline, GF_XMLNS_SVG },
     578             :         { "prefetch", TAG_SVG_prefetch, GF_XMLNS_SVG },
     579             :         { "radialGradient", TAG_SVG_radialGradient, GF_XMLNS_SVG },
     580             :         { "rect", TAG_SVG_rect, GF_XMLNS_SVG },
     581             :         { "script", TAG_SVG_script, GF_XMLNS_SVG },
     582             :         { "set", TAG_SVG_set, GF_XMLNS_SVG },
     583             :         { "solidColor", TAG_SVG_solidColor, GF_XMLNS_SVG },
     584             :         { "stop", TAG_SVG_stop, GF_XMLNS_SVG },
     585             :         { "svg", TAG_SVG_svg, GF_XMLNS_SVG },
     586             :         { "switch", TAG_SVG_switch, GF_XMLNS_SVG },
     587             :         { "tbreak", TAG_SVG_tbreak, GF_XMLNS_SVG },
     588             :         { "text", TAG_SVG_text, GF_XMLNS_SVG },
     589             :         { "textArea", TAG_SVG_textArea, GF_XMLNS_SVG },
     590             :         { "title", TAG_SVG_title, GF_XMLNS_SVG },
     591             :         { "tspan", TAG_SVG_tspan, GF_XMLNS_SVG },
     592             :         { "use", TAG_SVG_use, GF_XMLNS_SVG },
     593             :         { "video", TAG_SVG_video, GF_XMLNS_SVG },
     594             :         { "filter", TAG_SVG_filter, GF_XMLNS_SVG },
     595             :         { "feDistantLight", TAG_SVG_feDistantLight, GF_XMLNS_SVG },
     596             :         { "fePointLight", TAG_SVG_fePointLight, GF_XMLNS_SVG },
     597             :         { "feSpotLight", TAG_SVG_feSpotLight, GF_XMLNS_SVG },
     598             :         { "feBlend", TAG_SVG_feBlend, GF_XMLNS_SVG },
     599             :         { "feColorMatrix", TAG_SVG_feColorMatrix, GF_XMLNS_SVG },
     600             :         { "feComponentTransfer", TAG_SVG_feComponentTransfer, GF_XMLNS_SVG },
     601             :         { "feFuncR", TAG_SVG_feFuncR, GF_XMLNS_SVG },
     602             :         { "feFuncG", TAG_SVG_feFuncG, GF_XMLNS_SVG },
     603             :         { "feFuncB", TAG_SVG_feFuncB, GF_XMLNS_SVG },
     604             :         { "feFuncA", TAG_SVG_feFuncA, GF_XMLNS_SVG },
     605             :         { "feComposite", TAG_SVG_feComposite, GF_XMLNS_SVG },
     606             :         { "feConvolveMatrix", TAG_SVG_feConvolveMatrix, GF_XMLNS_SVG },
     607             :         { "feDiffuseLighting", TAG_SVG_feDiffuseLighting, GF_XMLNS_SVG },
     608             :         { "feDisplacementMap", TAG_SVG_feDisplacementMap, GF_XMLNS_SVG },
     609             :         { "feFlood", TAG_SVG_feFlood, GF_XMLNS_SVG },
     610             :         { "feGaussianBlur", TAG_SVG_feGaussianBlur, GF_XMLNS_SVG },
     611             :         { "feImage", TAG_SVG_feImage, GF_XMLNS_SVG },
     612             :         { "feMerge", TAG_SVG_feMerge, GF_XMLNS_SVG },
     613             :         { "feMorphology", TAG_SVG_feMorphology, GF_XMLNS_SVG },
     614             :         { "feOffset", TAG_SVG_feOffset, GF_XMLNS_SVG },
     615             :         { "feSpecularLighting", TAG_SVG_feSpecularLighting, GF_XMLNS_SVG },
     616             :         { "feTile", TAG_SVG_feTile, GF_XMLNS_SVG },
     617             :         { "feTurbulence", TAG_SVG_feTurbulence, GF_XMLNS_SVG },
     618             : 
     619             :         /*LASeR*/
     620             :         { "conditional", TAG_LSR_conditional, GF_XMLNS_LASER },
     621             :         { "rectClip", TAG_LSR_rectClip, GF_XMLNS_LASER },
     622             :         { "cursorManager", TAG_LSR_cursorManager, GF_XMLNS_LASER },
     623             :         { "selector", TAG_LSR_selector, GF_XMLNS_LASER },
     624             :         { "simpleLayout", TAG_LSR_simpleLayout, GF_XMLNS_LASER },
     625             :         { "updates", TAG_LSR_updates, GF_XMLNS_LASER },
     626             : 
     627             : };
     628             : 
     629             : GF_EXPORT
     630        3705 : u32 gf_xml_get_element_tag(const char *element_name, u32 ns)
     631             : {
     632             :         u32 i, count;
     633             : //      if (!element_name) return TAG_UndefinedNode;
     634             :         count = sizeof(xml_elements) / sizeof(struct xml_elt_def);
     635      108283 :         for (i=0; i<count; i++) {
     636      108145 :                 if (!strcmp(xml_elements[i].name, element_name)) {
     637        3567 :                         if (!ns || (xml_elements[i].xmlns==ns) )
     638        3567 :                                 return xml_elements[i].tag;
     639             :                 }
     640             :         }
     641             :         return TAG_UndefinedNode;
     642             : }
     643             : 
     644        4226 : const char *gf_xml_get_element_name(GF_Node *n)
     645             : {
     646             :         u32 i, count, ns;
     647             : 
     648        4226 :         ns = n ? gf_sg_get_namespace_code(n->sgprivate->scenegraph, NULL) : 0;
     649             :         count = sizeof(xml_elements) / sizeof(struct xml_elt_def);
     650      117767 :         for (i=0; i<count; i++) {
     651      117744 :                 if (n && n->sgprivate && (n->sgprivate->tag==xml_elements[i].tag)) {
     652             :                         char *xmlns;
     653        4203 :                         if (ns == xml_elements[i].xmlns)
     654        3666 :                                 return xml_elements[i].name;
     655             : 
     656         537 :                         xmlns = (char *) gf_sg_get_namespace_qname(n->sgprivate->scenegraph, xml_elements[i].xmlns);
     657         537 :                         if (xmlns) {
     658          34 :                                 sprintf(n->sgprivate->scenegraph->szNameBuffer, "%s:%s", xmlns, xml_elements[i].name);
     659          34 :                                 return n->sgprivate->scenegraph->szNameBuffer;
     660             :                         }
     661         503 :                         return xml_elements[i].name;
     662             :                 }
     663             :         }
     664             :         return "UndefinedNode";
     665             : }
     666             : 
     667         528 : GF_NamespaceType gf_xml_get_element_namespace(GF_Node *n)
     668             : {
     669             :         u32 i, count;
     670        1995 :         if (n->sgprivate->tag==TAG_DOMFullNode) {
     671             :                 GF_DOMFullNode *elt = (GF_DOMFullNode *)n;
     672           5 :                 return elt->ns;
     673             :         }
     674             : 
     675             :         count = sizeof(xml_elements) / sizeof(struct xml_elt_def);
     676       41338 :         for (i=0; i<count; i++) {
     677       43328 :                 if (n->sgprivate->tag==xml_elements[i].tag) return xml_elements[i].xmlns;
     678             :         }
     679             :         return GF_XMLNS_UNDEFINED;
     680             : }
     681             : 
     682        2807 : u32 gf_node_get_attribute_count(GF_Node *node)
     683             : {
     684             :         u32 count = 0;
     685             :         GF_DOMAttribute *atts;
     686        2807 :         if (!node) return 0;
     687           0 :         atts =  ((GF_DOMNode *)node)->attributes;
     688           0 :         while (atts) {
     689           0 :                 count++;
     690           0 :                 atts = atts->next;
     691             :         }
     692             :         return count;
     693             : }
     694             : 
     695           7 : GF_Err gf_node_get_attribute_info(GF_Node *node, GF_FieldInfo *info)
     696             : {
     697             :         GF_DOMNode *dom = (GF_DOMNode *)node;
     698           7 :         GF_DOMAttribute *atts = dom->attributes;
     699          31 :         while (atts) {
     700          24 :                 if (atts->tag == info->fieldIndex) {
     701           7 :                         info->fieldType = atts->data_type;
     702           7 :                         info->far_ptr  = atts->data;
     703           7 :                         return GF_OK;
     704             :                 }
     705          17 :                 atts = atts->next;
     706             :         }
     707           0 :         info->fieldType = 0;
     708           0 :         info->far_ptr  = NULL;
     709           0 :         return GF_NOT_SUPPORTED;
     710             : }
     711             : 
     712        5467 : void gf_node_delete_attributes(GF_Node *node)
     713             : {
     714        5467 :         GF_DOMAttribute *att = ((GF_DOMNode*)node)->attributes;
     715       24207 :         while(att) {
     716             :                 GF_DOMAttribute *tmp;
     717       13273 :                 gf_svg_delete_attribute_value(att->data_type, att->data, node->sgprivate->scenegraph);
     718             :                 tmp = att;
     719       13273 :                 att = att->next;
     720       13273 :                 if (tmp->tag==TAG_DOM_ATT_any) {
     721        1013 :                         gf_free( ((GF_DOMFullAttribute*)tmp)->name);
     722             :                 }
     723       13273 :                 gf_free(tmp);
     724             :         }
     725        5467 : }
     726             : 
     727       12260 : SVGAttribute *gf_node_create_attribute_from_datatype(u32 data_type, u32 attribute_tag)
     728             : {
     729             :         SVGAttribute *att;
     730       12260 :         if (!data_type) return NULL;
     731             : 
     732       12260 :         GF_SAFEALLOC(att, SVGAttribute);
     733       12260 :         if (!att) return NULL;
     734       12260 :         att->data_type = (u16) data_type;
     735       12260 :         att->tag = (u16) attribute_tag;
     736       12260 :         att->data = gf_svg_create_attribute_value(att->data_type);
     737       12260 :         return att;
     738             : }
     739             : 
     740             : GF_EXPORT
     741       10233 : GF_Err gf_node_get_attribute_by_name(GF_Node *node, char *name, u32 xmlns_code, Bool create_if_not_found, Bool set_default, GF_FieldInfo *field)
     742             : {
     743       10233 :         u32 attribute_tag = gf_xml_get_attribute_tag(node, name, xmlns_code);
     744       10233 :         if (attribute_tag == TAG_DOM_ATT_any) {
     745             :                 u32 len = 0;
     746             :                 const char *ns = NULL;
     747             :                 SVGAttribute *last_att = NULL;
     748         673 :                 GF_DOMFullAttribute *att = (GF_DOMFullAttribute *) ((SVG_Element*)node)->attributes;
     749         673 :                 if (xmlns_code) ns = gf_sg_get_namespace_qname(node->sgprivate->scenegraph, xmlns_code);
     750         659 :                 if (ns) len = (u32) strlen(ns);
     751             : 
     752        4551 :                 while (att) {
     753        3878 :                         if (((u32) att->tag == TAG_DOM_ATT_any) &&
     754        1896 :                                 ((!ns && !strcmp(name, att->name)) || (ns && !strncmp(att->name, ns, len) && !strcmp(att->name+len+1, name)))
     755             :                            ) {
     756           0 :                                 field->fieldIndex = att->tag;
     757           0 :                                 field->fieldType = att->data_type;
     758           0 :                                 field->far_ptr = att->data;
     759           0 :                                 return GF_OK;
     760             :                         }
     761             :                         last_att = (SVGAttribute *) att;
     762        3878 :                         att = (GF_DOMFullAttribute *) att->next;
     763             :                 }
     764         673 :                 if (create_if_not_found) {
     765         673 :                         GF_SAFEALLOC(att, GF_DOMFullAttribute);
     766         673 :                         if (!att) return GF_OUT_OF_MEM;
     767         673 :                         att->data_type = (u16) DOM_String_datatype;
     768         673 :                         att->tag = (u16) TAG_DOM_ATT_any;
     769         673 :                         att->data = gf_svg_create_attribute_value(att->data_type);
     770             : 
     771         673 :                         att->name = gf_strdup(name);
     772         673 :                         if (!xmlns_code)
     773          14 :                                 att->xmlns = gf_xml_get_element_namespace(node);
     774             :                         else
     775         659 :                                 att->xmlns = xmlns_code;
     776             : 
     777         673 :                         if (last_att) last_att->next = (SVGAttribute *)att;
     778         102 :                         else ((SVG_Element*)node)->attributes = (SVGAttribute *)att;
     779             : 
     780         673 :                         field->far_ptr = att->data;
     781         673 :                         field->fieldType = att->data_type;
     782         673 :                         field->fieldIndex = att->tag;
     783         673 :                         return GF_OK;
     784             :                 }
     785             :                 return GF_NOT_SUPPORTED;
     786             :         }
     787        9560 :         return gf_node_get_attribute_by_tag(node, attribute_tag, create_if_not_found, set_default, field);
     788             : }
     789             : 
     790             : 
     791         244 : static void attributes_set_default_value(GF_Node *node, SVGAttribute *att)
     792             : {
     793         244 :         u32 node_tag = node->sgprivate->tag;
     794         244 :         switch (att->tag) {
     795          32 :         case TAG_SVG_ATT_width:
     796             :         case TAG_SVG_ATT_height:
     797          32 :                 if (node_tag == TAG_SVG_svg) {
     798           0 :                         SVG_Length *len = att->data;
     799           0 :                         len->type = SVG_NUMBER_PERCENTAGE;
     800           0 :                         len->value = INT2FIX(100);
     801             :                 }
     802             :                 break;
     803           0 :         case TAG_SVG_ATT_x2:
     804           0 :                 if (node_tag == TAG_SVG_linearGradient) {
     805           0 :                         ((SVG_Number *)att->data)->value = FIX_ONE;
     806             :                 }
     807             :                 break;
     808           0 :         case TAG_SVG_ATT_cx:
     809             :         case TAG_SVG_ATT_cy:
     810             :         case TAG_SVG_ATT_fx:
     811             :         case TAG_SVG_ATT_fy:
     812             :         case TAG_SVG_ATT_r:
     813           0 :                 if (node_tag == TAG_SVG_radialGradient) {
     814           0 :                         ((SVG_Number *)att->data)->value = FIX_ONE/2;
     815             :                 }
     816             :                 break;
     817           0 :         case TAG_SVG_ATT_dur:
     818           0 :                 if (node_tag == TAG_SVG_video ||
     819           0 :                         node_tag == TAG_SVG_audio ||
     820             :                         node_tag == TAG_SVG_animation)
     821             :                 {
     822           0 :                         ((SMIL_Duration *)att->data)->type = SMIL_DURATION_MEDIA;
     823             :                 } else {
     824             :                         /*is this correct?*/
     825           0 :                         ((SMIL_Duration *)att->data)->type = SMIL_DURATION_INDEFINITE;
     826             :                 }
     827             :                 break;
     828           0 :         case TAG_SVG_ATT_min:
     829           0 :                 ((SMIL_Duration *)att->data)->type = SMIL_DURATION_DEFINED;
     830             :                 break;
     831           0 :         case TAG_SVG_ATT_repeatDur:
     832           0 :                 ((SMIL_Duration *)att->data)->type = SMIL_DURATION_INDEFINITE;
     833             :                 break;
     834           0 :         case TAG_SVG_ATT_calcMode:
     835           0 :                 if (node_tag == TAG_SVG_animateMotion)
     836           0 :                         *((SMIL_CalcMode *)att->data) = SMIL_CALCMODE_PACED;
     837             :                 else
     838           0 :                         *((SMIL_CalcMode *)att->data) = SMIL_CALCMODE_LINEAR;
     839             :                 break;
     840          30 :         case TAG_SVG_ATT_color:
     841          30 :                 ((SVG_Paint *)att->data)->type = SVG_PAINT_COLOR;
     842          30 :                 ((SVG_Paint *)att->data)->color.type = SVG_COLOR_INHERIT;
     843             :                 break;
     844           2 :         case TAG_SVG_ATT_solid_color:
     845             :         case TAG_SVG_ATT_stop_color:
     846           2 :                 ((SVG_Paint *)att->data)->type = SVG_PAINT_COLOR;
     847           2 :                 ((SVG_Paint *)att->data)->color.type = SVG_COLOR_RGBCOLOR;
     848             :                 break;
     849           0 :         case TAG_SVG_ATT_opacity:
     850             :         case TAG_SVG_ATT_solid_opacity:
     851             :         case TAG_SVG_ATT_stop_opacity:
     852             :         case TAG_SVG_ATT_audio_level:
     853             :         case TAG_SVG_ATT_viewport_fill_opacity:
     854           0 :                 ((SVG_Number *)att->data)->value = FIX_ONE;
     855             :                 break;
     856           4 :         case TAG_SVG_ATT_display:
     857           4 :                 *((SVG_Display *)att->data) = SVG_DISPLAY_INLINE;
     858             :                 break;
     859          18 :         case TAG_SVG_ATT_fill:
     860             :         case TAG_SVG_ATT_stroke:
     861          18 :                 ((SVG_Paint *)att->data)->type = SVG_PAINT_INHERIT;
     862             :                 break;
     863           2 :         case TAG_SVG_ATT_stroke_dasharray:
     864           2 :                 ((SVG_StrokeDashArray *)att->data)->type = SVG_STROKEDASHARRAY_INHERIT;
     865             :                 break;
     866          36 :         case TAG_SVG_ATT_fill_opacity:
     867             :         case TAG_SVG_ATT_stroke_opacity:
     868             :         case TAG_SVG_ATT_stroke_width:
     869             :         case TAG_SVG_ATT_font_size:
     870             :         case TAG_SVG_ATT_line_increment:
     871             :         case TAG_SVG_ATT_stroke_dashoffset:
     872             :         case TAG_SVG_ATT_stroke_miterlimit:
     873          36 :                 ((SVG_Number *)att->data)->type = SVG_NUMBER_INHERIT;
     874             :                 break;
     875           0 :         case TAG_SVG_ATT_vector_effect:
     876           0 :                 *((SVG_VectorEffect *)att->data) = SVG_VECTOREFFECT_NONE;
     877             :                 break;
     878           0 :         case TAG_SVG_ATT_fill_rule:
     879           0 :                 *((SVG_FillRule *)att->data) = SVG_FILLRULE_INHERIT;
     880             :                 break;
     881           6 :         case TAG_SVG_ATT_font_weight:
     882           6 :                 *((SVG_FontWeight *)att->data) = SVG_FONTWEIGHT_INHERIT;
     883             :                 break;
     884           0 :         case TAG_SVG_ATT_visibility:
     885           0 :                 *((SVG_Visibility *)att->data) = SVG_VISIBILITY_INHERIT;
     886             :                 break;
     887           0 :         case TAG_SVG_ATT_smil_fill:
     888           0 :                 *((SMIL_Fill *)att->data) = SMIL_FILL_REMOVE;
     889             :                 break;
     890           0 :         case TAG_XMLEV_ATT_defaultAction:
     891           0 :                 *((XMLEV_DefaultAction *)att->data) = XMLEVENT_DEFAULTACTION_PERFORM;
     892             :                 break;
     893           0 :         case TAG_SVG_ATT_zoomAndPan:
     894           0 :                 *((SVG_ZoomAndPan *)att->data) = SVG_ZOOMANDPAN_MAGNIFY;
     895             :                 break;
     896           0 :         case TAG_SVG_ATT_stroke_linecap:
     897           0 :                 *(SVG_StrokeLineCap*)att->data = SVG_STROKELINECAP_INHERIT;
     898             :                 break;
     899           0 :         case TAG_SVG_ATT_stroke_linejoin:
     900           0 :                 *(SVG_StrokeLineJoin*)att->data = SVG_STROKELINEJOIN_INHERIT;
     901             :                 break;
     902             : 
     903           4 :         case TAG_SVG_ATT_transform:
     904           8 :                 gf_mx2d_init(((SVG_Transform*)att->data)->mat);
     905             :                 break;
     906             : 
     907             : 
     908             :         /*all default=0 values (don't need init)*/
     909             :         case TAG_SVG_ATT_font_family:
     910             :         case TAG_SVG_ATT_font_style:
     911             :         case TAG_SVG_ATT_text_anchor:
     912             :         case TAG_SVG_ATT_x:
     913             :         case TAG_SVG_ATT_y:
     914             :                 break;
     915             : 
     916          43 :         default:
     917          43 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_SCENE, ("[Scene] Cannot create default value for SVG attribute %s\n", gf_svg_get_attribute_name(node, att->tag)));
     918             :         }
     919         244 : }
     920             : 
     921             : GF_EXPORT
     922       19556 : GF_Err gf_node_get_attribute_by_tag(GF_Node *node, u32 attribute_tag, Bool create_if_not_found, Bool set_default, GF_FieldInfo *field)
     923             : {
     924             :         SVG_Element *elt = (SVG_Element *)node;
     925       19556 :         SVGAttribute *att = elt->attributes;
     926             :         SVGAttribute *last_att = NULL;
     927             : 
     928       96253 :         while (att) {
     929       62627 :                 if ((u32) att->tag == attribute_tag) {
     930        5486 :                         field->fieldIndex = att->tag;
     931        5486 :                         field->fieldType = att->data_type;
     932        5486 :                         field->far_ptr  = att->data;
     933        5486 :                         return GF_OK;
     934             :                 }
     935             :                 last_att = att;
     936       57141 :                 att = att->next;
     937             :         }
     938             : 
     939       14070 :         if (create_if_not_found) {
     940             :                 /* field not found create one */
     941             :                 att = gf_xml_create_attribute(node, attribute_tag);
     942       12260 :                 if (att) {
     943       12260 :                         if (!elt->attributes) elt->attributes = att;
     944        8438 :                         else last_att->next = att;
     945       12260 :                         field->far_ptr = att->data;
     946       12260 :                         field->fieldType = att->data_type;
     947       12260 :                         field->fieldIndex = att->tag;
     948             :                         /* attribute name should not be called, if needed use gf_svg_get_attribute_name(att->tag);*/
     949       12260 :                         field->name = NULL;
     950       12260 :                         if (set_default) attributes_set_default_value(node, att);
     951             :                         return GF_OK;
     952             :                 }
     953             :         }
     954             : 
     955             :         return GF_NOT_SUPPORTED;
     956             : }
     957             : 
     958             : GF_EXPORT
     959         322 : void gf_node_register_iri(GF_SceneGraph *sg, XMLRI *target)
     960             : {
     961             : #ifndef GPAC_DISABLE_SVG
     962         322 :         if (gf_list_find(sg->xlink_hrefs, target)<0) {
     963         320 :                 gf_list_add(sg->xlink_hrefs, target);
     964             :         }
     965             : #endif
     966         322 : }
     967             : 
     968             : GF_EXPORT
     969        2955 : void gf_node_unregister_iri(GF_SceneGraph *sg, XMLRI *target)
     970             : {
     971             : #ifndef GPAC_DISABLE_SVG
     972        2955 :         gf_list_del_item(sg->xlink_hrefs, target);
     973             : #endif
     974        2955 : }
     975             : 
     976        2808 : GF_Node *gf_xml_node_clone(GF_SceneGraph *inScene, GF_Node *orig, GF_Node *cloned_parent, char *inst_id, Bool deep)
     977             : {
     978             :         GF_DOMAttribute *att;
     979             :         GF_Node *clone;
     980        2808 :         if (!orig) return NULL;
     981           1 :         clone = gf_node_new(inScene, orig->sgprivate->tag);
     982           1 :         if (!clone) return NULL;
     983             : 
     984           1 :         if (orig->sgprivate->tag == TAG_DOMText) {
     985             :                 GF_DOMText *n_src,*n_dst;
     986             :                 n_src = (GF_DOMText *)orig;
     987             :                 n_dst = (GF_DOMText *)clone;
     988           0 :                 n_dst->type = n_src->type;
     989           0 :                 n_dst->textContent = gf_strdup(n_src->textContent);
     990             :         } else {
     991           1 :                 if (orig->sgprivate->tag == TAG_DOMFullNode) {
     992             :                         GF_DOMFullNode *n_src,*n_dst;
     993             :                         n_src = (GF_DOMFullNode *)orig;
     994             :                         n_dst = (GF_DOMFullNode *)clone;
     995           1 :                         n_dst->ns = n_src->ns;
     996           1 :                         n_dst->name = gf_strdup(n_src->name);
     997             :                 }
     998             : 
     999           1 :                 att = ((GF_DOMNode *)orig)->attributes;
    1000           4 :                 while (att) {
    1001             :                         GF_FieldInfo dst, src;
    1002             :                         /*create by name*/
    1003           2 :                         if (att->tag==TAG_DOM_ATT_any) {
    1004           2 :                                 gf_node_get_attribute_by_name(clone, ((GF_DOMFullAttribute*)att)->name, 0, 1, 0, &dst);
    1005             :                         } else {
    1006           0 :                                 gf_node_get_attribute_by_tag(clone, att->tag, 1, 0, &dst);
    1007             :                         }
    1008           2 :                         src.far_ptr = att->data;
    1009           2 :                         src.fieldType = att->data_type;
    1010           2 :                         src.fieldIndex = att->tag;
    1011           2 :                         gf_svg_attributes_copy(&dst, &src, 0);
    1012           2 :                         if (att->tag==TAG_XLINK_ATT_href) {
    1013           0 :                                 XMLRI *iri = (XMLRI *)att->data;
    1014           0 :                                 if (iri->target == gf_node_get_parent(orig, 0)) {
    1015           0 :                                         ((XMLRI *)dst.far_ptr)->target = cloned_parent;
    1016             :                                 } else {
    1017           0 :                                         ((XMLRI *)dst.far_ptr)->target = NULL;
    1018             :                                 }
    1019             :                         }
    1020           2 :                         att = att->next;
    1021             :                 }
    1022             :         }
    1023           1 :         if (cloned_parent) {
    1024           0 :                 gf_node_list_add_child( & ((GF_ParentNode*)cloned_parent)->children, clone);
    1025           0 :                 gf_node_register(clone, cloned_parent);
    1026             :                 /*TO CLARIFY: can we init the node right now or should we wait for insertion in the scene tree ?*/
    1027           0 :                 gf_node_init(clone);
    1028             :         }
    1029           1 :         if (deep) {
    1030           0 :                 GF_ChildNodeItem *child = ((GF_ParentNode *)orig)->children;
    1031           0 :                 while (child) {
    1032           0 :                         gf_node_clone(inScene, child->node, clone, inst_id, 1);
    1033           0 :                         child = child->next;
    1034             :                 }
    1035             :         }
    1036             :         return clone;
    1037             : }
    1038             : 
    1039             : /*TODO FIXME, this is ugly, add proper cache system*/
    1040             : #include <gpac/base_coding.h>
    1041             : 
    1042             : 
    1043           0 : static u32 check_existing_file(char *base_file, char *ext, char *data, u32 data_size, u32 idx)
    1044             : {
    1045             :         char szFile[GF_MAX_PATH];
    1046             :         u64 fsize;
    1047             :         FILE *f;
    1048             :         int concatres;
    1049             : 
    1050             :         concatres = snprintf(szFile, GF_MAX_PATH, "%s%04X%s", base_file, idx, ext);
    1051           0 :         if (concatres<0) {
    1052           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("Path too long (limit %d) when trying to concatenate %s and %s\n", GF_MAX_PATH, base_file, ext));
    1053             :         }
    1054             : 
    1055           0 :         f = gf_fopen(szFile, "rb");
    1056           0 :         if (!f) return 0;
    1057             : 
    1058           0 :         fsize = gf_fsize(f);
    1059           0 :         if (fsize==data_size) {
    1060             :                 u32 offset=0;
    1061             :                 char cache[1024];
    1062             : 
    1063           0 :                 while (fsize) {
    1064           0 :                         u32 read = (u32) gf_fread(cache, 1024, f);
    1065           0 :                         if ((s32) read < 0) return 0;
    1066           0 :                         fsize -= read;
    1067           0 :                         if (memcmp(cache, data+offset, sizeof(char)*read)) break;
    1068           0 :                         offset+=read;
    1069             :                 }
    1070           0 :                 gf_fclose(f);
    1071             :                 f = NULL;
    1072             :                 /*same file*/
    1073           0 :                 if (!fsize) return 2;
    1074             :         }
    1075             :         if (f)
    1076           0 :                 gf_fclose(f);
    1077             :         return 1;
    1078             : }
    1079             : 
    1080             : 
    1081             : GF_EXPORT
    1082          27 : GF_Err gf_node_store_embedded_data(XMLRI *iri, const char *cache_dir, const char *base_filename)
    1083             : {
    1084             :         char szFile[GF_MAX_PATH], buf[20], *sep, *data=NULL, *ext;
    1085             :         u32 data_size=0, idx;
    1086             :         Bool existing;
    1087             : 
    1088          27 :         if (!cache_dir || !base_filename || !iri || !iri->string || strncmp(iri->string, "data:", 5)) return GF_OK;
    1089             : 
    1090             :         /*handle "data:" scheme when cache is specified*/
    1091             :         strcpy(szFile, cache_dir);
    1092           0 :         data_size = (u32) strlen(szFile);
    1093           0 :         if (szFile[data_size-1] != GF_PATH_SEPARATOR) {
    1094           0 :                 szFile[data_size] = GF_PATH_SEPARATOR;
    1095           0 :                 szFile[data_size+1] = 0;
    1096             :         }
    1097             : 
    1098           0 :         sep = strrchr(base_filename, GF_PATH_SEPARATOR);
    1099             : #ifdef WIN32
    1100             :         if (!sep) sep = strrchr(base_filename, '/');
    1101             : #endif
    1102           0 :         if (!sep) sep = (char *) base_filename;
    1103           0 :         else sep += 1;
    1104             :         strcat(szFile, sep);
    1105             : 
    1106           0 :         sep = gf_file_ext_start(szFile);
    1107           0 :         if (sep) sep[0] = 0;
    1108             :         strcat(szFile, "_img_");
    1109             : 
    1110             :         /*get mime type*/
    1111           0 :         sep = (char *)iri->string + 5;
    1112           0 :         if (!strncmp(sep, "image/jpg", 9) || !strncmp(sep, "image/jpeg", 10)) ext = ".jpg";
    1113           0 :         else if (!strncmp(sep, "image/png", 9)) ext = ".png";
    1114           0 :         else if (!strncmp(sep, "image/svg+xml", 13)) ext = ".svg";
    1115             :         else return GF_BAD_PARAM;
    1116             : 
    1117             : 
    1118             :         data = NULL;
    1119           0 :         sep = strchr(iri->string, ';');
    1120           0 :         if (!strncmp(sep, ";base64,", 8)) {
    1121           0 :                 sep += 8;
    1122           0 :                 data_size = 2 * (u32) strlen(sep);
    1123           0 :                 data = (char*)gf_malloc(sizeof(char)*data_size);
    1124           0 :                 if (!data) return GF_OUT_OF_MEM;
    1125           0 :                 data_size = gf_base64_decode(sep, (u32) strlen(sep), data, data_size);
    1126             :         }
    1127           0 :         else if (!strncmp(sep, ";base16,", 8)) {
    1128           0 :                 data_size = 2 * (u32) strlen(sep);
    1129           0 :                 data = (char*)gf_malloc(sizeof(char)*data_size);
    1130           0 :                 if (!data) return GF_OUT_OF_MEM;
    1131           0 :                 sep += 8;
    1132           0 :                 data_size = gf_base16_decode(sep, (u32) strlen(sep), data, data_size);
    1133             :         }
    1134           0 :         if (!data || !data_size) return GF_OK;
    1135             : 
    1136           0 :         iri->type = XMLRI_STRING;
    1137             : 
    1138             :         existing = 0;
    1139             :         idx = 0;
    1140           0 :         while (1) {
    1141           0 :                 u32 res = check_existing_file(szFile, ext, data, data_size, idx);
    1142           0 :                 if (!res) break;
    1143           0 :                 if (res==2) {
    1144             :                         existing = 1;
    1145             :                         break;
    1146             :                 }
    1147           0 :                 idx++;
    1148             :         }
    1149             :         sprintf(buf, "%04X", idx);
    1150             :         strcat(szFile, buf);
    1151             :         strcat(szFile, ext);
    1152             : 
    1153           0 :         if (!existing) {
    1154           0 :                 FILE *f = gf_fopen(szFile, "wb");
    1155           0 :                 if (!f) {
    1156           0 :                         gf_free(data);
    1157           0 :                         gf_free(iri->string);
    1158           0 :                         iri->string = NULL;
    1159           0 :                         return GF_IO_ERR;
    1160             :                 }
    1161           0 :                 gf_fwrite(data, data_size, f);
    1162           0 :                 gf_fclose(f);
    1163             :         }
    1164           0 :         gf_free(data);
    1165           0 :         gf_free(iri->string);
    1166           0 :         iri->string = gf_strdup(szFile);
    1167           0 :         return GF_OK;
    1168             : }
    1169             : 
    1170             : 
    1171             : #endif /*GPAC_DISABLE_SVG*/

Generated by: LCOV version 1.13