mxVsdxCanvas2D.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /**
  2. * Copyright (c) 2006-2017, JGraph Ltd
  3. */
  4. /**
  5. * Class: mxVsdxCanvas2D
  6. *
  7. * Constructor: mxVsdxCanvas2D
  8. *
  9. * Constructs a new abstract canvas.
  10. */
  11. function mxVsdxCanvas2D(zip)
  12. {
  13. mxAbstractCanvas2D.call(this);
  14. };
  15. /**
  16. * Extends mxAbstractCanvas2D
  17. */
  18. mxUtils.extend(mxVsdxCanvas2D, mxAbstractCanvas2D);
  19. /**
  20. * Variable: textEnabled
  21. *
  22. * Specifies if text output should be enabled. Default is true.
  23. */
  24. mxVsdxCanvas2D.prototype.textEnabled = true;
  25. /**
  26. * Function: init
  27. *
  28. * Initialize the canvas for a new vsdx file.
  29. */
  30. mxVsdxCanvas2D.prototype.init = function (zip)
  31. {
  32. this.filesLoading = 0;
  33. this.zip = zip;
  34. };
  35. /**
  36. * Function: createElt
  37. *
  38. * Create a new geo section.
  39. */
  40. mxVsdxCanvas2D.prototype.createElt = function (name)
  41. {
  42. return (this.xmlDoc.createElementNS != null) ? this.xmlDoc.createElementNS(VsdxExport.prototype.XMLNS, name) :
  43. this.xmlDoc.createElement(name);
  44. };
  45. /**
  46. * Function: createGeoSec
  47. *
  48. * Create a new geo section.
  49. */
  50. mxVsdxCanvas2D.prototype.createGeoSec = function ()
  51. {
  52. if (this.geoSec != null)
  53. {
  54. this.shape.appendChild(this.geoSec);
  55. }
  56. var geoSec = this.createElt("Section");
  57. geoSec.setAttribute("N", "Geometry");
  58. geoSec.setAttribute("IX", this.geoIndex++);
  59. this.geoSec = geoSec;
  60. this.geoStepIndex = 1;
  61. this.lastX = 0;
  62. this.lastY = 0;
  63. this.lastMoveToX = 0;
  64. this.lastMoveToY = 0;
  65. };
  66. /**
  67. * Function: newShape
  68. *
  69. * Create a new shape.
  70. */
  71. mxVsdxCanvas2D.prototype.newShape = function (shape, cellState, xmlDoc)
  72. {
  73. this.geoIndex = 0;
  74. this.shape = shape;
  75. this.cellState = cellState;
  76. this.xmGeo = cellState.cell.geometry;
  77. this.xmlDoc = xmlDoc;
  78. this.geoSec = null;
  79. this.shapeImg = null;
  80. this.shapeType = "Shape";
  81. this.createGeoSec();
  82. };
  83. /**
  84. * Function: newEdge
  85. *
  86. * Create a new edge.
  87. */
  88. mxVsdxCanvas2D.prototype.newEdge = function (shape, cellState, xmlDoc)
  89. {
  90. this.shape = shape;
  91. this.cellState = cellState;
  92. this.xmGeo = cellState.cellBounds;
  93. var s = this.state;
  94. this.xmlDoc = xmlDoc;
  95. };
  96. /**
  97. * Function: endShape
  98. *
  99. * End current shape.
  100. */
  101. mxVsdxCanvas2D.prototype.endShape = function ()
  102. {
  103. if (this.shapeImg != null)
  104. {
  105. this.addForeignData(this.shapeImg.type, this.shapeImg.id);
  106. }
  107. };
  108. /**
  109. * Function: newPage
  110. *
  111. * Start a new page.
  112. */
  113. mxVsdxCanvas2D.prototype.newPage = function ()
  114. {
  115. this.images = [];
  116. };
  117. /**
  118. * Function: newPage
  119. *
  120. * Start a new page.
  121. */
  122. mxVsdxCanvas2D.prototype.getShapeType = function ()
  123. {
  124. return this.shapeType;
  125. };
  126. /**
  127. * Function: getShapeGeo
  128. *
  129. * return the current geo section.
  130. */
  131. mxVsdxCanvas2D.prototype.getShapeGeo = function ()
  132. {
  133. return this.geoSec;
  134. };
  135. /**
  136. * Function: createCellElemScaled
  137. *
  138. * Creates a cell element and scale the value.
  139. */
  140. mxVsdxCanvas2D.prototype.createCellElemScaled = function (name, val, formula)
  141. {
  142. return this.createCellElem(name, val / VsdxExport.prototype.CONVERSION_FACTOR, formula);
  143. };
  144. /**
  145. * Function: createCellElem
  146. *
  147. * Creates a cell element.
  148. */
  149. mxVsdxCanvas2D.prototype.createCellElem = function (name, val, formula)
  150. {
  151. var cell = this.createElt("Cell");
  152. cell.setAttribute("N", name);
  153. cell.setAttribute("V", val);
  154. if (formula) cell.setAttribute("F", formula);
  155. return cell;
  156. };
  157. mxVsdxCanvas2D.prototype.createRowRel = function(type, index, x, y, a, b, c , d)
  158. {
  159. var row = this.createElt("Row");
  160. row.setAttribute("T", type);
  161. row.setAttribute("IX", index);
  162. row.appendChild(this.createCellElem("X", x));
  163. row.appendChild(this.createCellElem("Y", y));
  164. if (a != null) row.appendChild(this.createCellElem("A", a));
  165. if (b != null) row.appendChild(this.createCellElem("B", b));
  166. if (c != null) row.appendChild(this.createCellElem("C", c));
  167. if (d != null) row.appendChild(this.createCellElem("D", d));
  168. return row;
  169. };
  170. /**
  171. * Function: begin
  172. *
  173. * Extends superclass to create path.
  174. */
  175. mxVsdxCanvas2D.prototype.begin = function()
  176. {
  177. if (this.geoStepIndex > 1) this.createGeoSec();
  178. };
  179. /**
  180. * Function: rect
  181. *
  182. * Private helper function to create SVG elements
  183. */
  184. mxVsdxCanvas2D.prototype.rect = function(x, y, w, h)
  185. {
  186. if (this.geoStepIndex > 1) this.createGeoSec();
  187. var s = this.state;
  188. w = w * s.scale;
  189. h = h * s.scale;
  190. var geo = this.xmGeo;
  191. x = ((x - geo.x + s.dx) * s.scale) /w;
  192. y = ((geo.height - y + geo.y - s.dy) * s.scale) /h;
  193. this.geoSec.appendChild(this.createRowRel("RelMoveTo", this.geoStepIndex++, x, y));
  194. this.geoSec.appendChild(this.createRowRel("RelLineTo", this.geoStepIndex++, x + 1, y));
  195. this.geoSec.appendChild(this.createRowRel("RelLineTo", this.geoStepIndex++, x + 1, y - 1));
  196. this.geoSec.appendChild(this.createRowRel("RelLineTo", this.geoStepIndex++, x, y - 1));
  197. this.geoSec.appendChild(this.createRowRel("RelLineTo", this.geoStepIndex++, x, y));
  198. };
  199. /**
  200. * Function: roundrect
  201. *
  202. * Private helper function to create SVG elements
  203. */
  204. mxVsdxCanvas2D.prototype.roundrect = function(x, y, w, h, dx, dy)
  205. {
  206. this.rect(x, y, w, h);
  207. //TODO this assume dx and dy are equal and only one rounding is needed
  208. this.shape.appendChild(this.createCellElemScaled("Rounding", dx));
  209. };
  210. /**
  211. * Function: ellipse
  212. *
  213. * Private helper function to create SVG elements
  214. */
  215. mxVsdxCanvas2D.prototype.ellipse = function(x, y, w, h)
  216. {
  217. if (this.geoStepIndex > 1) this.createGeoSec();
  218. var s = this.state;
  219. w = w * s.scale;
  220. h = h * s.scale;
  221. var geo = this.xmGeo;
  222. var gh = geo.height * s.scale;
  223. var gw = geo.width * s.scale;
  224. x = (x - geo.x + s.dx) * s.scale;
  225. y = gh + (-y + geo.y - s.dy) * s.scale;
  226. var hr = h/gh;
  227. var wr = w/gw;
  228. this.geoSec.appendChild(this.createRowRel("RelMoveTo", this.geoStepIndex++, x/gw, y/gh - hr * 0.5));
  229. var row = this.createRowRel("RelEllipticalArcTo", this.geoStepIndex++, x/gw, y/gh - hr * 0.5001, wr * 0.5 + x/gw, y/gh - hr, 0);
  230. row.appendChild(this.createCellElem("D", w/h, "Width/Height*"+(wr/hr)));
  231. this.geoSec.appendChild(row);
  232. };
  233. /**
  234. * Function: moveTo
  235. *
  236. * Moves the current path the given point.
  237. *
  238. * Parameters:
  239. *
  240. * x - Number that represents the x-coordinate of the point.
  241. * y - Number that represents the y-coordinate of the point.
  242. */
  243. mxVsdxCanvas2D.prototype.moveTo = function(x, y)
  244. {
  245. //MoveTo inside a geo usually produce incorrect fill
  246. if (this.geoStepIndex > 1) this.createGeoSec();
  247. this.lastMoveToX = x;
  248. this.lastMoveToY = y;
  249. this.lastX = x;
  250. this.lastY = y;
  251. var geo = this.xmGeo;
  252. var s = this.state;
  253. x = (x - geo.x + s.dx) * s.scale;
  254. y = (geo.height - y + geo.y - s.dy) * s.scale;
  255. var h = geo.height * s.scale;
  256. var w = geo.width * s.scale;
  257. this.geoSec.appendChild(this.createRowRel("RelMoveTo", this.geoStepIndex++, x/w, y/h));
  258. };
  259. /**
  260. * Function: lineTo
  261. *
  262. * Draws a line to the given coordinates.
  263. *
  264. * Parameters:
  265. *
  266. * x - Number that represents the x-coordinate of the endpoint.
  267. * y - Number that represents the y-coordinate of the endpoint.
  268. */
  269. mxVsdxCanvas2D.prototype.lineTo = function(x, y)
  270. {
  271. this.lastX = x;
  272. this.lastY = y;
  273. var geo = this.xmGeo;
  274. var s = this.state;
  275. x = (x - geo.x + s.dx) * s.scale;
  276. y = (geo.height - y + geo.y - s.dy) * s.scale;
  277. var h = geo.height * s.scale;
  278. var w = geo.width * s.scale;
  279. this.geoSec.appendChild(this.createRowRel("RelLineTo", this.geoStepIndex++, x/w, y/h));
  280. };
  281. /**
  282. * Function: quadTo
  283. *
  284. * Adds a quadratic curve to the current path.
  285. *
  286. * Parameters:
  287. *
  288. * x1 - Number that represents the x-coordinate of the control point.
  289. * y1 - Number that represents the y-coordinate of the control point.
  290. * x2 - Number that represents the x-coordinate of the endpoint.
  291. * y2 - Number that represents the y-coordinate of the endpoint.
  292. */
  293. mxVsdxCanvas2D.prototype.quadTo = function(x1, y1, x2, y2)
  294. {
  295. this.lastX = x2;
  296. this.lastY = y2;
  297. var s = this.state;
  298. var geo = this.xmGeo;
  299. var h = geo.height * s.scale;
  300. var w = geo.width * s.scale;
  301. x1 = (x1 - geo.x + s.dx) * s.scale;
  302. y1 = (geo.height - y1 + geo.y - s.dy) * s.scale;
  303. x2 = (x2 - geo.x + s.dx) * s.scale;
  304. y2 = (geo.height - y2 + geo.y - s.dy) * s.scale;
  305. x1 = x1 / w;
  306. y1 = y1 / h;
  307. x2 = x2 / w;
  308. y2 = y2 / h;
  309. this.geoSec.appendChild(this.createRowRel("RelQuadBezTo", this.geoStepIndex++, x2, y2, x1, y1));
  310. };
  311. /**
  312. * Function: curveTo
  313. *
  314. * Adds a bezier curve to the current path.
  315. *
  316. * Parameters:
  317. *
  318. * x1 - Number that represents the x-coordinate of the first control point.
  319. * y1 - Number that represents the y-coordinate of the first control point.
  320. * x2 - Number that represents the x-coordinate of the second control point.
  321. * y2 - Number that represents the y-coordinate of the second control point.
  322. * x3 - Number that represents the x-coordinate of the endpoint.
  323. * y3 - Number that represents the y-coordinate of the endpoint.
  324. */
  325. mxVsdxCanvas2D.prototype.curveTo = function(x1, y1, x2, y2, x3, y3)
  326. {
  327. this.lastX = x3;
  328. this.lastY = y3;
  329. var s = this.state;
  330. var geo = this.xmGeo;
  331. var h = geo.height * s.scale;
  332. var w = geo.width * s.scale;
  333. x1 = (x1 - geo.x + s.dx) * s.scale;
  334. y1 = (geo.height - y1 + geo.y - s.dy) * s.scale;
  335. x2 = (x2 - geo.x + s.dx) * s.scale;
  336. y2 = (geo.height - y2 + geo.y - s.dy) * s.scale;
  337. x3 = (x3 - geo.x + s.dx) * s.scale;
  338. y3 = (geo.height - y3 + geo.y - s.dy) * s.scale;
  339. x1 = x1 / w;
  340. y1 = y1 / h;
  341. x2 = x2 / w;
  342. y2 = y2 / h;
  343. x3 = x3 / w;
  344. y3 = y3 / h;
  345. this.geoSec.appendChild(this.createRowRel("RelCubBezTo", this.geoStepIndex++, x3, y3, x1, y1, x2, y2));
  346. };
  347. /**
  348. * Function: close
  349. *
  350. * Closes the current path.
  351. */
  352. mxVsdxCanvas2D.prototype.close = function()
  353. {
  354. //Closing with a line if last point != last MoveTo point
  355. if (this.lastMoveToX != this.lastX || this.lastMoveToY != this.lastY)
  356. this.lineTo(this.lastMoveToX, this.lastMoveToY);
  357. };
  358. /**
  359. * Function: addForeignData
  360. *
  361. * Add ForeignData to current shape using last image in the images array
  362. */
  363. mxVsdxCanvas2D.prototype.addForeignData = function(type, index)
  364. {
  365. var foreignData = this.createElt("ForeignData");
  366. foreignData.setAttribute("ForeignType", "Bitmap");
  367. type = type.toUpperCase();
  368. if (type != "BMP")
  369. foreignData.setAttribute("CompressionType", type);
  370. var rel = this.createElt("Rel");
  371. rel.setAttribute("r:id", "rId" + index);
  372. foreignData.appendChild(rel);
  373. this.shape.appendChild(foreignData);
  374. this.shapeType = "Foreign";
  375. };
  376. /**
  377. * Function: image
  378. *
  379. * Add image to vsdx file as a media (Foreign Object)
  380. */
  381. mxVsdxCanvas2D.prototype.image = function(x, y, w, h, src, aspect, flipH, flipV)
  382. {
  383. //TODO image reusing, if the same image is used more than once, reuse it. Applicable for URLs specifically (but can also be applied to embedded ones)
  384. var imgName = "image" + (this.images.length + 1) + ".";
  385. var type;
  386. if (src.indexOf("data:") == 0)
  387. {
  388. var p = src.indexOf("base64,");
  389. var base64 = src.substring(p + 7); //7 is the length of "base64,"
  390. type = src.substring(11, p-1); //5 is the length of "data:image/"
  391. imgName += type;
  392. this.zip.file("visio/media/" + imgName, base64, {base64: true});
  393. }
  394. else if (window.XMLHttpRequest) //URL src, fetch it
  395. {
  396. src = this.converter.convert(src);
  397. this.filesLoading++;
  398. var that = this;
  399. var p = src.lastIndexOf(".");
  400. type = src.substring(p+1);
  401. imgName += type;
  402. //The old browsers binary workaround doesn't work with jszip and converting to base64 encoding doesn't work also
  403. var xhr = new XMLHttpRequest();
  404. xhr.open('GET', src, true);
  405. xhr.responseType = 'arraybuffer';
  406. xhr.onreadystatechange = function(e)
  407. {
  408. if (this.readyState == 4)
  409. {
  410. if (this.status == 200)
  411. {
  412. that.zip.file("visio/media/" + imgName, this.response);
  413. }
  414. that.filesLoading--;
  415. }
  416. };
  417. xhr.send();
  418. }
  419. this.images.push(imgName);
  420. //TODO can a shape has more than one image?
  421. //We add one to the id as rId1 is reserved for the edges master
  422. this.shapeImg = {type: type, id: this.images.length + 1};
  423. //TODO support these!
  424. aspect = (aspect != null) ? aspect : true;
  425. flipH = (flipH != null) ? flipH : false;
  426. flipV = (flipV != null) ? flipV : false;
  427. var s = this.state;
  428. w = w * s.scale;
  429. h = h * s.scale;
  430. var geo = this.xmGeo;
  431. x = (x - geo.x + s.dx) * s.scale;
  432. y = (geo.height - y + geo.y - s.dy) * s.scale;
  433. this.shape.appendChild(this.createCellElemScaled("ImgOffsetX", x));
  434. this.shape.appendChild(this.createCellElemScaled("ImgOffsetY", y - h));
  435. this.shape.appendChild(this.createCellElemScaled("ImgWidth", w));
  436. this.shape.appendChild(this.createCellElemScaled("ImgHeight", h));
  437. // var s = this.state;
  438. // x += s.dx;
  439. // y += s.dy;
  440. //
  441. // if (s.alpha < 1 || s.fillAlpha < 1)
  442. // {
  443. // node.setAttribute('opacity', s.alpha * s.fillAlpha);
  444. // }
  445. //
  446. // var tr = this.state.transform || '';
  447. //
  448. // if (flipH || flipV)
  449. // {
  450. // var sx = 1;
  451. // var sy = 1;
  452. // var dx = 0;
  453. // var dy = 0;
  454. //
  455. // if (flipH)
  456. // {
  457. // sx = -1;
  458. // dx = -w - 2 * x;
  459. // }
  460. //
  461. // if (flipV)
  462. // {
  463. // sy = -1;
  464. // dy = -h - 2 * y;
  465. // }
  466. //
  467. // // Adds image tansformation to existing transform
  468. // tr += 'scale(' + sx + ',' + sy + ')translate(' + (dx * s.scale) + ',' + (dy * s.scale) + ')';
  469. // }
  470. //
  471. // if (tr.length > 0)
  472. // {
  473. // node.setAttribute('transform', tr);
  474. // }
  475. //
  476. // if (!this.pointerEvents)
  477. // {
  478. // node.setAttribute('pointer-events', 'none');
  479. // }
  480. };
  481. /**
  482. * Function: text
  483. *
  484. * Paints the given text. Possible values for format are empty string for
  485. * plain text and html for HTML markup. Background and border color as well
  486. * as clipping is not available in plain text labels for VML. HTML labels
  487. * are not available as part of shapes with no foreignObject support in SVG
  488. * (eg. IE9, IE10).
  489. *
  490. * Parameters:
  491. *
  492. * x - Number that represents the x-coordinate of the text.
  493. * y - Number that represents the y-coordinate of the text.
  494. * w - Number that represents the available width for the text or 0 for automatic width.
  495. * h - Number that represents the available height for the text or 0 for automatic height.
  496. * str - String that specifies the text to be painted.
  497. * align - String that represents the horizontal alignment.
  498. * valign - String that represents the vertical alignment.
  499. * wrap - Boolean that specifies if word-wrapping is enabled. Requires w > 0.
  500. * format - Empty string for plain text or 'html' for HTML markup.
  501. * overflow - Specifies the overflow behaviour of the label. Requires w > 0 and/or h > 0.
  502. * clip - Boolean that specifies if the label should be clipped. Requires w > 0 and/or h > 0.
  503. * rotation - Number that specifies the angle of the rotation around the anchor point of the text.
  504. * dir - Optional string that specifies the text direction. Possible values are rtl and lrt.
  505. */
  506. mxVsdxCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation, dir)
  507. {
  508. var that = this;
  509. if (this.textEnabled && str != null)
  510. {
  511. if (mxUtils.isNode(str))
  512. {
  513. str = mxUtils.getOuterHtml(str);
  514. }
  515. //TODO support HTML text formatting and remaining attributes
  516. if (format == 'html')
  517. {
  518. if (mxUtils.getValue(this.cellState.style, 'nl2Br', '1') != '0')
  519. {
  520. // Removes newlines from HTML and converts breaks to newlines
  521. // to match the HTML output in plain text
  522. str = str.replace(/\n/g, '').replace(/<br\s*.?>/g, '\n');
  523. }
  524. // Removes HTML tags
  525. if (this.html2txtDiv == null)
  526. this.html2txtDiv = document.createElement('div');
  527. this.html2txtDiv.innerHTML = str;
  528. str = mxUtils.extractTextWithWhitespace(this.html2txtDiv.childNodes);
  529. }
  530. var s = this.state;
  531. var geo = this.xmGeo;
  532. var fontSize = this.cellState.style["fontSize"];
  533. var fontFamily = this.cellState.style["fontFamily"];
  534. w = w * s.scale;
  535. h = h * s.scale;
  536. var charSect = this.createElt("Section");
  537. charSect.setAttribute('N', 'Character');
  538. var text = this.createElt("Text");
  539. var rgb2hex = function (rgb){
  540. rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
  541. return (rgb && rgb.length === 4) ? "#" +
  542. ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
  543. ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
  544. ("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
  545. };
  546. var rowIndex = 0;
  547. var calcW = 0, calcH = 0, newLineH = 0;
  548. var createTextRow = function(fontColor, fontSize, fontFamily, charSect, textEl, txt)
  549. {
  550. var strRect = mxUtils.getSizeForString(txt, fontSize, fontFamily, wrap? w : null);
  551. calcW = Math.max(calcW, strRect.width);
  552. calcH += strRect.height + newLineH;
  553. newLineH = 6;
  554. var charRow = that.createElt("Row");
  555. charRow.setAttribute('IX', rowIndex);
  556. if (fontColor) charRow.appendChild(that.createCellElem("Color", fontColor));
  557. if (fontSize) charRow.appendChild(that.createCellElemScaled("Size", fontSize * 0.97)); //the magic number 0.97 is needed such that text do not overflow
  558. if (fontFamily) charRow.appendChild(that.createCellElem("Font", fontFamily));
  559. charRow.appendChild(that.createCellElem("Case", "0"));
  560. charRow.appendChild(that.createCellElem("Pos", "0"));
  561. charRow.appendChild(that.createCellElem("FontScale", "1"));
  562. charRow.appendChild(that.createCellElem("Letterspace", "0"));
  563. charSect.appendChild(charRow);
  564. var cp = that.createElt("cp");
  565. cp.setAttribute('IX', rowIndex++);
  566. textEl.appendChild(cp);
  567. var txtNode = that.xmlDoc.createTextNode(txt+"\n");
  568. textEl.appendChild(txtNode);
  569. };
  570. var processNodeChildren = function(ch, fontSize, fontFamily)
  571. {
  572. for (var i=0; i<ch.length; i++)
  573. {
  574. if (ch[i].nodeType == 3)
  575. { //#text
  576. var fontColor = that.cellState.style["fontColor"];
  577. createTextRow(fontColor, fontSize, fontFamily, charSect, text, ch[i].textContent);
  578. }
  579. else if (ch[i].nodeType == 1)
  580. { //element
  581. var chLen = ch[i].childNodes.length;
  582. if (chLen > 0 && !(chLen == 1 && ch[i].childNodes[0].nodeType == 3))
  583. {
  584. processNodeChildren(ch[i].childNodes, fontSize, fontFamily);
  585. }
  586. else
  587. {
  588. var style = window.getComputedStyle(ch[i], null);
  589. var fontColor = rgb2hex(style.getPropertyValue('color'));
  590. var fontSize = style.getPropertyValue('font-size');
  591. if (fontSize)
  592. {
  593. fontSize = parseFloat(fontSize);
  594. }
  595. var fontFamily = style.getPropertyValue('font-family');
  596. if (fontFamily)
  597. {
  598. fontFamily = fontFamily.replace(/"/g, ''); //remove quotes
  599. }
  600. createTextRow(fontColor, fontSize, fontFamily, charSect, text, ch[i].textContent);
  601. }
  602. }
  603. }
  604. };
  605. if (format == 'html' && mxClient.IS_SVG)
  606. {
  607. //Get the actual HTML label node
  608. var ch = this.cellState.text.node.getElementsByTagName('div')[mxClient.NO_FO? 0 : 1].childNodes;
  609. processNodeChildren(ch, fontSize, fontFamily);
  610. }
  611. else
  612. {
  613. //If it is not HTML or SVG, we fall back to removing html format
  614. var fontColor = this.cellState.style["fontColor"];
  615. createTextRow(fontColor, fontSize, fontFamily, charSect, text, str);
  616. }
  617. var wShift = 0;
  618. var hShift = 0;
  619. switch(align)
  620. {
  621. case "right": wShift = calcW/2; break;
  622. case "center": wShift = 0; break;
  623. case "left": wShift = -calcW/2; break;
  624. }
  625. switch(valign)
  626. {
  627. case "top": hShift = calcH/2; break;
  628. case "middle": hShift = 0; break;
  629. case "bottom": hShift = -calcH/2; break;
  630. }
  631. h = Math.max(h, calcH);
  632. w = Math.max(w, calcW);
  633. x = (x - geo.x + s.dx) * s.scale;
  634. y = (geo.height - y + geo.y - s.dy) * s.scale;
  635. var hw = w/2, hh = h/2;
  636. this.shape.appendChild(this.createCellElemScaled("TxtPinX", x));
  637. this.shape.appendChild(this.createCellElemScaled("TxtPinY", y));
  638. this.shape.appendChild(this.createCellElemScaled("TxtWidth", w));
  639. this.shape.appendChild(this.createCellElemScaled("TxtHeight", h));
  640. this.shape.appendChild(this.createCellElemScaled("TxtLocPinX", hw + wShift));
  641. this.shape.appendChild(this.createCellElemScaled("TxtLocPinY", hh + hShift));
  642. if (rotation != 0)
  643. this.shape.appendChild(this.createCellElemScaled("TxtAngle", (360 - rotation) * Math.PI / 180));
  644. this.shape.appendChild(charSect);
  645. this.shape.appendChild(text);
  646. // if (overflow != null)
  647. // {
  648. // elem.setAttribute('overflow', overflow);
  649. // }
  650. //
  651. // if (clip != null)
  652. // {
  653. // elem.setAttribute('clip', (clip) ? '1' : '0');
  654. // }
  655. //
  656. // if (dir != null)
  657. // {
  658. // elem.setAttribute('dir', dir);
  659. // }
  660. }
  661. };
  662. /**
  663. * Function: rotate
  664. *
  665. * Sets the rotation of the canvas. Note that rotation cannot be concatenated.
  666. */
  667. mxVsdxCanvas2D.prototype.rotate = function(theta, flipH, flipV, cx, cy)
  668. {
  669. //Vsdx has flipX/Y support separate from rotation
  670. if (theta != 0)
  671. {
  672. var s = this.state;
  673. cx += s.dx;
  674. cy += s.dy;
  675. cx *= s.scale;
  676. cy *= s.scale;
  677. this.shape.appendChild(this.createCellElem("Angle", (360 - theta) * Math.PI / 180));
  678. s.rotation = s.rotation + theta;
  679. s.rotationCx = cx;
  680. s.rotationCy = cy;
  681. }
  682. };
  683. /**
  684. * Function: stroke
  685. *
  686. * Paints the outline of the current drawing buffer.
  687. */
  688. mxVsdxCanvas2D.prototype.stroke = function()
  689. {
  690. this.geoSec.appendChild(this.createCellElem("NoFill", "1"));
  691. this.geoSec.appendChild(this.createCellElem("NoLine", "0"));
  692. };
  693. /**
  694. * Function: fill
  695. *
  696. * Fills the current drawing buffer.
  697. */
  698. mxVsdxCanvas2D.prototype.fill = function()
  699. {
  700. this.geoSec.appendChild(this.createCellElem("NoFill", "0"));
  701. this.geoSec.appendChild(this.createCellElem("NoLine", "1"));
  702. };
  703. /**
  704. * Function: fillAndStroke
  705. *
  706. * Fills the current drawing buffer and its outline.
  707. */
  708. mxVsdxCanvas2D.prototype.fillAndStroke = function()
  709. {
  710. this.geoSec.appendChild(this.createCellElem("NoFill", "0"));
  711. this.geoSec.appendChild(this.createCellElem("NoLine", "0"));
  712. };