otsdaq_utilities  v2_05_02_indev
saveSvgAsPng.js
1 (function() {
2  var out$ = typeof exports != 'undefined' && exports || this;
3 
4  var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
5 
6  function isExternal(url) {
7  return url && url.lastIndexOf('http',0) == 0 && url.lastIndexOf(window.location.host) == -1;
8  }
9 
10  function inlineImages(el, callback) {
11  var images = el.querySelectorAll('image');
12  var left = images.length;
13  if (left == 0) {
14  callback();
15  }
16  for (var i = 0; i < images.length; i++) {
17  (function(image) {
18  var href = image.getAttributeNS("http://www.w3.org/1999/xlink", "href");
19  if (href) {
20  if (isExternal(href.value)) {
21  console.warn("Cannot render embedded images linking to external hosts: "+href.value);
22  return;
23  }
24  }
25  var canvas = document.createElement('canvas');
26  var ctx = canvas.getContext('2d');
27  var img = new Image();
28  href = href || image.getAttribute('href');
29  img.src = href;
30  img.onload = function() {
31  canvas.width = img.width;
32  canvas.height = img.height;
33  ctx.drawImage(img, 0, 0);
34  image.setAttributeNS("http://www.w3.org/1999/xlink", "href", canvas.toDataURL('image/png'));
35  left--;
36  if (left == 0) {
37  callback();
38  }
39  }
40  img.onerror = function() {
41  console.log("Could not load "+href);
42  left--;
43  if (left == 0) {
44  callback();
45  }
46  }
47  })(images[i]);
48  }
49  }
50 
51  function styles(el, selectorRemap) {
52  var css = "";
53  var sheets = document.styleSheets;
54  for (var i = 0; i < sheets.length; i++) {
55  try {
56  var rules = sheets[i].cssRules;
57  } catch (e) {
58  console.warn("Stylesheet could not be loaded: "+sheets[i].href);
59  continue;
60  }
61 
62  if (rules != null) {
63  for (var j = 0; j < rules.length; j++) {
64  var rule = rules[j];
65  if (typeof(rule.style) != "undefined") {
66  var match = null;
67  try {
68  match = el.querySelector(rule.selectorText);
69  } catch(err) {
70  console.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
71  }
72  if (match) {
73  var selector = selectorRemap ? selectorRemap(rule.selectorText) : rule.selectorText;
74  css += selector + " { " + rule.style.cssText + " }\n";
75  } else if(rule.cssText.match(/^@font-face/)) {
76  css += rule.cssText + '\n';
77  }
78  }
79  }
80  }
81  }
82  return css;
83  }
84 
85  function getDimension(el, clone, dim) {
86  var v = (el.viewBox.baseVal && el.viewBox.baseVal[dim]) ||
87  (clone.getAttribute(dim) !== null && !clone.getAttribute(dim).match(/%$/) && parseInt(clone.getAttribute(dim))) ||
88  el.getBoundingClientRect()[dim] ||
89  parseInt(clone.style[dim]) ||
90  parseInt(window.getComputedStyle(el).getPropertyValue(dim));
91  return (typeof v === 'undefined' || v === null || isNaN(parseFloat(v))) ? 0 : v;
92  }
93 
94  function reEncode(data) {
95  data = encodeURIComponent(data);
96  data = data.replace(/%([0-9A-F]{2})/g, function(match, p1) {
97  var c = String.fromCharCode('0x'+p1);
98  return c === '%' ? '%25' : c;
99  });
100  return decodeURIComponent(data);
101  }
102 
103  out$.svgAsDataUri = function(el, options, cb) {
104  options = options || {};
105  options.scale = options.scale || 1;
106  var xmlns = "http://www.w3.org/2000/xmlns/";
107 
108  inlineImages(el, function() {
109  var outer = document.createElement("div");
110  var clone = el.cloneNode(true);
111  var width, height;
112  if(el.tagName == 'svg') {
113  width = options.width || getDimension(el, clone, 'width');
114  height = options.height || getDimension(el, clone, 'height');
115  } else if(el.getBBox) {
116  var box = el.getBBox();
117  width = box.x + box.width;
118  height = box.y + box.height;
119  clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, ''));
120 
121  var svg = document.createElementNS('http://www.w3.org/2000/svg','svg')
122  svg.appendChild(clone)
123  clone = svg;
124  } else {
125  console.error('Attempted to render non-SVG element', el);
126  return;
127  }
128 
129  clone.setAttribute("version", "1.1");
130  clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg");
131  clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink");
132  clone.setAttribute("width", width * options.scale);
133  clone.setAttribute("height", height * options.scale);
134  clone.setAttribute("viewBox", [
135  options.left || 0,
136  options.top || 0,
137  width,
138  height
139  ].join(" "));
140 
141  outer.appendChild(clone);
142 
143  var css = styles(el, options.selectorRemap);
144  var s = document.createElement('style');
145  s.setAttribute('type', 'text/css');
146  s.innerHTML = "<![CDATA[\n" + css + "\n]]>";
147  var defs = document.createElement('defs');
148  defs.appendChild(s);
149  clone.insertBefore(defs, clone.firstChild);
150 
151  var svg = doctype + outer.innerHTML;
152  var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(svg));
153  if (cb) {
154  cb(uri);
155  }
156  });
157  }
158 
159  out$.svgAsPngUri = function(el, options, cb) {
160  out$.svgAsDataUri(el, options, function(uri) {
161  var image = new Image();
162  image.onload = function() {
163  var canvas = document.createElement('canvas');
164  canvas.width = image.width;
165  canvas.height = image.height;
166  var context = canvas.getContext('2d');
167  if(options && options.backgroundColor){
168  context.fillStyle = options.backgroundColor;
169  context.fillRect(0, 0, canvas.width, canvas.height);
170  }
171  context.drawImage(image, 0, 0);
172  var a = document.createElement('a');
173  cb(canvas.toDataURL('image/png'));
174  }
175  image.src = uri;
176  });
177  }
178 
179  out$.saveSvgAsPng = function(el, name, options) {
180  options = options || {};
181  out$.svgAsPngUri(el, options, function(uri) {
182  var a = document.createElement('a');
183  a.download = name;
184  a.href = uri;
185  document.body.appendChild(a);
186  a.addEventListener("click", function(e) {
187  a.parentNode.removeChild(a);
188  });
189  a.click();
190  });
191  }
192 })();