parseSVG.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. import Group from '../graphic/Group.js';
  2. import ZRImage from '../graphic/Image.js';
  3. import Circle from '../graphic/shape/Circle.js';
  4. import Rect from '../graphic/shape/Rect.js';
  5. import Ellipse from '../graphic/shape/Ellipse.js';
  6. import Line from '../graphic/shape/Line.js';
  7. import Polygon from '../graphic/shape/Polygon.js';
  8. import Polyline from '../graphic/shape/Polyline.js';
  9. import * as matrix from '../core/matrix.js';
  10. import { createFromString } from './path.js';
  11. import { defaults, trim, each, map, keys, hasOwn } from '../core/util.js';
  12. import LinearGradient from '../graphic/LinearGradient.js';
  13. import RadialGradient from '../graphic/RadialGradient.js';
  14. import TSpan from '../graphic/TSpan.js';
  15. import { parseXML } from './parseXML.js';
  16. import * as colorTool from './color.js';
  17. ;
  18. var nodeParsers;
  19. var INHERITABLE_STYLE_ATTRIBUTES_MAP = {
  20. 'fill': 'fill',
  21. 'stroke': 'stroke',
  22. 'stroke-width': 'lineWidth',
  23. 'opacity': 'opacity',
  24. 'fill-opacity': 'fillOpacity',
  25. 'stroke-opacity': 'strokeOpacity',
  26. 'stroke-dasharray': 'lineDash',
  27. 'stroke-dashoffset': 'lineDashOffset',
  28. 'stroke-linecap': 'lineCap',
  29. 'stroke-linejoin': 'lineJoin',
  30. 'stroke-miterlimit': 'miterLimit',
  31. 'font-family': 'fontFamily',
  32. 'font-size': 'fontSize',
  33. 'font-style': 'fontStyle',
  34. 'font-weight': 'fontWeight',
  35. 'text-anchor': 'textAlign',
  36. 'visibility': 'visibility',
  37. 'display': 'display'
  38. };
  39. var INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS = keys(INHERITABLE_STYLE_ATTRIBUTES_MAP);
  40. var SELF_STYLE_ATTRIBUTES_MAP = {
  41. 'alignment-baseline': 'textBaseline',
  42. 'stop-color': 'stopColor'
  43. };
  44. var SELF_STYLE_ATTRIBUTES_MAP_KEYS = keys(SELF_STYLE_ATTRIBUTES_MAP);
  45. var SVGParser = (function () {
  46. function SVGParser() {
  47. this._defs = {};
  48. this._root = null;
  49. }
  50. SVGParser.prototype.parse = function (xml, opt) {
  51. opt = opt || {};
  52. var svg = parseXML(xml);
  53. if (process.env.NODE_ENV !== 'production') {
  54. if (!svg) {
  55. throw new Error('Illegal svg');
  56. }
  57. }
  58. this._defsUsePending = [];
  59. var root = new Group();
  60. this._root = root;
  61. var named = [];
  62. var viewBox = svg.getAttribute('viewBox') || '';
  63. var width = parseFloat((svg.getAttribute('width') || opt.width));
  64. var height = parseFloat((svg.getAttribute('height') || opt.height));
  65. isNaN(width) && (width = null);
  66. isNaN(height) && (height = null);
  67. parseAttributes(svg, root, null, true, false);
  68. var child = svg.firstChild;
  69. while (child) {
  70. this._parseNode(child, root, named, null, false, false);
  71. child = child.nextSibling;
  72. }
  73. applyDefs(this._defs, this._defsUsePending);
  74. this._defsUsePending = [];
  75. var viewBoxRect;
  76. var viewBoxTransform;
  77. if (viewBox) {
  78. var viewBoxArr = splitNumberSequence(viewBox);
  79. if (viewBoxArr.length >= 4) {
  80. viewBoxRect = {
  81. x: parseFloat((viewBoxArr[0] || 0)),
  82. y: parseFloat((viewBoxArr[1] || 0)),
  83. width: parseFloat(viewBoxArr[2]),
  84. height: parseFloat(viewBoxArr[3])
  85. };
  86. }
  87. }
  88. if (viewBoxRect && width != null && height != null) {
  89. viewBoxTransform = makeViewBoxTransform(viewBoxRect, { x: 0, y: 0, width: width, height: height });
  90. if (!opt.ignoreViewBox) {
  91. var elRoot = root;
  92. root = new Group();
  93. root.add(elRoot);
  94. elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale;
  95. elRoot.x = viewBoxTransform.x;
  96. elRoot.y = viewBoxTransform.y;
  97. }
  98. }
  99. if (!opt.ignoreRootClip && width != null && height != null) {
  100. root.setClipPath(new Rect({
  101. shape: { x: 0, y: 0, width: width, height: height }
  102. }));
  103. }
  104. return {
  105. root: root,
  106. width: width,
  107. height: height,
  108. viewBoxRect: viewBoxRect,
  109. viewBoxTransform: viewBoxTransform,
  110. named: named
  111. };
  112. };
  113. SVGParser.prototype._parseNode = function (xmlNode, parentGroup, named, namedFrom, isInDefs, isInText) {
  114. var nodeName = xmlNode.nodeName.toLowerCase();
  115. var el;
  116. var namedFromForSub = namedFrom;
  117. if (nodeName === 'defs') {
  118. isInDefs = true;
  119. }
  120. if (nodeName === 'text') {
  121. isInText = true;
  122. }
  123. if (nodeName === 'defs' || nodeName === 'switch') {
  124. el = parentGroup;
  125. }
  126. else {
  127. if (!isInDefs) {
  128. var parser_1 = nodeParsers[nodeName];
  129. if (parser_1 && hasOwn(nodeParsers, nodeName)) {
  130. el = parser_1.call(this, xmlNode, parentGroup);
  131. var nameAttr = xmlNode.getAttribute('name');
  132. if (nameAttr) {
  133. var newNamed = {
  134. name: nameAttr,
  135. namedFrom: null,
  136. svgNodeTagLower: nodeName,
  137. el: el
  138. };
  139. named.push(newNamed);
  140. if (nodeName === 'g') {
  141. namedFromForSub = newNamed;
  142. }
  143. }
  144. else if (namedFrom) {
  145. named.push({
  146. name: namedFrom.name,
  147. namedFrom: namedFrom,
  148. svgNodeTagLower: nodeName,
  149. el: el
  150. });
  151. }
  152. parentGroup.add(el);
  153. }
  154. }
  155. var parser = paintServerParsers[nodeName];
  156. if (parser && hasOwn(paintServerParsers, nodeName)) {
  157. var def = parser.call(this, xmlNode);
  158. var id = xmlNode.getAttribute('id');
  159. if (id) {
  160. this._defs[id] = def;
  161. }
  162. }
  163. }
  164. if (el && el.isGroup) {
  165. var child = xmlNode.firstChild;
  166. while (child) {
  167. if (child.nodeType === 1) {
  168. this._parseNode(child, el, named, namedFromForSub, isInDefs, isInText);
  169. }
  170. else if (child.nodeType === 3 && isInText) {
  171. this._parseText(child, el);
  172. }
  173. child = child.nextSibling;
  174. }
  175. }
  176. };
  177. SVGParser.prototype._parseText = function (xmlNode, parentGroup) {
  178. var text = new TSpan({
  179. style: {
  180. text: xmlNode.textContent
  181. },
  182. silent: true,
  183. x: this._textX || 0,
  184. y: this._textY || 0
  185. });
  186. inheritStyle(parentGroup, text);
  187. parseAttributes(xmlNode, text, this._defsUsePending, false, false);
  188. applyTextAlignment(text, parentGroup);
  189. var textStyle = text.style;
  190. var fontSize = textStyle.fontSize;
  191. if (fontSize && fontSize < 9) {
  192. textStyle.fontSize = 9;
  193. text.scaleX *= fontSize / 9;
  194. text.scaleY *= fontSize / 9;
  195. }
  196. var font = (textStyle.fontSize || textStyle.fontFamily) && [
  197. textStyle.fontStyle,
  198. textStyle.fontWeight,
  199. (textStyle.fontSize || 12) + 'px',
  200. textStyle.fontFamily || 'sans-serif'
  201. ].join(' ');
  202. textStyle.font = font;
  203. var rect = text.getBoundingRect();
  204. this._textX += rect.width;
  205. parentGroup.add(text);
  206. return text;
  207. };
  208. SVGParser.internalField = (function () {
  209. nodeParsers = {
  210. 'g': function (xmlNode, parentGroup) {
  211. var g = new Group();
  212. inheritStyle(parentGroup, g);
  213. parseAttributes(xmlNode, g, this._defsUsePending, false, false);
  214. return g;
  215. },
  216. 'rect': function (xmlNode, parentGroup) {
  217. var rect = new Rect();
  218. inheritStyle(parentGroup, rect);
  219. parseAttributes(xmlNode, rect, this._defsUsePending, false, false);
  220. rect.setShape({
  221. x: parseFloat(xmlNode.getAttribute('x') || '0'),
  222. y: parseFloat(xmlNode.getAttribute('y') || '0'),
  223. width: parseFloat(xmlNode.getAttribute('width') || '0'),
  224. height: parseFloat(xmlNode.getAttribute('height') || '0')
  225. });
  226. rect.silent = true;
  227. return rect;
  228. },
  229. 'circle': function (xmlNode, parentGroup) {
  230. var circle = new Circle();
  231. inheritStyle(parentGroup, circle);
  232. parseAttributes(xmlNode, circle, this._defsUsePending, false, false);
  233. circle.setShape({
  234. cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
  235. cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
  236. r: parseFloat(xmlNode.getAttribute('r') || '0')
  237. });
  238. circle.silent = true;
  239. return circle;
  240. },
  241. 'line': function (xmlNode, parentGroup) {
  242. var line = new Line();
  243. inheritStyle(parentGroup, line);
  244. parseAttributes(xmlNode, line, this._defsUsePending, false, false);
  245. line.setShape({
  246. x1: parseFloat(xmlNode.getAttribute('x1') || '0'),
  247. y1: parseFloat(xmlNode.getAttribute('y1') || '0'),
  248. x2: parseFloat(xmlNode.getAttribute('x2') || '0'),
  249. y2: parseFloat(xmlNode.getAttribute('y2') || '0')
  250. });
  251. line.silent = true;
  252. return line;
  253. },
  254. 'ellipse': function (xmlNode, parentGroup) {
  255. var ellipse = new Ellipse();
  256. inheritStyle(parentGroup, ellipse);
  257. parseAttributes(xmlNode, ellipse, this._defsUsePending, false, false);
  258. ellipse.setShape({
  259. cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
  260. cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
  261. rx: parseFloat(xmlNode.getAttribute('rx') || '0'),
  262. ry: parseFloat(xmlNode.getAttribute('ry') || '0')
  263. });
  264. ellipse.silent = true;
  265. return ellipse;
  266. },
  267. 'polygon': function (xmlNode, parentGroup) {
  268. var pointsStr = xmlNode.getAttribute('points');
  269. var pointsArr;
  270. if (pointsStr) {
  271. pointsArr = parsePoints(pointsStr);
  272. }
  273. var polygon = new Polygon({
  274. shape: {
  275. points: pointsArr || []
  276. },
  277. silent: true
  278. });
  279. inheritStyle(parentGroup, polygon);
  280. parseAttributes(xmlNode, polygon, this._defsUsePending, false, false);
  281. return polygon;
  282. },
  283. 'polyline': function (xmlNode, parentGroup) {
  284. var pointsStr = xmlNode.getAttribute('points');
  285. var pointsArr;
  286. if (pointsStr) {
  287. pointsArr = parsePoints(pointsStr);
  288. }
  289. var polyline = new Polyline({
  290. shape: {
  291. points: pointsArr || []
  292. },
  293. silent: true
  294. });
  295. inheritStyle(parentGroup, polyline);
  296. parseAttributes(xmlNode, polyline, this._defsUsePending, false, false);
  297. return polyline;
  298. },
  299. 'image': function (xmlNode, parentGroup) {
  300. var img = new ZRImage();
  301. inheritStyle(parentGroup, img);
  302. parseAttributes(xmlNode, img, this._defsUsePending, false, false);
  303. img.setStyle({
  304. image: xmlNode.getAttribute('xlink:href') || xmlNode.getAttribute('href'),
  305. x: +xmlNode.getAttribute('x'),
  306. y: +xmlNode.getAttribute('y'),
  307. width: +xmlNode.getAttribute('width'),
  308. height: +xmlNode.getAttribute('height')
  309. });
  310. img.silent = true;
  311. return img;
  312. },
  313. 'text': function (xmlNode, parentGroup) {
  314. var x = xmlNode.getAttribute('x') || '0';
  315. var y = xmlNode.getAttribute('y') || '0';
  316. var dx = xmlNode.getAttribute('dx') || '0';
  317. var dy = xmlNode.getAttribute('dy') || '0';
  318. this._textX = parseFloat(x) + parseFloat(dx);
  319. this._textY = parseFloat(y) + parseFloat(dy);
  320. var g = new Group();
  321. inheritStyle(parentGroup, g);
  322. parseAttributes(xmlNode, g, this._defsUsePending, false, true);
  323. return g;
  324. },
  325. 'tspan': function (xmlNode, parentGroup) {
  326. var x = xmlNode.getAttribute('x');
  327. var y = xmlNode.getAttribute('y');
  328. if (x != null) {
  329. this._textX = parseFloat(x);
  330. }
  331. if (y != null) {
  332. this._textY = parseFloat(y);
  333. }
  334. var dx = xmlNode.getAttribute('dx') || '0';
  335. var dy = xmlNode.getAttribute('dy') || '0';
  336. var g = new Group();
  337. inheritStyle(parentGroup, g);
  338. parseAttributes(xmlNode, g, this._defsUsePending, false, true);
  339. this._textX += parseFloat(dx);
  340. this._textY += parseFloat(dy);
  341. return g;
  342. },
  343. 'path': function (xmlNode, parentGroup) {
  344. var d = xmlNode.getAttribute('d') || '';
  345. var path = createFromString(d);
  346. inheritStyle(parentGroup, path);
  347. parseAttributes(xmlNode, path, this._defsUsePending, false, false);
  348. path.silent = true;
  349. return path;
  350. }
  351. };
  352. })();
  353. return SVGParser;
  354. }());
  355. var paintServerParsers = {
  356. 'lineargradient': function (xmlNode) {
  357. var x1 = parseInt(xmlNode.getAttribute('x1') || '0', 10);
  358. var y1 = parseInt(xmlNode.getAttribute('y1') || '0', 10);
  359. var x2 = parseInt(xmlNode.getAttribute('x2') || '10', 10);
  360. var y2 = parseInt(xmlNode.getAttribute('y2') || '0', 10);
  361. var gradient = new LinearGradient(x1, y1, x2, y2);
  362. parsePaintServerUnit(xmlNode, gradient);
  363. parseGradientColorStops(xmlNode, gradient);
  364. return gradient;
  365. },
  366. 'radialgradient': function (xmlNode) {
  367. var cx = parseInt(xmlNode.getAttribute('cx') || '0', 10);
  368. var cy = parseInt(xmlNode.getAttribute('cy') || '0', 10);
  369. var r = parseInt(xmlNode.getAttribute('r') || '0', 10);
  370. var gradient = new RadialGradient(cx, cy, r);
  371. parsePaintServerUnit(xmlNode, gradient);
  372. parseGradientColorStops(xmlNode, gradient);
  373. return gradient;
  374. }
  375. };
  376. function parsePaintServerUnit(xmlNode, gradient) {
  377. var gradientUnits = xmlNode.getAttribute('gradientUnits');
  378. if (gradientUnits === 'userSpaceOnUse') {
  379. gradient.global = true;
  380. }
  381. }
  382. function parseGradientColorStops(xmlNode, gradient) {
  383. var stop = xmlNode.firstChild;
  384. while (stop) {
  385. if (stop.nodeType === 1
  386. && stop.nodeName.toLocaleLowerCase() === 'stop') {
  387. var offsetStr = stop.getAttribute('offset');
  388. var offset = void 0;
  389. if (offsetStr && offsetStr.indexOf('%') > 0) {
  390. offset = parseInt(offsetStr, 10) / 100;
  391. }
  392. else if (offsetStr) {
  393. offset = parseFloat(offsetStr);
  394. }
  395. else {
  396. offset = 0;
  397. }
  398. var styleVals = {};
  399. parseInlineStyle(stop, styleVals, styleVals);
  400. var stopColor = styleVals.stopColor
  401. || stop.getAttribute('stop-color')
  402. || '#000000';
  403. var stopOpacity = styleVals.stopOpacity
  404. || stop.getAttribute('stop-opacity');
  405. if (stopOpacity) {
  406. var rgba = colorTool.parse(stopColor);
  407. var stopColorOpacity = rgba && rgba[3];
  408. if (stopColorOpacity) {
  409. rgba[3] *= colorTool.parseCssFloat(stopOpacity);
  410. stopColor = colorTool.stringify(rgba, 'rgba');
  411. }
  412. }
  413. gradient.colorStops.push({
  414. offset: offset,
  415. color: stopColor
  416. });
  417. }
  418. stop = stop.nextSibling;
  419. }
  420. }
  421. function inheritStyle(parent, child) {
  422. if (parent && parent.__inheritedStyle) {
  423. if (!child.__inheritedStyle) {
  424. child.__inheritedStyle = {};
  425. }
  426. defaults(child.__inheritedStyle, parent.__inheritedStyle);
  427. }
  428. }
  429. function parsePoints(pointsString) {
  430. var list = splitNumberSequence(pointsString);
  431. var points = [];
  432. for (var i = 0; i < list.length; i += 2) {
  433. var x = parseFloat(list[i]);
  434. var y = parseFloat(list[i + 1]);
  435. points.push([x, y]);
  436. }
  437. return points;
  438. }
  439. function parseAttributes(xmlNode, el, defsUsePending, onlyInlineStyle, isTextGroup) {
  440. var disp = el;
  441. var inheritedStyle = disp.__inheritedStyle = disp.__inheritedStyle || {};
  442. var selfStyle = {};
  443. if (xmlNode.nodeType === 1) {
  444. parseTransformAttribute(xmlNode, el);
  445. parseInlineStyle(xmlNode, inheritedStyle, selfStyle);
  446. if (!onlyInlineStyle) {
  447. parseAttributeStyle(xmlNode, inheritedStyle, selfStyle);
  448. }
  449. }
  450. disp.style = disp.style || {};
  451. if (inheritedStyle.fill != null) {
  452. disp.style.fill = getFillStrokeStyle(disp, 'fill', inheritedStyle.fill, defsUsePending);
  453. }
  454. if (inheritedStyle.stroke != null) {
  455. disp.style.stroke = getFillStrokeStyle(disp, 'stroke', inheritedStyle.stroke, defsUsePending);
  456. }
  457. each([
  458. 'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize'
  459. ], function (propName) {
  460. if (inheritedStyle[propName] != null) {
  461. disp.style[propName] = parseFloat(inheritedStyle[propName]);
  462. }
  463. });
  464. each([
  465. 'lineDashOffset', 'lineCap', 'lineJoin', 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign'
  466. ], function (propName) {
  467. if (inheritedStyle[propName] != null) {
  468. disp.style[propName] = inheritedStyle[propName];
  469. }
  470. });
  471. if (isTextGroup) {
  472. disp.__selfStyle = selfStyle;
  473. }
  474. if (inheritedStyle.lineDash) {
  475. disp.style.lineDash = map(splitNumberSequence(inheritedStyle.lineDash), function (str) {
  476. return parseFloat(str);
  477. });
  478. }
  479. if (inheritedStyle.visibility === 'hidden' || inheritedStyle.visibility === 'collapse') {
  480. disp.invisible = true;
  481. }
  482. if (inheritedStyle.display === 'none') {
  483. disp.ignore = true;
  484. }
  485. }
  486. function applyTextAlignment(text, parentGroup) {
  487. var parentSelfStyle = parentGroup.__selfStyle;
  488. if (parentSelfStyle) {
  489. var textBaseline = parentSelfStyle.textBaseline;
  490. var zrTextBaseline = textBaseline;
  491. if (!textBaseline || textBaseline === 'auto') {
  492. zrTextBaseline = 'alphabetic';
  493. }
  494. else if (textBaseline === 'baseline') {
  495. zrTextBaseline = 'alphabetic';
  496. }
  497. else if (textBaseline === 'before-edge' || textBaseline === 'text-before-edge') {
  498. zrTextBaseline = 'top';
  499. }
  500. else if (textBaseline === 'after-edge' || textBaseline === 'text-after-edge') {
  501. zrTextBaseline = 'bottom';
  502. }
  503. else if (textBaseline === 'central' || textBaseline === 'mathematical') {
  504. zrTextBaseline = 'middle';
  505. }
  506. text.style.textBaseline = zrTextBaseline;
  507. }
  508. var parentInheritedStyle = parentGroup.__inheritedStyle;
  509. if (parentInheritedStyle) {
  510. var textAlign = parentInheritedStyle.textAlign;
  511. var zrTextAlign = textAlign;
  512. if (textAlign) {
  513. if (textAlign === 'middle') {
  514. zrTextAlign = 'center';
  515. }
  516. text.style.textAlign = zrTextAlign;
  517. }
  518. }
  519. }
  520. var urlRegex = /^url\(\s*#(.*?)\)/;
  521. function getFillStrokeStyle(el, method, str, defsUsePending) {
  522. var urlMatch = str && str.match(urlRegex);
  523. if (urlMatch) {
  524. var url = trim(urlMatch[1]);
  525. defsUsePending.push([el, method, url]);
  526. return;
  527. }
  528. if (str === 'none') {
  529. str = null;
  530. }
  531. return str;
  532. }
  533. function applyDefs(defs, defsUsePending) {
  534. for (var i = 0; i < defsUsePending.length; i++) {
  535. var item = defsUsePending[i];
  536. item[0].style[item[1]] = defs[item[2]];
  537. }
  538. }
  539. var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;
  540. function splitNumberSequence(rawStr) {
  541. return rawStr.match(numberReg) || [];
  542. }
  543. var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.eE,]*)\)/g;
  544. var DEGREE_TO_ANGLE = Math.PI / 180;
  545. function parseTransformAttribute(xmlNode, node) {
  546. var transform = xmlNode.getAttribute('transform');
  547. if (transform) {
  548. transform = transform.replace(/,/g, ' ');
  549. var transformOps_1 = [];
  550. var mt = null;
  551. transform.replace(transformRegex, function (str, type, value) {
  552. transformOps_1.push(type, value);
  553. return '';
  554. });
  555. for (var i = transformOps_1.length - 1; i > 0; i -= 2) {
  556. var value = transformOps_1[i];
  557. var type = transformOps_1[i - 1];
  558. var valueArr = splitNumberSequence(value);
  559. mt = mt || matrix.create();
  560. switch (type) {
  561. case 'translate':
  562. matrix.translate(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || '0')]);
  563. break;
  564. case 'scale':
  565. matrix.scale(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || valueArr[0])]);
  566. break;
  567. case 'rotate':
  568. matrix.rotate(mt, mt, -parseFloat(valueArr[0]) * DEGREE_TO_ANGLE, [
  569. parseFloat(valueArr[1] || '0'),
  570. parseFloat(valueArr[2] || '0')
  571. ]);
  572. break;
  573. case 'skewX':
  574. var sx = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE);
  575. matrix.mul(mt, [1, 0, sx, 1, 0, 0], mt);
  576. break;
  577. case 'skewY':
  578. var sy = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE);
  579. matrix.mul(mt, [1, sy, 0, 1, 0, 0], mt);
  580. break;
  581. case 'matrix':
  582. mt[0] = parseFloat(valueArr[0]);
  583. mt[1] = parseFloat(valueArr[1]);
  584. mt[2] = parseFloat(valueArr[2]);
  585. mt[3] = parseFloat(valueArr[3]);
  586. mt[4] = parseFloat(valueArr[4]);
  587. mt[5] = parseFloat(valueArr[5]);
  588. break;
  589. }
  590. }
  591. node.setLocalTransform(mt);
  592. }
  593. }
  594. var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g;
  595. function parseInlineStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
  596. var style = xmlNode.getAttribute('style');
  597. if (!style) {
  598. return;
  599. }
  600. styleRegex.lastIndex = 0;
  601. var styleRegResult;
  602. while ((styleRegResult = styleRegex.exec(style)) != null) {
  603. var svgStlAttr = styleRegResult[1];
  604. var zrInheritableStlAttr = hasOwn(INHERITABLE_STYLE_ATTRIBUTES_MAP, svgStlAttr)
  605. ? INHERITABLE_STYLE_ATTRIBUTES_MAP[svgStlAttr]
  606. : null;
  607. if (zrInheritableStlAttr) {
  608. inheritableStyleResult[zrInheritableStlAttr] = styleRegResult[2];
  609. }
  610. var zrSelfStlAttr = hasOwn(SELF_STYLE_ATTRIBUTES_MAP, svgStlAttr)
  611. ? SELF_STYLE_ATTRIBUTES_MAP[svgStlAttr]
  612. : null;
  613. if (zrSelfStlAttr) {
  614. selfStyleResult[zrSelfStlAttr] = styleRegResult[2];
  615. }
  616. }
  617. }
  618. function parseAttributeStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
  619. for (var i = 0; i < INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
  620. var svgAttrName = INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS[i];
  621. var attrValue = xmlNode.getAttribute(svgAttrName);
  622. if (attrValue != null) {
  623. inheritableStyleResult[INHERITABLE_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
  624. }
  625. }
  626. for (var i = 0; i < SELF_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
  627. var svgAttrName = SELF_STYLE_ATTRIBUTES_MAP_KEYS[i];
  628. var attrValue = xmlNode.getAttribute(svgAttrName);
  629. if (attrValue != null) {
  630. selfStyleResult[SELF_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
  631. }
  632. }
  633. }
  634. export function makeViewBoxTransform(viewBoxRect, boundingRect) {
  635. var scaleX = boundingRect.width / viewBoxRect.width;
  636. var scaleY = boundingRect.height / viewBoxRect.height;
  637. var scale = Math.min(scaleX, scaleY);
  638. return {
  639. scale: scale,
  640. x: -(viewBoxRect.x + viewBoxRect.width / 2) * scale + (boundingRect.x + boundingRect.width / 2),
  641. y: -(viewBoxRect.y + viewBoxRect.height / 2) * scale + (boundingRect.y + boundingRect.height / 2)
  642. };
  643. }
  644. export function parseSVG(xml, opt) {
  645. var parser = new SVGParser();
  646. return parser.parse(xml, opt);
  647. }
  648. export { parseXML };