diff --git a/node.js/index.js b/node.js/index.js index ee8ffc97..9cb6035d 100644 --- a/node.js/index.js +++ b/node.js/index.js @@ -21,6 +21,7 @@ __dirname = path.resolve(__dirname, '../src/'); var context = vm.createContext({ options: { server: true, + svg: true, parser: 'acorn', version: 'dev' }, diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index 518b0643..e819a53c 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -261,7 +261,7 @@ var Matrix = this.Matrix = Base.extend(/** @lends Matrix# */{ * @return {String} A string representation of this transform. */ toString: function() { - var format = Base.formatFloat; + var format = Format.number; return '[[' + [format(this._a), format(this._b), format(this._tx)].join(', ') + '], [' + [format(this._c), format(this._d), diff --git a/src/basic/Point.js b/src/basic/Point.js index c045cf34..15e6f6d0 100644 --- a/src/basic/Point.js +++ b/src/basic/Point.js @@ -165,8 +165,8 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ }, _serialize: function(options) { - var format = Base.formatFloat; - // For speed reasons, we directly call formatFloat() here with + var format = Format.number; + // For speed reasons, we directly call Format.number() here with // precision, instead of converting array through Base.serialize() which // makes a copy. return [format(this.x, options.precision), @@ -214,7 +214,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{ * @return {String} A string representation of the point. */ toString: function() { - var format = Base.formatFloat; + var format = Format.number; return '{ x: ' + format(this.x) + ', y: ' + format(this.y) + ' }'; }, diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js index d1e1256d..52ea6cca 100644 --- a/src/basic/Rectangle.js +++ b/src/basic/Rectangle.js @@ -419,7 +419,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ * @return {String} A string representation of this rectangle. */ toString: function() { - var format = Base.formatFloat; + var format = Format.number; return '{ x: ' + format(this.x) + ', y: ' + format(this.y) + ', width: ' + format(this.width) diff --git a/src/basic/Size.js b/src/basic/Size.js index 2d47ca3e..addc7515 100644 --- a/src/basic/Size.js +++ b/src/basic/Size.js @@ -125,7 +125,7 @@ var Size = this.Size = Base.extend(/** @lends Size# */{ * @return {String} A string representation of the size. */ toString: function() { - var format = Base.formatFloat; + var format = Format.number; return '{ width: ' + format(this.width) + ', height: ' + format(this.height) + ' }'; }, diff --git a/src/color/Color.js b/src/color/Color.js index fffad69e..e5e8b964 100644 --- a/src/color/Color.js +++ b/src/color/Color.js @@ -283,7 +283,7 @@ var Color = this.Color = Base.extend(new function() { var component = this._components[i], value = this['_' + component]; if (component !== 'alpha' || value != null && value < 1) - res.push(Base.formatFloat(value, options.precision)); + res.push(Format.number(value, options.precision)); } return res; }, @@ -471,7 +471,7 @@ var Color = this.Color = Base.extend(new function() { */ toString: function() { var parts = [], - format = Base.formatFloat; + format = Format.number; for (var i = 0, l = this._components.length; i < l; i++) { var component = this._components[i], value = this['_' + component]; diff --git a/src/core/Base.js b/src/core/Base.js index bb1be6a5..252c78e7 100644 --- a/src/core/Base.js +++ b/src/core/Base.js @@ -40,7 +40,7 @@ this.Base = Base.inject(/** @lends Base# */{ if (!/^_/.test(key)) { var type = typeof value; this.push(key + ': ' + (type === 'number' - ? Base.formatFloat(value) + ? Format.number(value) : type === 'string' ? "'" + value + "'" : value)); } }, []).join(', ') + ' }'; @@ -324,7 +324,7 @@ this.Base = Base.inject(/** @lends Base# */{ res[i] = Base.serialize(obj[i], options, compact, dictionary); } else if (typeof obj === 'number') { - res = Base.formatFloat(obj, options.precision); + res = Format.number(obj, options.precision); } else { res = obj; } @@ -458,18 +458,6 @@ this.Base = Base.inject(/** @lends Base# */{ */ hyphenate: function(str) { return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); - }, - - /** - * Utility function for rendering numbers to strings at a precision of - * up to the amount of fractional digits. - * - * @param {Number} num the number to be converted to a string - * @param {Number} [precision=5] the amount of fractional digits. - */ - formatFloat: function(num, precision) { - precision = precision ? Math.pow(10, precision) : 100000; - return Math.round(num * precision) / precision; } } }); diff --git a/src/load.js b/src/load.js index ca24f1fc..45d819be 100644 --- a/src/load.js +++ b/src/load.js @@ -18,6 +18,7 @@ var options = { browser: true, stats: true, + svg: true, version: 'dev', parser: 'acorn', debug: false diff --git a/src/paper.js b/src/paper.js index 1d0b5e6b..26ba81b5 100644 --- a/src/paper.js +++ b/src/paper.js @@ -81,10 +81,6 @@ var paper = new function() { /*#*/ include('text/TextItem.js'); /*#*/ include('text/PointText.js'); -/*#*/ include('svg/SvgStyles.js'); -/*#*/ include('svg/SvgExport.js'); -/*#*/ include('svg/SvgImport.js'); - /*#*/ include('style/Style.js'); /*#*/ include('style/PathStyle.js'); /*#*/ include('style/ParagraphStyle.js'); @@ -116,6 +112,7 @@ var paper = new function() { /*#*/ include('tool/Tool.js'); /*#*/ } // options.browser +/*#*/ include('util/Format.js'); /*#*/ include('util/CanvasProvider.js'); /*#*/ include('util/Numerical.js'); /*#*/ include('util/BlendMode.js'); @@ -123,6 +120,12 @@ var paper = new function() { /*#*/ include('util/ProxyContext.js'); /*#*/ } // options.browser +/*#*/ if (options.svg) { +/*#*/ include('svg/SvgStyles.js'); +/*#*/ include('svg/SvgExport.js'); +/*#*/ include('svg/SvgImport.js'); +/*#*/ } // options.svg + /*#*/ include('core/PaperScript.js'); /*#*/ if (options.browser) { diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js index becd1ead..1e722244 100644 --- a/src/path/CurveLocation.js +++ b/src/path/CurveLocation.js @@ -231,9 +231,9 @@ var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# * parts.push('index: ' + index); var parameter = this.getParameter(); if (parameter != null) - parts.push('parameter: ' + Base.formatFloat(parameter)); + parts.push('parameter: ' + Format.number(parameter)); if (this._distance != null) - parts.push('distance: ' + Base.formatFloat(this._distance)); + parts.push('distance: ' + Format.number(this._distance)); return '{ ' + parts.join(', ') + ' }'; } }); diff --git a/src/svg/SvgExport.js b/src/svg/SvgExport.js index 63da2de5..858947ef 100644 --- a/src/svg/SvgExport.js +++ b/src/svg/SvgExport.js @@ -15,27 +15,18 @@ * Paper.js DOM to a Paper.js DOM. */ new function() { - // Shortcut to Base.formatFloat - var formatFloat = Base.formatFloat, + // Shortcut to Format.number + var format = Format.number, namespaces = { href: 'http://www.w3.org/1999/xlink' }; - function formatPoint(point) { - return formatFloat(point.x) + ',' + formatFloat(point.y); - } - - function formatRectangle(rect) { - return formatFloat(rect.x) + ',' + formatFloat(rect.y) - + ',' + formatFloat(rect.width) + ',' + formatFloat(rect.height); - } - function setAttributes(node, attrs) { for (var key in attrs) { var val = attrs[key], namespace = namespaces[key]; if (typeof val === 'number') - val = formatFloat(val); + val = format(val); if (namespace) { node.setAttributeNS(namespace, key, val); } else { @@ -81,11 +72,11 @@ new function() { angle = decomposed.rotation, scale = decomposed.scaling; if (trans && !trans.isZero()) - parts.push('translate(' + formatPoint(trans) + ')'); + parts.push('translate(' + Format.point(trans) + ')'); if (!Numerical.isZero(scale.x - 1) || !Numerical.isZero(scale.y - 1)) - parts.push('scale(' + formatPoint(scale) +')'); + parts.push('scale(' + Format.point(scale) +')'); if (angle) - parts.push('rotate(' + formatFloat(angle) + ')'); + parts.push('rotate(' + format(angle) + ')'); attrs.transform = parts.join(' '); } else { attrs.transform = 'matrix(' + matrix.getValues().join(',') + ')'; @@ -269,7 +260,7 @@ new function() { case 'polygon': var parts = []; for(i = 0, l = segments.length; i < l; i++) - parts.push(formatPoint(segments[i]._point)); + parts.push(Format.point(segments[i]._point)); attrs = { points: parts.join(' ') }; @@ -342,8 +333,8 @@ new function() { break; } if (angle) { - attrs.transform = 'rotate(' + formatFloat(angle) + ',' - + formatPoint(center) + ')'; + attrs.transform = 'rotate(' + format(angle) + ',' + + Format.point(center) + ')'; // Tell applyStyle() that to transform the gradient the other way item._gradientMatrix = new Matrix().rotate(-angle, center); } @@ -355,7 +346,7 @@ new function() { children = item._children, paths = []; for (var i = 0, l = children.length; i < l; i++) - paths.push(getPath(children[i])); + paths.push(children[i].getPathData()); attrs.d = paths.join(' '); return createElement('path', attrs); } @@ -368,7 +359,7 @@ new function() { bounds = definition.getBounds(); if (!symbolNode) { symbolNode = createElement('symbol', { - viewBox: formatRectangle(bounds) + viewBox: Format.rectangle(bounds) }); symbolNode.appendChild(exportSvg(definition)); setDefinition(symbol, symbolNode); @@ -376,8 +367,8 @@ new function() { attrs.href = '#' + symbolNode.id; attrs.x += bounds.x; attrs.y += bounds.y; - attrs.width = formatFloat(bounds.width); - attrs.height = formatFloat(bounds.height); + attrs.width = format(bounds.width); + attrs.height = format(bounds.height); return createElement('use', attrs); } @@ -472,7 +463,7 @@ new function() { : entry.type === 'array' ? value.join(',') : entry.type === 'number' - ? formatFloat(value) + ? format(value) : value; } }); diff --git a/src/util/Format.js b/src/util/Format.js new file mode 100644 index 00000000..326351a7 --- /dev/null +++ b/src/util/Format.js @@ -0,0 +1,39 @@ +var Format = new function() { + // Cache for precision values, linking prec -> Math.pow(10, prec) + var precisions = {}; + + function number(val, prec) { + prec = prec + ? precisions[prec] || (precisions[prec] = Math.pow(10, prec)) + : 100000; // Default is 5 + return Math.round(val * prec) / prec; + } + + function point(val, prec, separator) { + return number(val.x, prec) + (separator || ',') + number(val.y, prec); + } + + function size(val, prec, separator) { + return number(val.width, prec) + (separator || ',') + + number(val.height, prec); + } + + function rectangle(val, prec, separator) { + return point(val, prec, separator) + (separator || ',') + + size(val, prec, separator); + } + + return { + /** + * Utility function for rendering numbers as strings at a precision of + * up to the amount of fractional digits. + * + * @param {Number} num the number to be converted to a string + * @param {Number} [precision=5] the amount of fractional digits. + */ + number: number, + point: point, + size: size, + rectangle: rectangle + }; +};