PageRenderTime 91ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

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