From fa9786b3441434ff0f6fb356eddbc1537ea3fa3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Wed, 2 Apr 2014 20:53:18 +0200 Subject: [PATCH] Switch to new simpler convention for control of beans creation in straps.js --- .jshintrc | 2 +- bower.json | 2 +- src/basic/Matrix.js | 24 +- src/basic/Point.js | 490 +++++++++++++++++++------------------- src/basic/Rectangle.js | 9 +- src/item/Item.js | 26 +- src/path/CompoundPath.js | 14 +- src/path/CurveLocation.js | 26 +- src/path/Path.js | 93 ++++---- src/path/PathItem.js | 9 + src/path/Segment.js | 4 +- src/style/Style.js | 5 +- 12 files changed, 352 insertions(+), 352 deletions(-) diff --git a/.jshintrc b/.jshintrc index 390bf433..2dde2a7d 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,5 +1,5 @@ { - "browser" : true, + "browser": true, "evil": true, "wsh": true, "trailing": false, diff --git a/bower.json b/bower.json index 01f76c9b..1be82938 100644 --- a/bower.json +++ b/bower.json @@ -13,7 +13,7 @@ "test" ], "devDependencies": { - "straps": "~1.4.3", + "straps": "~1.5.0", "acorn": "git://github.com/paperjs/acorn#0.3.2", "esprima": "~1.0.3", "stats.js": "r11" diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index 7e400064..95fc8623 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -716,17 +716,15 @@ var Matrix = Base.extend(/** @lends Matrix# */{ applyToContext: function(ctx) { ctx.transform(this._a, this._c, this._b, this._d, this._tx, this._ty); } -}, new function() { +}, Base.each(['a', 'c', 'b', 'd', 'tx', 'ty'], function(name) { // Create getters and setters for all internal attributes. - return Base.each(['a', 'c', 'b', 'd', 'tx', 'ty'], function(name) { - var part = Base.capitalize(name), - prop = '_' + name; - this['get' + part] = function() { - return this[prop]; - }; - this['set' + part] = function(value) { - this[prop] = value; - this._changed(); - }; - }, {}); -}); + var part = Base.capitalize(name), + prop = '_' + name; + this['get' + part] = function() { + return this[prop]; + }; + this['set' + part] = function(value) { + this[prop] = value; + this._changed(); + }; +}, {})); diff --git a/src/basic/Point.js b/src/basic/Point.js index da895d45..23743da2 100644 --- a/src/basic/Point.js +++ b/src/basic/Point.js @@ -1,3 +1,4 @@ + /* * Paper.js - The Swiss Army Knife of Vector Graphics Scripting. * http://paperjs.org/ @@ -238,6 +239,246 @@ var Point = Base.extend(/** @lends Point# */{ return [f.number(this.x), f.number(this.y)]; }, + /** + * The length of the vector that is represented by this point's coordinates. + * Each point can be interpreted as a vector that points from the origin + * ({@code x = 0}, {@code y = 0}) to the point's location. + * Setting the length changes the location but keeps the vector's angle. + * + * @type Number + * @bean + */ + getLength: function() { + return Math.sqrt(this.x * this.x + this.y * this.y); + }, + + setLength: function(length) { + // Whenever chaining both x & y, use #set() instead of direct + // assignment, so LinkedPoint does not report changes twice. + if (this.isZero()) { + var angle = this._angle || 0; + this.set( + Math.cos(angle) * length, + Math.sin(angle) * length + ); + } else { + var scale = length / this.getLength(); + // Force calculation of angle now, so it will be preserved even when + // x and y are 0 + if (Numerical.isZero(scale)) + this.getAngle(); + this.set( + this.x * scale, + this.y * scale + ); + } + }, + /** + * Returns the smaller angle between two vectors. The angle is unsigned, no + * information about rotational direction is given. + * + * @name Point#getAngle + * @function + * @param {Point} point + * @return {Number} the angle in degrees + */ + /** + * The vector's angle in degrees, measured from the x-axis to the vector. + * + * @name Point#getAngle + * @bean + * @type Number + */ + getAngle: function(/* point */) { + return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI; + }, + + setAngle: function(angle) { + this.setAngleInRadians.call(this, angle * Math.PI / 180); + }, + + getAngleInDegrees: '#getAngle', + setAngleInDegrees: '#setAngle', + + /** + * Returns the smaller angle between two vectors in radians. The angle is + * unsigned, no information about rotational direction is given. + * + * @name Point#getAngleInRadians + * @function + * @param {Point} point + * @return {Number} the angle in radians + */ + /** + * The vector's angle in radians, measured from the x-axis to the vector. + * + * @name Point#getAngleInRadians + * @bean + * @type Number + */ + getAngleInRadians: function(/* point */) { + if (!arguments.length) { + return this.isZero() + // Return the preserved angle in case the vector has no + // length, and update the internal _angle in case the + // vector has a length. See #setAngle() for more + // explanations. + ? this._angle || 0 + : this._angle = Math.atan2(this.y, this.x); + } else { + var point = Point.read(arguments), + div = this.getLength() * point.getLength(); + if (Numerical.isZero(div)) { + return NaN; + } else { + return Math.acos(this.dot(point) / div); + } + } + }, + + setAngleInRadians: function(angle) { + // We store a reference to _angle internally so we still preserve it + // when the vector's length is set to zero, and then anything else. + // Note that we cannot rely on it if x and y are something else than 0, + // since updating x / y does not automatically change _angle! + this._angle = angle; + if (!this.isZero()) { + var length = this.getLength(); + // Use #set() instead of direct assignment of x/y, so LinkedPoint + // does not report changes twice. + this.set( + Math.cos(angle) * length, + Math.sin(angle) * length + ); + } + }, + + /** + * The quadrant of the {@link #angle} of the point. + * + * Angles between 0 and 90 degrees are in quadrant {@code 1}. Angles between + * 90 and 180 degrees are in quadrant {@code 2}, angles between 180 and 270 + * degrees are in quadrant {@code 3} and angles between 270 and 360 degrees + * are in quadrant {@code 4}. + * + * @type Number + * @bean + * + * @example + * var point = new Point({ + * angle: 10, + * length: 20 + * }); + * console.log(point.quadrant); // 1 + * + * point.angle = 100; + * console.log(point.quadrant); // 2 + * + * point.angle = 190; + * console.log(point.quadrant); // 3 + * + * point.angle = 280; + * console.log(point.quadrant); // 4 + */ + getQuadrant: function() { + return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3; + } +}, /** @lends Point# */{ + // Explicitly deactivate the creation of beans, as we have functions here + // that look like bean getters but actually read arguments. + // See #getDirectedAngle(), #getDistance() + beans: false, + + /** + * Returns the angle between two vectors. The angle is directional and + * signed, giving information about the rotational direction. + * + * Read more about angle units and orientation in the description of the + * {@link #angle} property. + * + * @param {Point} point + * @return {Number} the angle between the two vectors + */ + getDirectedAngle: function(/* point */) { + var point = Point.read(arguments); + return Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI; + }, + + /** + * Returns the distance between the point and another point. + * + * @param {Point} point + * @param {Boolean} [squared=false] Controls whether the distance should + * remain squared, or its square root should be calculated. + * @return {Number} + */ + getDistance: function(/* point, squared */) { + var point = Point.read(arguments), + x = point.x - this.x, + y = point.y - this.y, + d = x * x + y * y, + squared = Base.read(arguments); + return squared ? d : Math.sqrt(d); + }, + + /** + * Normalize modifies the {@link #length} of the vector to {@code 1} without + * changing its angle and returns it as a new point. The optional + * {@code length} parameter defines the length to normalize to. + * The object itself is not modified! + * + * @param {Number} [length=1] The length of the normalized vector + * @return {Point} the normalized vector of the vector that is represented + * by this point's coordinates + */ + normalize: function(length) { + if (length === undefined) + length = 1; + var current = this.getLength(), + scale = current !== 0 ? length / current : 0, + point = new Point(this.x * scale, this.y * scale); + // Preserve angle. + if (scale >= 0) + point._angle = this._angle; + return point; + }, + + /** + * Rotates the point by the given angle around an optional center point. + * The object itself is not modified. + * + * Read more about angle units and orientation in the description of the + * {@link #angle} property. + * + * @param {Number} angle the rotation angle + * @param {Point} center the center point of the rotation + * @returns {Point} the rotated point + */ + rotate: function(angle, center) { + if (angle === 0) + return this.clone(); + angle = angle * Math.PI / 180; + var point = center ? this.subtract(center) : this, + s = Math.sin(angle), + c = Math.cos(angle); + point = new Point( + point.x * c - point.y * s, + point.x * s + point.y * c + ); + return center ? point.add(center) : point; + }, + + /** + * Transforms the point by the matrix as a new point. The object itself is + * not modified! + * + * @param {Matrix} matrix + * @return {Point} the transformed point + */ + transform: function(matrix) { + return matrix ? matrix._transformPoint(this) : this; + }, + /** * Returns the addition of the supplied value to both coordinates of * the point as a new point. @@ -429,255 +670,6 @@ var Point = Base.extend(/** @lends Point# */{ return new Point(-this.x, -this.y); }, - /** - * Transforms the point by the matrix as a new point. The object itself - * is not modified! - * - * @param {Matrix} matrix - * @return {Point} the transformed point - */ - transform: function(matrix) { - return matrix ? matrix._transformPoint(this) : this; - }, - - /** - * {@grouptitle Distance & Length} - * - * Returns the distance between the point and another point. - * - * @param {Point} point - * @param {Boolean} [squared=false] Controls whether the distance should - * remain squared, or its square root should be calculated. - * @return {Number} - */ - getDistance: function(point, squared) { - // NOTE: Although we're reading from the argument list, we need the - // above arguments to prevent beans from being created (Straps.js issue) - // And for browser optimization we shouldn't re-assign an object to it, - // but we need to prevent the minifier from removing it again, so: - var _point = Point.read(arguments), - x = _point.x - this.x, - y = _point.y - this.y, - d = x * x + y * y; - // Reassigning boolean values to arguments is apparently OK. - squared = Base.read(arguments); - return squared ? d : Math.sqrt(d); - }, - - /** - * The length of the vector that is represented by this point's coordinates. - * Each point can be interpreted as a vector that points from the origin - * ({@code x = 0}, {@code y = 0}) to the point's location. - * Setting the length changes the location but keeps the vector's angle. - * - * @type Number - * @bean - */ - getLength: function() { - return Math.sqrt(this.x * this.x + this.y * this.y); - }, - - setLength: function(length) { - // Whenever chaining both x & y, use #set() instead of direct - // assignment, so LinkedPoint does not report changes twice. - if (this.isZero()) { - var angle = this._angle || 0; - this.set( - Math.cos(angle) * length, - Math.sin(angle) * length - ); - } else { - var scale = length / this.getLength(); - // Force calculation of angle now, so it will be preserved even when - // x and y are 0 - if (Numerical.isZero(scale)) - this.getAngle(); - this.set( - this.x * scale, - this.y * scale - ); - } - }, - - /** - * Normalize modifies the {@link #length} of the vector to {@code 1} without - * changing its angle and returns it as a new point. The optional - * {@code length} parameter defines the length to normalize to. - * The object itself is not modified! - * - * @param {Number} [length=1] The length of the normalized vector - * @return {Point} the normalized vector of the vector that is represented - * by this point's coordinates - */ - normalize: function(length) { - if (length === undefined) - length = 1; - var current = this.getLength(), - scale = current !== 0 ? length / current : 0, - point = new Point(this.x * scale, this.y * scale); - // Preserve angle. - if (scale >= 0) - point._angle = this._angle; - return point; - }, - - /** - * {@grouptitle Angle & Rotation} - * Returns the smaller angle between two vectors. The angle is unsigned, no - * information about rotational direction is given. - * - * @name Point#getAngle - * @function - * @param {Point} point - * @return {Number} the angle in degrees - */ - /** - * The vector's angle in degrees, measured from the x-axis to the vector. - * - * @name Point#getAngle - * @bean - * @type Number - */ - getAngle: function(/* point */) { - return this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI; - }, - - setAngle: function(angle) { - this.setAngleInRadians.call(this, angle * Math.PI / 180); - }, - - getAngleInDegrees: '#getAngle', - setAngleInDegrees: '#setAngle', - - /** - * Returns the smaller angle between two vectors in radians. The angle is - * unsigned, no information about rotational direction is given. - * - * @name Point#getAngleInRadians - * @function - * @param {Point} point - * @return {Number} the angle in radians - */ - /** - * The vector's angle in radians, measured from the x-axis to the vector. - * - * @name Point#getAngleInRadians - * @bean - * @type Number - */ - getAngleInRadians: function(/* point */) { - if (!arguments.length) { - return this.isZero() - // Return the preseved angle in case the vector has no - // length, and update the internal _angle in case the - // vector has a length. See #setAngle() for more - // explanations. - ? this._angle || 0 - : this._angle = Math.atan2(this.y, this.x); - } else { - var point = Point.read(arguments), - div = this.getLength() * point.getLength(); - if (Numerical.isZero(div)) { - return NaN; - } else { - return Math.acos(this.dot(point) / div); - } - } - }, - - setAngleInRadians: function(angle) { - // We store a reference to _angle internally so we still preserve it - // when the vector's length is set to zero, and then anything else. - // Note that we cannot rely on it if x and y are something else than 0, - // since updating x / y does not automatically change _angle! - this._angle = angle; - if (!this.isZero()) { - var length = this.getLength(); - // Use #set() instead of direct assignment of x/y, so LinkedPoint - // does not report changes twice. - this.set( - Math.cos(angle) * length, - Math.sin(angle) * length - ); - } - }, - - /** - * The quadrant of the {@link #angle} of the point. - * - * Angles between 0 and 90 degrees are in quadrant {@code 1}. Angles between - * 90 and 180 degrees are in quadrant {@code 2}, angles between 180 and 270 - * degrees are in quadrant {@code 3} and angles between 270 and 360 degrees - * are in quadrant {@code 4}. - * - * @type Number - * @bean - * - * @example - * var point = new Point({ - * angle: 10, - * length: 20 - * }); - * console.log(point.quadrant); // 1 - * - * point.angle = 100; - * console.log(point.quadrant); // 2 - * - * point.angle = 190; - * console.log(point.quadrant); // 3 - * - * point.angle = 280; - * console.log(point.quadrant); // 4 - */ - getQuadrant: function() { - return this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3; - }, - - /** - * Returns the angle between two vectors. The angle is directional and - * signed, giving information about the rotational direction. - * - * Read more about angle units and orientation in the description of the - * {@link #angle} property. - * - * @param {Point} point - * @return {Number} the angle between the two vectors - */ - getDirectedAngle: function(point) { - // NOTE: Although we're reading from the argument list, we need the - // above arguments to prevent beans from being created (Straps.js issue) - // And for browser optimization we shouldn't re-asign an object to it, - // but we need to prevent the minifier from removing it again, so: - var _point = point; - _point = Point.read(arguments); - return Math.atan2(this.cross(_point), this.dot(_point)) * 180 / Math.PI; - }, - - /** - * Rotates the point by the given angle around an optional center point. - * The object itself is not modified. - * - * Read more about angle units and orientation in the description of the - * {@link #angle} property. - * - * @param {Number} angle the rotation angle - * @param {Point} center the center point of the rotation - * @returns {Point} the rotated point - */ - rotate: function(angle, center) { - if (angle === 0) - return this.clone(); - angle = angle * Math.PI / 180; - var point = center ? this.subtract(center) : this, - s = Math.sin(angle), - c = Math.cos(angle); - point = new Point( - point.x * c - point.y * s, - point.x * s + point.y * c - ); - return center ? point.add(center) : point; - }, - /** * {@grouptitle Tests} * diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js index 89fd8a68..e285ceb9 100644 --- a/src/basic/Rectangle.js +++ b/src/basic/Rectangle.js @@ -21,6 +21,9 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{ _class: 'Rectangle', // Tell Base.read that the Rectangle constructor supports reading with index _readIndex: true, + // Enforce creation of beans, as bean getters have hidden parameters. + // See #getPoint() below. + beans: true, /** * Creates a Rectangle object. @@ -821,7 +824,11 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{ this[setX](point.x); this[setY](point.y); }; - }, {}); + }, { + // Enforce creation of beans, as bean getters have hidden parameters + // See _dontLink argument above. + beans: true + }); }); /** diff --git a/src/item/Item.js b/src/item/Item.js index 97d2fb16..9def02e9 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -476,6 +476,10 @@ var Item = Base.extend(Callback, /** @lends Item# */{ } }; }, {}), /** @lends Item# */{ + // Enforce creation of beans, as bean getters have hidden parameters. + // See #getPosition() below. + beans: true, + // Note: These properties have their getter / setters produced in the // injection scope above. @@ -873,14 +877,12 @@ var Item = Base.extend(Callback, /** @lends Item# */{ bounds.height, this, 'setBounds') : bounds; }; - // As the function defines a _matrix parameter and has no setter, - // Straps.js doesn't produce a bean for it. Explicitely define an - // accesor now too: - this[key] = { - get: this[getter] - }; }, /** @lends Item# */{ + // Enforce creation of beans, as bean getters have hidden parameters. + // See _matrix parameter above. + beans: true, + /** * Protected method used in all the bounds getters. It loops through all the * children, gets their bounds and finds the bounds around all of them. @@ -1062,6 +1064,10 @@ var Item = Base.extend(Callback, /** @lends Item# */{ * @ignore */ }), /** @lends Item# */{ + // Enforce creation of beans, as bean getters have hidden parameters. + // See #getGlobalMatrix() below. + beans: true, + _decompose: function() { return this._decomposed = this._matrix.decompose(); }, @@ -1146,7 +1152,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ * @type Matrix * @bean */ - getGlobalMatrix: function() { + getGlobalMatrix: function(_internal) { var matrix = this._globalMatrix, updateVersion = this._project._updateVersion, viewMatrix = this.getView()._matrix; @@ -1164,9 +1170,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ : viewMatrix); matrix._updateVersion = updateVersion; } - // TODO: Fix Straps.js so we can pass this on as _internal argument and - // still have a bean created. - return arguments[0] ? matrix : viewMatrix.inverted().concatenate(matrix); + return _internal ? matrix : viewMatrix.inverted().concatenate(matrix); }, /** @@ -1194,7 +1198,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{ */ getTransformContent: '#getApplyMatrix', setTransformContent: '#setApplyMatrix', - +}, /** @lends Item# */{ /** * {@grouptitle Project Hierarchy} * The project that this item belongs to. diff --git a/src/path/CompoundPath.js b/src/path/CompoundPath.js index 9258f596..f6d51661 100644 --- a/src/path/CompoundPath.js +++ b/src/path/CompoundPath.js @@ -219,16 +219,20 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{ for (var i = 0, l = children.length; i < l; i++) area += children[i].getArea(); return area; - }, + } +}, /** @lends CompoundPath# */{ + // Enforce bean creation for getPathData(), as it has hidden parameters. + beans: true, - getPathData: function(precision) { + getPathData: function(_precision) { + // NOTE: #setPathData() is defined in PathItem. var children = this._children, paths = []; for (var i = 0, l = children.length; i < l; i++) - paths.push(children[i].getPathData(precision)); + paths.push(children[i].getPathData(_precision)); return paths.join(' '); - }, - + } +}, /** @lends CompoundPath# */{ _getChildHitTestOptions: function(options) { // If we're not specifically asked to returns paths through // options.type == 'path' do not test children for fill, since a diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js index 8d1980bb..132fde67 100644 --- a/src/path/CurveLocation.js +++ b/src/path/CurveLocation.js @@ -28,6 +28,10 @@ */ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ _class: 'CurveLocation', + // Enforce creation of beans, as bean getters have hidden parameters. + // See #getSegment() below. + beans: true, + // DOCS: CurveLocation class description: add these back when the mentioned // functioned have been added: {@link Path#split(location)} /** @@ -82,13 +86,6 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ return this._segment; }, - setSegment: function(segment) { - // NOTE: We only include this setter so the above getter can declare - // the _preferFirst parameter without having to hide it. - // See Straps.js beans conventions. - this._segment = segment; - }, - /** * The curve by which the location is defined. * @@ -109,11 +106,6 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ return this._curve; }, - setCurve: function(curve) { - // See #setSegment() - this._curve = curve; - }, - /** * The curve location on the intersecting curve, if this location is the * result of a call to {@link PathItem#getIntersections(path)} / @@ -199,11 +191,6 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ return this._parameter; }, - setParameter: function(parameter) { - // See #setSegment() - this._parameter = parameter; - }, - /** * The point which is defined by the {@link #curve} and * {@link #parameter}. @@ -219,11 +206,6 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ return this._point; }, - setPoint: function(point) { - // See #setSegment() - this._point = point; - }, - /** * The tangential vector to the {@link #curve} at the given location. * diff --git a/src/path/Path.js b/src/path/Path.js index 48e0ea55..ae6fa418 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -254,51 +254,6 @@ var Path = PathItem.extend(/** @lends Path# */{ return curves[curves.length - 1]; }, - /** - * The segments contained within the path, described as SVG style path data. - * - * @type String - * @bean - */ - getPathData: function(precision) { - var segments = this._segments, - f = Formatter.instance, - parts = []; - - // TODO: Add support for H/V and/or relative commands, where appropriate - // and resulting in shorter strings - function addCurve(seg1, seg2, skipLine) { - var point1 = seg1._point, - point2 = seg2._point, - handle1 = seg1._handleOut, - handle2 = seg2._handleIn; - if (handle1.isZero() && handle2.isZero()) { - if (!skipLine) { - // L = absolute lineto: moving to a point with drawing - parts.push('L' + f.point(point2, precision)); - } - } else { - // c = relative curveto: handle1, handle2 + end - start, - // end - start - var end = point2.subtract(point1); - parts.push('c' + f.point(handle1, precision) - + ' ' + f.point(end.add(handle2), precision) - + ' ' + f.point(end, precision)); - } - } - - if (segments.length === 0) - return ''; - parts.push('M' + f.point(segments[0]._point)); - for (var i = 0, l = segments.length - 1; i < l; i++) - addCurve(segments[i], segments[i + 1], false); - if (this._closed) { - addCurve(segments[segments.length - 1], segments[0], true); - parts.push('z'); - } - return parts.join(''); - }, - /** * Specifies whether the path is closed. If it is closed, Paper.js connects * the first and last segments. @@ -336,7 +291,51 @@ var Path = PathItem.extend(/** @lends Path# */{ // up-to-date and don't need notification. this._changed(/*#=*/ Change.SEGMENTS); } - }, + } +}, /** @lends Path# */{ + // Enforce bean creation for getPathData(), as it has hidden parameters. + beans: true, + + getPathData: function(_precision) { + // NOTE: #setPathData() is defined in PathItem. + var segments = this._segments, + f = Formatter.instance, + parts = []; + + // TODO: Add support for H/V and/or relative commands, where appropriate + // and resulting in shorter strings + function addCurve(seg1, seg2, skipLine) { + var point1 = seg1._point, + point2 = seg2._point, + handle1 = seg1._handleOut, + handle2 = seg2._handleIn; + if (handle1.isZero() && handle2.isZero()) { + if (!skipLine) { + // L = absolute lineto: moving to a point with drawing + parts.push('L' + f.point(point2, _precision)); + } + } else { + // c = relative curveto: handle1, handle2 + end - start, + // end - start + var end = point2.subtract(point1); + parts.push('c' + f.point(handle1, _precision) + + ' ' + f.point(end.add(handle2), _precision) + + ' ' + f.point(end, _precision)); + } + } + + if (segments.length === 0) + return ''; + parts.push('M' + f.point(segments[0]._point)); + for (var i = 0, l = segments.length - 1; i < l; i++) + addCurve(segments[i], segments[i + 1], false); + if (this._closed) { + addCurve(segments[segments.length - 1], segments[0], true); + parts.push('z'); + } + return parts.join(''); + } +}, /** @lends Path# */{ // TODO: Consider adding getSubPath(a, b), returning a part of the current // path, with the added benefit that b can be < a, and closed looping is @@ -2439,7 +2438,7 @@ var Path = PathItem.extend(/** @lends Path# */{ z = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)), segments = []; for (var i = 0; i <= count; i++) { - // Explicitely use to point for last segment, since depending + // Explicitly use to point for last segment, since depending // on values the calculation adds imprecision: var pt = to, out = null; diff --git a/src/path/PathItem.js b/src/path/PathItem.js index 1b122257..4fdba676 100644 --- a/src/path/PathItem.js +++ b/src/path/PathItem.js @@ -181,7 +181,16 @@ var PathItem = Item.extend(/** @lends PathItem# */{ return locations; }, + /** + * The path's geometry, formatted as SVG style path data. + * + * @name PathItem#getPathData + * @type String + * @bean + */ + setPathData: function(data) { + // NOTE: #getPathData() is defined in CompoundPath / Path // This is a very compact SVG Path Data parser that works both for Path // and CompoundPath. diff --git a/src/path/Segment.js b/src/path/Segment.js index 329e730c..80c44b57 100644 --- a/src/path/Segment.js +++ b/src/path/Segment.js @@ -24,6 +24,7 @@ */ var Segment = Base.extend(/** @lends Segment# */{ _class: 'Segment', + beans: true, /** * Creates a new Segment object. @@ -146,7 +147,8 @@ var Segment = Base.extend(/** @lends Segment# */{ _serialize: function(options) { // If the Segment is linear, only serialize point, otherwise handles too return Base.serialize(this.isLinear() ? this._point - : [this._point, this._handleIn, this._handleOut], options, true); + : [this._point, this._handleIn, this._handleOut], + options, true); }, _changed: function(point) { diff --git a/src/style/Style.js b/src/style/Style.js index 33a08d48..8b5e3908 100644 --- a/src/style/Style.js +++ b/src/style/Style.js @@ -116,7 +116,10 @@ var Style = Base.extend(new function() { // Override default fillColor for text items _textDefaults: new Base(defaults, { fillColor: new Color() // black - }) + }), + // Enforce creation of beans, as bean getters have hidden parameters + // See _dontMerge argument below. + beans: true }; Base.each(defaults, function(value, key) {