PageRenderTime 659ms CodeModel.GetById 6ms app.highlight 569ms RepoModel.GetById 1ms app.codeStats 3ms

/ext/gpac/src/scenegraph/svg_attributes.c

https://github.com/paulcbetts/yikes
C | 5816 lines | 5425 code | 280 blank | 111 comment | 1405 complexity | 3aeb496d80ffcd900b05cc19ea685d13 MD5 | raw file
   1/*
   2 *					GPAC Multimedia Framework
   3 *
   4 *			Authors: Cyril Concolato - Jean le Feuvre - Jean-Claude Moissinac
   5 *				Copyright (c) 2005-200X ENST
   6 *					All rights reserved
   7 *
   8 *  This file is part of GPAC / SVG Loader module
   9 *
  10 *  GPAC is free software; 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; 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; 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; see the file COPYING.  If not, write to
  22 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  23 *
  24 */
  25
  26#include <gpac/base_coding.h>
  27#include <gpac/events.h>
  28#include <gpac/scenegraph_svg.h>
  29#include <gpac/internal/scenegraph_dev.h>
  30
  31#define DUMP_COORDINATES 1
  32
  33/*
  34	    list of supported events in Tiny 1.2 as of 2005/09/10:
  35		repeat is somehow a special case ...
  36*/
  37u32 gf_dom_event_type_by_name(const char *name)
  38{
  39	if ((name[0]=='o') && (name[1]=='n')) name += 2;
  40
  41	if (!strcmp(name, "abort"))	return GF_EVENT_ABORT;
  42	if (!strcmp(name, "activate"))	return GF_EVENT_ACTIVATE;
  43	if (!strcmp(name, "begin"))		return GF_EVENT_BEGIN;
  44	if (!strcmp(name, "beginEvent"))	return GF_EVENT_BEGIN_EVENT;
  45	if (!strcmp(name, "click"))		return GF_EVENT_CLICK;
  46	if (!strcmp(name, "end"))		return GF_EVENT_END;
  47	if (!strcmp(name, "endEvent"))	return GF_EVENT_END_EVENT;
  48	if (!strcmp(name, "error"))		return GF_EVENT_ERROR;
  49	if (!strcmp(name, "focusin") || !strcmp(name, "DOMFocusIn"))	return GF_EVENT_FOCUSIN;
  50	if (!strcmp(name, "focusout") || !strcmp(name, "DOMFocusOut"))	return GF_EVENT_FOCUSOUT;
  51	if (!strcmp(name, "keydown"))	return GF_EVENT_KEYDOWN;
  52	if (!strcmp(name, "keypress") || !stricmp(name, "accesskey"))	return GF_EVENT_KEYDOWN;
  53	if (!strcmp(name, "keyup"))		return GF_EVENT_KEYUP;
  54	if (!strcmp(name, "load"))		return GF_EVENT_LOAD;
  55	if (!strcmp(name, "SVGLoad"))	return GF_EVENT_LOAD;
  56	if (!strcmp(name, "longkeypress") || !stricmp(name, "longaccesskey"))	return GF_EVENT_LONGKEYPRESS;
  57	if (!strcmp(name, "mousedown")) return GF_EVENT_MOUSEDOWN;
  58	if (!strcmp(name, "mousemove")) return GF_EVENT_MOUSEMOVE;
  59	if (!strcmp(name, "mouseout"))	return GF_EVENT_MOUSEOUT;
  60	if (!strcmp(name, "mouseover")) return GF_EVENT_MOUSEOVER;
  61	if (!strcmp(name, "mouseup"))	return GF_EVENT_MOUSEUP;
  62	if (!strcmp(name, "repeat"))	return GF_EVENT_REPEAT;
  63	if (!strcmp(name, "repeatEvent"))	return GF_EVENT_REPEAT_EVENT;
  64	if (!strcmp(name, "resize"))	return GF_EVENT_RESIZE;
  65	if (!strcmp(name, "scroll"))	return GF_EVENT_SCROLL;
  66	if (!strcmp(name, "textInput"))	return GF_EVENT_TEXTINPUT;
  67	if (!strcmp(name, "unload"))	return GF_EVENT_UNLOAD;
  68	if (!strcmp(name, "zoom"))		return GF_EVENT_ZOOM;
  69
  70	/*LASeR events*/
  71	if (!strcmp(name, "activatedEvent"))	return GF_EVENT_ACTIVATED;
  72	if (!strcmp(name, "deactivatedEvent"))	return GF_EVENT_DEACTIVATED;
  73	if (!strcmp(name, "executionTime"))	return GF_EVENT_EXECUTION_TIME;
  74	if (!strcmp(name, "pause"))	return GF_EVENT_PAUSE;
  75	if (!strcmp(name, "pausedEvent"))	return GF_EVENT_PAUSED_EVENT;
  76	if (!strcmp(name, "play"))	return GF_EVENT_PLAY;
  77	if (!strcmp(name, "repeatKey"))	return GF_EVENT_REPEAT_KEY;
  78	if (!strcmp(name, "resumedEvent"))	return GF_EVENT_RESUME_EVENT;
  79	if (!strcmp(name, "shortAccessKey"))	return GF_EVENT_SHORT_ACCESSKEY;
  80	/*LASeR unofficial events*/
  81	if (!strcmp(name, "battery"))		return GF_EVENT_BATTERY;
  82	if (!strcmp(name, "cpu"))		return GF_EVENT_CPU;
  83	GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[DOM Events] Unknown event found \"%s\"\n", name));
  84	return GF_EVENT_UNKNOWN;
  85}
  86
  87const char *gf_dom_event_get_name(u32 type)
  88{
  89
  90	switch (type) {
  91	case GF_EVENT_ABORT: return "abort";
  92	case GF_EVENT_ACTIVATE: return "activate";
  93	case GF_EVENT_BEGIN: return "begin";
  94	case GF_EVENT_BEGIN_EVENT: return "beginEvent";
  95	case GF_EVENT_CLICK: return "click";
  96	case GF_EVENT_END: return "end";
  97	case GF_EVENT_END_EVENT: return "endEvent";
  98	case GF_EVENT_ERROR: return "error";
  99	case GF_EVENT_FOCUSIN: return "focusin";
 100	case GF_EVENT_FOCUSOUT: return "focusout";
 101	case GF_EVENT_KEYDOWN: return "keydown";
 102	case GF_EVENT_KEYUP: return "keyup";
 103	case GF_EVENT_LOAD: return "load";
 104	case GF_EVENT_LONGKEYPRESS: return "longaccesskey";
 105	case GF_EVENT_MOUSEDOWN: return "mousedown";
 106	case GF_EVENT_MOUSEMOVE: return "mousemove";
 107	case GF_EVENT_MOUSEOUT: return "mouseout";
 108	case GF_EVENT_MOUSEOVER: return "mouseover";
 109	case GF_EVENT_MOUSEUP: return "mouseup";
 110	case GF_EVENT_REPEAT: return "repeat";
 111	case GF_EVENT_REPEAT_EVENT: return "repeatEvent";
 112	case GF_EVENT_RESIZE: return "resize";
 113	case GF_EVENT_SCROLL: return "scroll";
 114	case GF_EVENT_TEXTINPUT: return "textInput";
 115	case GF_EVENT_UNLOAD: return "unload";
 116	case GF_EVENT_ZOOM: return "zoom";
 117
 118	/*LASeR events*/
 119	case GF_EVENT_ACTIVATED: return "activatedEvent";
 120	case GF_EVENT_DEACTIVATED: return "deactivatedEvent";
 121	case GF_EVENT_EXECUTION_TIME: return "executionTime";
 122	case GF_EVENT_PAUSE: return "pause";
 123	case GF_EVENT_PAUSED_EVENT: return "pausedEvent";
 124	case GF_EVENT_PLAY: return "play";
 125	case GF_EVENT_REPEAT_KEY: return "repeatKey";
 126	case GF_EVENT_RESUME_EVENT: return "resumedEvent";
 127	case GF_EVENT_SHORT_ACCESSKEY: return "shortAccessKey";
 128	/*LASeR unofficial events*/
 129	case GF_EVENT_BATTERY: return "battery";
 130	case GF_EVENT_CPU: return "cpu";
 131
 132	default: return "unknown";
 133	}
 134}
 135
 136static const struct predef_keyid {u32 key_code;  const char *name; } predefined_key_identifiers[] = 
 137{
 138	{ GF_KEY_ACCEPT, "Accept" },
 139	{ GF_KEY_AGAIN, "Again" },
 140	{ GF_KEY_ALLCANDIDATES, "AllCandidates" },
 141	{ GF_KEY_ALPHANUM, "Alphanumeric" },
 142	{ GF_KEY_ALT, "Alt" },
 143	{ GF_KEY_ALTGRAPH, "AltGraph" },
 144	{ GF_KEY_APPS, "Apps" },
 145	{ GF_KEY_ATTN, "Attn" },
 146	{ GF_KEY_BROWSERBACK, "BrowserBack" },
 147	{ GF_KEY_BROWSERFAVORITES, "BrowserFavorites" },
 148	{ GF_KEY_BROWSERFORWARD, "BrowserForward" },
 149	{ GF_KEY_BROWSERHOME, "BrowserHome" },
 150	{ GF_KEY_BROWSERREFRESH, "BrowserRefresh" },
 151	{ GF_KEY_BROWSERSEARCH, "BrowserSearch" },
 152	{ GF_KEY_BROWSERSTOP, "BrowserStop" },
 153	{ GF_KEY_CAPSLOCK, "CapsLock" },
 154	{ GF_KEY_CLEAR, "Clear" },
 155	{ GF_KEY_CODEINPUT, "CodeInput" },
 156	{ GF_KEY_COMPOSE, "Compose" },
 157	{ GF_KEY_CONTROL, "Control" },
 158	{ GF_KEY_CRSEL, "Crsel" },
 159	{ GF_KEY_CONVERT, "Convert" },
 160	{ GF_KEY_COPY, "Copy"  },
 161	{ GF_KEY_CUT, "Cut" },
 162	{ GF_KEY_DOWN, "Down" },
 163	{ GF_KEY_END, "End" },
 164	{ GF_KEY_ENTER, "Enter" },
 165	{ GF_KEY_ERASEEOF, "EraseEof" },
 166	{ GF_KEY_EXECUTE, "Execute" },
 167	{ GF_KEY_EXSEL, "Exsel" },
 168	{ GF_KEY_F1, "F1" },
 169	{ GF_KEY_F2, "F2" },
 170	{ GF_KEY_F3, "F3" },
 171	{ GF_KEY_F4, "F4" },
 172	{ GF_KEY_F5, "F5" },
 173	{ GF_KEY_F6, "F6" },
 174	{ GF_KEY_F7, "F7" },
 175	{ GF_KEY_F8, "F8" },
 176	{ GF_KEY_F9, "F9" },
 177	{ GF_KEY_F10, "F10" },
 178	{ GF_KEY_F11, "F11" },
 179	{ GF_KEY_F12, "F12" },
 180	{ GF_KEY_F13, "F13" },
 181	{ GF_KEY_F14, "F14" },
 182	{ GF_KEY_F15, "F15" },
 183	{ GF_KEY_F16, "F16" },
 184	{ GF_KEY_F17, "F17" },
 185	{ GF_KEY_F18, "F18" },
 186	{ GF_KEY_F19, "F19" },
 187	{ GF_KEY_F20, "F20" },
 188	{ GF_KEY_F21, "F21" },
 189	{ GF_KEY_F22, "F22" },
 190	{ GF_KEY_F23, "F23" },
 191	{ GF_KEY_F24, "F24" },
 192	{ GF_KEY_FINALMODE, "FinalMode" },
 193	{ GF_KEY_FIND, "Find" },
 194	{ GF_KEY_FULLWIDTH, "FullWidth" },
 195	{ GF_KEY_HALFWIDTH, "HalfWidth" },
 196	{ GF_KEY_HANGULMODE, "HangulMode" },
 197	{ GF_KEY_HANJAMODE, "HanjaMode"   },
 198	{ GF_KEY_HELP, "Help" },
 199	{ GF_KEY_HIRAGANA, "Hiragana" },
 200	{ GF_KEY_HOME, "Home" },
 201	{ GF_KEY_INSERT, "Insert" },
 202	{ GF_KEY_JAPANESEHIRAGANA, "JapaneseHiragana" },
 203	{ GF_KEY_JAPANESEKATAKANA, "JapaneseKatakana" },
 204	{ GF_KEY_JAPANESEROMAJI, "JapaneseRomaji" },
 205	{ GF_KEY_JUNJAMODE, "JunjaMode" },
 206	{ GF_KEY_KANAMODE, "KanaMode"   },
 207	{ GF_KEY_KANJIMODE, "KanjiMode" },
 208	{ GF_KEY_KATAKANA, "Katakana"   },
 209	{ GF_KEY_LAUNCHAPPLICATION1, "LaunchApplication1" },
 210	{ GF_KEY_LAUNCHAPPLICATION2, "LaunchApplication2" },
 211	{ GF_KEY_LAUNCHMAIL, "LaunchMail" },
 212	{ GF_KEY_LEFT, "Left" },
 213	{ GF_KEY_META, "Meta" },
 214	{ GF_KEY_MEDIANEXTTRACK, "MediaNextTrack" },
 215	{ GF_KEY_MEDIAPLAYPAUSE, "MediaPlayPause" },
 216	{ GF_KEY_MEDIAPREVIOUSTRACK, "MediaPreviousTrack" },
 217	{ GF_KEY_MEDIASTOP, "MediaStop" },
 218	{ GF_KEY_MODECHANGE, "ModeChange" },
 219	{ GF_KEY_NONCONVERT, "Nonconvert" },
 220	{ GF_KEY_NUMLOCK, "NumLock" },
 221	{ GF_KEY_PAGEDOWN, "PageDown" },
 222	{ GF_KEY_PAGEUP, "PageUp" },
 223	{ GF_KEY_PASTE, "Paste" },
 224	{ GF_KEY_PAUSE, "Pause" },
 225	{ GF_KEY_PLAY, "Play" },
 226	{ GF_KEY_PREVIOUSCANDIDATE, "PreviousCandidate" },
 227	{ GF_KEY_PRINTSCREEN, "PrintScreen" },
 228	{ GF_KEY_PROCESS, "Process" },
 229	{ GF_KEY_PROPS, "Props" },
 230	{ GF_KEY_RIGHT, "Right" },
 231	{ GF_KEY_ROMANCHARACTERS, "RomanCharacters" },
 232	{ GF_KEY_SCROLL, "Scroll" },
 233	{ GF_KEY_SELECT, "Select" },
 234	{ GF_KEY_SELECTMEDIA, "SelectMedia" },
 235	{ GF_KEY_SHIFT, "Shift" },
 236	{ GF_KEY_STOP, "Stop" },
 237	{ GF_KEY_UP, "Up" },
 238	{ GF_KEY_UNDO, "Undo" },
 239	{ GF_KEY_VOLUMEDOWN, "VolumeDown" },
 240	{ GF_KEY_VOLUMEMUTE, "VolumeMute" },
 241	{ GF_KEY_VOLUMEUP, "VolumeUp" },
 242	{ GF_KEY_WIN, "Win" },
 243	{ GF_KEY_ZOOM, "Zoom" },
 244	{ GF_KEY_BACKSPACE, "U+0008" },
 245	{ GF_KEY_TAB, "U+0009" },
 246	{ GF_KEY_CANCEL, "U+0018" },
 247	{ GF_KEY_ESCAPE, "U+001B" },
 248	{ GF_KEY_SPACE, "U+0020" },
 249	{ GF_KEY_EXCLAMATION, "U+0021" },
 250	{ GF_KEY_QUOTATION, "U+0022" },
 251	{ GF_KEY_NUMBER, "U+0023" },
 252	{ GF_KEY_DOLLAR, "U+0024" },
 253	{ GF_KEY_AMPERSAND, "U+0026" },
 254	{ GF_KEY_APOSTROPHE, "U+0027" },
 255	{ GF_KEY_LEFTPARENTHESIS, "U+0028" },
 256	{ GF_KEY_RIGHTPARENTHESIS, "U+0029" },
 257	{ GF_KEY_STAR, "U+002A" },
 258	{ GF_KEY_PLUS, "U+002B" },
 259	{ GF_KEY_COMMA, "U+002C" },
 260	{ GF_KEY_HYPHEN, "U+002D" },
 261	{ GF_KEY_FULLSTOP, "U+002E" },
 262	{ GF_KEY_SLASH, "U+002F" },
 263	{ GF_KEY_0, "U+0030" },
 264	{ GF_KEY_1, "U+0031" },
 265	{ GF_KEY_2, "U+0032" },
 266	{ GF_KEY_3, "U+0033" },
 267	{ GF_KEY_4, "U+0034" },
 268	{ GF_KEY_5, "U+0035" },
 269	{ GF_KEY_6, "U+0036" },
 270	{ GF_KEY_7, "U+0037" },
 271	{ GF_KEY_8, "U+0038" },
 272	{ GF_KEY_9, "U+0039" },
 273	{ GF_KEY_COLON, "U+003A" },
 274	{ GF_KEY_SEMICOLON, "U+003B" },
 275	{ GF_KEY_LESSTHAN, "U+003C" },
 276	{ GF_KEY_EQUALS, "U+003D" },
 277	{ GF_KEY_GREATERTHAN, "U+003E" },
 278	{ GF_KEY_QUESTION, "U+003F" },
 279	{ GF_KEY_AT, "U+0040" },
 280	{ GF_KEY_A, "U+0041" },
 281	{ GF_KEY_B, "U+0042" },
 282	{ GF_KEY_C, "U+0043" },
 283	{ GF_KEY_D, "U+0044" },
 284	{ GF_KEY_E, "U+0045" },
 285	{ GF_KEY_F, "U+0046" },
 286	{ GF_KEY_G, "U+0047" },
 287	{ GF_KEY_H, "U+0048" },
 288	{ GF_KEY_I, "U+0049" },
 289	{ GF_KEY_J, "U+004A" },
 290	{ GF_KEY_K, "U+004B" },
 291	{ GF_KEY_L, "U+004C" },
 292	{ GF_KEY_M, "U+004D" },
 293	{ GF_KEY_N, "U+004E" },
 294	{ GF_KEY_O, "U+004F" },
 295	{ GF_KEY_P, "U+0050" },
 296	{ GF_KEY_Q, "U+0051" },
 297	{ GF_KEY_R, "U+0052" },
 298	{ GF_KEY_S, "U+0053" },
 299	{ GF_KEY_T, "U+0054" },
 300	{ GF_KEY_U, "U+0055" },
 301	{ GF_KEY_V, "U+0056" },
 302	{ GF_KEY_W, "U+0057" },
 303	{ GF_KEY_X, "U+0058" },
 304	{ GF_KEY_Y, "U+0059" },
 305	{ GF_KEY_Z, "U+005A" },
 306	{ GF_KEY_LEFTSQUAREBRACKET, "U+005B" },
 307	{ GF_KEY_BACKSLASH, "U+005C" },
 308	{ GF_KEY_RIGHTSQUAREBRACKET, "U+005D" },
 309	{ GF_KEY_CIRCUM, "U+005E" },
 310	{ GF_KEY_UNDERSCORE, "U+005F" },
 311	{ GF_KEY_GRAVEACCENT, "U+0060" },
 312	{ GF_KEY_LEFTCURLYBRACKET, "U+007B" },
 313	{ GF_KEY_PIPE, "U+007C" },
 314	{ GF_KEY_RIGHTCURLYBRACKET, "U+007D" },
 315	{ GF_KEY_DEL, "U+007F" },
 316	{ GF_KEY_INVERTEXCLAMATION, "U+00A1" },
 317	{ GF_KEY_DEADGRAVE, "U+0300" },
 318	{ GF_KEY_DEADEACUTE, "U+0301" },
 319	{ GF_KEY_DEADCIRCUM, "U+0302" },
 320	{ GF_KEY_DEADTILDE, "U+0303" },
 321	{ GF_KEY_DEADMACRON, "U+0304" },
 322	{ GF_KEY_DEADBREVE, "U+0306" },
 323	{ GF_KEY_DEADABOVEDOT, "U+0307" },
 324	{ GF_KEY_DEADDIARESIS, "U+0308" },
 325	{ GF_KEY_DEADRINGABOVE, "U+030A" },
 326	{ GF_KEY_DEADDOUBLEACUTE, "U+030B" },
 327	{ GF_KEY_DEADCARON, "U+030C" },
 328	{ GF_KEY_DEADCEDILLA, "U+0327" },
 329	{ GF_KEY_DEADOGONEK, "U+0328" },
 330	{ GF_KEY_DEADIOTA, "U+0345" },
 331	{ GF_KEY_EURO, "U+20AC" },
 332	{ GF_KEY_DEADVOICESOUND, "U+3099" },
 333	{ GF_KEY_DEADSEMIVOICESOUND, "U+309A" }
 334};
 335const char *gf_dom_get_key_name(u32 key_identifier)
 336{
 337	u32 count = sizeof(predefined_key_identifiers) / sizeof(struct predef_keyid);
 338	if (!key_identifier || count<=key_identifier) return "Unknown";
 339	return predefined_key_identifiers[key_identifier-1].name;
 340}
 341
 342
 343u32 gf_dom_get_key_type(char *key_name)
 344{
 345	if (strlen(key_name) == 1) {
 346		char c[2];
 347		c[0] = key_name[0];
 348		c[1] = 0;
 349		strupr(c);
 350		if (c[0] >= 'A' && c[0] <= 'Z') 
 351			return (GF_KEY_A + (c[0] - 'A') );
 352		
 353		if (c[0] >= '0' && c[0] <= '9')
 354			return ( GF_KEY_0 + (c[0] - '0') );
 355		
 356		switch (c[0]) {
 357		case '@': return GF_KEY_AT;
 358		case '*': return GF_KEY_STAR;
 359		case '#': return GF_KEY_NUMBER;
 360		case ' ': return GF_KEY_SPACE;
 361		case '!': return GF_KEY_EXCLAMATION;
 362		case '"': return GF_KEY_QUOTATION;
 363		case '$': return GF_KEY_DOLLAR;
 364		case '&': return GF_KEY_AMPERSAND;
 365		case '\'': return GF_KEY_APOSTROPHE;
 366		case '(': return GF_KEY_LEFTPARENTHESIS;
 367		case ')': return GF_KEY_RIGHTPARENTHESIS;
 368		case '+': return GF_KEY_PLUS;
 369		case ',': return GF_KEY_COMMA;
 370		case '-': return GF_KEY_HYPHEN;
 371		case '.': return GF_KEY_FULLSTOP;
 372		case '/': return GF_KEY_SLASH;
 373		case ':': return GF_KEY_COLON;
 374		case ';': return GF_KEY_SEMICOLON;
 375		case '<': return GF_KEY_LESSTHAN;
 376		case '=': return GF_KEY_EQUALS;
 377		case '>': return GF_KEY_GREATERTHAN;
 378		case '?': return GF_KEY_QUESTION;
 379		case '[': return GF_KEY_LEFTSQUAREBRACKET;
 380		case '\\': return GF_KEY_BACKSLASH;
 381		case ']': return GF_KEY_RIGHTSQUAREBRACKET;
 382		case '^': return GF_KEY_CIRCUM;
 383		case '_': return GF_KEY_UNDERSCORE;
 384		case '`': return GF_KEY_GRAVEACCENT;
 385		case '{': return GF_KEY_LEFTCURLYBRACKET;
 386		case '|': return GF_KEY_PIPE;
 387		case '}': return GF_KEY_RIGHTCURLYBRACKET;
 388		case 'ยก': return GF_KEY_INVERTEXCLAMATION;
 389		default: return GF_KEY_UNIDENTIFIED;
 390		}
 391	} else {
 392		u32 i, count;
 393		count = sizeof(predefined_key_identifiers) / sizeof(struct predef_keyid);
 394		for (i=0; i<count; i++) {
 395			if (!stricmp(key_name, predefined_key_identifiers[i].name)) {
 396				return predefined_key_identifiers[i].key_code;
 397			}
 398		}
 399		return GF_KEY_UNIDENTIFIED;
 400	}
 401}
 402
 403/* Basic SVG datatype parsing functions */
 404static const struct predef_col { const char *name; u8 r; u8 g; u8 b; } predefined_colors[] = 
 405{
 406	{"aliceblue",240, 248, 255},
 407	{"antiquewhite",250, 235, 215},
 408	{"aqua", 0, 255, 255},
 409	{"aquamarine",127, 255, 212},
 410	{"azure",240, 255, 255},
 411	{"beige",245, 245, 220},
 412	{"bisque",255, 228, 196},
 413	{"black", 0, 0, 0},
 414	{"blanchedalmond",255, 235, 205},
 415	{"blue", 0, 0, 255},
 416	{"blueviolet",138, 43, 226},
 417	{"brown",165, 42, 42},
 418	{"burlywood",222, 184, 135},
 419	{"cadetblue", 95, 158, 160},
 420	{"chartreuse",127, 255, 0},
 421	{"chocolate",210, 105, 30},
 422	{"coral",255, 127, 80},
 423	{"lightpink",255, 182, 193},
 424	{"lightsalmon",255, 160, 122},
 425	{"lightseagreen", 32, 178, 170},
 426	{"lightskyblue",135, 206, 250},
 427	{"lightslategray",119, 136, 153},
 428	{"lightslategrey",119, 136, 153},
 429	{"lightsteelblue",176, 196, 222},
 430	{"lightyellow",255, 255, 224},
 431	{"lime", 0, 255, 0},
 432	{"limegreen", 50, 205, 50},
 433	{"linen",250, 240, 230},
 434	{"magenta",255, 0, 255},
 435	{"maroon",128, 0, 0},
 436	{"mediumaquamarine",102, 205, 170},
 437	{"mediumblue", 0, 0, 205},
 438	{"mediumorchid",186, 85, 211},
 439	{"cornflowerblue",100, 149, 237},
 440	{"cornsilk",255, 248, 220},
 441	{"crimson",220, 20, 60},
 442	{"cyan", 0, 255, 255},
 443	{"darkblue", 0, 0, 139},
 444	{"darkcyan", 0, 139, 139},
 445	{"darkgoldenrod",184, 134, 11},
 446	{"darkgray",169, 169, 169},
 447	{"darkgreen", 0, 100, 0},
 448	{"darkgrey",169, 169, 169},
 449	{"darkkhaki",189, 183, 107},
 450	{"darkmagenta",139, 0, 139},
 451	{"darkolivegreen", 85, 107, 47},
 452	{"darkorange",255, 140, 0},
 453	{"darkorchid",153, 50, 204},
 454	{"darkred",139, 0, 0},
 455	{"darksalmon",233, 150, 122},
 456	{"darkseagreen",143, 188, 143},
 457	{"darkslateblue", 72, 61, 139},
 458	{"darkslategray", 47, 79, 79},
 459	{"darkslategrey", 47, 79, 79},
 460	{"darkturquoise", 0, 206, 209},
 461	{"darkviolet",148, 0, 211},
 462	{"deeppink",255, 20, 147},
 463	{"deepskyblue", 0, 191, 255},
 464	{"dimgray",105, 105, 105},
 465	{"dimgrey",105, 105, 105},
 466	{"dodgerblue", 30, 144, 255},
 467	{"firebrick",178, 34, 34},
 468	{"floralwhite",255, 250, 240},
 469	{"forestgreen", 34, 139, 34},
 470	{"fuchsia",255, 0, 255},
 471	{"gainsboro",220, 220, 220},
 472	{"ghostwhite",248, 248, 255},
 473	{"gold",255, 215, 0},
 474	{"goldenrod",218, 165, 32},
 475	{"gray",128, 128, 128},
 476	{"grey",128, 128, 128},
 477	{"green", 0, 128, 0},
 478	{"greenyellow",173, 255, 47},
 479	{"honeydew",240, 255, 240},
 480	{"hotpink",255, 105, 180},
 481	{"indianred",205, 92, 92},
 482	{"indigo", 75, 0, 130},
 483	{"ivory",255, 255, 240},
 484	{"khaki",240, 230, 140},
 485	{"lavender",230, 230, 25},
 486	{"lavenderblush",255, 240, 245},
 487	{"mediumpurple",147, 112, 219},
 488	{"mediumseagreen", 60, 179, 113},
 489	{"mediumslateblue",123, 104, 238},
 490	{"mediumspringgreen", 0, 250, 154},
 491	{"mediumturquoise", 72, 209, 204},
 492	{"mediumvioletred",199, 21, 133},
 493	{"midnightblue", 25, 25, 112},
 494	{"mintcream",245, 255, 250},
 495	{"mistyrose",255, 228, 225},
 496	{"moccasin",255, 228, 181},
 497	{"navajowhite",255, 222, 173},
 498	{"navy", 0, 0, 128},
 499	{"oldlace",253, 245, 230},
 500	{"olive",128, 128, 0},
 501	{"olivedrab",107, 142, 35},
 502	{"orange",255, 165, 0},
 503	{"orangered",255, 69, 0},
 504	{"orchid",218, 112, 214},
 505	{"palegoldenrod",238, 232, 170},
 506	{"palegreen",152, 251, 152},
 507	{"paleturquoise",175, 238, 238},
 508	{"palevioletred",219, 112, 147},
 509	{"papayawhip",255, 239, 213},
 510	{"peachpuff",255, 218, 185},
 511	{"peru",205, 133, 63},
 512	{"pink",255, 192, 203},
 513	{"plum",221, 160, 221},
 514	{"powderblue",176, 224, 230},
 515	{"purple",128, 0, 128},
 516	{"red",255, 0, 0},
 517	{"rosybrown",188, 143, 143},
 518	{"royalblue", 65, 105, 225},
 519	{"saddlebrown",139, 69, 19},
 520	{"salmon",250, 128, 114},
 521	{"sandybrown",244, 164, 96},
 522	{"seagreen", 46, 139, 87},
 523	{"seashell",255, 245, 238},
 524	{"sienna",160, 82, 45},
 525	{"silver",192, 192, 192},
 526	{"skyblue",135, 206, 235},
 527	{"slateblue",106, 90, 205},
 528	{"slategray",112, 128, 144},
 529	{"slategrey",112, 128, 144},
 530	{"snow",255, 250, 250},
 531	{"springgreen", 0, 255, 127},
 532	{"steelblue", 70, 130, 180},
 533	{"tan",210, 180, 140},
 534	{"teal", 0, 128, 128},
 535	{"lawngreen",124, 252, 0},
 536	{"lemonchiffon",255, 250, 205},
 537	{"lightblue",173, 216, 230},
 538	{"lightcoral",240, 128, 128},
 539	{"lightcyan",224, 255, 255},
 540	{"lightgoldenrodyellow",250, 250, 210},
 541	{"lightgray",211, 211, 211},
 542	{"lightgreen",144, 238, 144},
 543	{"lightgrey",211, 211, 211},
 544	{"thistle",216, 191, 216},
 545	{"tomato",255, 99, 71},
 546	{"turquoise", 64, 224, 208},
 547	{"violet",238, 130, 238},
 548	{"wheat",245, 222, 179},
 549	{"white",255, 255, 255},
 550	{"whitesmoke",245, 245, 245},
 551	{"yellow",255, 255, 0},
 552	{"yellowgreen",154, 205, 50}
 553
 554};
 555
 556
 557/* Basic SVG datatype parsing functions */
 558static const struct sys_col { const char *name; u8 type; } system_colors[] = 
 559{
 560	{"ActiveBorder", SVG_COLOR_ACTIVE_BORDER},
 561	{"ActiveCaption", SVG_COLOR_ACTIVE_CAPTION},
 562	{"AppWorkspace", SVG_COLOR_APP_WORKSPACE},
 563	{"Background", SVG_COLOR_BACKGROUND},
 564	{"ButtonFace", SVG_COLOR_BUTTON_FACE},
 565	{"ButtonHighlight", SVG_COLOR_BUTTON_HIGHLIGHT},
 566	{"ButtonShadow", SVG_COLOR_BUTTON_SHADOW},
 567	{"ButtonText", SVG_COLOR_BUTTON_TEXT},
 568	{"CaptionText", SVG_COLOR_CAPTION_TEXT},
 569	{"GrayText", SVG_COLOR_GRAY_TEXT},
 570	{"Highlight", SVG_COLOR_HIGHLIGHT},
 571	{"HighlightText", SVG_COLOR_HIGHLIGHT_TEXT},
 572	{"InactiveBorder", SVG_COLOR_INACTIVE_BORDER},
 573	{"InactiveCaption", SVG_COLOR_INACTIVE_CAPTION},
 574	{"InactiveCaptionText", SVG_COLOR_INACTIVE_CAPTION_TEXT},
 575	{"InfoBackground", SVG_COLOR_INFO_BACKGROUND},
 576	{"InfoText", SVG_COLOR_INFO_TEXT},
 577	{"Menu", SVG_COLOR_MENU},
 578	{"MenuText", SVG_COLOR_MENU_TEXT},
 579	{"Scrollbar", SVG_COLOR_SCROLLBAR},
 580	{"ThreeDDarkShadow", SVG_COLOR_3D_DARK_SHADOW},
 581	{"ThreeDFace", SVG_COLOR_3D_FACE},
 582	{"ThreeDHighlight", SVG_COLOR_3D_HIGHLIGHT},
 583	{"ThreeDLightShadow", SVG_COLOR_3D_LIGHT_SHADOW},
 584	{"ThreeDShadow", SVG_COLOR_3D_SHADOW},
 585	{"Window", SVG_COLOR_WINDOW},
 586	{"WindowFrame", SVG_COLOR_WINDOW_FRAME},
 587	{"WindowText", SVG_COLOR_WINDOW_TEXT},
 588};
 589
 590/* parses an color from a named color HTML or CSS 2 */
 591static void svg_parse_named_color(SVG_Color *col, char *attribute_content)
 592{
 593	u32 i, count;
 594	count = sizeof(predefined_colors) / sizeof(struct predef_col);
 595	for (i=0; i<count; i++) {
 596		if (!strcmp(attribute_content, predefined_colors[i].name)) {
 597			col->red = INT2FIX(predefined_colors[i].r) / 255;
 598			col->green = INT2FIX(predefined_colors[i].g) / 255;
 599			col->blue = INT2FIX(predefined_colors[i].b) / 255;
 600			col->type = SVG_COLOR_RGBCOLOR;
 601			return;
 602		}
 603	}
 604	count = sizeof(system_colors) / sizeof(struct sys_col);
 605	for (i=0; i<count; i++) {
 606		if (!strcmp(attribute_content, system_colors[i].name)) {
 607			col->type = system_colors[i].type;
 608			return;
 609		}
 610	}
 611}
 612
 613const char *gf_svg_get_system_paint_server_name(u32 paint_type)
 614{
 615	u32 i, count;
 616	count = sizeof(system_colors) / sizeof(struct sys_col);
 617	for (i=0; i<count; i++) {
 618		if (paint_type == system_colors[i].type) return system_colors[i].name;
 619	}
 620	return "undefined";
 621}
 622
 623u32 gf_svg_get_system_paint_server_type(const char *name)
 624{
 625	u32 i, count;
 626	count = sizeof(system_colors) / sizeof(struct sys_col);
 627	for (i=0; i<count; i++) {
 628		if (!strcmp(name, system_colors[i].name)) return system_colors[i].type;
 629	}
 630	return 0;
 631}
 632
 633/* Reads an SVG Color 
 634   either #RRGGBB, #RGB, rgb(r,g,b) in [0,255] , colorname, or 'r g b' in [0,1]
 635   ignores any space, comma, semi-column before and any space after
 636   TODO: 
 637	transform the char into char and duplicate the input, instead of modifying it
 638		be more robust to errors in color description ex rgb(0 0 0)
 639*/
 640static void svg_parse_color(SVG_Color *col, char *attribute_content)
 641{
 642	char *str = attribute_content;
 643	while (str[strlen(attribute_content)-1] == ' ') str[strlen(attribute_content)-1] = 0;
 644	while (*str != 0 && (*str == ' ' || *str == ',' || *str == ';')) str++;
 645
 646	if (!strcmp(str, "currentColor")) {
 647		col->type = SVG_COLOR_CURRENTCOLOR;
 648		return;
 649	} else if (!strcmp(str, "inherit")) {
 650		col->type = SVG_COLOR_INHERIT;
 651		return;
 652	} else if (str[0]=='#') {
 653		u32 val;
 654		sscanf(str+1, "%x", &val);
 655		if (strlen(str) == 7) {
 656			col->red = INT2FIX((val>>16) & 0xFF) / 255;
 657			col->green = INT2FIX((val>>8) & 0xFF) / 255;
 658			col->blue = INT2FIX(val & 0xFF) / 255;
 659		} else {
 660			col->red = INT2FIX((val>>8) & 0xF) / 15;
 661			col->green = INT2FIX((val>>4) & 0xF) / 15;
 662			col->blue = INT2FIX(val & 0xF) / 15;
 663		}
 664		col->type = SVG_COLOR_RGBCOLOR;
 665	} else if (strstr(str, "rgb(") || strstr(str, "RGB(")) {
 666		Float _val;
 667		u8 is_percentage= 0;
 668		if (strstr(str, "%")) is_percentage = 1;
 669		str = strstr(str, "(");
 670		str++;
 671		sscanf(str, "%f", &_val); col->red = FLT2FIX(_val);
 672		str = strstr(str, ",");
 673		str++;
 674		sscanf(str, "%f", &_val); col->green = FLT2FIX(_val);
 675		str = strstr(str, ",");
 676		str++;
 677		sscanf(str, "%f", &_val); col->blue = FLT2FIX(_val);
 678		if (is_percentage) {
 679			col->red /= 100;
 680			col->green /= 100;
 681			col->blue /= 100;
 682		} else {
 683			col->red /= 255;
 684			col->green /= 255;
 685			col->blue /= 255;
 686		}
 687		col->type = SVG_COLOR_RGBCOLOR;
 688	} else if ((str[0] >= 'a' && str[0] <= 'z')
 689		|| (str[0] >= 'A' && str[0] <= 'Z')) {
 690		svg_parse_named_color(col, str);
 691	} else {
 692		Float _r, _g, _b;
 693		sscanf(str, "%f %f %f", &_r, &_g, &_b);
 694		col->red = FLT2FIX(_r);
 695		col->green = FLT2FIX(_g);
 696		col->blue = FLT2FIX(_b);
 697		col->type = SVG_COLOR_RGBCOLOR;
 698	}
 699}
 700
 701/* 
 702	Reads a float in scientific notation 
 703		trims any space, comma, semi-column before or after
 704		reads an optional + or -
 705		then reads a digit between 0 and 9
 706		optionally followed by an '.' and digits between 0 and 9
 707		optionally followed by e or E and digits between 0 and 9
 708	Returns the number of char read in d 
 709*/
 710static u32 svg_parse_float(char *d, Fixed *f, Bool is_angle) 
 711{
 712	Bool is_negative = 0;
 713	Float _val = 0;
 714	u32 i = 0;
 715	while ((d[i] != 0) && strchr(" ,;\r\n\t", d[i])) i++;
 716	if (!d[i]) goto end;
 717	if (d[i] == '+') i++;
 718	if (d[i] == '-') {
 719		is_negative = 1;
 720		i++;
 721	}
 722	while (d[i] >= '0' && d[i] <= '9' && d[i] != 0) {
 723		_val = _val*10 + (d[i]-'0');
 724		i++;
 725	}
 726	if (!d[i]) goto end;
 727	if (d[i] == '.') {
 728		u32 nb_digit_after = 0;
 729		i++;
 730		while (d[i] >= '0' && d[i] <= '9' && d[i] != 0) {
 731			_val = _val*10 + (d[i]-'0');
 732			nb_digit_after++;
 733			i++;
 734		}
 735		_val /= (Float)pow(10,nb_digit_after);
 736		if (!d[i]) goto end;
 737	}
 738	if (d[i] == 'e' || d[i] == 'E') {
 739		u32 exp = 0;
 740		i++;
 741		if (d[i] == '+' || d[i] == '-') i++;
 742		while (d[i] >= '0' && d[i] <= '9' && d[i] != 0) {
 743			exp = exp*10 + (d[i]-'0');
 744			i++;
 745		}
 746		_val *= (Float)pow(10, exp);
 747	}
 748end:
 749	if (is_negative) _val *= -1;
 750	//_val = atof(d);
 751	if (is_angle) {
 752		_val/=180;
 753		(*f) = gf_mulfix(FLT2FIX(_val), GF_PI);
 754	} else {
 755		(*f) = FLT2FIX(_val);
 756	}
 757	while (d[i] != 0 && (d[i] == ' ' || d[i] == ',' || d[i] == ';')) i++;
 758	return i;
 759}
 760
 761/*
 762   Parse an Offset Value, i.e +/- Clock Value
 763*/
 764static void svg_parse_clock_value(char *d, Double *clock_value) 
 765{
 766	char *tmp;
 767	s32 sign = 1;
 768	if (d[0] == '+') d++;
 769	if (d[0] == '-') { sign = -1; d++; }
 770	while (*d == ' ') d++;
 771
 772	if ((tmp = strchr(d, ':'))) {
 773		/* Full or Partial Clock value */
 774		tmp++;
 775		if ((tmp = strchr(tmp, ':'))) {
 776			/* Full Clock value : hh:mm:ss(.frac) */
 777			u32 hours;
 778			u32 minutes;
 779			Float seconds;
 780			sscanf(d, "%d:%d:%f", &hours, &minutes, &seconds);
 781			*clock_value = hours*3600 + minutes*60 + seconds;
 782		} else {
 783			/* Partial Clock value : mm:ss(.frac) */
 784			s32 minutes;
 785			Float seconds;
 786			sscanf(d, "%d:%f", &minutes, &seconds);
 787			*clock_value = minutes*60 + seconds;
 788		}
 789	} else if ((tmp = strstr(d, "h"))) {
 790		Float f;
 791		sscanf(d, "%fh", &f);
 792		*clock_value = 3600*f;
 793	} else if (strstr(d, "min")) {
 794		Float f;
 795		sscanf(d, "%fmin", &f);
 796		*clock_value = 60*f;
 797	} else if ((tmp = strstr(d, "ms"))) {
 798		Float f;
 799		sscanf(d, "%fms", &f);
 800		*clock_value = f/1000;
 801	} else if (strchr(d, 's')) {
 802		Float f;
 803		sscanf(d, "%fs", &f);
 804		*clock_value = f;
 805	} else {
 806		*clock_value = atof(d);
 807	}
 808	*clock_value *= sign;
 809}
 810/* Parses one SVG time value:
 811	  'indefinite', 
 812	  'name.begin', 'name.end', 
 813	  wallclock,
 814	  accessKey,
 815	  events, 
 816	  clock value.
 817 */
 818static void smil_parse_time(GF_Node *e, SMIL_Time *v, char *d) 
 819{
 820	char *tmp;
 821
 822	/* Offset Values */
 823	if ((d[0] >= '0' && d[0] <= '9') || d[0] == '+' || d[0] == '-'){
 824		v->type = GF_SMIL_TIME_CLOCK;
 825		svg_parse_clock_value(d, &(v->clock));
 826		return;
 827	} 
 828	
 829	/* Indefinite Values */
 830	else if (!strcmp(d, "indefinite")) {
 831		v->type = GF_SMIL_TIME_INDEFINITE;
 832		return;
 833	} 
 834
 835	/* Wallclock Values */
 836	else if ((tmp = strstr(d, "wallclock("))) {
 837		u32 year, month, day;
 838		u32 hours, minutes;
 839		u32 nhours, nminutes;
 840		Float seconds;
 841		char *tmp1, *tmp2;
 842
 843		v->type = GF_SMIL_TIME_WALLCLOCK;
 844		tmp += 10;
 845		if ((tmp1 = strchr(tmp, 'T')) ) {
 846			/* From tmp to wallStartTime, we parse a date */
 847			sscanf(tmp, "%d-%d-%dT", &year, &month, &day);
 848			tmp1++;
 849			tmp = tmp1;
 850		} 	
 851		if ((tmp1 = strchr(tmp, ':')) ) {
 852			if ((tmp2 = strchr(tmp1, ':')) ) {
 853				/* HHMMSS */
 854				sscanf(tmp, "%d:%d:%f", &hours, &minutes, &seconds);		
 855			} else {
 856				/* HHMM */
 857				sscanf(tmp, "%d:%d", &hours, &minutes);		
 858			}
 859		}
 860		if (strchr(tmp, 'Z')) {
 861			return;
 862		} else {
 863			if ( (tmp1 = strchr(tmp, '+')) ) {
 864				sscanf(tmp1, "%d:%d", &nhours, &nminutes);		
 865			} else if ( (tmp1 = strchr(tmp, '-')) ) {
 866				sscanf(tmp1, "%d:%d", &nhours, &nminutes);		
 867			}
 868		}
 869		return;
 870	} 
 871
 872	/* AccessKey Values */
 873	else if ((tmp = strstr(d, "accessKey("))) {
 874		char *sep;
 875		v->type = GF_SMIL_TIME_EVENT;
 876		v->event.type = GF_EVENT_KEYDOWN;
 877		v->element = e->sgprivate->scenegraph->RootNode;
 878		tmp+=10;
 879		sep = strchr(d, ')');
 880		sep[0] = 0;
 881		v->event.parameter = gf_dom_get_key_type(tmp);
 882		sep++;
 883		if ((tmp = strchr(sep, '+')) || (tmp = strchr(sep, '-'))) {
 884			char c = *tmp;
 885			tmp++;
 886			svg_parse_clock_value(tmp, &(v->clock));
 887			if (c == '-') v->clock *= -1;
 888		} 
 889		return;
 890	} 
 891
 892	else {
 893		Bool had_param = 0;
 894		char *tmp2;
 895		v->type = GF_SMIL_TIME_EVENT;
 896		if ((tmp = strchr(d, '.'))) {
 897			tmp[0] = 0;
 898			v->element_id = strdup(d);
 899			tmp[0] = '.';
 900			tmp++;
 901		} else {
 902			tmp = d;
 903		}
 904		if ((tmp2 = strchr(tmp, '('))) {
 905			tmp2[0] = 0;
 906			v->event.type = gf_dom_event_type_by_name(tmp);
 907			tmp2[0] = '(';
 908			tmp2++;
 909			had_param = 1;
 910			v->event.parameter = atoi(tmp2);
 911			tmp = strchr(tmp2, ')');
 912			if (!tmp) {
 913				GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] expecting ')' in SMIL Time %s\n", d));
 914				return;
 915			}			
 916			tmp++;
 917		} 
 918		if ((tmp2 = strchr(tmp, '+')) || (tmp2 = strchr(tmp, '-'))) {
 919			char c = *tmp2;
 920			char *tmp3 = tmp2;
 921			tmp2[0] = 0;
 922			tmp3--;
 923			while (*tmp3==' ') { *tmp3=0; tmp3--; }
 924			if (v->event.type == 0) v->event.type = gf_dom_event_type_by_name(tmp);
 925			if (!had_param && (v->event.type == GF_EVENT_REPEAT || v->event.type == GF_EVENT_REPEAT_EVENT))
 926				v->event.parameter = 1;
 927			tmp2[0] = c;
 928			tmp2++;
 929			svg_parse_clock_value(tmp2, &(v->clock));
 930			if (c == '-') v->clock *= -1;
 931		} else {
 932			if (v->event.type == 0) v->event.type = gf_dom_event_type_by_name(tmp);
 933			if (!had_param && (v->event.type == GF_EVENT_REPEAT || v->event.type == GF_EVENT_REPEAT_EVENT))
 934				v->event.parameter = 1;
 935		}
 936	}
 937}
 938
 939/* Parses a list of SVG transformations and collapses them in the given matrix */
 940static void svg_parse_transformlist(GF_Matrix2D *mat, char *attribute_content) 
 941{
 942	GF_Matrix2D tmp;
 943
 944	char *str;
 945	u32 i;
 946	
 947	gf_mx2d_init(*mat);
 948	
 949	str = attribute_content;
 950	i = 0;
 951	while (str[i] != 0) {
 952		while (str[i] == ' ') i++;
 953		if (str[i] == ',') i++;
 954		while (str[i] == ' ') i++;
 955		if (strstr(str+i, "scale")==str+i) {
 956			Fixed sx, sy;
 957			i += 5;
 958			while(str[i] != 0 && str[i] == ' ') i++;
 959			if (str[i] == '(') {
 960				i++;
 961				i+=svg_parse_float(&(str[i]), &sx, 0);
 962				if (str[i] == ')') {
 963					sy = sx;
 964				} else {
 965					i+=svg_parse_float(&(str[i]), &sy, 0);
 966				}
 967				i++;
 968			}
 969			gf_mx2d_init(tmp);
 970			gf_mx2d_add_scale(&tmp, sx, sy);
 971			gf_mx2d_add_matrix(&tmp, mat);
 972			gf_mx2d_copy(*mat, tmp);
 973			while(str[i] != 0 && str[i] == ' ') i++;
 974		} else if (strstr(str+i, "translate")==str+i) {
 975			Fixed tx, ty;
 976			i += 9;
 977			while(str[i] != 0 && str[i] == ' ') i++;
 978			if (str[i] == '(') {
 979				i++;
 980				i+=svg_parse_float(&(str[i]), &tx, 0);
 981				if (str[i] == ')') {
 982					ty = 0;
 983				} else {
 984					i+=svg_parse_float(&(str[i]), &ty, 0);
 985				}
 986				i++;
 987			}
 988			gf_mx2d_init(tmp);
 989			gf_mx2d_add_translation(&tmp, tx, ty);
 990			gf_mx2d_add_matrix(&tmp, mat);
 991			gf_mx2d_copy(*mat, tmp);
 992			while(str[i] != 0 && str[i] == ' ') i++;
 993		} else if (strstr(str+i, "rotate")==str+i) {
 994			Fixed angle, cx, cy;
 995			i += 6;
 996			while(str[i] != 0 && str[i] == ' ') i++;
 997			if (str[i] == '(') {
 998				i++;
 999				i+=svg_parse_float(&(str[i]), &angle, 1);
1000				if (str[i] == ')') {
1001					cx = cy = 0;
1002				} else {
1003					i+=svg_parse_float(&(str[i]), &cx, 0);
1004					i+=svg_parse_float(&(str[i]), &cy, 0);
1005				}
1006				i++;
1007			}
1008			gf_mx2d_init(tmp);
1009			gf_mx2d_add_rotation(&tmp, cx, cy, angle);
1010			gf_mx2d_add_matrix(&tmp, mat);
1011			gf_mx2d_copy(*mat, tmp);
1012			while(str[i] != 0 && str[i] == ' ') i++;
1013		} else if (strstr(str+i, "skewX")==str+i) {
1014			Fixed angle;
1015			i += 5;
1016			while(str[i] != 0 && str[i] == ' ') i++;
1017			if (str[i] == '(') {
1018				i++;
1019				i+=svg_parse_float(&(str[i]), &angle, 1);
1020				i++;
1021			}
1022			gf_mx2d_init(tmp);
1023			gf_mx2d_add_skew_x(&tmp, angle);
1024			gf_mx2d_add_matrix(&tmp, mat);
1025			gf_mx2d_copy(*mat, tmp);
1026			while(str[i] != 0 && str[i] == ' ') i++;
1027		} else if (strstr(str+i, "skewY")==str+i) {
1028			Fixed angle;
1029			i += 5;
1030			while(str[i] != 0 && str[i] == ' ') i++;
1031			if (str[i] == '(') {
1032				i++;
1033				i+=svg_parse_float(&(str[i]), &angle, 1);
1034				i++;
1035			}
1036			gf_mx2d_init(tmp);
1037			gf_mx2d_add_skew_y(&tmp, angle);
1038			gf_mx2d_add_matrix(&tmp, mat);
1039			gf_mx2d_copy(*mat, tmp);
1040			while(str[i] != 0 && str[i] == ' ') i++;
1041		} else if (strstr(str+i, "matrix")==str+i) {
1042			i+=6;
1043			while(str[i] != 0 && str[i] == ' ') i++;
1044			if (str[i] == '(') {
1045				i++;
1046				i+=svg_parse_float(&(str[i]), &(tmp.m[0]), 0);
1047				i+=svg_parse_float(&(str[i]), &(tmp.m[3]), 0);
1048				i+=svg_parse_float(&(str[i]), &(tmp.m[1]), 0);
1049				i+=svg_parse_float(&(str[i]), &(tmp.m[4]), 0);
1050				i+=svg_parse_float(&(str[i]), &(tmp.m[2]), 0);
1051				i+=svg_parse_float(&(str[i]), &(tmp.m[5]), 0);
1052				i++;
1053			}
1054			gf_mx2d_add_matrix(&tmp, mat);
1055			gf_mx2d_copy(*mat, tmp);
1056			while(str[i] != 0 && str[i] == ' ') i++;
1057			if (str[i] == ')') i++;
1058		} 
1059	}
1060}
1061
1062/* Parses an SVG transform attribute and collapses all in the given matrix */
1063static Bool svg_parse_transform(SVG_Transform *t, char *attribute_content) 
1064{
1065	char *str;
1066	u32 i;
1067	str = attribute_content;
1068	i = 0;
1069
1070	if ((str = strstr(attribute_content, "ref("))) {
1071		t->is_ref = 1;
1072		gf_mx2d_init(t->mat);
1073		str+=3;
1074		while(str[i] != 0 && str[i] == ' ') i++;
1075		if (str[i] == 's' && str[i+1] == 'v' && str[i+2] == 'g') {
1076			i+=3;
1077			while(str[i] != 0 && str[i] == ' ') i++;					
1078			if (str[i] == ',') i++;
1079			else if (str[i] == ')') {
1080				i++;
1081				return GF_OK;
1082			}
1083			i+=svg_parse_float(&(str[i]), &(t->mat.m[2]), 0);
1084			i+=svg_parse_float(&(str[i]), &(t->mat.m[5]), 0);
1085			while(str[i] != 0 && str[i] == ' ') i++;
1086			if (str[i] == ')')  i++;
1087			i++;
1088			return GF_OK;
1089		} else {
1090			while(str[i] != 0 && str[i] != ')') i++;
1091			i++;
1092			return GF_NOT_SUPPORTED;
1093		}
1094		
1095	} else {
1096		svg_parse_transformlist(&t->mat, attribute_content);
1097	}
1098	return GF_OK;
1099}
1100
1101#undef REMOVE_ALLOC
1102
1103#if USE_GF_PATH    
1104
1105//#define PARSE_PATH_ONLY
1106
1107static void svg_parse_path(SVG_PathData *path, char *attribute_content) 
1108{
1109	char *d = attribute_content;
1110	
1111	/* Point used to start a new subpath when the previous subpath is closed */
1112	SVG_Point prev_m_pt;
1113	/* Point used to convert relative 'lower-case commands' into absolute */
1114	SVG_Point rel_ref_pt;
1115	/* Points used to convert S, T commands into C, Q */
1116	SVG_Point orig, ct_orig, ct_end, end;
1117	/* Used by elliptical arcs */
1118	Fixed x_axis_rotation, large_arc_flag, sweep_flag;
1119
1120	char c, prev_c;
1121	u32 i;
1122
1123	if (*d == 0) return;
1124
1125	i = 0;
1126	prev_c = 'M';
1127	orig.x = orig.y = ct_orig.x = ct_orig.y = prev_m_pt.x = prev_m_pt.y = rel_ref_pt.x = rel_ref_pt.y = 0;
1128	while(1) {
1129		while ( (d[i]==' ') || (d[i] =='\t') || (d[i] =='\r') || (d[i] =='\n') ) i++;			
1130		c = d[i];
1131		if (! c) break;
1132next_command:
1133		switch (c) {
1134		case 'm':
1135		case 'M':
1136			i++;
1137			i += svg_parse_float(&(d[i]), &(orig.x), 0);
1138			i += svg_parse_float(&(d[i]), &(orig.y), 0);				
1139			if (c == 'm') {
1140				orig.x += rel_ref_pt.x;
1141				orig.y += rel_ref_pt.y;
1142			}
1143#ifndef PARSE_PATH_ONLY
1144			gf_path_add_move_to(path, orig.x, orig.y);
1145#endif
1146			rel_ref_pt = orig;
1147			prev_m_pt = orig;
1148			/*provision for nextCurveTo when no curve is specified:
1149				"If there is no previous command or if the previous command was not an C, c, S or s, 
1150				assume the first control point is coincident with the current point.
1151			*/
1152			ct_orig = orig;
1153			prev_c = c;
1154			break;
1155		case 'L':
1156		case 'l':
1157			i++;
1158			i += svg_parse_float(&(d[i]), &(orig.x), 0);
1159			i += svg_parse_float(&(d[i]), &(orig.y), 0);				
1160			if (c == 'l') {
1161				orig.x += rel_ref_pt.x;
1162				orig.y += rel_ref_pt.y;
1163			}
1164#ifndef PARSE_PATH_ONLY
1165			gf_path_add_line_to(path, orig.x, orig.y);
1166#endif
1167			rel_ref_pt = orig;
1168			orig = end;
1169			/*cf above*/
1170			ct_orig = orig;
1171			prev_c = c;
1172			break;
1173		case 'H':
1174		case 'h':
1175			i++;				
1176			i += svg_parse_float(&(d[i]), &(orig.x), 0);
1177			if (c == 'h') {
1178				orig.x += rel_ref_pt.x;
1179			}
1180			orig.y = rel_ref_pt.y;
1181#ifndef PARSE_PATH_ONLY
1182			gf_path_add_line_to(path, orig.x, orig.y);			
1183#endif
1184			rel_ref_pt.x = orig.x;
1185			orig = end;
1186			/*cf above*/
1187			ct_orig = orig;
1188			prev_c = c;
1189			break;
1190		case 'V':
1191		case 'v':
1192			i++;				
1193			i += svg_parse_float(&(d[i]), &(orig.y), 0);
1194			if (c == 'v') {
1195				orig.y += rel_ref_pt.y;
1196			}
1197			orig.x = rel_ref_pt.x;
1198#ifndef PARSE_PATH_ONLY
1199			gf_path_add_line_to(path, orig.x, orig.y);			
1200#endif
1201			rel_ref_pt.y = orig.y;
1202			orig = end;
1203			/*cf above*/
1204			ct_orig = orig;
1205			prev_c = c;
1206			break;
1207		case 'C':
1208		case 'c':
1209			i++;				
1210			i += svg_parse_float(&(d[i]), &(ct_orig.x), 0);
1211			i += svg_parse_float(&(d[i]), &(ct_orig.y), 0);
1212			if (c == 'c') {
1213				ct_orig.x += rel_ref_pt.x;
1214				ct_orig.y += rel_ref_pt.y;
1215			}
1216			i += svg_parse_float(&(d[i]), &(ct_end.x), 0);
1217			i += svg_parse_float(&(d[i]), &(ct_end.y), 0);
1218			if (c == 'c') {
1219				ct_end.x += rel_ref_pt.x;
1220				ct_end.y += rel_ref_pt.y;
1221			}
1222			i += svg_parse_float(&(d[i]), &(end.x), 0);
1223			i += svg_parse_float(&(d[i]), &(end.y), 0);
1224			if (c == 'c') {
1225				end.x += rel_ref_pt.x;
1226				end.y += rel_ref_pt.y;
1227			}
1228#ifndef PARSE_PATH_ONLY
1229			gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
1230#endif
1231			rel_ref_pt = end;
1232			ct_orig = ct_end;
1233			orig = end;
1234			prev_c = c;
1235			break;
1236		case 'S':
1237		case 's':
1238			i++;				
1239			ct_orig.x = 2*orig.x - ct_orig.x;
1240			ct_orig.y = 2*orig.y - ct_orig.y;
1241			i += svg_parse_float(&(d[i]), &(ct_end.x), 0);
1242			i += svg_parse_float(&(d[i]), &(ct_end.y), 0);
1243			if (c == 's') {
1244				ct_end.x += rel_ref_pt.x;
1245				ct_end.y += rel_ref_pt.y;
1246			}
1247			i += svg_parse_float(&(d[i]), &(end.x), 0);
1248			i += svg_parse_float(&(d[i]), &(end.y), 0);
1249			if (c == 's') {
1250				end.x += rel_ref_pt.x;
1251				end.y += rel_ref_pt.y;
1252			}
1253#ifndef PARSE_PATH_ONLY
1254			gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
1255#endif
1256			rel_ref_pt = end;
1257			ct_orig = ct_end;
1258			orig = end;
1259			prev_c = c;
1260			break;
1261		case 'Q':
1262		case 'q':
1263			i++;				
1264			i += svg_parse_float(&(d[i]), &(ct_orig.x), 0);
1265			i += svg_parse_float(&(d[i]), &(ct_orig.y), 0);				
1266			if (c == 'q') {
1267				ct_orig.x += rel_ref_pt.x;
1268				ct_orig.y += rel_ref_pt.y;
1269			}
1270			i += svg_parse_float(&(d[i]), &(end.x), 0);
1271			i += svg_parse_float(&(d[i]), &(end.y), 0);				
1272			if (c == 'q') {
1273				end.x += rel_ref_pt.x;
1274				end.y += rel_ref_pt.y;
1275			}
1276#ifndef PARSE_PATH_ONLY
1277			gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);			
1278#endif
1279			rel_ref_pt = end;
1280			orig = end;
1281			prev_c = c;
1282			break;
1283		case 'T':
1284		case 't':
1285			i++;				
1286			ct_orig.x = 2*orig.x - ct_orig.x;
1287			ct_orig.y = 2*orig.y - ct_orig.y;
1288			i += svg_parse_float(&(d[i]), &(end.x), 0);
1289			i += svg_parse_float(&(d[i]), &(end.y), 0);				
1290			if (c == 't') {
1291				end.x += rel_ref_pt.x;
1292				end.y += rel_ref_pt.y;
1293			}
1294#ifndef PARSE_PATH_ONLY
1295			gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);
1296#endif
1297			rel_ref_pt = end;
1298			orig = end;
1299			prev_c = c;
1300			break;
1301		case 'A':
1302		case 'a':
1303			i++;				
1304
1305			i += svg_parse_float(&(d[i]), &(orig.x), 0);	
1306			i += svg_parse_float(&(d[i]), &(orig.y), 0);				
1307			if (c == 'a') {
1308				orig.x += rel_ref_pt.x;
1309				orig.y += rel_ref_pt.y;
1310			}
1311
1312			i += svg_parse_float(&(d[i]), &(x_axis_rotation), 0);	
1313			i += svg_parse_float(&(d[i]), &(large_arc_flag), 0);				
1314			i += svg_parse_float(&(d[i]), &(sweep_flag), 0);	
1315			
1316			i += svg_parse_float(&(d[i]), &(end.x), 0);	
1317			i += svg_parse_float(&(d[i]), &(end.y), 0);				
1318			if (c == 'a') {
1319				end.x += rel_ref_pt.x;
1320				end.y += rel_ref_pt.y;
1321			}
1322			//gf_path_add_svg_arc_to(path, orig.x, orig.y, x_axis_rotation, large_arc_flag, sweep_flag, end.x, end.y);
1323			rel_ref_pt = end;
1324			ct_orig = end;
1325			prev_c = c;
1326			break;
1327		case 'Z':
1328		case 'z':
1329			i++;				
1330#ifndef PARSE_PATH_ONLY
1331			gf_path_close(path);
1332#endif
1333			prev_c = c;
1334			rel_ref_pt = prev_m_pt;
1335			break;
1336		default:
1337			i--;
1338			switch (prev_c) {
1339			case 'M':
1340				c = 'L';
1341				break;
1342			case 'm':
1343				c = 'l';
1344				break;
1345			default:
1346				c = prev_c;
1347			}
1348			goto next_command;
1349		}
1350	}
1351}
1352#else
1353/* TODO: Change the function to handle elliptical arcs, requires changing data structure */
1354static void svg_parse_path(SVG_PathData *d_attribute, char *attribute_content) 
1355{
1356	GF_List *d_commands = d_attribute->commands;
1357	GF_List *d_points = d_attribute->points;
1358	char *d = attribute_content;
1359
1360	if (strlen(d)) {
1361		SVG_Point *pt, cur_pt, prev_m_pt;
1362		u8 *command;
1363		u32 i, k;
1364		char c, prev_c = 'M';
1365#ifdef REMOVE_ALLOC
1366		GF_SAFEALLOC(pt, SVG_Point)
1367#endif
1368		i = 0;
1369		cur_pt.x = cur_pt.y = 0;
1370		prev_m_pt.x = prev_m_pt.y = 0;
1371		while(1) {
1372			while ( (d[i]==' ') || (d[i] =='\t') ) i++;			
1373			c = d[i];
1374			if (! c) break;
1375next_command:
1376			switch (c) {
1377			case 'm':
1378			case 'M':
1379				i++;
1380#ifndef REMOVE_ALLOC
1381				GF_SAFEALLOC(command, u8)
1382				gf_list_add(d_commands, command);
1383				*command = SVG_PATHCOMMAND_M;
1384
1385				GF_SAFEALLOC(pt, SVG_Point)
1386				gf_list_add(d_points, pt);
1387#endif
1388				i += svg_parse_float(&(d[i]), &(pt->x), 0);
1389				i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1390				if (c == 'm') {
1391					pt->x += cur_pt.x;
1392					pt->y += cur_pt.y;
1393				}
1394				cur_pt.x = pt->x;
1395				cur_pt.y = pt->y;
1396				prev_m_pt = cur_pt;
1397				prev_c = c;
1398				break;
1399			case 'L':
1400			case 'l':
1401				i++;
1402#ifndef REMOVE_ALLOC
1403				GF_SAFEALLOC(command, u8)
1404				gf_list_add(d_commands, command);
1405				*command = SVG_PATHCOMMAND_L;
1406				
1407				GF_SAFEALLOC(pt, SVG_Point)
1408				gf_list_add(d_points, pt);
1409#endif
1410				i += svg_parse_float(&(d[i]), &(pt->x), 0);
1411				i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1412				if (c == 'l') {
1413					pt->x += cur_pt.x;
1414					pt->y += cur_pt.y;
1415				}
1416				cur_pt.x = pt->x;
1417				cur_pt.y = pt->y;
1418				prev_c = c;
1419				break;
1420			case 'H':
1421			case 'h':
1422				i++;				
1423#ifndef REMOVE_ALLOC
1424				GF_SAFEALLOC(command, u8)
1425				gf_list_add(d_commands, command);
1426				*command = SVG_PATHCOMMAND_L;
1427
1428				GF_SAFEALLOC(pt, SVG_Point)
1429				gf_list_add(d_points, pt);
1430#endif
1431				i += svg_parse_float(&(d[i]), &(pt->x), 0);
1432				if (c == 'h') {
1433					pt->x += cur_pt.x;
1434				}
1435				pt->y = cur_pt.y;
1436				cur_pt.x = pt->x;
1437				prev_c = c;
1438				break;
1439			case 'V':
1440			case 'v':
1441				i++;				
1442#ifndef REMOVE_ALLOC
1443				GF_SAFEALLOC(command, u8)
1444				gf_list_add(d_commands, command);
1445				*command = SVG_PATHCOMMAND_L;
1446
1447				GF_SAFEALLOC(pt, SVG_Point)
1448				gf_list_add(d_points, pt);
1449#endif
1450				i += svg_parse_float(&(d[i]), &(pt->y), 0);
1451				if (c == 'v') {
1452					pt->y += cur_pt.y;
1453				}
1454				pt->x = cur_pt.x;
1455				cur_pt.y = pt->y;
1456				prev_c = c;
1457				break;
1458			case 'C':
1459			case 'c':
1460				i++;				
1461#ifndef REMOVE_ALLOC
1462				GF_SAFEALLOC(command, u8)
1463				gf_list_add(d_commands, command);
1464				*command = SVG_PATHCOMMAND_C;
1465#endif
1466				
1467				for (k=0; k<3; k++) {
1468#ifndef REMOVE_ALLOC
1469					GF_SAFEALLOC(pt, SVG_Point)
1470					gf_list_add(d_points, pt);
1471#endif
1472					i += svg_parse_float(&(d[i]), &(pt->x), 0);
1473					i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1474					if (c == 'c') {
1475						pt->x += cur_pt.x;
1476						pt->y += cur_pt.y;
1477					}
1478				}				
1479				cur_pt.x = pt->x;
1480				cur_pt.y = pt->y;
1481				prev_c = c;
1482				break;
1483			case 'S':
1484			case 's':
1485				i++;				
1486#ifndef REMOVE_ALLOC
1487				GF_SAFEALLOC(command, u8)
1488				gf_list_add(d_commands, command);
1489				*command = SVG_PATHCOMMAND_S;
1490#endif
1491				
1492				for (k=0; k<2; k++) {
1493#ifndef REMOVE_ALLOC
1494					GF_SAFEALLOC(pt, SVG_Point)
1495					gf_list_add(d_points, pt);
1496#endif
1497					i += svg_parse_float(&(d[i]), &(pt->x), 0);
1498					i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1499					if (c == 's') {
1500						pt->x += cur_pt.x;
1501						pt->y += cur_pt.y;
1502					}
1503				}				
1504				cur_pt.x = pt->x;
1505				cur_pt.y = pt->y;
1506				prev_c = c;
1507				break;
1508			case 'Q':
1509			case 'q':
1510				i++;				
1511#ifndef REMOVE_ALLOC
1512				GF_SAFEALLOC(command, u8)
1513				gf_list_add(d_commands, command);
1514				*command = SVG_PATHCOMMAND_Q;
1515#endif
1516				
1517				for (k=0; k<2; k++) {
1518#ifndef REMOVE_ALLOC
1519					GF_SAFEALLOC(pt, SVG_Point)
1520					gf_list_add(d_points, pt);
1521#endif
1522					i += svg_parse_float(&(d[i]), &(pt->x), 0);
1523					i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1524					if (c == 'q') {
1525						pt->x += cur_pt.x;
1526						pt->y += cur_pt.y;
1527					}
1528				}				
1529				cur_pt.x = pt->x;
1530				cur_pt.y = pt->y;
1531				prev_c = c;
1532				break;
1533			case 'T':
1534			case 't':
1535				i++;				
1536#ifndef REMOVE_ALLOC
1537				GF_SAFEALLOC(command, u8)
1538				gf_list_add(d_commands, command);
1539				*command = SVG_PATHCOMMAND_T;
1540				
1541				GF_SAFEALLOC(pt, SVG_Point)
1542				gf_list_add(d_points, pt);
1543#endif
1544				i += svg_parse_float(&(d[i]), &(pt->x), 0);
1545				i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1546				if (c == 't') {
1547					pt->x += cur_pt.x;
1548					pt->y += cur_pt.y;
1549				}
1550				cur_pt.x = pt->x;
1551				cur_pt.y = pt->y;
1552				prev_c = c;
1553				break;
1554			case 'A':
1555			case 'a':
1556				{
1557					Fixed tmp;
1558					i++;				
1559#ifndef REMOVE_ALLOC
1560					GF_SAFEALLOC(command, u8)
1561					gf_list_add(d_commands, command);
1562					*command = SVG_PATHCOMMAND_A;
1563	
1564					GF_SAFEALLOC(pt, SVG_Point)
1565					gf_list_add(d_points, pt);
1566#endif
1567					i += svg_parse_float(&(d[i]), &(pt->x), 0);	
1568					i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1569
1570					i += svg_parse_float(&(d[i]), &(tmp), 0);	
1571					i += svg_parse_float(&(d[i]), &(tmp), 0);				
1572					i += svg_parse_float(&(d[i]), &(tmp), 0);	
1573					
1574#ifndef REMOVE_ALLOC
1575					GF_SAFEALLOC(pt, SVG_Point)
1576					gf_list_add(d_points, pt);
1577#endif
1578					i += svg_parse_float(&(d[i]), &(pt->x), 0);	
1579					i += svg_parse_float(&(d[i]), &(pt->y), 0);				
1580					if (c == 'a') {
1581						pt->x += cur_pt.x;
1582						pt->y += cur_pt.y;
1583					}
1584					cur_pt.x = pt->x;
1585					cur_pt.y = pt->y;
1586				}
1587				prev_c = c;
1588				break;
1589			case 'Z':
1590			case 'z':
1591				i++;				
1592#ifndef REMOVE_ALLOC
1593				GF_SAFEALLOC(command, u8)
1594				gf_list_add(d_commands, command);
1595				*command = SVG_PATHCOMMAND_Z;
1596#endif
1597				prev_c = c;
1598				cur_pt = prev_m_pt;
1599				break;
1600			default:
1601				i--;
1602				switch (prev_c) {
1603				case 'M':
1604					c = 'L';
1605					break;
1606				case 'm':
1607					c = 'l';
1608					break;
1609				default:
1610					c = prev_c;
1611				}
1612				goto next_command;
1613			}
1614		}
1615	}
1616}
1617#endif
1618
1619static void svg_parse_iri(GF_Node *elt, XMLRI *iri, char *attribute_content)
1620{
1621	/* TODO: Handle xpointer(id()) syntax */
1622	if (attribute_content[0] == '#') {
1623		iri->string = strdup(attribute_content);
1624		iri->target = gf_sg_find_node_by_name(elt->sgprivate->scenegraph, attribute_content + 1);
1625		if (!iri->target) {
1626			iri->type = XMLRI_STRING;
1627		} else {
1628			iri->type = XMLRI_ELEMENTID;
1629			gf_svg_register_iri(elt->sgprivate->scenegraph, iri);
1630		}
1631	} else {
1632		iri->type = XMLRI_STRING;
1633		iri->string = strdup(attribute_content);
1634	}
1635}
1636
1637static void svg_parse_idref(GF_Node *elt, XML_IDREF *iri, char *attribute_content)
1638{
1639	iri->type = XMLRI_ELEMENTID;
1640	iri->target = gf_sg_find_node_by_name(elt->sgprivate->scenegraph, attribute_content);
1641	if (!iri->target) {
1642		iri->string = strdup(attribute_content);
1643	} else {
1644		gf_svg_register_iri(elt->sgprivate->scenegraph, iri);
1645	}
1646}
1647
1648/* Parses a paint attribute: none, inherit or color */
1649static void svg_parse_paint(GF_Node *n, SVG_Paint *paint, char *attribute_content)
1650{
1651	if (!strcmp(attribute_content, "none")) {
1652		paint->type = SVG_PAINT_NONE;
1653	} else if (!strcmp(attribute_content, "inherit")) {
1654		paint->type = SVG_PAINT_INHERIT;
1655	} else if (!strncmp(attribute_content, "url(", 4) ) {
1656		u32 len = strlen(attribute_content);
1657		paint->type = SVG_PAINT_URI;
1658		attribute_content[len-1] = 0;
1659		svg_parse_iri(n, &paint->iri, attribute_content+4);
1660		attribute_content[len-1] = ')';
1661	} else {
1662		paint->type = SVG_PAINT_COLOR;
1663		svg_parse_color(&paint->color, attribute_content);
1664	}
1665}
1666
1667
1668static u32 svg_parse_number(SVG_Number *number, char *value_string, Bool clamp0to1)
1669{
1670	char *unit = NULL;
1671	u32 len = 0;
1672	if (!strcmp(value_string, "inherit")) {
1673		number->type = SVG_NUMBER_INHERIT;
1674		return 7;
1675	} else if (!strcmp(value_string, "auto")) {
1676		number->type = SVG_NUMBER_AUTO;
1677		return 4;
1678	} else if (!strcmp(value_string, "auto-reverse")) {
1679		number->type = SVG_NUMBER_AUTO_REVERSE;
1680		return 12;
1681	} else if ((unit = strstr(value_string, "%")) ) {
1682		number->type = SVG_NUMBER_PERCENTAGE;
1683	} else if ((unit = strstr(value_string, "em"))) {
1684		number->type = SVG_NUMBER_EMS;
1685	} else if ((unit = strstr(value_string, "ex"))) {
1686		number->type = SVG_NUMBER_EXS;
1687	} else if ((unit = strstr(value_string, "px"))) {
1688		number->type = SVG_NUMBER_PX;
1689	} else if ((unit = strstr(value_string, "cm"))) {
1690		number->type = SVG_NUMBER_CM;
1691	} else if ((unit = strstr(value_string, "mm"))) {
1692		number->type = SVG_NUMBER_MM;
1693	} else if ((unit = strstr(value_string, "in"))) {
1694		number->type = SVG_NUMBER_IN;
1695	} else if ((unit = strstr(value_string, "pt"))) {
1696		number->type = SVG_NUMBER_PT;
1697	} else if ((unit = strstr(value_string, "pc"))) {
1698		number->type = SVG_NUMBER_PC;
1699	} else {
1700		number->type = SVG_NUMBER_VALUE;
1701	}
1702	if (unit) len = strlen(unit); 
1703	len+=svg_parse_float(value_string, &(number->value), 0);
1704
1705	if (clamp0to1) number->value = MAX(0, MIN(1, number->value));
1706	return len;
1707}
1708
1709static void svg_parse_visibility(SVG_Visibility *value, char *value_string)
1710{
1711	if (!strcmp(value_string, "inherit")) {
1712		*value = SVG_VISIBILITY_INHERIT;
1713	} else if (!strcmp(value_string, "visible")) {
1714		*value = SVG_VISIBILITY_VISIBLE;
1715	} else if (!strcmp(value_string, "hidden")) {
1716		*value = SVG_VISIBILITY_HIDDEN;
1717	} else if (!strcmp(value_string, "collapse")) {
1718		*value = SVG_VISIBILITY_COLLAPSE;
1719	} 
1720}
1721
1722static void svg_parse_display(SVG_Display *value, char *value_string)
1723{
1724	if (!strcmp(value_string, "inherit")) {
1725		*value = SVG_DISPLAY_INHERIT;
1726	} else if (!strcmp(value_string, "none")) {
1727		*value = SVG_DISPLAY_NONE;
1728	} else if (!strcmp(value_string, "inline")) {
1729		*value = SVG_DISPLAY_INLINE;
1730	} else if (!strcmp(value_string, "block")) {
1731		*value = SVG_DISPLAY_BLOCK;
1732	} else if (!strcmp(value_string, "list-item")) {
1733		*value = SVG_DISPLAY_LIST_ITEM;
1734	} else if (!strcmp(value_string, "run-in")) {
1735		*value = SVG_DISPLAY_RUN_IN;
1736	} else if (!strcmp(value_string, "compact")) {
1737		*value = SVG_DISPLAY_COMPACT;
1738	} else if (!strcmp(value_string, "marker")) {
1739		*value = SVG_DISPLAY_MARKER;
1740	} else if (!strcmp(value_string, "table")) {
1741		*value = SVG_DISPLAY_TABLE;
1742	} else if (!strcmp(value_string, "inline-table")) {
1743		*value = SVG_DISPLAY_INLINE_TABLE;
1744	} else if (!strcmp(value_string, "table-row-group")) {
1745		*value = SVG_DISPLAY_TABLE_ROW_GROUP;
1746	} else if (!strcmp(value_string, "table-header-group")) {
1747		*value = SVG_DISPLAY_TABLE_HEADER_GROUP;
1748	} else if (!strcmp(value_string, "table-footer-group")) {
1749		*value = SVG_DISPLAY_TABLE_FOOTER_GROUP;
1750	} else if (!strcmp(value_string, "table-row")) {
1751		*value = SVG_DISPLAY_TABLE_ROW;
1752	} else if (!strcmp(value_string, "table-column-group")) {
1753		*value = SVG_DISPLAY_TABLE_COLUMN_GROUP;
1754	} else if (!strcmp(value_string, "table-column")) {
1755		*value = SVG_DISPLAY_TABLE_COLUMN;
1756	} else if (!strcmp(value_string, "table-cell")) {
1757		*value = SVG_DISPLAY_TABLE_CELL;
1758	} else if (!strcmp(value_string, "table-caption")) {
1759		*value = SVG_DISPLAY_TABLE_CAPTION;
1760	} 
1761}
1762
1763static void svg_parse_displayalign(SVG_DisplayAlign *value, char *value_string)
1764{ 
1765	if (!strcmp(value_string, "inherit")) {
1766		*value = SVG_DISPLAYALIGN_INHERIT;
1767	} else if (!strcmp(value_string, "auto")) {
1768		*value = SVG_DISPLAYALIGN_AUTO;
1769	} else if (!strcmp(value_string, "before")) {
1770		*value = SVG_DISPLAYALIGN_BEFORE;
1771	} else if (!strcmp(value_string, "center")) {
1772		*value = SVG_DISPLAYALIGN_CENTER;
1773	} else if (!strcmp(value_string, "after")) {
1774		*value = SVG_DISPLAYALIGN_AFTER;
1775	}
1776}
1777
1778static void svg_parse_textalign(SVG_TextAlign *value, char *value_string)
1779{ 
1780	if (!strcmp(value_string, "inherit")) {
1781		*value = SVG_TEXTALIGN_INHERIT;
1782	} else if (!strcmp(value_string, "start")) {
1783		*value = SVG_TEXTALIGN_START;
1784	} else if (!strcmp(value_string, "center")) {
1785		*value = SVG_TEXTALIGN_CENTER;
1786	} else if (!strcmp(value_string, "end")) {
1787		*value = SVG_TEXTALIGN_END;
1788	} 
1789}
1790
1791static void svg_parse_pointerevents(SVG_PointerEvents *value, char *value_string)
1792{
1793	if (!strcmp(value_string, "inherit")) {
1794		*value = SVG_POINTEREVENTS_INHERIT;
1795	} else if (!strcmp(value_string, "visiblePainted")) {
1796		*value = SVG_POINTEREVENTS_VISIBLEPAINTED;
1797	} else if (!strcmp(value_string, "visibleFill")) {
1798		*value = SVG_POINTEREVENTS_VISIBLEFILL;
1799	} else if (!strcmp(value_string, "visibleStroke")) {
1800		*value = SVG_POINTEREVENTS_VISIBLESTROKE;
1801	} else if (!strcmp(value_string, "visible")) {
1802		*value = SVG_POINTEREVENTS_VISIBLE;
1803	} else if (!strcmp(value_string, "painted")) {
1804		*value = SVG_POINTEREVENTS_PAINTED;
1805	} else if (!strcmp(value_string, "fill")) {
1806		*value = SVG_POINTEREVENTS_FILL;
1807	} else if (!strcmp(value_string, "stroke")) {
1808		*value = SVG_POINTEREVENTS_STROKE;
1809	} else if (!strcmp(value_string, "all")) {
1810		*value = SVG_POINTEREVENTS_ALL;
1811	} else if (!strcmp(value_string, "boundingBox")) {
1812		*value = SVG_POINTEREVENTS_BOUNDINGBOX;
1813	} else if (!strcmp(value_string, "none")) {
1814		*value = SVG_POINTEREVENTS_NONE;
1815	}
1816}
1817
1818static void svg_parse_renderinghint(SVG_RenderingHint *value, char *value_string)
1819{
1820	if (!strcmp(value_string, "inherit")) {
1821		*value = SVG_RENDERINGHINT_INHERIT;
1822	} else if (!strcmp(value_string, "auto")) {
1823		*value = SVG_RENDERINGHINT_AUTO;
1824	} else if (!strcmp(value_string, "optimizeQuality")) {
1825		*value = SVG_RENDERINGHINT_OPTIMIZEQUALITY;
1826	} else if (!strcmp(value_string, "optimizeSpeed")) {
1827		*value = SVG_RENDERINGHINT_OPTIMIZESPEED;
1828	} else if (!strcmp(value_string, "optimizeLegibility")) {
1829		*value = SVG_RENDERINGHINT_OPTIMIZELEGIBILITY;
1830	} else if (!strcmp(value_string, "crispEdges")) {
1831		*value = SVG_RENDERINGHINT_CRISPEDGES;
1832	} else if (!strcmp(value_string, "geometricPrecision")) {
1833		*value = SVG_RENDERINGHINT_GEOMETRICPRECISION;
1834	}
1835}
1836
1837static void svg_parse_vectoreffect(SVG_VectorEffect *value, char *value_string)
1838{
1839	if (!strcmp(value_string, "inherit")) {
1840		*value = SVG_VECTOREFFECT_INHERIT;
1841	} else if (!strcmp(value_string, "none")) {
1842		*value = SVG_VECTOREFFECT_NONE;
1843	} else if (!strcmp(value_string, "non-scaling-stroke")) {
1844		*value = SVG_VECTOREFFECT_NONSCALINGSTROKE;
1845	}
1846}
1847
1848static void svg_parse_playbackorder(SVG_VectorEffect *value, char *value_string)
1849{
1850	if (!strcmp(value_string, "forwardOnly")) {
1851		*value = SVG_PLAYBACKORDER_FORWARDONLY;
1852	} else if (!strcmp(value_string, "all")) {
1853		*value = SVG_PLAYBACKORDER_ALL;
1854	}
1855}
1856
1857static void svg_parse_timelinebegin(SVG_TimelineBegin *value, char *value_string)
1858{
1859	if (!strcmp(value_string, "onStart")) {
1860		*value = SVG_TIMELINEBEGIN_ONSTART;
1861	} else if (!strcmp(value_string, "onLoad")) {
1862		*value = SVG_TIMELINEBEGIN_ONLOAD;
1863	}
1864}
1865
1866static void svg_parse_xmlspace(XML_Space *value, char *value_string)
1867{
1868	if (!strcmp(value_string, "default")) {
1869		*value = XML_SPACE_DEFAULT;
1870	} else if (!strcmp(value_string, "preserve")) {
1871		*value = XML_SPACE_PRESERVE;
1872	}
1873}
1874
1875static void svg_parse_xmlev_propagate(XMLEV_Propagate *value, char *value_string)
1876{
1877	if (!strcmp(value_string, "continue")) {
1878		*value = XMLEVENT_PROPAGATE_CONTINUE;
1879	} else if (!strcmp(value_string, "stop")) {
1880		*value = XMLEVENT_PROPAGATE_STOP;
1881	}
1882}
1883
1884static void svg_parse_xmlev_defaultAction(XMLEV_DefaultAction *value, char *value_string)
1885{
1886	if (!strcmp(value_string, "cancel")) {
1887		*value = XMLEVENT_DEFAULTACTION_CANCEL;
1888	} else if (!strcmp(value_string, "perform")) {
1889		*value = XMLEVENT_DEFAULTACTION_PERFORM;
1890	}
1891}
1892
1893static void svg_parse_xmlev_phase(XMLEV_Phase *value, char *value_string)
1894{
1895	if (!strcmp(value_string, "default")) {
1896		*value = XMLEVENT_PHASE_DEFAULT;
1897	} else if (!strcmp(value_string, "capture")) {
1898		*value = XMLEVENT_PHASE_CAPTURE;
1899	}
1900}
1901
1902static void svg_parse_overflow(SVG_Overflow *value, char *value_string)
1903{
1904	if (!strcmp(value_string, "inherit")) {
1905		*value = SVG_OVERFLOW_INHERIT;
1906	} else if (!strcmp(value_string, "visible")) {
1907		*value = SVG_OVERFLOW_VISIBLE;
1908	} else if (!strcmp(value_string, "hidden")) {
1909		*value = SVG_OVERFLOW_HIDDEN;
1910	} else if (!strcmp(value_string, "scroll")) {
1911		*value = SVG_OVERFLOW_SCROLL;
1912	} else if (!strcmp(value_string, "auto")) {
1913		*value = SVG_OVERFLOW_AUTO;
1914	}
1915}
1916
1917static void svg_parse_textanchor(SVG_TextAnchor *value, char *value_string)
1918{
1919	if (!strcmp(value_string, "inherit")) {
1920		*value = SVG_TEXTANCHOR_INHERIT;
1921	} else if (!strcmp(value_string, "start")) {
1922		*value = SVG_TEXTANCHOR_START;
1923	} else if (!strcmp(value_string, "middle")) {
1924		*value = SVG_TEXTANCHOR_MIDDLE;
1925	} else if (!strcmp(value_string, "end")) {
1926		*value = SVG_TEXTANCHOR_END;
1927	}
1928}
1929
1930static void svg_parse_clipfillrule(SVG_FillRule *value, char *value_string)
1931{
1932	if (!strcmp(value_string, "inherit")) {
1933		*value = SVG_FILLRULE_INHERIT;
1934	} else if (!strcmp(value_string, "nonzero")) {
1935		*value = SVG_FILLRULE_NONZERO;
1936	} else if (!strcmp(value_string, "evenodd")) {
1937		*value = SVG_FILLRULE_EVENODD;
1938	} 
1939}
1940
1941static void svg_parse_strokelinejoin(SVG_StrokeLineJoin *value, char *value_string)
1942{
1943	if (!strcmp(value_string, "inherit")) {
1944		*value = SVG_STROKELINEJOIN_INHERIT;
1945	} else if (!strcmp(value_string, "miter")) {
1946		*value = SVG_STROKELINEJOIN_MITER;
1947	} else if (!strcmp(value_string, "round")) {
1948		*value = SVG_STROKELINEJOIN_ROUND;
1949	} else if (!strcmp(value_string, "bevel")) {
1950		*value = SVG_STROKELINEJOIN_BEVEL;
1951	} 
1952}
1953
1954static void svg_parse_strokelinecap(SVG_StrokeLineCap *value, char *value_string)
1955{
1956	if (!strcmp(value_string, "inherit")) {
1957		*value = SVG_STROKELINECAP_INHERIT;
1958	} else if (!strcmp(value_string, "butt")) {
1959		*value = SVG_STROKELINECAP_BUTT;
1960	} else if (!strcmp(value_string, "round")) {
1961		*value = SVG_STROKELINECAP_ROUND;
1962	} else if (!strcmp(value_string, "square")) {
1963		*value = SVG_STROKELINECAP_SQUARE;
1964	} 
1965}
1966
1967static void svg_parse_fontfamily(SVG_FontFamily *value, char *value_string)
1968{
1969	if (!strcmp(value_string, "inherit")) {
1970		value->type = SVG_FONTFAMILY_INHERIT;
1971	} else {
1972		value->type = SVG_FONTFAMILY_VALUE;
1973		value->value = strdup(value_string);
1974	}
1975}
1976
1977static void svg_parse_fontstyle(SVG_FontStyle *value, char *value_string)
1978{
1979	if (!strcmp(value_string, "inherit")) {
1980		*value = SVG_FONTSTYLE_INHERIT;
1981	} else if (!strcmp(value_string, "normal")) {
1982		*value = SVG_FONTSTYLE_NORMAL;
1983	} else if (!strcmp(value_string, "italic")) {
1984		*value = SVG_FONTSTYLE_ITALIC;
1985	} else if (!strcmp(value_string, "oblique")) {
1986		*value = SVG_FONTSTYLE_OBLIQUE;
1987	} 
1988}
1989
1990static void svg_parse_fontweight(SVG_FontWeight *value, char *value_string)
1991{
1992	if (!strcmp(value_string, "inherit")) {
1993		*value = SVG_FONTWEIGHT_INHERIT;
1994	} else if (!strcmp(value_string, "normal")) {
1995		*value = SVG_FONTWEIGHT_NORMAL;
1996	} else if (!strcmp(value_string, "bold")) {
1997		*value = SVG_FONTWEIGHT_BOLD;
1998	} else if (!strcmp(value_string, "bolder")) {
1999		*value = SVG_FONTWEIGHT_BOLDER;
2000	} else if (!strcmp(value_string, "lighter")) {
2001		*value = SVG_FONTWEIGHT_LIGHTER;
2002	} else if (!strcmp(value_string, "100")) {
2003		*value = SVG_FONTWEIGHT_100;
2004	} else if (!strcmp(value_string, "200")) {
2005		*value = SVG_FONTWEIGHT_200;
2006	} else if (!strcmp(value_string, "300")) {
2007		*value = SVG_FONTWEIGHT_300;
2008	} else if (!strcmp(value_string, "400")) {
2009		*value = SVG_FONTWEIGHT_400;
2010	} else if (!strcmp(value_string, "500")) {
2011		*value = SVG_FONTWEIGHT_500;
2012	} else if (!strcmp(value_string, "600")) {
2013		*value = SVG_FONTWEIGHT_600;
2014	} else if (!strcmp(value_string, "700")) {
2015		*value = SVG_FONTWEIGHT_700;
2016	} else if (!strcmp(value_string, "800")) {
2017		*value = SVG_FONTWEIGHT_800;
2018	} else if (!strcmp(value_string, "900")) {
2019		*value = SVG_FONTWEIGHT_900;
2020	} 
2021}
2022
2023static void svg_parse_fontvariant(SVG_FontVariant *value, char *value_string)
2024{
2025	if (!strcmp(value_string, "inherit")) {
2026		*value = SVG_FONTVARIANT_INHERIT;
2027	} else if (!strcmp(value_string, "normal")) {
2028		*value = SVG_FONTVARIANT_NORMAL;
2029	} else if (!strcmp(value_string, "small-caps")) {
2030		*value = SVG_FONTVARIANT_SMALLCAPS;
2031	} 
2032}
2033
2034static void svg_parse_boolean(SVG_Boolean *value, char *value_string)
2035{
2036	if (!strcmp(value_string, "1") || !strcmp(value_string, "true"))
2037		*value = 1;
2038	else
2039		*value = 0;
2040}
2041
2042
2043static void smil_parse_time_list(GF_Node *e, GF_List *values, char *begin_or_end_list)
2044{
2045	SMIL_Time *value;
2046	char value_string[500];
2047	char *str = begin_or_end_list, *tmp;
2048	u32 len;
2049
2050	/* get rid of leading spaces */
2051	while (*str == ' ') str++;
2052
2053	while ((tmp = strchr(str, ';'))) {
2054		len = tmp-str;
2055		memcpy(value_string, str, len);
2056		while (value_string[len - 1] == ' ' && len > 0) len--;
2057		value_string[len] = 0;
2058
2059		GF_SAFEALLOC(value, SMIL_Time)
2060		smil_parse_time(e, value, value_string);
2061 		gf_list_add(values, value);
2062
2063		str = tmp + 1;
2064		while (*str == ' ') str++;
2065	}
2066
2067	len = strlen(str);
2068	memcpy(value_string, str, len);
2069	while (value_string[len - 1] == ' ' && len > 0) len--;
2070	value_string[len] = 0;
2071
2072	GF_SAFEALLOC(value, SMIL_Time)
2073	smil_parse_time(e, value, value_string);
2074 	gf_list_add(values, value);
2075
2076	/* sorting timing values */
2077	if (gf_list_count(values) > 1) {
2078		SMIL_Time *v, *sv;
2079		GF_List *sorted = gf_list_new();
2080		u32 i, count;
2081		u8 added = 0;
2082		do {
2083			v = (SMIL_Time*)gf_list_get(values, 0);
2084			gf_list_rem(values, 0);
2085			added = 0;
2086			count = gf_list_count(sorted);
2087			for (i=0; i<count; i++) {
2088				sv = (SMIL_Time*)gf_list_get(sorted, i);
2089				if (v->type >= GF_SMIL_TIME_EVENT) {
2090					/* unresolved or indefinite so add at the end of the sorted list */
2091					gf_list_add(sorted, v);
2092					added = 1;
2093					break;
2094				} else {
2095					if (sv->type >= GF_SMIL_TIME_EVENT) {
2096						gf_list_insert(sorted, v, i);
2097						added = 1;
2098						break;
2099					} else {
2100						if (v->clock <= sv->clock) {
2101							gf_list_insert(sorted, v, i);
2102							added = 1;
2103							break;
2104						}
2105					}
2106				}
2107			}
2108			if (!added) gf_list_add(sorted, v);
2109		} while (gf_list_count(values) > 0);
2110
2111		count = gf_list_count(sorted);
2112		for (i = 0; i < count; i++) {
2113			gf_list_add(values, gf_list_get(sorted, i));
2114		}
2115		gf_list_del(sorted);
2116	}
2117}
2118
2119static void smil_parse_attributeType(SMIL_AttributeType *value, char *value_string)
2120{
2121	if (!strcmp(value_string, "auto")) {
2122		*value = SMIL_ATTRIBUTETYPE_AUTO;
2123	} else if (!strcmp(value_string, "XML")) {
2124		*value = SMIL_ATTRIBUTETYPE_XML;
2125	} else if (!strcmp(value_string, "CSS")) {
2126		*value = SMIL_ATTRIBUTETYPE_CSS;
2127	}
2128}
2129
2130static void smil_parse_min_max_dur_repeatdur(SMIL_Duration *value, char *value_string)
2131{
2132	if (!strcmp(value_string, "indefinite")) {
2133		value->type = SMIL_DURATION_INDEFINITE;
2134	} else if (!strcmp(value_string, "media")) {
2135		value->type = SMIL_DURATION_MEDIA;
2136	} else {
2137		Double ftime;
2138		svg_parse_clock_value(value_string, &ftime);
2139		value->clock_value = ftime;
2140		value->type = SMIL_DURATION_DEFINED;
2141	}
2142}
2143
2144static void smil_parse_repeatcount(SMIL_RepeatCount *value, char *value_string)
2145{
2146	if (!strcmp(value_string, "indefinite")) {
2147		value->type = SMIL_REPEATCOUNT_INDEFINITE;
2148	} else {
2149		Float _val;
2150		sscanf(value_string, "%f", &_val);
2151		value->type = SMIL_REPEATCOUNT_DEFINED;
2152		value->count = FLT2FIX(_val);
2153	}
2154}
2155
2156static void smil_parse_fill(SMIL_Fill *value, char *value_string)
2157{
2158	if (!strcmp(value_string, "freeze")) {
2159		*value = SMIL_FILL_FREEZE;
2160	} else if (!strcmp(value_string, "remove")) {
2161		*value = SMIL_FILL_REMOVE;
2162	}
2163}
2164
2165static void smil_parse_restart(SMIL_Restart *value, char *value_string)
2166{
2167	if (!strcmp(value_string, "always")) {
2168		*value = SMIL_RESTART_ALWAYS;
2169	} else if (!strcmp(value_string, "whenNotActive")) {
2170		*value = SMIL_RESTART_WHENNOTACTIVE;
2171	} else if (!strcmp(value_string, "never")) {
2172		*value = SMIL_RESTART_NEVER;
2173	}
2174}
2175
2176static void smil_parse_calcmode(SMIL_CalcMode *value, char *value_string)
2177{
2178	if (!strcmp(value_string, "discrete")) {
2179		*value = SMIL_CALCMODE_DISCRETE;
2180	} else if (!strcmp(value_string, "linear")) {
2181		*value = SMIL_CALCMODE_LINEAR;
2182	} else if (!strcmp(value_string, "paced")) {
2183		*value = SMIL_CALCMODE_PACED;
2184	} else if (!strcmp(value_string, "spline")) {
2185		*value = SMIL_CALCMODE_SPLINE;
2186	} 
2187}
2188
2189static void smil_parse_additive(SMIL_Additive *value, char *value_string)
2190{
2191	if (!strcmp(value_string, "replace")) {
2192		*value = SMIL_ADDITIVE_REPLACE;
2193	} else if (!strcmp(value_string, "sum")) {
2194		*value = SMIL_ADDITIVE_SUM;
2195	} 
2196}
2197
2198static void smil_parse_accumulate(SMIL_Accumulate *value, char *value_string)
2199{
2200	if (!strcmp(value_string, "none")) {
2201		*value = SMIL_ACCUMULATE_NONE;
2202	} else if (!strcmp(value_string, "sum")) {
2203		*value = SMIL_ACCUMULATE_SUM;
2204	} 
2205}
2206
2207static void smil_parse_syncBehaviorOrDefault(SMIL_SyncBehavior *value, char *value_string)
2208{
2209	if (!strcmp(value_string, "inherit")) {
2210		*value = SMIL_SYNCBEHAVIOR_INHERIT;
2211	} else if (!strcmp(value_string, "default")) {
2212		*value = SMIL_SYNCBEHAVIOR_DEFAULT;
2213	} else if (!strcmp(value_string, "locked")) {
2214		*value = SMIL_SYNCBEHAVIOR_LOCKED;
2215	} else if (!strcmp(value_string, "canSlip")) {
2216		*value = SMIL_SYNCBEHAVIOR_CANSLIP;
2217	} else if (!strcmp(value_string, "independent")) {
2218		*value = SMIL_SYNCBEHAVIOR_INDEPENDENT;
2219	} 
2220}
2221
2222static void smil_parse_syncToleranceOrDefault(SMIL_SyncTolerance *value, char *value_string)
2223{
2224	if (!strcmp(value_string, "inherit")) {
2225		value->type = SMIL_SYNCTOLERANCE_INHERIT;
2226	} else if (!strcmp(value_string, "default")) {
2227		value->type = SMIL_SYNCTOLERANCE_DEFAULT;
2228	} else {
2229		value->type = SMIL_SYNCBEHAVIOR_LOCKED;
2230		svg_parse_clock_value(value_string, &(value->value));
2231	}
2232}
2233
2234static void svg_parse_viewbox(SVG_ViewBox *value, char *value_string)
2235{
2236	char *str = value_string;
2237	if (!strcmp(str, "none")) {
2238		value->is_set = 0;
2239	} else {
2240		u32 i = 0;
2241		value->is_set = 1;
2242		i+=svg_parse_float(&(str[i]), &(value->x), 0);
2243		i+=svg_parse_float(&(str[i]), &(value->y), 0);
2244		i+=svg_parse_float(&(str[i]), &(value->width), 0);
2245		i+=svg_parse_float(&(str[i]), &(value->height), 0);
2246	}
2247}
2248
2249static void svg_parse_coordinates(GF_List *values, char *value_string)
2250{
2251	SVG_Coordinate *c;
2252	u32 i = 0;
2253	char *str = value_string;
2254	u32 len = strlen(str);
2255
2256	while (gf_list_count(values)) {
2257		c = (SVG_Coordinate*)gf_list_get(values, 0);
2258		gf_list_rem(values, 0);
2259		free(c);
2260	}
2261	while (i < len) {
2262		GF_SAFEALLOC(c, SVG_Coordinate)
2263		i+=svg_parse_number(c, &(str[i]), 0);
2264		gf_list_add(values, c);
2265	}
2266}
2267
2268u32 svg_parse_point(SVG_Point *p, char *value_string)
2269{
2270	u32 i = 0;
2271	i+=svg_parse_float(&(value_string[i]), &(p->x), 0);
2272	i+=svg_parse_float(&(value_string[i]), &(p->y), 0);
2273	return i;
2274}
2275
2276static u32 svg_parse_point_into_matrix(GF_Matrix2D *p, char *value_string)
2277{
2278	u32 i = 0;
2279	gf_mx2d_init(*p);
2280	i+=svg_parse_float(&(value_string[i]), &(p->m[2]), 0);
2281	i+=svg_parse_float(&(value_string[i]), &(p->m[5]), 0);
2282	return i;
2283}
2284
2285static void svg_parse_points(GF_List *values, char *value_string)
2286{
2287	u32 i = 0;
2288	char *str = value_string;
2289	u32 len = strlen(str);
2290	while (i < len) {
2291		SVG_Point *p;
2292		GF_SAFEALLOC(p, SVG_Point)
2293		i += svg_parse_point(p, &str[i]);
2294		gf_list_add(values, p);
2295	}
2296}
2297
2298static void svg_parse_floats(GF_List *values, char *value_string, Bool is_angle)
2299{
2300	u32 i = 0;
2301	char *str = value_string;
2302	u32 len = strlen(str);
2303	while (i < len) {
2304		Fixed *f;
2305		GF_SAFEALLOC(f, Fixed)
2306		i+=svg_parse_float(&(str[i]), f, is_angle);
2307		gf_list_add(values, f);
2308	}
2309}
2310
2311static void svg_string_list_add(GF_List *values, char *string, u32 string_type)
2312{
2313	XMLRI *iri;
2314	switch (string_type) {
2315	case 1:
2316		iri = (XMLRI*)malloc(sizeof(XMLRI));
2317		iri->type = XMLRI_STRING;
2318		iri->string = strdup(string);
2319		gf_list_add(values, iri);
2320		break;
2321	default:
2322		gf_list_add(values, strdup(string));
2323		break;
2324	}
2325}
2326
2327static void svg_parse_strings(GF_List *values, char *value_string, u32 string_type)
2328{
2329	char *next, *sep = value_string;
2330
2331	while (gf_list_count(values)) {
2332		next = (char*)gf_list_last(values);
2333		gf_list_rem_last(values);
2334		free(next);
2335	}
2336	
2337	while (1) {
2338		while (sep && sep[0]==' ') sep++;
2339		if (!sep) break;
2340		next = strchr(sep, ';');
2341		if (!next) {
2342			svg_string_list_add(values, sep, string_type);
2343			break;
2344		}
2345		next[0]=0;
2346		svg_string_list_add(values, sep, string_type);
2347		next[0]=';';
2348		sep = next+1;
2349	}
2350}
2351
2352static void svg_parse_strokedasharray(SVG_StrokeDashArray *value, char *value_string)
2353{
2354	if (!strcmp(value_string, "none")) {
2355		value->type = SVG_STROKEDASHARRAY_NONE;
2356	} else if (!strcmp(value_string, "inherit")) {
2357		value->type = SVG_STROKEDASHARRAY_INHERIT;
2358	} else {
2359		Array *vals = &(value->array);
2360		GF_List *values = gf_list_new();
2361		u32 i = 0;
2362		u32 len = strlen(value_string);
2363		char *str = value_string;
2364		while (i < len) {
2365			Fixed *f;
2366			GF_SAFEALLOC(f, Fixed)
2367			i+=svg_parse_float(&(str[i]), f, 0);
2368			gf_list_add(values, f);
2369		}
2370		vals->count = gf_list_count(values);
2371		vals->vals = (Fixed *) malloc(sizeof(Fixed)*vals->count);
2372		for (i = 0; i < vals->count; i++) {
2373			Fixed *f = (Fixed *)gf_list_get(values, i);
2374			vals->vals[i] = *f;
2375			free(f);
2376		}
2377		gf_list_del(values);
2378		value->type = SVG_STROKEDASHARRAY_ARRAY;
2379	}
2380}
2381
2382static void svg_parse_zoomandpan(SVG_ZoomAndPan *value, char *value_string)
2383{
2384	if (!strcmp(value_string, "disable")) {
2385		*value = SVG_ZOOMANDPAN_DISABLE;
2386	} else if (!strcmp(value_string, "magnify")) {
2387		*value = SVG_ZOOMANDPAN_MAGNIFY;
2388	} 
2389}
2390
2391static void svg_parse_preserveaspectratio(SVG_PreserveAspectRatio *par, char *attribute_content)
2392{
2393	char *content = attribute_content;
2394	while (*content == ' ') content++;
2395	if (strstr(content, "defer")) {
2396		par->defer = 1;
2397		content += 4;
2398	} else {
2399		content = attribute_content;
2400	}
2401	while (*content == ' ') content++;
2402	if (strstr(content, "none")) {
2403		par->align = SVG_PRESERVEASPECTRATIO_NONE;
2404		content+=4;
2405	} else if (strstr(content, "xMinYMin")) {
2406		par->align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
2407		content+=8;
2408	} else if (strstr(content, "xMidYMin")) {
2409		par->align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
2410		content+=8;
2411	} else if (strstr(content, "xMaxYMin")) {
2412		par->align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
2413		content+=8;
2414	} else if (strstr(content, "xMinYMid")) {
2415		par->align = SVG_PRESERVEASPECTRATIO_XMINYMID;
2416		content+=8;
2417	} else if (strstr(content, "xMidYMid")) {
2418		par->align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
2419		content+=8;
2420	} else if (strstr(content, "xMaxYMid")) {
2421		par->align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
2422		content+=8;
2423	} else if (strstr(content, "xMinYMax")) {
2424		par->align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
2425		content+=8;
2426	} else if (strstr(content, "xMidYMax")) {
2427		par->align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
2428		content+=8;
2429	} else if (strstr(content, "xMaxYMax")) {
2430		par->align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
2431		content+=8;
2432	}
2433	while (*content == ' ') content++;
2434	if (*content == 0) return;
2435	if (strstr(content, "meet")) {
2436		par->meetOrSlice = SVG_MEETORSLICE_MEET;
2437	} else if (strstr(content, "slice")) {
2438		par->meetOrSlice = SVG_MEETORSLICE_SLICE;
2439	}
2440}
2441
2442static void svg_parse_animatetransform_type(SVG_TransformType *anim_transform_type, char *attribute_content)
2443{
2444	*anim_transform_type = SVG_TRANSFORM_MATRIX;
2445	if (!strcmp(attribute_content, "scale")) {
2446		*anim_transform_type = SVG_TRANSFORM_SCALE;
2447	} else if (!strcmp(attribute_content, "rotate")) {
2448		*anim_transform_type = SVG_TRANSFORM_ROTATE;
2449	} else if (!strcmp(attribute_content, "translate")) {
2450		*anim_transform_type = SVG_TRANSFORM_TRANSLATE;
2451	} else if (!strcmp(attribute_content, "skewX")) {
2452		*anim_transform_type = SVG_TRANSFORM_SKEWX;
2453	} else if (!strcmp(attribute_content, "skewY")) {
2454		*anim_transform_type = SVG_TRANSFORM_SKEWY;
2455	}
2456}
2457
2458static void svg_parse_focushighlight(SVG_FocusHighlight *fh, char *attribute_content)
2459{
2460	if (!strcmp(attribute_content, "auto")) {
2461		*fh = SVG_FOCUSHIGHLIGHT_AUTO;
2462	} else if (!strcmp(attribute_content, "none")) {
2463		*fh = SVG_FOCUSHIGHLIGHT_NONE;
2464	}
2465}
2466
2467static void svg_parse_focusable(SVG_Focusable *f, char *attribute_content)
2468{
2469	if (!strcmp(attribute_content, "true")) {
2470		*f = SVG_FOCUSABLE_TRUE;
2471	} else if (!strcmp(attribute_content, "false")) {
2472		*f = SVG_FOCUSABLE_FALSE;
2473	} else {
2474		*f = SVG_FOCUSABLE_AUTO;
2475	}
2476}
2477
2478static void svg_parse_initialvisibility(SVG_InitialVisibility *iv, char *attribute_content)
2479{
2480	if (!strcmp(attribute_content, "whenStarted")) {
2481		*iv = SVG_INITIALVISIBILTY_WHENSTARTED;
2482	} else if (!strcmp(attribute_content, "always")) {
2483		*iv = SVG_INITIALVISIBILTY_ALWAYS;
2484	}
2485}
2486
2487static void svg_parse_overlay(SVG_Overlay *o, char *attribute_content)
2488{
2489	if (!strcmp(attribute_content, "none")) {
2490		*o = SVG_OVERLAY_NONE;
2491	} else if (!strcmp(attribute_content, "top")) {
2492		*o = SVG_OVERLAY_TOP;
2493	}
2494}
2495
2496static void svg_parse_transformbehavior(SVG_TransformBehavior *tb, char *attribute_content)
2497{
2498	if (!strcmp(attribute_content, "geometric")) {
2499		*tb = SVG_TRANSFORMBEHAVIOR_GEOMETRIC;
2500	} else if (!strcmp(attribute_content, "pinned")) {
2501		*tb = SVG_TRANSFORMBEHAVIOR_PINNED;
2502	} else if (!strcmp(attribute_content, "pinned90")) {
2503		*tb = SVG_TRANSFORMBEHAVIOR_PINNED90;
2504	} else if (!strcmp(attribute_content, "pinned180")) {
2505		*tb = SVG_TRANSFORMBEHAVIOR_PINNED180;
2506	} else if (!strcmp(attribute_content, "pinned270")) {
2507		*tb = SVG_TRANSFORMBEHAVIOR_PINNED270;
2508	}
2509}
2510
2511static void svg_parse_focus(GF_Node *e,  SVG_Focus *o, char *attribute_content)
2512{
2513	if (o->target.string) free(o->target.string);
2514	o->target.string = NULL;
2515	o->target.target = NULL;
2516
2517	if (!strcmp(attribute_content, "self")) o->type = SVG_FOCUS_SELF;
2518	else if (!strcmp(attribute_content, "auto")) o->type = SVG_FOCUS_AUTO;
2519	else if (!strnicmp(attribute_content, "url(", 4)) {
2520		char *sep = strrchr(attribute_content, ')');
2521		if (sep) sep[0] = 0;
2522		o->type = SVG_FOCUS_IRI;
2523		svg_parse_iri(e, &o->target, attribute_content+4);
2524		if (sep) sep[0] = ')';
2525	}
2526}
2527
2528/* end of Basic SVG datatype parsing functions */
2529
2530void svg_parse_one_anim_value(GF_Node *n, SMIL_AnimateValue *anim_value, char *attribute_content, u8 anim_value_type)
2531{
2532	GF_FieldInfo info;
2533	info.fieldType = anim_value_type;
2534	info.far_ptr = gf_svg_create_attribute_value(anim_value_type);
2535	if (info.far_ptr) gf_svg_parse_attribute(n, &info, attribute_content, 0);
2536
2537	anim_value->value = info.far_ptr;
2538	anim_value->type = anim_value_type;
2539}
2540
2541void svg_parse_anim_values(GF_Node *n, SMIL_AnimateValues *anim_values, char *anim_values_string, u8 anim_value_type)
2542{
2543	u32 i = 0;
2544	char *str;
2545	s32 psemi = -1;
2546	GF_FieldInfo info;
2547	info.fieldType = anim_value_type;
2548	anim_values->type = anim_value_type;
2549	
2550	str = anim_values_string;
2551	while (1) {
2552		if (str[i] == ';' || str[i] == 0) {
2553			u32 single_value_len = 0;
2554			char c;
2555			single_value_len = i - (psemi+1);
2556			c = str [ (psemi+1) + single_value_len];
2557			str [ (psemi+1) + single_value_len] = 0;
2558			info.far_ptr = gf_svg_create_attribute_value(anim_value_type);
2559			if (info.far_ptr) {
2560				gf_svg_parse_attribute(n, &info, str + (psemi+1), anim_value_type);
2561				gf_list_add(anim_values->values, info.far_ptr);
2562			}
2563			str [ (psemi+1) + single_value_len] = c;
2564			psemi = i;
2565			if (!str[i]) return;
2566		}
2567		i++;
2568	}
2569}
2570
2571GF_Err laser_parse_choice(LASeR_Choice *choice, char *attribute_content)
2572{
2573	if (!strcmp(attribute_content, "none")) {
2574		choice->type = LASeR_CHOICE_NONE;
2575	} else if (!strcmp(attribute_content, "all")) {
2576		choice->type = LASeR_CHOICE_ALL;
2577	} else {
2578		choice->type = LASeR_CHOICE_N;
2579		choice->choice_index = atoi(attribute_content);
2580	}
2581	return GF_OK;
2582}
2583
2584GF_Err laser_parse_size(LASeR_Size *size, char *attribute_content)
2585{
2586	char *str = attribute_content;
2587	u32 i = 0;
2588	i+=svg_parse_float(&(str[i]), &(size->width), 0);
2589	i+=svg_parse_float(&(str[i]), &(size->height), 0);
2590	return GF_OK;
2591}
2592
2593GF_Err gf_svg_parse_element_id(GF_Node *n, const char *nodename, Bool warning_if_defined)
2594{
2595	GF_SceneGraph *sg = gf_node_get_graph((GF_Node *)n);
2596#if 0
2597	SVG_SA_Element *unided_elt;
2598	GF_SceneGraph *sg = gf_node_get_graph(n);
2599
2600	unided_elt = (SVG_SA_Element *)gf_sg_find_node_by_name(sg, (char *) nodename);
2601	if (unided_elt) {
2602		/* An element with the same id is already in the document
2603		   Is it in an update, in which case it may be normal, otherwise it's an error.*/		
2604		if (!warning_if_defined) {
2605			GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] element with id='%s' already defined in document.\n", nodename));
2606		} else {
2607			GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[SVG Parsing] element with id='%s' already defined in document.\n", nodename));
2608			gf_node_set_id(n, gf_node_get_id((GF_Node*)unided_elt), nodename);
2609		}
2610	} else {
2611		u32 id;
2612		if (sscanf(nodename, "N%d", &id) == 1) {
2613			GF_Node *n;
2614			id++;
2615			n = gf_sg_find_node(sg, id);
2616			if (n) { /* an existing node was found with this binary id, reassign a new one */
2617				u32 nID = gf_sg_get_next_available_node_id(sg);
2618				const char *nname = gf_node_get_name(n);
2619				gf_node_set_id(n, nID, nname);
2620			}
2621		} else {
2622			id = gf_sg_get_next_available_node_id(sg);
2623		}
2624		gf_node_set_id(n, id, nodename);
2625	}
2626#else
2627	u32 id;
2628	id = gf_sg_get_max_node_id(sg) + 1;
2629	gf_node_set_id(n, id, nodename);
2630#endif
2631	return GF_OK;
2632}
2633
2634/* Parse an SVG attribute */
2635GF_Err gf_svg_parse_attribute(GF_Node *n, GF_FieldInfo *info, char *attribute_content, u8 anim_value_type)
2636{
2637	u32 len;
2638	while (*attribute_content == ' ') attribute_content++;
2639	len = strlen(attribute_content);
2640	while (attribute_content[len-1] == ' ') { attribute_content[len-1] = 0; len--; }
2641
2642	switch (info->fieldType) {
2643	case SVG_Boolean_datatype:
2644		svg_parse_boolean((SVG_Boolean *)info->far_ptr, attribute_content);
2645	    break;
2646	case SVG_Color_datatype:
2647		svg_parse_color((SVG_Color *)info->far_ptr, attribute_content);
2648	    break;
2649	case SVG_Paint_datatype:
2650		svg_parse_paint(n, (SVG_Paint *)info->far_ptr, attribute_content);
2651		break;
2652
2653/* beginning of keyword type parsing */
2654	case SVG_FillRule_datatype:
2655		svg_parse_clipfillrule((SVG_FillRule *)info->far_ptr, attribute_content);
2656		break;
2657	case SVG_StrokeLineJoin_datatype:
2658		svg_parse_strokelinejoin((SVG_StrokeLineJoin *)info->far_ptr, attribute_content);
2659		break;
2660	case SVG_StrokeLineCap_datatype:
2661		svg_parse_strokelinecap((SVG_StrokeLineCap *)info->far_ptr, attribute_content);
2662		break;
2663	case SVG_FontStyle_datatype:
2664		svg_parse_fontstyle((SVG_FontStyle *)info->far_ptr, attribute_content);
2665		break;
2666	case SVG_FontWeight_datatype:
2667		svg_parse_fontweight((SVG_FontWeight *)info->far_ptr, attribute_content);
2668		break;
2669	case SVG_FontVariant_datatype:
2670		svg_parse_fontvariant((SVG_FontVariant *)info->far_ptr, attribute_content);
2671		break;
2672	case SVG_TextAnchor_datatype:
2673		svg_parse_textanchor((SVG_TextAnchor *)info->far_ptr, attribute_content);
2674		break;
2675	case SVG_Display_datatype:
2676		svg_parse_display((SVG_Display *)info->far_ptr, attribute_content);
2677		break;
2678	case SVG_Visibility_datatype:
2679		svg_parse_visibility((SVG_Visibility *)info->far_ptr, attribute_content);
2680		break;
2681	case SVG_Overflow_datatype:
2682		svg_parse_overflow((SVG_Overflow *)info->far_ptr, attribute_content);
2683		break;
2684	case SVG_ZoomAndPan_datatype:
2685		svg_parse_zoomandpan((SVG_ZoomAndPan *)info->far_ptr, attribute_content);
2686		break;
2687	case SVG_DisplayAlign_datatype:
2688		svg_parse_displayalign((SVG_DisplayAlign *)info->far_ptr, attribute_content);
2689		break;
2690	case SVG_TextAlign_datatype:
2691		svg_parse_textalign((SVG_TextAlign *)info->far_ptr, attribute_content);
2692		break;
2693	case SVG_PointerEvents_datatype:
2694		svg_parse_pointerevents((SVG_PointerEvents *)info->far_ptr, attribute_content);
2695		break;
2696	case SVG_RenderingHint_datatype:
2697		svg_parse_renderinghint((SVG_RenderingHint *)info->far_ptr, attribute_content);
2698		break;
2699	case SVG_VectorEffect_datatype:
2700		svg_parse_vectoreffect((SVG_VectorEffect *)info->far_ptr, attribute_content);
2701		break;
2702	case SVG_PlaybackOrder_datatype:
2703		svg_parse_playbackorder((SVG_PlaybackOrder *)info->far_ptr, attribute_content);
2704		break;
2705	case SVG_TimelineBegin_datatype:
2706		svg_parse_timelinebegin((SVG_TimelineBegin *)info->far_ptr, attribute_content);
2707		break;
2708	case XML_Space_datatype:
2709		svg_parse_xmlspace((XML_Space *)info->far_ptr, attribute_content);
2710		break;
2711	case XMLEV_Propagate_datatype:
2712		svg_parse_xmlev_propagate((XMLEV_Propagate *)info->far_ptr, attribute_content);
2713		break;
2714	case XMLEV_DefaultAction_datatype:
2715		svg_parse_xmlev_defaultAction((XMLEV_DefaultAction *)info->far_ptr, attribute_content);
2716		break;
2717	case XMLEV_Phase_datatype:
2718		svg_parse_xmlev_phase((XMLEV_Phase *)info->far_ptr, attribute_content);
2719		break;
2720	case SMIL_SyncBehavior_datatype:
2721		smil_parse_syncBehaviorOrDefault((SMIL_SyncBehavior *)info->far_ptr, attribute_content);
2722		break;
2723	case SMIL_SyncTolerance_datatype:
2724		smil_parse_syncToleranceOrDefault((SMIL_SyncTolerance *)info->far_ptr, attribute_content);
2725		break;
2726	case SMIL_AttributeType_datatype:
2727		smil_parse_attributeType((SMIL_AttributeType *)info->far_ptr, attribute_content);
2728		break;	
2729	case SMIL_CalcMode_datatype:
2730		smil_parse_calcmode((SMIL_CalcMode *)info->far_ptr, attribute_content);
2731		break;
2732	case SMIL_Additive_datatype:
2733		smil_parse_additive((SMIL_CalcMode *)info->far_ptr, attribute_content);
2734		break;
2735	case SMIL_Accumulate_datatype:
2736		smil_parse_accumulate((SMIL_Accumulate *)info->far_ptr, attribute_content);
2737		break;
2738	case SMIL_Restart_datatype:
2739		smil_parse_restart((SMIL_Restart *)info->far_ptr, attribute_content);
2740		break;
2741	case SMIL_Fill_datatype:
2742		smil_parse_fill((SMIL_Fill *)info->far_ptr, attribute_content);
2743		break;
2744	case SVG_GradientUnit_datatype:
2745		*((SVG_GradientUnit *)info->far_ptr) = !strcmp(attribute_content, "userSpaceOnUse") ? SVG_GRADIENTUNITS_USER : SVG_GRADIENTUNITS_OBJECT;
2746		break;
2747	case SVG_FocusHighlight_datatype:
2748		svg_parse_focushighlight((SVG_FocusHighlight*)info->far_ptr, attribute_content);
2749		break;
2750	case SVG_Focusable_datatype:
2751		svg_parse_focusable((SVG_Focusable*)info->far_ptr, attribute_content);
2752		break;
2753
2754	case SVG_InitialVisibility_datatype:
2755		svg_parse_initialvisibility((SVG_InitialVisibility*)info->far_ptr, attribute_content);
2756		break;
2757	case SVG_Overlay_datatype:
2758		svg_parse_overlay((SVG_Overlay*)info->far_ptr, attribute_content);
2759		break;
2760	case SVG_TransformBehavior_datatype:
2761		svg_parse_transformbehavior((SVG_TransformBehavior*)info->far_ptr, attribute_content);
2762		break;
2763	case SVG_SpreadMethod_datatype:
2764		if (!strcmp(attribute_content, "reflect")) *(u8*)info->far_ptr = SVG_SPREAD_REFLECT;
2765		else if (!strcmp(attribute_content, "repeat")) *(u8*)info->far_ptr = SVG_SPREAD_REPEAT;
2766		else *(u8*)info->far_ptr = SVG_SPREAD_PAD;
2767		break;
2768/* end of keyword type parsing */
2769
2770	/* keyword | floats */
2771	case SVG_Length_datatype:
2772	case SVG_Coordinate_datatype: 
2773	case SVG_FontSize_datatype:
2774	case SVG_Rotate_datatype:
2775	case SVG_Number_datatype:
2776		svg_parse_number((SVG_Number*)info->far_ptr, attribute_content, 0);
2777		break;
2778
2779	case SMIL_AnimateValue_datatype:
2780		svg_parse_one_anim_value(n, (SMIL_AnimateValue*)info->far_ptr, attribute_content, anim_value_type);
2781		break;
2782	case SMIL_AnimateValues_datatype:
2783		svg_parse_anim_values(n, (SMIL_AnimateValues*)info->far_ptr, attribute_content, anim_value_type);
2784		break;
2785
2786	case XMLRI_datatype:
2787		svg_parse_iri(n, (XMLRI*)info->far_ptr, attribute_content);
2788		break;
2789	case XML_IDREF_datatype:
2790		svg_parse_idref(n, (XMLRI*)info->far_ptr, attribute_content);
2791		break;
2792	case SMIL_AttributeName_datatype:
2793		((SMIL_AttributeName *)info->far_ptr)->name = strdup(attribute_content);
2794		break;
2795	case SMIL_Times_datatype:
2796		smil_parse_time_list(n, *(GF_List **)info->far_ptr, attribute_content);
2797		break;
2798	case SMIL_Duration_datatype:
2799		smil_parse_min_max_dur_repeatdur((SMIL_Duration*)info->far_ptr, attribute_content);
2800		break;
2801	case SMIL_RepeatCount_datatype:
2802		smil_parse_repeatcount((SMIL_RepeatCount*)info->far_ptr, attribute_content);
2803		break;
2804	case SVG_PathData_datatype:
2805		svg_parse_path((SVG_PathData*)info->far_ptr, attribute_content);
2806		break;
2807	case SVG_Points_datatype:
2808		svg_parse_points(*(GF_List **)(info->far_ptr), attribute_content);
2809		break;
2810	case SMIL_KeyTimes_datatype:
2811	case SMIL_KeyPoints_datatype:
2812	case SMIL_KeySplines_datatype:
2813		svg_parse_floats(*(GF_List **)(info->far_ptr), attribute_content, 0);
2814		break;
2815	case SVG_Numbers_datatype:
2816	case SVG_Coordinates_datatype:
2817		svg_parse_coordinates(*(GF_List **)(info->far_ptr), attribute_content);
2818		break;
2819	case SVG_ViewBox_datatype:
2820		svg_parse_viewbox((SVG_ViewBox*)info->far_ptr, attribute_content);
2821		break;
2822	case SVG_StrokeDashArray_datatype:
2823		svg_parse_strokedasharray((SVG_StrokeDashArray*)info->far_ptr, attribute_content);
2824		break;
2825	case SVG_FontFamily_datatype:
2826		svg_parse_fontfamily((SVG_FontFamily*)info->far_ptr, attribute_content);
2827		break;
2828	case SVG_Motion_datatype:
2829		svg_parse_point_into_matrix((GF_Matrix2D*)info->far_ptr, attribute_content);
2830		break;
2831	case SVG_Transform_datatype:
2832		svg_parse_transform((SVG_Transform*)info->far_ptr, attribute_content);
2833		break;
2834	case SVG_Transform_Translate_datatype:
2835		{
2836			u32 i = 0;
2837			SVG_Point *p = (SVG_Point *)info->far_ptr;;
2838			i+=svg_parse_float(&(attribute_content[i]), &(p->x), 0);
2839			if (attribute_content[i] == 0) {
2840				p->y = 0;
2841			} else {
2842				i+=svg_parse_float(&(attribute_content[i]), &(p->y), 0);
2843			}
2844		}
2845		break;
2846	case SVG_Transform_Scale_datatype:
2847		{
2848			u32 i = 0;
2849			SVG_Point *p = (SVG_Point *)info->far_ptr;;
2850			i+=svg_parse_float(&(attribute_content[i]), &(p->x), 0);
2851			if (attribute_content[i] == 0) {
2852				p->y = p->x;
2853			} else {
2854				i+=svg_parse_float(&(attribute_content[i]), &(p->y), 0);
2855			}
2856		}
2857		break;
2858	case SVG_Transform_SkewX_datatype:
2859	case SVG_Transform_SkewY_datatype:
2860		{
2861			Fixed *p = (Fixed *)info->far_ptr;
2862			svg_parse_float(attribute_content, p, 1);
2863		}
2864		break;
2865	case SVG_Transform_Rotate_datatype:
2866		{
2867			u32 i = 0;
2868			SVG_Point_Angle *p = (SVG_Point_Angle *)info->far_ptr;;
2869			i+=svg_parse_float(&(attribute_content[i]), &(p->angle), 1);
2870			if (attribute_content[i] == 0) {
2871				p->y = p->x = 0;
2872			} else {
2873				i+=svg_parse_float(&(attribute_content[i]), &(p->x), 0);
2874				i+=svg_parse_float(&(attribute_content[i]), &(p->y), 0);
2875			}					
2876		}
2877		break;
2878	case SVG_PreserveAspectRatio_datatype:
2879		svg_parse_preserveaspectratio((SVG_PreserveAspectRatio*)info->far_ptr, attribute_content);
2880		break;
2881	case SVG_TransformType_datatype:
2882		svg_parse_animatetransform_type((SVG_TransformType*)info->far_ptr, attribute_content);
2883		break;
2884
2885	case SVG_ID_datatype:
2886		/* This should not be use when parsing a LASeR update */
2887		/* If an ID is parsed outside from the parser (e.g. script), we may try to resolve animations ... */
2888		gf_svg_parse_element_id(n, attribute_content, 0);
2889		break;
2890
2891	case SVG_String_datatype:
2892	case SVG_ContentType_datatype:
2893	case SVG_LanguageID_datatype:
2894		*(SVG_String *)info->far_ptr = strdup(attribute_content);
2895		break;
2896
2897	case SVG_FeatureList_datatype:
2898	case SVG_ExtensionList_datatype:
2899	case SVG_LanguageIDs_datatype:
2900		svg_parse_strings(*(GF_List **)info->far_ptr, attribute_content, 0);
2901		break;
2902	case SVG_ListOfIRI_datatype:
2903		svg_parse_strings(*(GF_List **)info->far_ptr, attribute_content, 1);
2904		break;
2905
2906	case XMLEV_Event_datatype:
2907	{
2908		XMLEV_Event *xml_ev = (XMLEV_Event *)info->far_ptr;
2909		char *sep = strchr(attribute_content, '(');
2910		if (sep) {
2911			sep[0] = 0;
2912			xml_ev->type = gf_dom_event_type_by_name(attribute_content);
2913			sep[0] = '(';
2914			if ((xml_ev->type == GF_EVENT_REPEAT) || (xml_ev->type == GF_EVENT_REPEAT_EVENT)) {
2915				char _v;
2916				sscanf(sep, "(%c)", &_v);
2917				xml_ev->parameter = _v;
2918			} else { /* key events ... */
2919				char *sep2 = strchr(attribute_content, ')');
2920				sep2[0] = 0;
2921				xml_ev->parameter = gf_dom_get_key_type(sep+1);
2922				sep2[0] = ')';
2923			}			
2924		} else {
2925			xml_ev->parameter = 0;
2926			xml_ev->type = gf_dom_event_type_by_name(attribute_content);
2927		}
2928	}
2929		break;
2930
2931	case SVG_Focus_datatype:
2932		svg_parse_focus(n, (SVG_Focus*)info->far_ptr, attribute_content);
2933		break;
2934	case LASeR_Choice_datatype:
2935		laser_parse_choice((LASeR_Choice*)info->far_ptr, attribute_content);
2936		break;
2937	case LASeR_Size_datatype:
2938		laser_parse_size((LASeR_Size*)info->far_ptr, attribute_content);
2939		break;
2940	case LASeR_TimeAttribute_datatype:
2941		if (!strcmp(attribute_content, "end")) *(u8 *)info->far_ptr = LASeR_TIMEATTRIBUTE_END;
2942		else *(u8 *)info->far_ptr = LASeR_TIMEATTRIBUTE_BEGIN;
2943		break;
2944	case SVG_Clock_datatype:
2945		svg_parse_clock_value(attribute_content, (SVG_Clock*)info->far_ptr);
2946		break;
2947	default:
2948		GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[SVG Parsing] Cannot parse attribute %s\n", info->name, gf_svg_attribute_type_to_string(info->fieldType)));
2949		break;
2950	}
2951	return GF_OK;
2952}
2953
2954void svg_parse_one_style(GF_Node *n, char *one_style) 
2955{
2956	GF_FieldInfo info;
2957	char *c, sep;
2958	u32 attributeNameLen;
2959
2960	while (*one_style == ' ') one_style++;
2961	c = strchr(one_style, ':');
2962	if (!c) return;
2963	attributeNameLen = (c - one_style);
2964	sep = one_style[attributeNameLen];
2965	one_style[attributeNameLen] = 0;
2966	if (!gf_node_get_field_by_name(n, one_style, &info)) {
2967		c++;
2968		gf_svg_parse_attribute(n, &info, c, 0);
2969	} else {
2970		GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] Attribute %s does not belong to element %s.\n", one_style, gf_node_get_class_name(n)));
2971	}
2972	one_style[attributeNameLen] = sep;
2973}
2974
2975void gf_svg_parse_style(GF_Node *n, char *style) 
2976{
2977	u32 i = 0;
2978	char *str = style;
2979	s32 psemi = -1;
2980	
2981	while (1) {
2982		if (str[i] == ';' || str[i] == 0) {
2983			u32 single_value_len = 0;
2984			single_value_len = i - (psemi+1);
2985			if (single_value_len) {
2986				char c = str[psemi+1 + single_value_len];
2987				str[psemi+1 + single_value_len] = 0;
2988				svg_parse_one_style(n, str + psemi+1);
2989				str[psemi+1 + single_value_len] = c;
2990				psemi = i;
2991			}
2992			if (!str[i]) return;
2993		}
2994		i++;
2995	}
2996
2997}
2998
2999void *gf_svg_create_attribute_value(u32 attribute_type)
3000{
3001	switch (attribute_type) {
3002	case SVG_Boolean_datatype:
3003		{
3004			SVG_Boolean *b;
3005			GF_SAFEALLOC(b, SVG_Boolean)
3006			return b;
3007		}
3008		break;
3009	case SVG_Color_datatype:
3010		{
3011			SVG_Color *color;
3012			GF_SAFEALLOC(color, SVG_Color)
3013			return color;
3014		}
3015		break;
3016	case SVG_Paint_datatype:
3017		{
3018			SVG_Paint *paint;				
3019			GF_SAFEALLOC(paint, SVG_Paint)
3020			return paint;
3021		}
3022		break;
3023	
3024	/* keyword types */
3025	case SVG_FillRule_datatype:
3026	case SVG_StrokeLineJoin_datatype:
3027	case SVG_StrokeLineCap_datatype:
3028	case SVG_FontStyle_datatype:
3029	case SVG_FontWeight_datatype:
3030	case SVG_FontVariant_datatype:
3031	case SVG_TextAnchor_datatype:
3032	case SVG_Display_datatype:
3033	case SVG_Visibility_datatype:
3034	case SVG_Overflow_datatype:
3035	case SVG_ZoomAndPan_datatype:
3036	case SVG_DisplayAlign_datatype:
3037	case SVG_TextAlign_datatype:
3038	case SVG_PointerEvents_datatype:
3039	case SVG_RenderingHint_datatype:
3040	case SVG_VectorEffect_datatype:
3041	case SVG_PlaybackOrder_datatype:
3042	case SVG_TimelineBegin_datatype:
3043	case XML_Space_datatype:
3044	case XMLEV_Propagate_datatype:
3045	case XMLEV_DefaultAction_datatype:
3046	case XMLEV_Phase_datatype:
3047	case SMIL_SyncBehavior_datatype:
3048	case SMIL_AttributeType_datatype:
3049	case SMIL_CalcMode_datatype:
3050	case SMIL_Additive_datatype:
3051	case SMIL_Accumulate_datatype:
3052	case SMIL_Restart_datatype:
3053	case SMIL_Fill_datatype:
3054	case SVG_TransformType_datatype:
3055	case SVG_FocusHighlight_datatype:
3056	case SVG_InitialVisibility_datatype:
3057	case SVG_GradientUnit_datatype:
3058	case SVG_Overlay_datatype:
3059	case SVG_TransformBehavior_datatype:
3060	case SVG_SpreadMethod_datatype:
3061	case SVG_Focusable_datatype:
3062		{
3063			u8 *keyword;
3064			GF_SAFEALLOC(keyword, u8)
3065			return keyword;
3066		}
3067		break;
3068	case SMIL_SyncTolerance_datatype:
3069		{
3070			SMIL_SyncTolerance *st;
3071			GF_SAFEALLOC(st, SMIL_SyncTolerance)
3072			return st;
3073		}
3074		break;
3075
3076	/* inheritable floats */
3077	case SVG_FontSize_datatype:
3078	case SVG_Length_datatype:
3079	case SVG_Coordinate_datatype:
3080	case SVG_Rotate_datatype:
3081	case SVG_Number_datatype:
3082		{
3083			SVG_Number *number;
3084			GF_SAFEALLOC(number, SVG_Number)
3085			return number;
3086		}
3087		break;	
3088	
3089	case SVG_StrokeDashArray_datatype:
3090		{
3091			SVG_StrokeDashArray *array;
3092			GF_SAFEALLOC(array, SVG_StrokeDashArray)
3093			return array;
3094		}
3095		break;
3096
3097	case SVG_Motion_datatype:
3098		{
3099			GF_Matrix2D *p;
3100			GF_SAFEALLOC(p, GF_Matrix2D)
3101			gf_mx2d_init(*p);
3102			return p;
3103		}
3104		break;
3105
3106	case SVG_Transform_datatype:
3107		{
3108			SVG_Transform *p;
3109			GF_SAFEALLOC(p, SVG_Transform)
3110			gf_mx2d_init(p->mat);
3111			return p;
3112		}
3113		break;
3114
3115	case SVG_Transform_Translate_datatype:
3116	case SVG_Transform_Scale_datatype:
3117		{
3118			SVG_Point *p;
3119			GF_SAFEALLOC(p, SVG_Point)
3120			return p;
3121		}
3122		break;
3123
3124	case SVG_Transform_SkewX_datatype:
3125	case SVG_Transform_SkewY_datatype:
3126		{
3127			Fixed *p;
3128			GF_SAFEALLOC(p, Fixed)
3129			return p;
3130		}
3131		break;
3132
3133	case SVG_Transform_Rotate_datatype:
3134		{
3135			SVG_Point_Angle *p;
3136			GF_SAFEALLOC(p, SVG_Point_Angle)
3137			return p;
3138		}
3139		break;
3140
3141	case SVG_ViewBox_datatype:
3142		{
3143			SVG_ViewBox *viewbox;
3144			GF_SAFEALLOC(viewbox, SVG_ViewBox)
3145			return viewbox;
3146		}
3147		break;
3148	case XMLRI_datatype:
3149	case XML_IDREF_datatype:
3150		{
3151			XMLRI *iri;
3152			GF_SAFEALLOC(iri, XMLRI)
3153			return iri;
3154		}
3155		break;
3156	case SVG_FontFamily_datatype:
3157		{
3158			SVG_FontFamily *fontfamily;
3159			GF_SAFEALLOC(fontfamily, SVG_FontFamily)
3160			return fontfamily;
3161		}
3162		break;
3163	case SVG_String_datatype:
3164	case SVG_ContentType_datatype:
3165	case SVG_LanguageID_datatype:
3166		{
3167			SVG_String *string;
3168			GF_SAFEALLOC(string, SVG_String)
3169			return string;
3170		}
3171		break;
3172	case SVG_FeatureList_datatype:
3173	case SVG_ExtensionList_datatype:
3174	case SVG_FormatList_datatype:
3175	case SVG_LanguageIDs_datatype:
3176	case SVG_ListOfIRI_datatype:
3177	case SVG_Points_datatype:
3178	case SVG_Coordinates_datatype:
3179	case SMIL_Times_datatype:
3180	case SMIL_KeySplines_datatype:
3181	case SMIL_KeyTimes_datatype:
3182	case SMIL_KeyPoints_datatype:
3183	case SVG_Numbers_datatype:
3184		{
3185			ListOfXXX *list;
3186			GF_SAFEALLOC(list, ListOfXXX)
3187			*list = gf_list_new();
3188			return list;
3189		}
3190		break;
3191	case SVG_PreserveAspectRatio_datatype:
3192		{
3193			SVG_PreserveAspectRatio *par;
3194			GF_SAFEALLOC(par, SVG_PreserveAspectRatio)
3195			return par;
3196		}
3197		break;
3198	case SVG_PathData_datatype:
3199		{
3200			SVG_PathData *path;
3201			GF_SAFEALLOC(path, SVG_PathData);
3202#if USE_GF_PATH
3203			gf_path_reset(path);
3204			path->fineness = FIX_ONE;
3205#else 
3206			path->commands = gf_list_new();
3207			path->points = gf_list_new();
3208#endif
3209			return path;
3210		}
3211		break;
3212	case LASeR_Choice_datatype:
3213		{
3214			LASeR_Choice *ch;
3215			GF_SAFEALLOC(ch, LASeR_Choice)
3216			return ch;
3217		}
3218	case SVG_Focus_datatype:
3219		{
3220			SVG_Focus *foc;
3221			GF_SAFEALLOC(foc, SVG_Focus)
3222			return foc;
3223		}
3224	case SMIL_AttributeName_datatype:
3225		{
3226			SMIL_AttributeName *an;
3227			GF_SAFEALLOC(an, SMIL_AttributeName)
3228			return an;
3229		}
3230	case SMIL_RepeatCount_datatype:
3231		{
3232			SMIL_RepeatCount *rc;
3233			GF_SAFEALLOC(rc, SMIL_RepeatCount)
3234			return rc;
3235		}
3236	case SMIL_Duration_datatype:
3237		{
3238			SMIL_Duration *sd;
3239			GF_SAFEALLOC(sd, SMIL_Duration)
3240			return sd;
3241		}
3242	case SMIL_AnimateValue_datatype:
3243		{
3244			SMIL_AnimateValue *av;
3245			GF_SAFEALLOC(av, SMIL_AnimateValue)
3246			return av;
3247		}
3248		break;
3249	case SMIL_AnimateValues_datatype:
3250		{
3251			SMIL_AnimateValues *av;
3252			GF_SAFEALLOC(av, SMIL_AnimateValues)
3253			av->values = gf_list_new();
3254			return av;
3255		}
3256		break;
3257	case SVG_Clock_datatype:
3258		{
3259			SVG_Clock *ck;
3260			GF_SAFEALLOC(ck, SVG_Clock)
3261			return ck;
3262		}
3263		break;
3264
3265	case XMLEV_Event_datatype:
3266		{
3267			XMLEV_Event *e;
3268			GF_SAFEALLOC(e, XMLEV_Event);
3269			return e;
3270		}
3271		break;
3272	case LASeR_Size_datatype:
3273		{
3274			LASeR_Size *s;
3275			GF_SAFEALLOC(s, LASeR_Size);
3276			return s;
3277		}
3278		break;
3279
3280	default:
3281		GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] Cannot create attribute value - Type %s not supported.\n", gf_svg_attribute_type_to_string(attribute_type)));
3282		break;
3283	} 
3284	return NULL;
3285}
3286
3287static void svg_dump_color(SVG_Color *col, char *attValue)
3288{
3289	if (col->type == SVG_COLOR_CURRENTCOLOR) strcpy(attValue, "currentColor");
3290	else if (col->type == SVG_COLOR_INHERIT) strcpy(attValue, "inherit");
3291	else if (col->type !=SVG_COLOR_RGBCOLOR) {
3292		u32 i, count;
3293		count = sizeof(system_colors) / sizeof(struct sys_col);
3294		for (i=0; i<count; i++) {
3295			if (col->type == system_colors[i].type) {
3296				strcpy(attValue, system_colors[i].name);
3297				return;
3298			}
3299		}
3300	} else {
3301		u32 i, count = sizeof(predefined_colors) / sizeof(struct predef_col);
3302		u32 r, g, b;
3303		r = FIX2INT(255*col->red);
3304		g = FIX2INT(255*col->green);
3305		b = FIX2INT(255*col->blue);
3306		for (i=0; i<count; i++) {
3307			if (
3308				(r == predefined_colors[i].r)
3309				&& (g == predefined_colors[i].g)
3310				&& (b == predefined_colors[i].b)
3311			) {
3312				strcpy(attValue, predefined_colors[i].name);
3313				return;
3314			}
3315		}
3316		sprintf(attValue, "#%02X%02X%02X", r, g, b);
3317		/*compress it...*/
3318		if ( (attValue[1]==attValue[2]) && (attValue[3]==attValue[4]) && (attValue[5]==attValue[6]) )
3319			sprintf(attValue, "#%c%c%c", attValue[1], attValue[3], attValue[5]);
3320	}
3321}
3322
3323static void svg_dump_number(SVG_Number *l, char *attValue)
3324{
3325	if (l->type==SVG_NUMBER_INHERIT) strcpy(attValue, "inherit");
3326	else if (l->type == SVG_NUMBER_AUTO) strcpy(attValue, "auto");
3327	else if (l->type == SVG_NUMBER_AUTO_REVERSE) strcpy(attValue, "auto-reverse");
3328	else {
3329		sprintf(attValue, "%g", FIX2FLT(l->value) );
3330		if (l->type == SVG_NUMBER_PERCENTAGE) strcat(attValue, "%");
3331		else if (l->type == SVG_NUMBER_EMS) strcat(attValue, "em");
3332		else if (l->type == SVG_NUMBER_EXS) strcat(attValue, "ex");
3333		else if (l->type == SVG_NUMBER_PX) strcat(attValue, "px");
3334		else if (l->type == SVG_NUMBER_CM) strcat(attValue, "cm");
3335		else if (l->type == SVG_NUMBER_MM) strcat(attValue, "mm");
3336		else if (l->type == SVG_NUMBER_IN) strcat(attValue, "in");
3337		else if (l->type == SVG_NUMBER_PT) strcat(attValue, "pt");
3338		else if (l->type == SVG_NUMBER_PC) strcat(attValue, "pc");
3339	}
3340}
3341
3342static void svg_dump_iri(XMLRI*iri, char *attValue)
3343{
3344	if (iri->type == XMLRI_ELEMENTID) {
3345		const char *name;
3346		name = gf_node_get_name((GF_Node *)iri->target);
3347		if (name) sprintf(attValue, "#%s", gf_node_get_name((GF_Node *)iri->target));
3348		else  sprintf(attValue, "#N%d", gf_node_get_id((GF_Node *)iri->target) - 1);
3349	}
3350	else if ((iri->type == XMLRI_STRING) && iri->string) strcpy(attValue, iri->string);
3351	else strcpy(attValue, "");
3352}
3353
3354static void svg_dump_idref(XMLRI*iri, char *attValue)
3355{
3356	const char *name;
3357	if (iri->target) {
3358		name = gf_node_get_name((GF_Node *)iri->target);
3359		if (name) sprintf(attValue, "%s", gf_node_get_name((GF_Node *)iri->target));
3360		else sprintf(attValue, "N%d", gf_node_get_id((GF_Node *)iri->target) - 1);
3361		return;
3362	}
3363	if (iri->string) strcpy(attValue, iri->string);
3364}
3365
3366#if USE_GF_PATH
3367static void svg_dump_path(SVG_PathData *path, char *attValue)
3368{
3369	char szT[1000];
3370	GF_Point2D *pt, last_pt, *ct1, *ct2, *end;
3371	u32 i, *contour;
3372	strcpy(attValue, "");
3373
3374	contour = path->contours;
3375
3376	for (i=0; i<path->n_points; ) {
3377		switch (path->tags[i]) {
3378		case GF_PATH_CURVE_ON:
3379		case GF_PATH_CLOSE:
3380			pt = &path->points[i];
3381			if (!i || (*contour == i-1) ) {
3382				sprintf(szT, "M%g %g", FIX2FLT(pt->x), FIX2FLT(pt->y));
3383			} else if (path->tags[i]==GF_PATH_CLOSE) {
3384				sprintf(szT, " z");
3385			} else {
3386				if (i && (last_pt.x==pt->x)) sprintf(szT, " V%g", FIX2FLT(pt->y));
3387				else if (i && (last_pt.y==pt->y)) sprintf(szT, " H%g", FIX2FLT(pt->x));
3388				sprintf(szT, " L%g %g", FIX2FLT(pt->x), FIX2FLT(pt->y));
3389			}
3390			strcat(attValue, szT);
3391			last_pt = *pt;
3392			i++;
3393			break;
3394		case GF_PATH_CURVE_CONIC:
3395			ct1 = &path->points[i];
3396			end = &path->points[i+2];
3397			sprintf(szT, " Q%g %g %g %g", FIX2FLT(ct1->x), FIX2FLT(ct1->y), FIX2FLT(end->x), FIX2FLT(end->y));
3398			strcat(attValue, szT);
3399			last_pt = *end;
3400			i+=2;
3401			break;
3402		case GF_PATH_CURVE_CUBIC:
3403			ct1 = &path->points[i];
3404			ct2 = &path->points[i+1];
3405			end = &path->points[i+2];
3406			sprintf(szT, " C%g %g %g %g %g %g", FIX2FLT(ct1->x), FIX2FLT(ct1->y), FIX2FLT(ct2->x), FIX2FLT(ct2->y), FIX2FLT(end->x), FIX2FLT(end->y));
3407			strcat(attValue, szT);
3408			last_pt = *end;
3409			i+=3;
3410			break;
3411		}
3412	}
3413
3414}
3415#else
3416static void svg_dump_point(SVG_Point *pt, char *attValue)
3417{
3418	if (pt) sprintf(attValue, "%g %g ", FIX2FLT(pt->x), FIX2FLT(pt->y) );
3419}
3420static void svg_dump_path(SVG_PathData *path, char *attValue)
3421{
3422	char szT[1000];
3423	u32 i, pt_i, count;
3424	count = gf_list_count(path->commands);
3425	pt_i = 0;
3426	strcpy(attValue, "");
3427	for (i = 0; i < count; i++) {
3428		u8 command = *(u8 *)gf_list_get(path->commands, i);
3429		switch(command) {
3430		case SVG_PATHCOMMAND_M:
3431			strcat(attValue, "M");			
3432			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3433			strcat(attValue, szT);
3434			pt_i++;
3435			break;
3436		case SVG_PATHCOMMAND_L:
3437			strcat(attValue, "L");
3438			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3439			strcat(attValue, szT);
3440			pt_i++;
3441			break;
3442		case SVG_PATHCOMMAND_C:
3443			strcat(attValue, "C");
3444			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3445			strcat(attValue, szT);
3446			pt_i++;
3447			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3448			strcat(attValue, szT);
3449			pt_i++;
3450			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3451			strcat(attValue, szT);
3452			pt_i++;
3453			break;
3454		case SVG_PATHCOMMAND_S:
3455			strcat(attValue, "S");
3456			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3457			strcat(attValue, szT);
3458			pt_i++;
3459			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3460			strcat(attValue, szT);
3461			pt_i++;
3462			break;
3463		case SVG_PATHCOMMAND_Q:
3464			strcat(attValue, "Q");
3465			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3466			strcat(attValue, szT);
3467			pt_i++;
3468			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3469			strcat(attValue, szT);
3470			pt_i++;
3471			break;
3472		case SVG_PATHCOMMAND_T:
3473			strcat(attValue, "T");
3474			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3475			strcat(attValue, szT);
3476			pt_i++;
3477			break;
3478		case SVG_PATHCOMMAND_A:
3479			strcat(attValue, "A");
3480			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3481			strcat(attValue, szT);
3482			pt_i++;
3483			strcat(attValue, "0 0 0 ");
3484			svg_dump_point((SVG_Point*)gf_list_get(path->points, pt_i), szT);
3485			strcat(attValue, szT);
3486			pt_i++;
3487			break;
3488		case SVG_PATHCOMMAND_Z:
3489			strcat(attValue, "Z");
3490			break;
3491		default:
3492			GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[SVG Parsing] unknown path command %d\n", command));
3493			break;
3494		}
3495	}
3496}
3497#endif
3498
3499static void svg_dump_access_key(XMLEV_Event *evt, char *attValue)
3500{
3501	u32 i, count;
3502	strcpy(attValue, "accessKey(");
3503	count = sizeof(predefined_key_identifiers) / sizeof(struct predef_keyid);
3504	for (i=0; i<count; i++) {
3505		if (evt->parameter == predefined_key_identifiers[i].key_code) {
3506			strcat(attValue, predefined_key_identifiers[i].name);
3507			break;
3508		}
3509	}
3510	/* OLD LASeR CODE 
3511	switch (evt->parameter) {
3512	case 0: strcat(attValue, "UP"); break;
3513	case 1: strcat(attValue, "DOWN"); break;
3514	case 2: strcat(attValue, "LEFT"); break;
3515	case 3: strcat(attValue, "RIGHT"); break;
3516	case 4: strcat(attValue, "FIRE"); break;
3517	case 5: strcat(attValue, "NO_KEY"); break;
3518	case 6: strcat(attValue, "ANY_KEY"); break;
3519	case 7: strcat(attValue, "SOFT_KEY_1"); break;
3520	case 8: strcat(attValue, "SOFT_KEY_2"); break;
3521	case 35: strcat(attValue, "#"); break;
3522	case 42: strcat(attValue, "*"); break;
3523	case 48: strcat(attValue, "0"); break;
3524	case 49: strcat(attValue, "1"); break;
3525	case 50: strcat(attValue, "2"); break;
3526	case 51: strcat(attValue, "3"); break;
3527	case 52: strcat(attValue, "4"); break;
3528	case 53: strcat(attValue, "5"); break;
3529	case 54: strcat(attValue, "6"); break;
3530	case 55: strcat(attValue, "7"); break;
3531	case 56: strcat(attValue, "8"); break;
3532	case 57: strcat(attValue, "9"); break;
3533	*/
3534	strcat(attValue, ")");
3535}
3536
3537static void gf_svg_dump_matrix(GF_Matrix2D *matrix, char *attValue)
3538{
3539	/*try to do a simple decomposition...*/
3540	if (!matrix->m[1] && !matrix->m[3]) {
3541		sprintf(attValue, "translate(%g,%g)", FIX2FLT(matrix->m[2]), FIX2FLT(matrix->m[5]) );
3542		if ((matrix->m[0]!=FIX_ONE) || (matrix->m[4]!=FIX_ONE)) {
3543			char szT[1024];
3544			if ((matrix->m[0]==-FIX_ONE) && (matrix->m[4]==-FIX_ONE)) {
3545				strcpy(szT, " rotate(180)");
3546			} else {
3547				sprintf(szT, " scale(%g,%g)", FIX2FLT(matrix->m[0]), FIX2FLT(matrix->m[4]) );
3548			}
3549			strcat(attValue, szT);
3550		}
3551	} else if (matrix->m[1] == - matrix->m[3]) {
3552		Fixed angle = gf_asin(matrix->m[3]);
3553		Fixed cos_a = gf_cos(angle);
3554		if (ABS(cos_a)>FIX_EPSILON) {
3555			Fixed sx, sy;
3556			sx = gf_divfix(matrix->m[0], cos_a);
3557			sy = gf_divfix(matrix->m[4], cos_a);
3558			angle = gf_divfix(180*angle, GF_PI);
3559			if ((sx==sy) && ( ABS(FIX_ONE - ABS(sx) ) < FIX_ONE/100)) {
3560				sprintf(attValue, "translate(%g,%g) rotate(%g)", FIX2FLT(matrix->m[2]), FIX2FLT(matrix->m[5]), FIX2FLT(gf_divfix(angle*180, GF_PI) ) );
3561			} else {
3562				sprintf(attValue, "translate(%g,%g) scale(%g,%g) rotate(%g)", FIX2FLT(matrix->m[2]), FIX2FLT(matrix->m[5]), FIX2FLT(sx), FIX2FLT(sy), FIX2FLT(gf_divfix(angle*180, GF_PI) ) );
3563			}
3564		} else {
3565			Fixed a = angle;
3566			if (a<0) a += GF_2PI;
3567			sprintf(attValue, "translate(%g,%g) rotate(%g)", FIX2FLT(matrix->m[2]), FIX2FLT(matrix->m[5]), FIX2FLT(gf_divfix(a*180, GF_PI) ) );
3568		}
3569	} 
3570	/*default*/
3571	if (!strlen(attValue))
3572	sprintf(attValue, "matrix(%g %g %g %g %g %g)", FIX2FLT(matrix->m[0]), FIX2FLT(matrix->m[3]), FIX2FLT(matrix->m[1]), FIX2FLT(matrix->m[4]), FIX2FLT(matrix->m[2]), FIX2FLT(matrix->m[5]) );
3573}
3574
3575GF_Err gf_svg_dump_attribute(GF_Node *elt, GF_FieldInfo *info, char *attValue)
3576{
3577	u8 intVal;
3578	strcpy(attValue, "");
3579	if (!info->far_ptr) return GF_OK;
3580	intVal = *(u8 *)info->far_ptr;
3581	
3582	switch (info->fieldType) {
3583	case SVG_Boolean_datatype:
3584		sprintf(attValue, "%s", *(SVG_Boolean *)info->far_ptr ? "true" : "false");
3585	    break;
3586	case SVG_Color_datatype:
3587	{
3588		SVG_Color *col = (SVG_Color *)info->far_ptr;
3589		svg_dump_color(col, attValue);
3590	}
3591	    break;
3592	case SVG_Paint_datatype:
3593	{
3594		SVG_Paint *paint = (SVG_Paint *)info->far_ptr;
3595		if (paint->type == SVG_PAINT_NONE) strcpy(attValue, "none");
3596		else if (paint->type == SVG_PAINT_INHERIT) strcpy(attValue, "inherit");
3597		else if (paint->type == SVG_PAINT_URI) {
3598			strcat(attValue, "url(#");
3599			svg_dump_iri(&paint->iri, attValue);
3600			strcat(attValue, ")");
3601		} else svg_dump_color(&paint->color, attValue);
3602	}
3603		break;
3604
3605/* beginning of keyword type parsing */
3606	case SVG_FillRule_datatype:
3607		if (intVal == SVG_FILLRULE_INHERIT) strcpy(attValue, "inherit");
3608		else if (intVal == SVG_FILLRULE_NONZERO) strcpy(attValue, "nonzero");
3609		else strcpy(attValue, "evenodd");
3610		break;
3611
3612	case SVG_StrokeLineJoin_datatype:
3613		if (intVal==SVG_STROKELINEJOIN_INHERIT) strcpy(attValue, "inherit");
3614		else if (intVal==SVG_STROKELINEJOIN_MITER) strcpy(attValue, "miter");
3615		else if (intVal==SVG_STROKELINEJOIN_ROUND) strcpy(attValue, "round");
3616		else if (intVal==SVG_STROKELINEJOIN_BEVEL) strcpy(attValue, "bevel");
3617		break;
3618	case SVG_StrokeLineCap_datatype:
3619		if (intVal==SVG_STROKELINECAP_INHERIT) strcpy(attValue, "inherit");
3620		else if (intVal==SVG_STROKELINECAP_BUTT) strcpy(attValue, "butt");
3621		else if (intVal==SVG_STROKELINECAP_ROUND) strcpy(attValue, "round");
3622		else if (intVal==SVG_STROKELINECAP_SQUARE) strcpy(attValue, "square");
3623		break;
3624	case SVG_FontStyle_datatype:
3625		if (intVal==SVG_FONTSTYLE_INHERIT) strcpy(attValue, "inherit");
3626		else if (intVal==SVG_FONTSTYLE_NORMAL) strcpy(attValue, "normal");
3627		else if (intVal==SVG_FONTSTYLE_ITALIC) strcpy(attValue, "italic");
3628		else if (intVal==SVG_FONTSTYLE_OBLIQUE) strcpy(attValue, "oblique");
3629		break;
3630	case SVG_FontWeight_datatype:
3631		if (intVal==SVG_FONTWEIGHT_INHERIT) strcpy(attValue, "inherit");
3632		else if (intVal==SVG_FONTWEIGHT_NORMAL) strcpy(attValue, "normal");
3633		else if (intVal==SVG_FONTWEIGHT_BOLD) strcpy(attValue, "bold");
3634		else if (intVal==SVG_FONTWEIGHT_BOLDER) strcpy(attValue, "bolder");
3635		else if (intVal==SVG_FONTWEIGHT_LIGHTER) strcpy(attValue, "lighter");
3636		else if (intVal==SVG_FONTWEIGHT_100) strcpy(attValue, "100");
3637		else if (intVal==SVG_FONTWEIGHT_200) strcpy(attValue, "200");
3638		else if (intVal==SVG_FONTWEIGHT_300) strcpy(attValue, "300");
3639		else if (intVal==SVG_FONTWEIGHT_400) strcpy(attValue, "400");
3640		else if (intVal==SVG_FONTWEIGHT_500) strcpy(attValue, "500");
3641		else if (intVal==SVG_FONTWEIGHT_600) strcpy(attValue, "600");
3642		else if (intVal==SVG_FONTWEIGHT_700) strcpy(attValue, "700");
3643		else if (intVal==SVG_FONTWEIGHT_800) strcpy(attValue, "800");
3644		else if (intVal==SVG_FONTWEIGHT_900) strcpy(attValue, "900");
3645		break;
3646	case SVG_FontVariant_datatype:
3647		if (intVal==SVG_FONTVARIANT_INHERIT) strcpy(attValue, "inherit");
3648		else if (intVal==SVG_FONTVARIANT_NORMAL) strcpy(attValue, "normal");
3649		else if (intVal==SVG_FONTVARIANT_SMALLCAPS) strcpy(attValue, "small-caps");
3650		break;
3651	case SVG_TextAnchor_datatype:
3652		if (intVal==SVG_TEXTANCHOR_INHERIT) strcpy(attValue, "inherit");
3653		else if (intVal==SVG_TEXTANCHOR_START) strcpy(attValue, "start");
3654		else if (intVal==SVG_TEXTANCHOR_MIDDLE) strcpy(attValue, "middle");
3655		else if (intVal==SVG_TEXTANCHOR_END) strcpy(attValue, "end");
3656		break;
3657	case SVG_Display_datatype:
3658		if (intVal==SVG_DISPLAY_INHERIT) strcpy(attValue, "inherit");
3659		else if (intVal==SVG_DISPLAY_NONE) strcpy(attValue, "none");
3660		else if (intVal==SVG_DISPLAY_INLINE) strcpy(attValue, "inline");
3661		else if (intVal==SVG_DISPLAY_BLOCK) strcpy(attValue, "block");
3662		else if (intVal==SVG_DISPLAY_LIST_ITEM) strcpy(attValue, "list-item");
3663		else if (intVal==SVG_DISPLAY_RUN_IN) strcpy(attValue, "run-in");
3664		else if (intVal==SVG_DISPLAY_COMPACT) strcpy(attValue, "compact");
3665		else if (intVal==SVG_DISPLAY_MARKER) strcpy(attValue, "marker");
3666		else if (intVal==SVG_DISPLAY_TABLE) strcpy(attValue, "table");
3667		else if (intVal==SVG_DISPLAY_INLINE_TABLE) strcpy(attValue, "inline-table");
3668		else if (intVal==SVG_DISPLAY_TABLE_ROW_GROUP) strcpy(attValue, "table-row-group");
3669		else if (intVal==SVG_DISPLAY_TABLE_HEADER_GROUP) strcpy(attValue, "table-header-group");
3670		else if (intVal==SVG_DISPLAY_TABLE_FOOTER_GROUP) strcpy(attValue, "table-footer-group");
3671		else if (intVal==SVG_DISPLAY_TABLE_ROW) strcpy(attValue, "table-row");
3672		else if (intVal==SVG_DISPLAY_TABLE_COLUMN_GROUP) strcpy(attValue, "table-column-group");
3673		else if (intVal==SVG_DISPLAY_TABLE_COLUMN) strcpy(attValue, "table-column");
3674		else if (intVal==SVG_DISPLAY_TABLE_CELL) strcpy(attValue, "table-cell");
3675		else if (intVal==SVG_DISPLAY_TABLE_CAPTION) strcpy(attValue, "table-caption");
3676		break;
3677	case SVG_Visibility_datatype:
3678		if (intVal==SVG_VISIBILITY_INHERIT) strcpy(attValue, "inherit");
3679		else if (intVal==SVG_VISIBILITY_VISIBLE) strcpy(attValue, "visible");
3680		else if (intVal==SVG_VISIBILITY_HIDDEN) strcpy(attValue, "hidden");
3681		else if (intVal==SVG_VISIBILITY_COLLAPSE) strcpy(attValue, "collapse");
3682		break;
3683	case SVG_Overflow_datatype:
3684		if (intVal==SVG_OVERFLOW_INHERIT) strcpy(attValue, "inherit");
3685		else if (intVal==SVG_OVERFLOW_VISIBLE) strcpy(attValue, "visible");
3686		else if (intVal==SVG_OVERFLOW_HIDDEN) strcpy(attValue, "hidden");
3687		else if (intVal==SVG_OVERFLOW_SCROLL) strcpy(attValue, "scroll");
3688		else if (intVal==SVG_OVERFLOW_AUTO) strcpy(attValue, "auto");
3689		break;
3690	case SVG_ZoomAndPan_datatype:
3691		if (intVal==SVG_ZOOMANDPAN_DISABLE) strcpy(attValue, "disable");
3692		else strcpy(attValue, "magnify");
3693		break;
3694	case SVG_DisplayAlign_datatype:
3695		if (intVal==SVG_DISPLAYALIGN_INHERIT) strcpy(attValue, "inherit");
3696		else if (intVal==SVG_DISPLAYALIGN_AUTO) strcpy(attValue, "auto");
3697		else if (intVal==SVG_DISPLAYALIGN_BEFORE) strcpy(attValue, "before");
3698		else if (intVal==SVG_DISPLAYALIGN_CENTER) strcpy(attValue, "center");
3699		else if (intVal==SVG_DISPLAYALIGN_AFTER) strcpy(attValue, "after");
3700		break;
3701	case SVG_TextAlign_datatype:
3702		if (intVal==SVG_TEXTALIGN_INHERIT) strcpy(attValue, "inherit");
3703		else if (intVal==SVG_TEXTALIGN_START) strcpy(attValue, "start");
3704		else if (intVal==SVG_TEXTALIGN_CENTER) strcpy(attValue, "center");
3705		else if (intVal==SVG_TEXTALIGN_END) strcpy(attValue, "end");
3706		break;
3707	case SVG_PointerEvents_datatype:
3708		if (intVal==SVG_POINTEREVENTS_INHERIT) strcpy(attValue, "inherit");
3709		else if (intVal==SVG_POINTEREVENTS_VISIBLEPAINTED) strcpy(attValue, "visiblePainted");
3710		else if (intVal==SVG_POINTEREVENTS_VISIBLEFILL) strcpy(attValue, "visibleFill");
3711		else if (intVal==SVG_POINTEREVENTS_VISIBLESTROKE) strcpy(attValue, "visibleStroke");
3712		else if (intVal==SVG_POINTEREVENTS_VISIBLE) strcpy(attValue, "visible");
3713		else if (intVal==SVG_POINTEREVENTS_PAINTED) strcpy(attValue, "painted");
3714		else if (intVal==SVG_POINTEREVENTS_FILL) strcpy(attValue, "fill");
3715		else if (intVal==SVG_POINTEREVENTS_STROKE) strcpy(attValue, "stroke");
3716		else if (intVal==SVG_POINTEREVENTS_ALL) strcpy(attValue, "all");
3717		else if (intVal==SVG_POINTEREVENTS_NONE) strcpy(attValue, "none");
3718		else if (intVal==SVG_POINTEREVENTS_BOUNDINGBOX) strcpy(attValue, "boundingBox");
3719		break;
3720	case SVG_RenderingHint_datatype:
3721		if (intVal==SVG_RENDERINGHINT_INHERIT) strcpy(attValue, "inherit");
3722		else if (intVal==SVG_RENDERINGHINT_AUTO) strcpy(attValue, "auto");
3723		else if (intVal==SVG_RENDERINGHINT_OPTIMIZEQUALITY) strcpy(attValue, "optimizeQuality");
3724		else if (intVal==SVG_RENDERINGHINT_OPTIMIZESPEED) strcpy(attValue, "optimizeSpeed");
3725		else if (intVal==SVG_RENDERINGHINT_OPTIMIZELEGIBILITY) strcpy(attValue, "optimizeLegibility");
3726		else if (intVal==SVG_RENDERINGHINT_CRISPEDGES) strcpy(attValue, "crispEdges");
3727		else if (intVal==SVG_RENDERINGHINT_GEOMETRICPRECISION) strcpy(attValue, "geometricPrecision");
3728		break;
3729	case SVG_VectorEffect_datatype:
3730		if (intVal==SVG_VECTOREFFECT_INHERIT) strcpy(attValue, "inherit");
3731		else if (intVal==SVG_VECTOREFFECT_NONE) strcpy(attValue, "none");
3732		else if (intVal==SVG_VECTOREFFECT_NONSCALINGSTROKE) strcpy(attValue, "non-scaling-stroke");
3733		break;
3734	case SVG_PlaybackOrder_datatype:
3735		if (intVal== SVG_PLAYBACKORDER_FORWARDONLY) strcpy(attValue, "forwardOnly");
3736		else if (intVal== SVG_PLAYBACKORDER_ALL) strcpy(attValue, "all");
3737		break;
3738	case SVG_TimelineBegin_datatype:
3739		if (intVal== SVG_TIMELINEBEGIN_ONSTART) strcpy(attValue, "onStart");
3740		else if (intVal== SVG_TIMELINEBEGIN_ONLOAD) strcpy(attValue, "onLoad");
3741		break;
3742	case XML_Space_datatype:
3743		if (intVal==XML_SPACE_DEFAULT) strcpy(attValue, "default");
3744		else if (intVal==XML_SPACE_PRESERVE) strcpy(attValue, "preserve");
3745		break;
3746	case XMLEV_Propagate_datatype:
3747		if (intVal==XMLEVENT_PROPAGATE_CONTINUE) strcpy(attValue, "continue");
3748		else if (intVal==XMLEVENT_PROPAGATE_STOP) strcpy(attValue, "stop");
3749		break;
3750	case XMLEV_DefaultAction_datatype:
3751		if (intVal==XMLEVENT_DEFAULTACTION_CANCEL) strcpy(attValue, "cancel");
3752		else if (intVal==XMLEVENT_DEFAULTACTION_PERFORM) strcpy(attValue, "perform");
3753		break;
3754	case XMLEV_Phase_datatype:
3755		if (intVal==XMLEVENT_PHASE_DEFAULT) strcpy(attValue, "default");
3756		else if (intVal==XMLEVENT_PHASE_CAPTURE) strcpy(attValue, "capture");
3757		break;
3758	case SMIL_SyncBehavior_datatype:
3759		if (intVal==SMIL_SYNCBEHAVIOR_INHERIT) strcpy(attValue, "inherit");
3760		else if (intVal==SMIL_SYNCBEHAVIOR_DEFAULT) strcpy(attValue, "default");
3761		else if (intVal==SMIL_SYNCBEHAVIOR_LOCKED) strcpy(attValue, "locked");
3762		else if (intVal==SMIL_SYNCBEHAVIOR_CANSLIP) strcpy(attValue, "canSlip");
3763		else if (intVal==SMIL_SYNCBEHAVIOR_INDEPENDENT) strcpy(attValue, "independent");
3764		break;
3765	case SMIL_SyncTolerance_datatype:
3766		if (((SMIL_SyncTolerance*)info->far_ptr)->type==SMIL_SYNCTOLERANCE_INHERIT) strcpy(attValue, "inherit");
3767		else if (((SMIL_SyncTolerance*)info->far_ptr)->type==SMIL_SYNCTOLERANCE_DEFAULT) strcpy(attValue, "default");
3768		else if (((SMIL_SyncTolerance*)info->far_ptr)->type==SMIL_SYNCBEHAVIOR_LOCKED) {
3769			sprintf(attValue, "%g", ((SMIL_SyncTolerance*)info->far_ptr)->value);
3770		}
3771		break;
3772	case SMIL_AttributeType_datatype:
3773		if (intVal==SMIL_ATTRIBUTETYPE_AUTO) strcpy(attValue, "auto");
3774		else if (intVal==SMIL_ATTRIBUTETYPE_XML) strcpy(attValue, "XML");
3775		else if (intVal==SMIL_ATTRIBUTETYPE_CSS) strcpy(attValue, "CSS");
3776		break;	
3777	case SMIL_CalcMode_datatype:
3778		if (intVal==SMIL_CALCMODE_DISCRETE) strcpy(attValue, "discrete");
3779		else if (intVal==SMIL_CALCMODE_LINEAR) strcpy(attValue, "linear");
3780		else if (intVal==SMIL_CALCMODE_PACED) strcpy(attValue, "paced");
3781		else if (intVal==SMIL_CALCMODE_SPLINE) strcpy(attValue, "spline");
3782		break;
3783	case SMIL_Additive_datatype:
3784		if (intVal==SMIL_ADDITIVE_REPLACE) strcpy(attValue, "replace");
3785		else if (intVal==SMIL_ADDITIVE_SUM) strcpy(attValue, "sum");
3786		break;
3787	case SMIL_Accumulate_datatype:
3788		if (intVal==SMIL_ACCUMULATE_NONE) strcpy(attValue, "none");
3789		else if (intVal==SMIL_ACCUMULATE_SUM) strcpy(attValue, "sum");
3790		break;
3791	case SMIL_Restart_datatype:
3792		if (intVal==SMIL_RESTART_ALWAYS) strcpy(attValue, "always");
3793		else if (intVal==SMIL_RESTART_WHENNOTACTIVE) strcpy(attValue, "whenNotActive");
3794		else if (intVal==SMIL_RESTART_NEVER) strcpy(attValue, "never");
3795		break;
3796	case SMIL_Fill_datatype:
3797		if (intVal==SMIL_FILL_FREEZE) strcpy(attValue, "freeze");
3798		else if (intVal==SMIL_FILL_REMOVE) strcpy(attValue, "remove");
3799		break;
3800
3801	case SVG_GradientUnit_datatype:
3802		if (intVal==SVG_GRADIENTUNITS_USER) strcpy(attValue, "userSpaceOnUse");
3803		else if (intVal==SVG_GRADIENTUNITS_OBJECT) strcpy(attValue, "objectBoundingBox");
3804		break;
3805	case SVG_InitialVisibility_datatype:
3806		if (intVal==SVG_INITIALVISIBILTY_WHENSTARTED) strcpy(attValue, "whenStarted");
3807		else if (intVal==SVG_INITIALVISIBILTY_ALWAYS) strcpy(attValue, "always");
3808		break;
3809	case SVG_FocusHighlight_datatype:
3810		if (intVal==SVG_FOCUSHIGHLIGHT_AUTO) strcpy(attValue, "auto");
3811		else if (intVal==SVG_FOCUSHIGHLIGHT_NONE) strcpy(attValue, "none");
3812		break;
3813	case SVG_Overlay_datatype:
3814		if (intVal==SVG_OVERLAY_NONE) strcpy(attValue, "none");
3815		else if (intVal==SVG_OVERLAY_TOP) strcpy(attValue, "top");
3816		break;
3817	case SVG_TransformBehavior_datatype:
3818		if (intVal==SVG_TRANSFORMBEHAVIOR_GEOMETRIC) strcpy(attValue, "geometric");
3819		else if (intVal==SVG_TRANSFORMBEHAVIOR_PINNED) strcpy(attValue, "pinned");
3820		else if (intVal==SVG_TRANSFORMBEHAVIOR_PINNED90) strcpy(attValue, "pinned90");
3821		else if (intVal==SVG_TRANSFORMBEHAVIOR_PINNED180) strcpy(attValue, "pinned180");
3822		else if (intVal==SVG_TRANSFORMBEHAVIOR_PINNED270) strcpy(attValue, "pinned270");
3823		break;
3824	case SVG_SpreadMethod_datatype:
3825		if (intVal==SVG_SPREAD_REFLECT) strcpy(attValue, "reflect");
3826		else if (intVal==SVG_SPREAD_REFLECT) strcpy(attValue, "repeat");
3827		else strcpy(attValue, "pad");
3828		break;
3829
3830	case LASeR_Choice_datatype:
3831		if (intVal==LASeR_CHOICE_ALL) strcpy(attValue, "all");
3832		else if (intVal==LASeR_CHOICE_NONE) strcpy(attValue, "none");
3833		else if (intVal==LASeR_CHOICE_N) {
3834			char szT[1000];
3835			sprintf(szT, "%d", ((LASeR_Choice *)info->far_ptr)->choice_index);		
3836			strcat(attValue, szT);
3837		}
3838		break;
3839	case LASeR_Size_datatype:
3840		{
3841			char szT[1000];
3842			sprintf(szT, "%g %g", FIX2FLT(((LASeR_Size *)info->far_ptr)->width), FIX2FLT(((LASeR_Size *)info->far_ptr)->height));		
3843			strcat(attValue, szT);
3844		}
3845		break;
3846	case LASeR_TimeAttribute_datatype:
3847		strcpy(attValue, (intVal==LASeR_TIMEATTRIBUTE_END) ? "end" : "begin");
3848		break;
3849/* end of keyword type parsing */
3850
3851	/* inheritable floats */
3852	case SVG_FontSize_datatype:
3853	case SVG_Length_datatype:
3854	case SVG_Coordinate_datatype:
3855	case SVG_Rotate_datatype:
3856	case SVG_Number_datatype:
3857#if DUMP_COORDINATES
3858		svg_dump_number((SVG_Number *)info->far_ptr, attValue);
3859#endif
3860		break;
3861
3862	case XMLRI_datatype:
3863		svg_dump_iri((XMLRI*)info->far_ptr, attValue);
3864		break;
3865	case XML_IDREF_datatype:
3866		svg_dump_idref((XMLRI*)info->far_ptr, attValue);
3867		break;
3868	case SVG_ListOfIRI_datatype:
3869	{
3870		GF_List *l = *(GF_List **)info->far_ptr;
3871		u32 i, count = gf_list_count(l);
3872		for (i=0; i<count; i++) {
3873			char szT[1024];
3874			XMLRI *iri = (XMLRI *)gf_list_get(l, i);
3875			svg_dump_iri(iri, szT);
3876			if (strlen(szT)) {
3877				if (strlen(attValue)) strcat(attValue, " ");
3878				strcat(attValue, szT);
3879			}
3880		}
3881	}
3882		break;
3883
3884	case SVG_PathData_datatype:
3885#if DUMP_COORDINATES
3886		svg_dump_path((SVG_PathData *)info->far_ptr, attValue);
3887#endif
3888		break;
3889	case SVG_Points_datatype:
3890	{
3891#if DUMP_COORDINATES
3892		GF_List *l = *(GF_List **) info->far_ptr;
3893		u32 i = 0;
3894		u32 count = gf_list_count(l);
3895		for (i=0; i<count; i++) {
3896			char szT[1000];
3897			SVG_Point *p = (SVG_Point *)gf_list_get(l, i);
3898			sprintf(szT, "%g %g", FIX2FLT(p->x), FIX2FLT(p->y));
3899			if (i) strcat(attValue, " ");
3900			strcat(attValue, szT);
3901		}
3902#endif
3903	}
3904		break;
3905	case SMIL_KeyTimes_datatype:
3906	case SMIL_KeyPoints_datatype:
3907	case SMIL_KeySplines_datatype:
3908	{
3909		GF_List *l = *(GF_List **) info->far_ptr;
3910		u32 i = 0;
3911		u32 count = gf_list_count(l);
3912		for (i=0; i<count; i++) {
3913			char szT[1000];
3914			Fixed *p = (Fixed *)gf_list_get(l, i);
3915			sprintf(szT, "%g", FIX2FLT(*p));
3916			if (i) strcat(attValue, " ");
3917			strcat(attValue, szT);
3918		}
3919	}
3920		break;
3921	case SVG_Coordinates_datatype:
3922	{
3923#if DUMP_COORDINATES
3924		GF_List *l = *(GF_List **) info->far_ptr;
3925		u32 i = 0;
3926		u32 count = gf_list_count(l);
3927		for (i=0; i<count; i++) {
3928			char szT[1000];
3929			SVG_Coordinate *p = (SVG_Coordinate *)gf_list_get(l, i);
3930			svg_dump_number((SVG_Length *)p, szT);
3931			if (strstr(szT, "pt")) {
3932				fprintf(stderr, "found pt in output\n");
3933			}
3934			if (i) strcat(attValue, " ");
3935			strcat(attValue, szT);
3936		}
3937#endif
3938	}
3939		break;
3940	case SVG_ViewBox_datatype:
3941	{
3942		SVG_ViewBox *v = (SVG_ViewBox *)info->far_ptr;
3943		if (v->is_set)
3944			sprintf(attValue, "%g %g %g %g", FIX2FLT(v->x), FIX2FLT(v->y), FIX2FLT(v->width), FIX2FLT(v->height) );
3945		else 
3946			strcat(attValue, "none");
3947	}
3948		break;
3949	case SVG_StrokeDashArray_datatype:
3950	{
3951		SVG_StrokeDashArray *p = (SVG_StrokeDashArray *)info->far_ptr;
3952		if (p->type==SVG_STROKEDASHARRAY_NONE) strcpy(attValue, "none");
3953		else if (p->type==SVG_STROKEDASHARRAY_INHERIT) strcpy(attValue, "inherit");
3954		else if (p->type==SVG_STROKEDASHARRAY_ARRAY) {
3955			u32 i = 0;
3956			for (i=0; i<p->array.count; i++) {
3957				char szT[1000];
3958				sprintf(szT, "%g", FIX2FLT(p->array.vals[i]));
3959				if (i) strcat(attValue, " ");
3960				strcat(attValue, szT);
3961			}
3962		}
3963	}
3964		break;
3965	case SVG_FontFamily_datatype:
3966	{
3967		SVG_FontFamily *f = (SVG_FontFamily *)info->far_ptr;
3968		strcpy(attValue, (f->type==SVG_FONTFAMILY_INHERIT) ? "inherit" : (const char *) f->value);
3969	}
3970		break;
3971	case SVG_PreserveAspectRatio_datatype:
3972	{
3973		SVG_PreserveAspectRatio *par = (SVG_PreserveAspectRatio *)info->far_ptr;
3974		if (par->defer) strcat(attValue, "defer ");
3975		if (par->align == SVG_PRESERVEASPECTRATIO_NONE) strcat(attValue, "none");
3976		else if (par->align == SVG_PRESERVEASPECTRATIO_XMINYMIN) strcat(attValue, "xMinYMin");
3977		else if (par->align == SVG_PRESERVEASPECTRATIO_XMIDYMIN) strcat(attValue, "xMidYMin");
3978		else if (par->align == SVG_PRESERVEASPECTRATIO_XMAXYMIN) strcat(attValue, "xMaxYMin");
3979		else if (par->align == SVG_PRESERVEASPECTRATIO_XMINYMID) strcat(attValue, "xMinYMid");
3980		else if (par->align == SVG_PRESERVEASPECTRATIO_XMIDYMID) strcat(attValue, "xMidYMid");
3981		else if (par->align == SVG_PRESERVEASPECTRATIO_XMAXYMID) strcat(attValue, "xMaxYMid");
3982		else if (par->align == SVG_PRESERVEASPECTRATIO_XMINYMAX) strcat(attValue, "xMinYMax");
3983		else if (par->align == SVG_PRESERVEASPECTRATIO_XMIDYMAX) strcat(attValue, "xMidYMax");
3984		else if (par->align == SVG_PRESERVEASPECTRATIO_XMAXYMAX) strcat(attValue, "xMaxYMax");
3985		if (par->meetOrSlice== SVG_MEETORSLICE_SLICE) strcat(attValue, " slice");
3986	}
3987		break;
3988	case SVG_Clock_datatype:
3989		sprintf(attValue, "%g", * (SVG_Clock *)info->far_ptr );
3990		break;
3991
3992	case SVG_ID_datatype:
3993	case SVG_LanguageID_datatype:
3994	case SVG_GradientOffset_datatype:
3995	case SVG_String_datatype:
3996	case SVG_ContentType_datatype:
3997		if (*(SVG_String *)info->far_ptr) 
3998			strcpy(attValue, *(SVG_String *)info->far_ptr );
3999		break;
4000	case SVG_Focus_datatype:
4001	{
4002		SVG_Focus *foc = (SVG_Focus *)info->far_ptr;
4003		if (foc->type==SVG_FOCUS_SELF) strcpy(attValue, "self");
4004		else if (foc->type==SVG_FOCUS_AUTO) strcpy(attValue, "auto");
4005		else sprintf(attValue, "#%s", foc->target.string);
4006	}
4007		break;
4008	case SVG_Focusable_datatype:
4009	{
4010		SVG_Focusable *f = (SVG_Focusable *)info->far_ptr;
4011		if (*f == SVG_FOCUSABLE_TRUE) strcpy(attValue, "true");
4012		else if (*f == SVG_FOCUSABLE_FALSE) strcpy(attValue, "false");
4013		else strcpy(attValue, "auto");
4014	}
4015		break;
4016
4017	/*not sure what we'll put in requiredFormats*/
4018	case SVG_FormatList_datatype:
4019	case SVG_LanguageIDs_datatype:
4020	case SVG_FontList_datatype:
4021	{
4022		GF_List *l1 = *(GF_List **) info->far_ptr;
4023		u32 i = 0;
4024		u32 count = gf_list_count(l1);
4025		for (i=0; i<count; i++) {
4026			char *p1 = (char *)gf_list_get(l1, i);
4027			if (strlen(attValue)) strcat(attValue, " ");
4028			strcat(attValue, p1);
4029		}
4030	}
4031		break;
4032	case SVG_Numbers_datatype:
4033	{
4034#if DUMP_COORDINATES
4035		GF_List *l1 = *(GF_List **) info->far_ptr;
4036		u32 i = 0;
4037		u32 count = gf_list_count(l1);
4038		for (i=0; i<count; i++) {
4039			char szT[1024];
4040			SVG_Number *p = (SVG_Number *)gf_list_get(l1, i);
4041			svg_dump_number(p, attValue);
4042			if (i) strcat(attValue, " ");
4043			strcat(attValue, szT);
4044		}
4045#endif
4046	}
4047		break;
4048
4049	case SVG_Motion_datatype:
4050		{
4051#if DUMP_COORDINATES
4052			GF_Matrix2D *m = (GF_Matrix2D *)info->far_ptr;
4053			sprintf(attValue, "%g %g", FIX2FLT(m->m[2]), FIX2FLT(m->m[5]));
4054#endif
4055		}
4056		break;
4057
4058	case SVG_Transform_datatype:
4059		{
4060			SVG_Transform *t= (SVG_Transform *)info->far_ptr;
4061			if (t->is_ref) {
4062				sprintf(attValue, "ref(svg,%g,%g)", FIX2FLT(t->mat.m[2]), FIX2FLT(t->mat.m[5]) );
4063			} else {
4064				gf_svg_dump_matrix(&t->mat, attValue);
4065			}
4066		}
4067		break;
4068
4069	case SVG_Transform_Translate_datatype:
4070		{
4071			SVG_Point *pt = (SVG_Point *)info->far_ptr;
4072#if DUMP_COORDINATES
4073			sprintf(attValue, "%g %g", FIX2FLT(pt->x), FIX2FLT(pt->y) );
4074#endif
4075		}
4076		break;
4077
4078	case SVG_Transform_Scale_datatype:
4079		{
4080			SVG_Point *pt = (SVG_Point *)info->far_ptr;
4081#if DUMP_COORDINATES
4082			if (pt->x == pt->y) {
4083				sprintf(attValue, "%g", FIX2FLT(pt->x));
4084			} else {
4085				sprintf(attValue, "%g %g", FIX2FLT(pt->x), FIX2FLT(pt->y) );
4086			}
4087#endif
4088		}
4089		break;
4090
4091	case SVG_Transform_SkewX_datatype:
4092	case SVG_Transform_SkewY_datatype:
4093		{
4094			Fixed *f = (Fixed *)info->far_ptr;
4095#if DUMP_COORDINATES
4096			sprintf(attValue, "%g", FIX2FLT( 180 * gf_divfix(*f, GF_PI) ));
4097#endif
4098		}
4099		break;
4100
4101	case SVG_Transform_Rotate_datatype:
4102		{
4103			SVG_Point_Angle *pt = (SVG_Point_Angle *)info->far_ptr;
4104#if DUMP_COORDINATES
4105			if (pt->x || pt->y) {
4106				sprintf(attValue, "%g %g %g", FIX2FLT( 180 * gf_divfix(pt->angle, GF_PI) ), FIX2FLT(pt->x), FIX2FLT(pt->y) );
4107			} else {
4108				sprintf(attValue, "%g", FIX2FLT(gf_divfix(180 * pt->angle, GF_PI) ));
4109			}
4110#endif
4111		}
4112		break;
4113
4114	case SMIL_AttributeName_datatype:
4115	{
4116		SMIL_AttributeName *att_name = (SMIL_AttributeName *) info->far_ptr;
4117		if (att_name->name) {
4118			strcpy(attValue, att_name->name);
4119			return GF_OK;
4120		}
4121		if (att_name->tag) {
4122			strcpy(attValue, gf_svg_get_attribute_name(att_name->tag));
4123			return GF_OK;
4124		}
4125
4126#if 0
4127		GF_Node *t=NULL;
4128		u32 i, count;
4129		if (!elt->xlink) break;
4130		t = (GF_Node *) elt->xlink->href.target;
4131		if (!t) break;
4132		count = gf_node_get_field_count(t);
4133		for (i=0; i<count; i++) {
4134			GF_FieldInfo fi;
4135			gf_node_get_field(t, i, &fi);
4136			if (fi.far_ptr == att_name->field_ptr) {
4137				sprintf(attValue, fi.name);
4138				return GF_OK;
4139			}
4140		}
4141#endif
4142	}
4143		break;
4144	case SMIL_Times_datatype:
4145	{
4146		u32 i, count;
4147		GF_Node *par = gf_node_get_parent((GF_Node *)elt, 0);
4148		GF_List *l = *(GF_List **) info->far_ptr;
4149		count = gf_list_count(l);
4150		for (i=0; i<count; i++) {
4151			char szBuf[1000];
4152			SMIL_Time *t = (SMIL_Time *)gf_list_get(l, i);
4153			if (i) strcat(attValue, ";");
4154			if (t->type == GF_SMIL_TIME_CLOCK) {
4155				sprintf(szBuf, "%gs", t->clock);
4156				strcat(attValue, szBuf);
4157			} else if (t->type==GF_SMIL_TIME_INDEFINITE) {
4158				strcat(attValue, "indefinite");
4159			} else if (t->type==GF_SMIL_TIME_WALLCLOCK) {
4160				u32 h, m, s;
4161				/*TODO - day month and year*/
4162				h = (u32) t->clock * 3600;
4163				m = (u32) (t->clock * 60 - 60*h);
4164				s = (u32) (t->clock - 3600*h - 60*m);
4165				sprintf(szBuf, "wallclock(%d:%d:%d)", h, m, s);
4166				strcat(attValue, szBuf);
4167			}
4168			else if (t->type==GF_SMIL_TIME_EVENT) {
4169				if (t->event.type == GF_EVENT_KEYDOWN) {
4170					svg_dump_access_key(&t->event, szBuf);
4171					strcat(attValue, szBuf);
4172				} else {
4173					if (t->element_id) {
4174						strcat(attValue, t->element_id);
4175						strcat(attValue, ".");
4176					} else if (t->element && (t->element!=par) && gf_node_get_id(t->element) ) {
4177						const char *name = gf_node_get_name(t->element);
4178						if (name) {
4179							strcat(attValue, name);
4180						} else {
4181							sprintf(szBuf, "N%d", gf_node_get_id(t->element)-1 );
4182							strcat(attValue, szBuf);
4183						}
4184						strcat(attValue, ".");
4185					}
4186					strcat(attValue, gf_dom_event_get_name(t->event.type));
4187				}
4188				if (t->clock) {
4189					sprintf(szBuf, "%gs", t->clock);
4190					strcat(attValue, "+");
4191					strcat(attValue, szBuf);
4192				}
4193			}
4194		}
4195	}
4196		break;
4197	case SMIL_Duration_datatype:
4198	{
4199		SMIL_Duration *dur = (SMIL_Duration *)info->far_ptr;
4200		if (dur->type == SMIL_DURATION_INDEFINITE) strcpy(attValue, "indefinite");
4201		else if (dur->type == SMIL_DURATION_MEDIA) strcpy(attValue, "media");
4202		else if (dur->type == SMIL_DURATION_DEFINED) sprintf(attValue, "%gs", dur->clock_value);
4203		else {
4204			GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[SVG Parsing] smil duration not assigned\n"));
4205		}
4206	}
4207		break;
4208	case SMIL_RepeatCount_datatype:
4209	{
4210		SMIL_RepeatCount *rep = (SMIL_RepeatCount *)info->far_ptr;
4211		if (rep->type == SMIL_REPEATCOUNT_INDEFINITE) strcpy(attValue, "indefinite");
4212		else if (rep->type == SMIL_REPEATCOUNT_DEFINED) sprintf(attValue, "%g", FIX2FLT(rep->count) );
4213		else {
4214			GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[SVG Parsing] smil repeat count not assigned\n"));
4215		}
4216	}
4217		break;
4218	case SVG_TransformType_datatype:
4219	{
4220		SVG_TransformType tr = *(SVG_TransformType *)info->far_ptr;
4221		if (tr == SVG_TRANSFORM_MATRIX) strcpy(attValue, "matrix");
4222		else if (tr == SVG_TRANSFORM_SCALE) strcpy(attValue, "scale");
4223		else if (tr == SVG_TRANSFORM_ROTATE) strcpy(attValue, "rotate");
4224		else if (tr == SVG_TRANSFORM_TRANSLATE) strcpy(attValue, "translate");
4225		else if (tr == SVG_TRANSFORM_SKEWX) strcpy(attValue, "skewX");
4226		else if (tr == SVG_TRANSFORM_SKEWY) strcpy(attValue, "skewY");
4227	}
4228		break;
4229
4230	case SMIL_AnimateValue_datatype:
4231	{
4232		GF_FieldInfo a_fi;
4233		SMIL_AnimateValue*av = (SMIL_AnimateValue*)info->far_ptr;
4234		a_fi.fieldIndex = 0;
4235		a_fi.fieldType = av->type;
4236		a_fi.name = info->name;
4237		a_fi.far_ptr = av->value;
4238		gf_svg_dump_attribute(elt, &a_fi, attValue);
4239	}
4240		break;
4241	case SMIL_AnimateValues_datatype:
4242	{
4243		GF_FieldInfo a_fi;
4244		u32 i, count;
4245		SMIL_AnimateValues *av = (SMIL_AnimateValues*)info->far_ptr;
4246		if (av->type) {
4247			count = gf_list_count(av->values);
4248			a_fi.fieldIndex = 0;
4249			a_fi.fieldType = av->type;
4250			a_fi.name = info->name;
4251			for (i=0; i<count; i++) {
4252				char szBuf[1024];
4253				a_fi.far_ptr = gf_list_get(av->values, i);
4254				gf_svg_dump_attribute(elt, &a_fi, szBuf);
4255				if (i) strcat(attValue, ";");
4256				strcat(attValue, szBuf);
4257			}
4258		}
4259	}
4260		break;
4261
4262	case XMLEV_Event_datatype:
4263	{
4264		XMLEV_Event *d = (XMLEV_Event *)info->far_ptr;
4265		if (d->parameter) {
4266			svg_dump_access_key(d, attValue);
4267		} else {
4268			strcpy(attValue, gf_dom_event_get_name(d->type));
4269		}
4270		break;
4271	}
4272	default:
4273		GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[SVG Parsing] dumping for field %s of type %s not supported\n", info->name, gf_svg_attribute_type_to_string(info->fieldType)));
4274		break;
4275	}
4276	return GF_OK;
4277}
4278
4279GF_Err gf_svg_dump_attribute_indexed(GF_Node *elt, GF_FieldInfo *info, char *attValue)
4280{