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*/
|