SvgExporter.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-draw-engine-SvgExporter'>/**
  19. </span> * A utility class for exporting a {@link Ext.draw.Surface Surface} to a string
  20. * that may be saved or used for processing on the server.
  21. *
  22. * @singleton
  23. */
  24. Ext.define('Ext.draw.engine.SvgExporter', function(){
  25. var commaRe = /,/g,
  26. fontRegex = /(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)\s('*.*'*)/,
  27. rgbColorRe = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g,
  28. rgbaColorRe = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,([\d\.]+)\)/g,
  29. surface, len, width, height,
  30. init = function(s){
  31. surface = s;
  32. len = surface.length;
  33. width = surface.width;
  34. height = surface.height;
  35. },
  36. spriteProcessor = {
  37. path: function(sprite){
  38. var attr = sprite.attr,
  39. path = attr.path,
  40. pathString = '',
  41. props, p, pLen;
  42. if (Ext.isArray(path[0])) {
  43. pLen = path.length;
  44. for (p = 0; p &lt; pLen; p++) {
  45. pathString += path[p].join(' ');
  46. }
  47. } else if (Ext.isArray(path)) {
  48. pathString = path.join(' ');
  49. } else {
  50. pathString = path.replace(commaRe,' ');
  51. }
  52. props = toPropertyString({
  53. d: pathString,
  54. fill: attr.fill || 'none',
  55. stroke: attr.stroke,
  56. 'fill-opacity': attr.opacity,
  57. 'stroke-width': attr['stroke-width'],
  58. 'stroke-opacity': attr['stroke-opacity'],
  59. &quot;z-index&quot;: attr.zIndex,
  60. transform: sprite.matrix.toSvg()
  61. });
  62. return '&lt;path ' + props + '/&gt;';
  63. },
  64. text: function(sprite){
  65. // TODO
  66. // implement multi line support (@see Svg.js tuneText)
  67. var attr = sprite.attr,
  68. match = fontRegex.exec(attr.font),
  69. size = (match &amp;&amp; match[1]) || &quot;12&quot;,
  70. // default font family is Arial
  71. family = (match &amp;&amp; match[3]) || 'Arial',
  72. text = attr.text,
  73. factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4,
  74. tspanString = '',
  75. props;
  76. sprite.getBBox();
  77. tspanString += '&lt;tspan x=&quot;' + (attr.x || '') + '&quot; dy=&quot;';
  78. tspanString += (size/factor)+'&quot;&gt;';
  79. tspanString += Ext.htmlEncode(text) + '&lt;/tspan&gt;';
  80. props = toPropertyString({
  81. x: attr.x,
  82. y: attr.y,
  83. 'font-size': size,
  84. 'font-family': family,
  85. 'font-weight': attr['font-weight'],
  86. 'text-anchor': attr['text-anchor'],
  87. // if no fill property is set it will be black
  88. fill: attr.fill || '#000',
  89. 'fill-opacity': attr.opacity,
  90. transform: sprite.matrix.toSvg()
  91. });
  92. return '&lt;text '+ props + '&gt;' + tspanString + '&lt;/text&gt;';
  93. },
  94. rect: function(sprite){
  95. var attr = sprite.attr,
  96. props = toPropertyString({
  97. x: attr.x,
  98. y: attr.y,
  99. rx: attr.rx,
  100. ry: attr.ry,
  101. width: attr.width,
  102. height: attr.height,
  103. fill: attr.fill || 'none',
  104. 'fill-opacity': attr.opacity,
  105. stroke: attr.stroke,
  106. 'stroke-opacity': attr['stroke-opacity'],
  107. 'stroke-width':attr['stroke-width'],
  108. transform: sprite.matrix &amp;&amp; sprite.matrix.toSvg()
  109. });
  110. return '&lt;rect ' + props + '/&gt;';
  111. },
  112. circle: function(sprite){
  113. var attr = sprite.attr,
  114. props = toPropertyString({
  115. cx: attr.x,
  116. cy: attr.y,
  117. r: attr.radius,
  118. fill: attr.translation.fill || attr.fill || 'none',
  119. 'fill-opacity': attr.opacity,
  120. stroke: attr.stroke,
  121. 'stroke-opacity': attr['stroke-opacity'],
  122. 'stroke-width':attr['stroke-width'],
  123. transform: sprite.matrix.toSvg()
  124. });
  125. return '&lt;circle ' + props + ' /&gt;';
  126. },
  127. image: function(sprite){
  128. var attr = sprite.attr,
  129. props = toPropertyString({
  130. x: attr.x - (attr.width/2 &gt;&gt; 0),
  131. y: attr.y - (attr.height/2 &gt;&gt; 0),
  132. width: attr.width,
  133. height: attr.height,
  134. 'xlink:href': attr.src,
  135. transform: sprite.matrix.toSvg()
  136. });
  137. return '&lt;image ' + props + ' /&gt;';
  138. }
  139. },
  140. svgHeader = function(){
  141. var svg = '&lt;?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;';
  142. svg += '&lt;!DOCTYPE svg PUBLIC &quot;-//W3C//DTD SVG 1.1//EN&quot; &quot;http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd&quot;&gt;';
  143. return svg;
  144. },
  145. svgContent = function(){
  146. var svg = '&lt;svg width=&quot;'+width+'px&quot; height=&quot;'+height+'px&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot; version=&quot;1.1&quot;&gt;',
  147. defs = '', item, itemsLen, items, gradient,
  148. getSvgString, colorstops, stop,
  149. coll, keys, colls, k, kLen, key, collI, i, j, stopsLen, sortedItems, za, zb;
  150. items = surface.items.items;
  151. itemsLen = items.length;
  152. getSvgString = function(node){
  153. var childs = node.childNodes,
  154. childLength = childs.length,
  155. i = 0,
  156. attrLength,
  157. j,
  158. svgString = '', child, attr, tagName, attrItem;
  159. for(; i &lt; childLength; i++){
  160. child = childs[i];
  161. attr = child.attributes;
  162. tagName = child.tagName;
  163. svgString += '&lt;' +tagName;
  164. for(j = 0, attrLength = attr.length; j &lt; attrLength; j++){
  165. attrItem = attr.item(j);
  166. svgString += ' '+attrItem.name+'=&quot;'+attrItem.value+'&quot;';
  167. }
  168. svgString += '&gt;';
  169. if(child.childNodes.length &gt; 0){
  170. svgString += getSvgString(child);
  171. }
  172. svgString += '&lt;/' + tagName + '&gt;';
  173. }
  174. return svgString;
  175. };
  176. if(surface.getDefs){
  177. defs = getSvgString(surface.getDefs());
  178. }else{
  179. // IE
  180. coll = surface.gradientsColl;
  181. if (coll) {
  182. keys = coll.keys;
  183. colls = coll.items;
  184. k = 0;
  185. kLen = keys.length;
  186. }
  187. for (; k &lt; kLen; k++) {
  188. key = keys[k];
  189. collI = colls[k];
  190. gradient = surface.gradientsColl.getByKey(key);
  191. defs += '&lt;linearGradient id=&quot;' + key + '&quot; x1=&quot;0&quot; y1=&quot;0&quot; x2=&quot;1&quot; y2=&quot;1&quot;&gt;';
  192. var color = gradient.colors.replace(rgbColorRe, 'rgb($1|$2|$3)');
  193. color = color.replace(rgbaColorRe, 'rgba($1|$2|$3|$4)')
  194. colorstops = color.split(',');
  195. for(i=0, stopsLen = colorstops.length; i &lt; stopsLen; i++){
  196. stop = colorstops[i].split(' ');
  197. color = Ext.draw.Color.fromString(stop[1].replace(/\|/g,','));
  198. defs += '&lt;stop offset=&quot;'+stop[0]+'&quot; stop-color=&quot;' + color.toString() + '&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;';
  199. }
  200. defs += '&lt;/linearGradient&gt;';
  201. }
  202. }
  203. svg += '&lt;defs&gt;' + defs + '&lt;/defs&gt;';
  204. // thats the background rectangle
  205. svg += spriteProcessor.rect({
  206. attr: {
  207. width: '100%',
  208. height: '100%',
  209. fill: '#fff',
  210. stroke: 'none',
  211. opacity: '0'
  212. }
  213. });
  214. // Sort the items (stable sort guaranteed)
  215. sortedItems = new Array(itemsLen);
  216. for(i = 0; i &lt; itemsLen; i++){
  217. sortedItems[i] = i;
  218. }
  219. sortedItems.sort(function (a, b) {
  220. za = items[a].attr.zIndex || 0;
  221. zb = items[b].attr.zIndex || 0;
  222. if (za == zb) {
  223. return a - b;
  224. }
  225. return za - zb;
  226. });
  227. for(i = 0; i &lt; itemsLen; i++){
  228. item = items[sortedItems[i]];
  229. if(!item.attr.hidden){
  230. svg += spriteProcessor[item.type](item);
  231. }
  232. }
  233. svg += '&lt;/svg&gt;';
  234. return svg;
  235. },
  236. toPropertyString = function(obj){
  237. var propString = '',
  238. key;
  239. for(key in obj){
  240. if(obj.hasOwnProperty(key) &amp;&amp; obj[key] != null){
  241. propString += key +'=&quot;'+ obj[key]+'&quot; ';
  242. }
  243. }
  244. return propString;
  245. };
  246. return {
  247. singleton: true,
  248. <span id='Ext-draw-engine-SvgExporter-method-generate'> /**
  249. </span> * Exports the passed surface to a SVG string representation
  250. * @param {Ext.draw.Surface} surface The surface to export
  251. * @param {Object} [config] Any configuration for the export. Currently this is
  252. * unused but may provide more options in the future
  253. * @return {String} The SVG as a string
  254. */
  255. generate: function(surface, config){
  256. config = config || {};
  257. init(surface);
  258. return svgHeader() + svgContent();
  259. }
  260. };
  261. });</pre>
  262. </body>
  263. </html>