1 | var mime = require('mime-types');
|
2 | var DOMParser = require('xmldom').DOMParser;
|
3 | var XMLparser = new DOMParser();
|
4 | var fastXmlParser = require('fast-xml-parser');
|
5 | var request = require('request');
|
6 |
|
7 | var deasync = require('deasync');
|
8 | var xmlNs = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>';
|
9 | var vm = require('vm2');
|
10 | var fs = require('fs');
|
11 | var gm = require('gm').subClass({imageMagick: true});
|
12 | var spawnSync = require('child_process').spawnSync;
|
13 | var spawn = require('child_process').spawn;
|
14 | var execSync = require('child_process').execSync;
|
15 | var extend = require('util')._extend;
|
16 | var opentype = require('opentype.js');
|
17 | var async = require('async');
|
18 | var defaultFontsDir = __dirname + '/../fonts';
|
19 | var promiseLibrary = typeof global.Promise === 'function' ? global.Promise : require('es6-promise').Promise;
|
20 | var isWin = /^win/.test(process.platform);
|
21 | var defaultParallelsTasks = 100;
|
22 | var convertQueue = async.queue(workerForConverting, defaultParallelsTasks);
|
23 | var fonts = {};
|
24 | var defaultBounds = {left: 0, top: 0, width: 1024, height: 768};
|
25 | var vectorImageParams = ['background', 'border', 'blur', 'contrast', 'crop', 'frame', 'gamma', 'monochrome', 'negative', 'noise', 'quality'];
|
26 | var childProcess;
|
27 |
|
28 | childProcess = spawn(isWin ? 'magick' : 'convert');
|
29 | childProcess.on('error', function(err) {
|
30 | if (err.code === 'ENOENT') {
|
31 | console.warn('Warning! Please install imagemagick utility. (https://www.imagemagick.org/script/binary-releases.php)');
|
32 | }
|
33 | });
|
34 | childProcess.stdin.on('error', function(err) {});
|
35 | childProcess.stdin.write('');
|
36 | childProcess.stdin.end();
|
37 |
|
38 | childProcess = spawn('rsvg-convert');
|
39 | childProcess.on('error', function(err) {
|
40 | if (err.code === 'ENOENT') {
|
41 | console.warn('Warning! Please install rsvglib utility. (https://github.com/AnyChart/AnyChart-NodeJS)');
|
42 | }
|
43 | });
|
44 | childProcess.stdin.on('error', function(err) {});
|
45 | childProcess.stdin.write('');
|
46 | childProcess.stdin.end();
|
47 |
|
48 | var uuidv4 = require('uuid/v4');
|
49 | var JSDOM = require('jsdom').JSDOM;
|
50 |
|
51 | var iframeDoc = null,
|
52 | rootDoc = null,
|
53 | iframes = {},
|
54 | anychart = typeof anychart === 'undefined' ? anychart : void 0;
|
55 |
|
56 | if (anychart) {
|
57 | var doc = anychart.global() && anychart.global().document || createDocument();
|
58 | setAsRootDocument(doc);
|
59 | } else {
|
60 | setAsRootDocument(createDocument());
|
61 | anychart = require('anychart')(rootDoc.defaultView);
|
62 | }
|
63 |
|
64 |
|
65 | function setAsRootDocument(doc) {
|
66 | rootDoc = doc;
|
67 | var window = rootDoc.defaultView;
|
68 | window.setTimeout = function(code, delay, arguments) {};
|
69 | window.setInterval = function(code, delay, arguments) {};
|
70 | anychartify(rootDoc);
|
71 |
|
72 | return rootDoc
|
73 | }
|
74 |
|
75 | function createDocument() {
|
76 | return (new JSDOM('', {runScripts: 'dangerously'})).window.document;
|
77 | }
|
78 |
|
79 | function createSandbox(containerTd) {
|
80 | var iframeId = 'iframe_' + uuidv4();
|
81 | var iframe = rootDoc.createElement('iframe');
|
82 | iframes[iframeId] = iframe;
|
83 | iframe.setAttribute('id', iframeId);
|
84 | rootDoc.body.appendChild(iframe);
|
85 | iframeDoc = iframe.contentDocument;
|
86 | var div = iframeDoc.createElement('div');
|
87 | div.setAttribute('id', containerTd);
|
88 | iframeDoc.body.appendChild(div);
|
89 |
|
90 | return iframeId;
|
91 | }
|
92 |
|
93 | function clearSandbox(iframeId) {
|
94 | var iFrame = rootDoc.getElementById(iframeId);
|
95 | if (!iframeId || !iFrame) return;
|
96 | iframeDoc = iFrame.contentDocument;
|
97 | var iframeWindow = iframeDoc.defaultView;
|
98 | iframeWindow.anychart = null;
|
99 | iframeWindow.acgraph = null;
|
100 | iframeDoc.createElementNS = null;
|
101 | iframeDoc.body.innerHTML = '';
|
102 | iFrame.contentDocument = null;
|
103 | rootDoc.body.removeChild(iFrame);
|
104 | delete iframes[iframeId];
|
105 | }
|
106 |
|
107 | function isPercent(value) {
|
108 | if (value == null)
|
109 | return false;
|
110 | var l = value.length - 1;
|
111 | return (typeof value == 'string') && l >= 0 && value.indexOf('%', l) == l;
|
112 | }
|
113 |
|
114 | function isDef(value) {
|
115 | return value != void 0;
|
116 | }
|
117 |
|
118 | function isVectorFormat(type) {
|
119 | return type === 'pdf' || type === 'ps' || type === 'svg';
|
120 | }
|
121 |
|
122 | function applyImageParams(img, params) {
|
123 | for (var i = 0, len = vectorImageParams.length; i < len; i++) {
|
124 | var paramName = vectorImageParams[i];
|
125 | var value = params[paramName];
|
126 | if (value)
|
127 | img[paramName].apply(img, Object.prototype.toString.call(value) === '[object Array]' ? value : [value]);
|
128 | }
|
129 | }
|
130 |
|
131 | function isFunction(value) {
|
132 | return typeof(value) == 'function';
|
133 | }
|
134 |
|
135 | function concurrency(count) {
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 | convertQueue.concurrency = count;
|
143 | }
|
144 |
|
145 | function getBBox() {
|
146 | var text = this.textContent;
|
147 | var fontSize = parseFloat(this.getAttribute('font-size'));
|
148 | var fontFamily = this.getAttribute('font-family');
|
149 | if (fontFamily) fontFamily = fontFamily.toLowerCase();
|
150 | var fontWeight = this.getAttribute('font-weight');
|
151 | if (fontWeight) fontWeight = fontWeight.toLowerCase();
|
152 | var fontStyle = this.getAttribute('font-style');
|
153 | if (fontStyle) fontStyle = fontStyle.toLowerCase();
|
154 |
|
155 | var fontsArr = fontFamily.split(', ');
|
156 |
|
157 | var font;
|
158 | for (var i = 0, len = fontsArr.length; i < len; i++) {
|
159 | var name = fontsArr[i] + (fontWeight == 'normal' || !isNaN(+fontWeight) ? '' : ' ' + fontWeight) + (fontStyle == 'normal' ? '' : ' ' + fontStyle);
|
160 | if (font = fonts[name])
|
161 | break;
|
162 | }
|
163 |
|
164 | if (!font)
|
165 | font = fonts['verdana'];
|
166 |
|
167 | var scale = 1 / font.unitsPerEm * fontSize;
|
168 |
|
169 | var top = -font.ascender * scale;
|
170 | var height = Math.abs(top) + Math.abs(font.descender * scale);
|
171 |
|
172 | var width = 0;
|
173 |
|
174 | font.forEachGlyph(text, 0, 0, fontSize, undefined, function(glyph, x, y, fontSize, options) {
|
175 | var metrics = glyph.getMetrics();
|
176 | metrics.xMin *= scale;
|
177 | metrics.xMax *= scale;
|
178 | metrics.leftSideBearing *= scale;
|
179 | metrics.rightSideBearing *= scale;
|
180 |
|
181 | width += Math.abs(metrics.xMax - metrics.xMin) + metrics.leftSideBearing + metrics.rightSideBearing
|
182 | });
|
183 |
|
184 | return {x: 0, y: top, width: width, height: height};
|
185 | }
|
186 |
|
187 | function anychartify(doc) {
|
188 | doc.createElementNS = function(ns, tagName) {
|
189 | var elem = doc.createElement(tagName);
|
190 | elem.getBBox = elem.getBBox || getBBox;
|
191 | return elem;
|
192 | };
|
193 | }
|
194 |
|
195 | function prepareDocumentForRender(doc) {
|
196 | anychartify(doc);
|
197 |
|
198 | var window = doc.defaultView;
|
199 | window.anychart = anychart;
|
200 | window.acgraph = anychart.graphics;
|
201 | window.isNodeJS = true;
|
202 | window.defaultBounds = defaultBounds;
|
203 | window.setTimeout = function(code, delay, arguments) {};
|
204 | window.setInterval = function(code, delay, arguments) {};
|
205 | }
|
206 |
|
207 | function getParams(args) {
|
208 | var arrLength = args.length;
|
209 | var lastArg = args[arrLength - 1];
|
210 | var callback = isFunction(lastArg) ? lastArg : null;
|
211 |
|
212 | var options = arrLength === 1 ? void 0 : callback ? arrLength > 2 ? args[arrLength - 2] : void 0: lastArg;
|
213 | var params = {};
|
214 |
|
215 | params.callback = callback;
|
216 |
|
217 | if (typeof options === 'string') {
|
218 | params.outputType = options;
|
219 | } else if (typeof options === 'object') {
|
220 | extend(params, options)
|
221 | }
|
222 |
|
223 | var target = args[0];
|
224 | if (target && !isDef(params.dataType)) {
|
225 | if (typeof target === 'string') {
|
226 | target = target.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
|
227 |
|
228 | try {
|
229 | JSON.parse(target);
|
230 | params.dataType = 'json';
|
231 | } catch (e) {
|
232 | if (fastXmlParser.validate(target)) {
|
233 | if (target.lastIndexOf('<svg') !== -1) {
|
234 | params.dataType = 'svg';
|
235 | } else {
|
236 | params.dataType = 'xml';
|
237 | }
|
238 | } else {
|
239 | params.dataType = 'javascript';
|
240 | }
|
241 | }
|
242 | } else {
|
243 | var isChart = typeof target.draw === 'function';
|
244 | var isStage = typeof target.resume === 'function';
|
245 | params.dataType = isChart ? 'chart' : isStage ? 'stage' : void 0;
|
246 | }
|
247 | }
|
248 |
|
249 | if (!params.outputType) {
|
250 | params.outputType = 'jpg';
|
251 | }
|
252 |
|
253 | if (!isDef(params.containerId)) {
|
254 | if (params.dataType === 'javascript') {
|
255 | var regex = /\.container\(('|")(.*)('|")\)/g;
|
256 | var result = regex.exec(target);
|
257 | params.containerId = result ? result[2] : 'container';
|
258 | } else {
|
259 | params.containerId = 'container';
|
260 | }
|
261 | }
|
262 |
|
263 | return params;
|
264 | }
|
265 |
|
266 | function fixSvg(svg) {
|
267 | return svg
|
268 |
|
269 | .replace(/textpath/g, 'textPath')
|
270 | .replace(/lineargradient/g, 'linearGradient')
|
271 | .replace(/radialgradient/g, 'radialGradient')
|
272 | .replace(/clippath/g, 'clipPath')
|
273 | .replace(/patternunits/g, 'patternUnits')
|
274 |
|
275 | .replace(/(id=")#/g, '$1')
|
276 | .replace(/(url\()##/g, '$1#')
|
277 |
|
278 | .replace(/aria-label=".*?"/g, '')
|
279 | }
|
280 |
|
281 | function applyResourcesToDoc(params, resources, callback) {
|
282 | var document = params.document;
|
283 | var head = document.getElementsByTagName('head')[0];
|
284 | var window = document.defaultView;
|
285 | var scripts = '';
|
286 |
|
287 | for (var i = 0, len = resources.length; i < len; i++) {
|
288 | var resource = resources[i];
|
289 | var type = resource.type;
|
290 |
|
291 | if (type == mime.contentType('css')) {
|
292 | var style = document.createElement('style');
|
293 | style.innerHTML = resource.body;
|
294 | head.appendChild(style);
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 | } else if (type == mime.contentType('js')) {
|
302 | scripts += ' ' + resource.body + ';';
|
303 | }
|
304 | }
|
305 |
|
306 | var err = null;
|
307 | try {
|
308 | var script = new vm.VM({
|
309 | timeout: 5000,
|
310 | sandbox: window
|
311 | });
|
312 | script.run(scripts);
|
313 | } catch (e) {
|
314 | console.log(e);
|
315 | err = e;
|
316 | }
|
317 |
|
318 | return callback(err, params);
|
319 | }
|
320 |
|
321 | function loadExternalResources(resources, params, callback) {
|
322 | if (Object.prototype.toString.call(resources) === '[object Array]') {
|
323 | var loadedResources = [];
|
324 | for (var i = 0, len = resources.length; i < len; i++) {
|
325 | request
|
326 | .get(resources[i], function(err, response, body) {
|
327 | if (err) {
|
328 | loadedResources.push('');
|
329 | } else {
|
330 | loadedResources.push({
|
331 | type: mime.contentType(response.headers['content-type']),
|
332 | body: body
|
333 | });
|
334 | }
|
335 |
|
336 | if (resources.length === loadedResources.length) {
|
337 | return applyResourcesToDoc(params, loadedResources, callback);
|
338 | }
|
339 | });
|
340 | }
|
341 | if (resources.length === loadedResources.length) {
|
342 | return applyResourcesToDoc(params, loadedResources, callback);
|
343 | }
|
344 | } else {
|
345 | return callback(null, params);
|
346 | }
|
347 | }
|
348 |
|
349 | function getSvgString(svgElement, width, height) {
|
350 | var svg = '';
|
351 | if (svgElement) {
|
352 | if (!width || isPercent(width))
|
353 | width = defaultBounds.width;
|
354 | if (!height || isPercent(height))
|
355 | height = defaultBounds.height;
|
356 |
|
357 | svgElement.setAttribute('width', width);
|
358 | svgElement.setAttribute('height', height);
|
359 | svg = xmlNs + svgElement.outerHTML;
|
360 | }
|
361 | return svg;
|
362 | }
|
363 |
|
364 | function getSvg(target, params, callback) {
|
365 | var dataType = params.dataType;
|
366 |
|
367 | if (dataType === 'svg') {
|
368 | return callback(null, fixSvg(target), params);
|
369 | } else {
|
370 | var svg, container, svgElement;
|
371 | var res = params.resources;
|
372 |
|
373 | var isChart = dataType === 'chart';
|
374 | var isStage = dataType === 'stage';
|
375 |
|
376 | if (!params.document && !(isChart || isStage)) {
|
377 | params.iframeId = createSandbox(params.containerId);
|
378 | params.document = iframeDoc;
|
379 | }
|
380 | if (params.document)
|
381 | prepareDocumentForRender(params.document);
|
382 |
|
383 | return loadExternalResources(res, params, function(err, params) {
|
384 | var document = params.document;
|
385 | var window = document && document.defaultView;
|
386 | var bounds, width, height;
|
387 |
|
388 | if (window)
|
389 | anychart.global(window);
|
390 |
|
391 | if (dataType === 'javascript') {
|
392 | var script = new vm.VM({
|
393 | timeout: 10000,
|
394 | sandbox: {
|
395 | anychart: window.anychart
|
396 | }
|
397 | });
|
398 | script.run(target);
|
399 |
|
400 | var svgElements = document.getElementsByTagName('svg');
|
401 | var chartToDispose = [];
|
402 | for (var i = 0, len = svgElements.length; i < len; i++) {
|
403 | svgElement = svgElements[i];
|
404 | if (!svgElement) continue;
|
405 | var id = svgElement.getAttribute('ac-id');
|
406 | var stage = anychart.graphics.getStage(id);
|
407 | if (stage) {
|
408 | var charts = stage.getCharts();
|
409 | for (var chartId in charts) {
|
410 | var chart = charts[chartId];
|
411 | bounds = chart.bounds();
|
412 | svg = getSvgString(svgElement, bounds.width(), bounds.height());
|
413 | chartToDispose.push(chart);
|
414 | }
|
415 | stage.dispose();
|
416 | }
|
417 | }
|
418 |
|
419 | for (i = 0, len = chartToDispose.length; i < len; i++) {
|
420 | chartToDispose[i].dispose();
|
421 | }
|
422 | } else {
|
423 | if (dataType === 'json') {
|
424 | target = anychart.fromJson(target);
|
425 | isChart = true;
|
426 | } else if (dataType === 'xml') {
|
427 | target = anychart.fromXml(XMLparser.parseFromString(target));
|
428 | isChart = true;
|
429 | }
|
430 | target.container(params.containerId);
|
431 |
|
432 | if (isChart || isStage) {
|
433 | if (target.animation)
|
434 | target.animation(false);
|
435 | if (target.a11y)
|
436 | target.a11y(false);
|
437 |
|
438 | container = target.container();
|
439 | if (!container) {
|
440 | if (params.document) {
|
441 | var div = params.document.createElement('div');
|
442 | div.setAttribute('id', params.containerId);
|
443 | params.document.body.appendChild(div);
|
444 | } else if (isChart) {
|
445 |
|
446 | params.iframeId = createSandbox(params.containerId);
|
447 | params.document = iframeDoc;
|
448 | prepareDocumentForRender(params.document);
|
449 | anychart.global(params.document.defaultView);
|
450 | target = anychart.fromJson(target.toJson());
|
451 | } else {
|
452 | console.warn('Warning! Cannot find context of executing. Please define \'document\' in exporting params.');
|
453 | return callback(null, '', params);
|
454 | }
|
455 | target.container(params.containerId);
|
456 | container = target.container();
|
457 | }
|
458 |
|
459 | if (isChart) {
|
460 | target.draw();
|
461 |
|
462 | bounds = target.bounds();
|
463 | width = bounds.width();
|
464 | height = bounds.height();
|
465 | } else {
|
466 | target.resume();
|
467 |
|
468 | bounds = target.getBounds();
|
469 | width = bounds.width;
|
470 | height = bounds.height;
|
471 | }
|
472 |
|
473 | svgElement = isChart ? container.getStage().domElement() : target.domElement();
|
474 | svg = getSvgString(svgElement, width, height);
|
475 |
|
476 | if (dataType === 'json' && dataType === 'xml') {
|
477 | target.dispose();
|
478 | }
|
479 | } else {
|
480 | console.warn('Warning! Wrong format of incoming data.');
|
481 | svg = '';
|
482 | }
|
483 | }
|
484 | clearSandbox(params.iframeId);
|
485 |
|
486 | return callback(null, fixSvg(svg), params);
|
487 | });
|
488 | }
|
489 | }
|
490 |
|
491 | function getAvailableProcessesCount() {
|
492 |
|
493 | var procMetrics = execSync('ulimit -u && ps ax | wc -l').toString().trim().split(/\n\s+/g);
|
494 | return procMetrics[0] - procMetrics[1];
|
495 | }
|
496 |
|
497 | function workerForConverting(task, done) {
|
498 | if (isVectorFormat(task.params.outputType)) {
|
499 | var childProcess;
|
500 | var callBackAlreadyCalled = false;
|
501 | try {
|
502 | var params = ['-f', task.params.outputType];
|
503 | if (isDef(task.params.width))
|
504 | params.push('-w', task.params.width);
|
505 | if (isDef(task.params.height))
|
506 | params.push('-h', task.params.height);
|
507 | if (isDef(task.params['aspect-ratio']) && String(task.params['aspect-ratio']).toLowerCase() != 'false')
|
508 | params.push('-a');
|
509 | if (isDef(task.params.background))
|
510 | params.push('-b', task.params.background);
|
511 |
|
512 | childProcess = spawn('rsvg-convert', params);
|
513 | var buffer;
|
514 | childProcess.stdout.on('data', function(data) {
|
515 | try {
|
516 | var prevBufferLength = (buffer ? buffer.length : 0),
|
517 | newBuffer = new Buffer(prevBufferLength + data.length);
|
518 |
|
519 | if (buffer) {
|
520 | buffer.copy(newBuffer, 0, 0);
|
521 | }
|
522 |
|
523 | data.copy(newBuffer, prevBufferLength, 0);
|
524 |
|
525 | buffer = newBuffer;
|
526 | } catch (err) {
|
527 | if (!callBackAlreadyCalled) {
|
528 | done(err, null);
|
529 | callBackAlreadyCalled = true;
|
530 | }
|
531 | }
|
532 | });
|
533 |
|
534 | childProcess.on('close', function(code, signal) {
|
535 | if (!code && !callBackAlreadyCalled) {
|
536 | done(null, buffer);
|
537 | } else {
|
538 | console.warn('Unexpected close of child process with code %s signal %s', code, signal);
|
539 | }
|
540 | });
|
541 |
|
542 | childProcess.stderr.on('data', function(data) {
|
543 | if (!callBackAlreadyCalled) {
|
544 | done(new Error(data), null);
|
545 | callBackAlreadyCalled = true;
|
546 | }
|
547 | });
|
548 |
|
549 | childProcess.on('error', function(err) {
|
550 | if (err.code === 'ENOENT') {
|
551 | console.warn('Warning! Please install librsvg package.');
|
552 | }
|
553 | if (!callBackAlreadyCalled) {
|
554 | done(err, null);
|
555 | callBackAlreadyCalled = true;
|
556 | }
|
557 | });
|
558 |
|
559 | childProcess.stdin.write(task.svg);
|
560 | childProcess.stdin.end();
|
561 | } catch (err) {
|
562 | if (!callBackAlreadyCalled) {
|
563 | done(err, null);
|
564 | callBackAlreadyCalled = true;
|
565 | }
|
566 | }
|
567 | } else {
|
568 | var img = gm(Buffer.from(task.svg, 'utf8'));
|
569 | applyImageParams(img, task.params);
|
570 | img.toBuffer(task.params.outputType, done);
|
571 |
|
572 |
|
573 |
|
574 |
|
575 |
|
576 |
|
577 |
|
578 |
|
579 |
|
580 |
|
581 |
|
582 |
|
583 |
|
584 |
|
585 |
|
586 |
|
587 |
|
588 |
|
589 |
|
590 |
|
591 |
|
592 |
|
593 |
|
594 |
|
595 |
|
596 |
|
597 |
|
598 |
|
599 |
|
600 |
|
601 |
|
602 |
|
603 |
|
604 |
|
605 |
|
606 |
|
607 |
|
608 |
|
609 |
|
610 |
|
611 |
|
612 | }
|
613 | }
|
614 |
|
615 | function loadDefaultFontsSync() {
|
616 | var fontFilesList = fs.readdirSync(defaultFontsDir);
|
617 |
|
618 | for (var i = 0, len = fontFilesList.length; i < len; i++) {
|
619 | var fileName = fontFilesList[i];
|
620 | var font = opentype.loadSync(defaultFontsDir + '/' + fileName);
|
621 | fonts[font.names.fullName.en.toLowerCase()] = font;
|
622 | }
|
623 |
|
624 | return fonts;
|
625 | }
|
626 |
|
627 | function convertSvgToImageData(svg, params, callback) {
|
628 | convertQueue.push({svg: svg, params: params}, callback);
|
629 | }
|
630 |
|
631 | function convertSvgToImageDataSync(svg, params) {
|
632 | if (isVectorFormat(params.outputType)) {
|
633 | var convertParams = ['-f', params.outputType];
|
634 | if (isDef(params.width))
|
635 | convertParams.push('-w', params.width);
|
636 | if (isDef(params.height))
|
637 | convertParams.push('-h', params.height);
|
638 | if (isDef(params['aspect-ratio']) && String(params['aspect-ratio']).toLowerCase() !== 'false')
|
639 | convertParams.push('-a');
|
640 | if (isDef(params.background))
|
641 | convertParams.push('-b', params.background);
|
642 |
|
643 | return spawnSync('rsvg-convert', convertParams, {input: svg}).stdout;
|
644 |
|
645 | } else {
|
646 |
|
647 | var done = false, data = null, error = null;
|
648 |
|
649 | var img = gm(Buffer.from(svg, 'utf8'));
|
650 | applyImageParams(img, params);
|
651 | img.toBuffer(params.outputType, function(err, buffer) {
|
652 | data = buffer;
|
653 | error = err;
|
654 | done = true;
|
655 | });
|
656 | deasync.loopWhile(function() {
|
657 | return !done;
|
658 | });
|
659 | return data;
|
660 | }
|
661 | }
|
662 |
|
663 |
|
664 |
|
665 |
|
666 | var AnychartExport = function() {
|
667 | };
|
668 |
|
669 | AnychartExport.prototype.exportTo = function(target, options, callback) {
|
670 | if (!target) {
|
671 | console.warn('Can\'t read input data for exporting.');
|
672 | }
|
673 |
|
674 | var params = getParams(arguments);
|
675 | callback = params.callback;
|
676 |
|
677 | if (typeof callback === 'function') {
|
678 | try {
|
679 | getSvg(target, params, function(err, svg, params) {
|
680 | if (params.outputType === 'svg') {
|
681 | process.nextTick(function() {
|
682 | callback(err, svg);
|
683 | });
|
684 | } else {
|
685 | convertSvgToImageData(svg, params, callback);
|
686 | }
|
687 | });
|
688 | } catch (e) {
|
689 | callback(e, null);
|
690 | return;
|
691 | }
|
692 | } else {
|
693 | return new promiseLibrary(function(resolve, reject) {
|
694 | try {
|
695 | getSvg(target, params, function(err, svg, params) {
|
696 | if (params.outputType === 'svg') {
|
697 | process.nextTick(function() {
|
698 | if (err) reject(err);
|
699 | else resolve(svg);
|
700 | });
|
701 | } else {
|
702 | var done = function(err, image) {
|
703 | if (err) reject(err);
|
704 | else resolve(image);
|
705 | };
|
706 | convertSvgToImageData(svg, params, done);
|
707 | }
|
708 | })
|
709 | } catch (e) {
|
710 | reject(e);
|
711 | return;
|
712 | }
|
713 | })
|
714 | }
|
715 | };
|
716 |
|
717 | AnychartExport.prototype.exportToSync = function(target, options) {
|
718 | var params = getParams(arguments);
|
719 | return getSvg(target, params, function(err, svg, params) {
|
720 | return params.outputType === 'svg' ? svg : convertSvgToImageDataSync(svg, params);
|
721 | });
|
722 | };
|
723 |
|
724 | AnychartExport.prototype.loadFont = function(path, callback) {
|
725 | if (typeof callback == 'function') {
|
726 | opentype.load(path, function(err, font) {
|
727 | if (!err)
|
728 | fonts[font.names.fullName.en.toLowerCase()] = font;
|
729 |
|
730 | callback(err, font);
|
731 | });
|
732 | } else {
|
733 | return new promiseLibrary(function(resolve, reject) {
|
734 | opentype.load(path, function(err, font) {
|
735 | if (err) {
|
736 | reject(err);
|
737 | } else {
|
738 | fonts[font.names.fullName.en.toLowerCase()] = font;
|
739 | resolve(font);
|
740 | }
|
741 | });
|
742 | })
|
743 | }
|
744 | };
|
745 |
|
746 | AnychartExport.prototype.loadFontSync = function(path) {
|
747 | return fonts[font.names.fullName.en.toLowerCase()] = opentype.loadSync(path);
|
748 | };
|
749 |
|
750 | AnychartExport.prototype.anychartify = anychartify;
|
751 |
|
752 | var AnychartExportWrapper = function(anychartInst) {
|
753 | if (anychartInst) {
|
754 | anychart = anychartInst;
|
755 | setAsRootDocument(anychart.global().document);
|
756 | }
|
757 | return new AnychartExport();
|
758 | };
|
759 |
|
760 | AnychartExportWrapper.exportTo = AnychartExport.prototype.exportTo;
|
761 |
|
762 | AnychartExportWrapper.exportToSync = AnychartExport.prototype.exportToSync;
|
763 |
|
764 | AnychartExportWrapper.loadFont = AnychartExport.prototype.loadFont;
|
765 |
|
766 | AnychartExportWrapper.loadFontSync = AnychartExport.prototype.loadFontSync;
|
767 |
|
768 | AnychartExportWrapper.anychartify = AnychartExport.prototype.anychartify;
|
769 |
|
770 |
|
771 |
|
772 | loadDefaultFontsSync();
|
773 |
|
774 | module.exports = AnychartExportWrapper; |
\ | No newline at end of file |