UNPKG

ai-helper-jimmy

Version:

A ai helper for web3 devs.

573 lines (504 loc) 17 kB
"use strict"; var fs = require('fs'), xml2js = require('xml2js'), _ = require('underscore'), builder = require('xmlbuilder'), async = require('async'), SvgParser = require(__dirname + '/parser'), Matrix = require(__dirname + '/matrix/extends'), gm = require('gm').subClass({ imageMagick: true }), utils = require(__dirname + '/matrix/utils'); var Svg = function Svg() { if (!(this instanceof Svg)) throw 'this function in a constructor. Use new to call it'; this.elements = []; this.size = { width: 100, height : 100 }; this.stylesheets = []; }; /** * Set Svg Elements * @param {Array} elements SvgObject Array (rect|polygon|polyline|...) */ Svg.prototype.setElements = function setElements(elements) { this.elements = elements; }; /** * Add SvgObject element to current SVG * @param {SvgObject} element SvgObject Element */ Svg.prototype.addElement = function toJSON(element) { this.elements.push(element); }; /** * Add Specific stylesheet in SVG * @param {string} cssFilePath Css File Path to add */ Svg.prototype.addStyleSheet = function addStyleSheet(cssFilePath) { this.stylesheets.push(cssFilePath); }; /** * Convert Svg to Json format * @param {boolean} matrix String representation without transform attribute * @returns {object} Svg Json Object representation */ Svg.prototype.toJSON = function toXml(matrix) { if(typeof matrix == 'undefined') matrix = false; var json = { elements : [], stylesheets : this.stylesheets, size : this.size }; _.each(this.elements, function (element) { json.elements.push(element.toJSON(matrix)); }); return json; }; /** * Convert Svg to Xml format * @param {boolean} matrix String representation without transform attribute * @returns {object} XMLBuilder Svg representation */ Svg.prototype.toXml = function toXml(matrix) { if(typeof matrix == 'undefined') matrix = false; var xml = builder.create('svg'); xml.att('version', '1.1'); xml.att('xmlns', 'http://www.w3.org/2000/svg'); xml.att('width', this.size.width+'px'); xml.att('height', this.size.height+'px'); _.each(this.stylesheets, function (styleSheet) { xml.ins('xml-stylesheet', 'type="text/xsl" href="'+ styleSheet +'"'); }); _.each(this.elements, function (element) { xml.importXMLBuilder(element.toXml(matrix)); }); return xml; }; /** * Convert SVG to String : * '<svg>...</svg>' * @param {boolean} content false : return only svg content, true : return all svg in <svg> tag * @param {boolean} [matrix] String representation without transform attribute * @returns {string} Svg String representation */ Svg.prototype.toString = function toString(content, matrix) { if(typeof matrix == 'undefined') matrix = false; if (content == true) { return this.toXml(matrix).toString(); } else { var string = ''; _.each(this.elements, function(element){ string += element.toXml(matrix).toString(); }); return string; } }; /** * Find elements in SVG and return new Svg object with all elements by selected type * * @param {string} type Selected type (rect|polygon|g|...) * @param {boolean} all true : find all type in groups and root, false : find only in root * @returns {Svg} new Svg object with selected types elements */ Svg.prototype.findByType = function findByType(type, all) { var svg = new Svg(); _.each(this.elements, function (elem) { if (elem.type == type) { svg.addElement(elem); } if (all && elem.type == 'g') { var group = elem.findByType(type, all); _.each(group.childs, function (child) { svg.addElement(child); }); } }); return svg; }; /** * Find one element by id in SVG * * @param {string} id Item id * @returns {SvgObject} SvgObject element */ Svg.prototype.findById = function (id) { var returnElem = null; _.each(this.elements, function (elem) { if (elem.id == id) { returnElem = elem; }else if (elem.type == 'g') { returnElem = elem.findById(id); } }); return returnElem; }; /** * Find one element by id and type in SVG * * @param {string} id Item id * @param {string} type Item type (rect, path, ...) * @returns {SvgObject} SvgObject element */ Svg.prototype.findByIdAndType = function findByIdAndType(id, type) { var returnElem = null; _.each(this.elements, function (elem) { if (elem.id == id && elem.type == type) { returnElem = elem; }else if (elem.type == 'g') { returnElem = elem.findByIdAndType(id, type); } }); return returnElem; }; /** * Find one element by id without param type in SVG * * @param {string} id Item id * @param {string} type Item type (rect, path, ...) * @returns {SvgObject} SvgObject element */ Svg.prototype.findByIdWithoutType = function findByIdWithoutType(id, type) { var returnElem = null; _.each(this.elements, function (elem) { if (elem.id === id && elem.type !== type) { returnElem = elem; }else if (elem.type === 'g') { returnElem = elem.findByIdWithoutType(id, type); } }); return returnElem; }; /** * Remove All elements by type. If type is 'g', all childs elements are moved on svg root node. * @param {string} type Type to remove */ Svg.prototype.removeAllByType = function removeAllByType(type) { var elements = []; _.each(this.elements, function (elem) { if (elem.type === 'g') { var elms = elem.removeAllByType(type); if (type === 'g') { elements = _.union(elements, elms); } } if (elem.type !== type) { elements.push(elem); } }); this.elements = elements; }; /** * Generate new Svg element with all applied matrix to all elements. * Convert rect into polygon * @param {array|Matrix} matrix Matrix to be applied in addition to those elements. * @param {function} callback Callback Function */ Svg.prototype.applyMatrix = function applyMatrix(matrix, callback) { var svg = new Svg(); var applyMatrix = new Matrix(); if (matrix != null) { if(matrix instanceof Array){ _.each(matrix, function(mat){ applyMatrix.add(mat); }); }else{ applyMatrix = matrix; } } async.each(this.elements, function (elem, c) { elem.getBBox( function (bbox) { var applyCloneMatrix = applyMatrix.clone(); var matrix = applyCloneMatrix.add(Matrix.fromElement(bbox, elem)); elem.applyMatrix(matrix, function(e){ svg.addElement(e); c(); }); }); }, function () { callback(svg); }); }; /** * Save Svg file * @param {object} params Functon Params * @param {string} [params.output] Output file * @param {function} callback Callback Function */ Svg.prototype.save = function save(params, callback) { var defOpts = { output : '/tmp/export_' + new Date().getTime() + '.svg' }; params = _.extend({}, defOpts, params); fs.writeFile(params.output, this.toString(true), function (err) { if (err) { callback(err); return; } callback(null, params.output); }); }; /** * Save Svg file in Png Format * @param {object} params Functon Params * @param {string} [params.output] Output file * @param {function} callback Callback Function */ Svg.prototype.savePng = function savePng(params, callback) { var defOpts = { output : '/tmp/export_' + new Date().getTime() + '.png' }; params = _.extend({}, defOpts, params); this.save({}, function (err, file) { if (err) { callback(err); return; } gm(file).write(params.output, function (err) { if (err) { callback(err); return; } callback(null, params.output); }); }); }; /** * Refresh SVG size * @param {function} callback Callback Function */ Svg.prototype.getSize = function getSize(callback) { var minX = +Infinity, maxX = -Infinity, minY = +Infinity, maxY = -Infinity, self = this; async.each(this.elements, function (child, done) { child.getBBox(function (bbox) { minX = Math.min(minX, bbox.x); minY = Math.min(minY, bbox.y); maxX = Math.max(maxX, bbox.x2); maxY = Math.max(maxY, bbox.y2); done(); }); }, function () { var bbox = utils.bbox(minX,minY,maxX,maxY); self.size = { width : bbox.w, height : bbox.h }; callback(self.size); }); }; /** * Get SVG bbox * @param {function} callback Callback Function */ Svg.prototype.getBBox = function getBBox(callback) { var minX = +Infinity, maxX = -Infinity, minY = +Infinity, maxY = -Infinity; async.each(this.elements, function (child, done) { child.getBBox(function (bbox) { minX = Math.min(minX, bbox.x); minY = Math.min(minY, bbox.y); maxX = Math.max(maxX, bbox.x2); maxY = Math.max(maxY, bbox.y2); done(); }); }, function () { callback(utils.bbox(minX,minY,maxX,maxY)); }); }; /** * Calculate all innerboxes in SVG. Return copy of current svg with elements with data attribute innerbox. * @param {function} callback Callback Function */ Svg.prototype.calculateAllInnerBoxes = function calculateAllInnerBoxes(callback) { var svg = new Svg(); async.each(this.elements, function (child, done) { switch (child.type) { case 'rect' : case 'polygon' : case 'polyline' : case 'circle' : child.getInnerBox(function (innerBox) { child.data.innerbox = innerBox; svg.addElement(child); done(); }); break; case 'g' : child.calculateAllInnerBoxes( function (group) { svg.addElement(child); done(); }); break; default : svg.addElement(child); done(); } }, function () { svg.getSize(function () { callback(svg); }); }); }; /** * Remove specifics types of objetcs in svg * @param {object} params Function params * @param {string|Array} params.type target type(s) (g, rect, ...) */ Svg.prototype.removeByType = function removeByType(params) { this.elements = _.filter(this.elements, function (element) { if (!_.isArray(params.type)) { var t = params.type; params.type = []; params.type.push(t); } if (element.type === 'g') { // remove elements for group element.removeByType(params); // if remove group type, add all elements in svg if (_.contains(params.type, 'g')) { _.union(this.elements, element.childs); } } return !_.contains(params.type, element.type); }, this); }; /** * Convert Svg elements into Path. * Works only on rect, polygon and polyline */ Svg.prototype.convertElementsToPath = function convertElementsToPath() { var elements = []; _.each(this.elements, function (element) { switch(element.type) { case 'rect' : case 'polygon' : case 'polyline' : elements.push(element.toPath()); break; case 'g' : element.convertElementsToPath(); elements.push(element); break; default : elements.push(element); } }, this); this.elements = elements; }; module.exports = Svg; /** * Create Svg from Svg Document * @param {string} path Uri of source file * @param {function} callback Callback Function */ module.exports.fromSvgDocument = function fromSvgDocument(path, callback) { fs.readFile(path, function (error, data) { if (error) { callback(error); return; } Svg.fromXmlString(data.toString(), callback); }); }; /** * Create Svg from Xml String representation * @param {string} string Svg string representation * @param {function} callback Callback Function */ module.exports.fromXmlString = function fromXmlString(string, callback) { var parser = new xml2js.Parser(); parser.addListener('end', function (result) { SvgParser.convertXml(result, function (err, elements) { if (err) { callback(err); return; } var svg = new Svg(); svg.setElements(elements); svg.getSize(function () { callback(null, svg); }); }); }); parser.parseString(string); }; module.exports.fromJsonFile = function fromJsonFile(path, callback) { fs.readFile(path, function (error, data) { if (error) { callback(error); return; } Svg.fromJsonString(data.toString(), callback); }); }; module.exports.fromJsonString = function fromJsonString(string, callback) { var json = JSON.parse(string); Svg.fromJson(json, callback); }; module.exports.fromJson = function fromJson(json, callback) { SvgParser.convertJson(json, function (err, elements) { if (err) { callback(err); return; } var svg = new Svg(); svg.setElements(elements); svg.getSize(function () { callback(null, svg); }); }); }; /** * Create SVG from dxf file * @param {object} params Function params * @param {string} params.path DXF File path * @param {Array} params.layers Import element for passed layers names * @param {function} callback Callback Function */ module.exports.fromDxfFile = function fromDxfFile(params, callback) { SvgParser.convertDxf(params, function (err, result) { if (err) { callback (err); return; } var svg = new Svg(); _.each(result.polygons, function (polygon) { // test if params.layers is set and if polygon is in specified layers if (!params.layers || params.layers.length == 0 || _.contains(params.layers, polygon.layer)) { svg.addElement(SvgParser.parseJsonPolygon({ points : polygon.points, fill : 'white', stroke : 'black' })); } }, this); _.each(result.circles, function (circle) { if (!params.layers || params.layers.length == 0 || _.contains(params.layers, circle.layer)) { svg.addElement(SvgParser.parseJsonPolygon({ points : circle.points, fill : 'white', stroke : 'black' })); } }); _.each(result.texts, function (text) { if (!params.layers || params.layers.length == 0 || _.contains(params.layers, text.layer)) { svg.addElement(SvgParser.parseJsonText({ fill : 'black', value : text.contents, x : text.point.x, y : text.point.y })); } }); svg.getBBox(function (bbox) { var matrix = new Matrix(1, 0, 0, -1, Math.abs(Math.min(bbox.x, bbox.x2))+10, Math.abs(Math.min(bbox.y, bbox.y2))+10); svg.applyMatrix(matrix, function (svg) { svg.getSize(function () { callback(null, svg); }); }); }); }); };