diff --git a/src/item/ChangeFlag.js b/src/item/ChangeFlag.js index 0ae08015..fdf28815 100644 --- a/src/item/ChangeFlag.js +++ b/src/item/ChangeFlag.js @@ -13,23 +13,26 @@ var ChangeFlag = { // Anything affecting the appearance of an item, including GEOMETRY, // STROKE, STYLE and ATTRIBUTE (except for the invisible ones: locked, name) - APPEARANCE: 1, + APPEARANCE: 0x1, // Change in item hierarchy - HIERARCHY: 2, + HIERARCHY: 0x2, // Item geometry (path, bounds) - GEOMETRY: 4, + GEOMETRY: 0x4, + // Only segment(s) have changed, and affected curves have alredy been + // notified. This is to implement an optimization in _changed() calls. + SEGMENTS: 0x8, // Stroke geometry (excluding color) - STROKE: 8, + STROKE: 0x10, // Fill style or stroke color / dash - STYLE: 16, + STYLE: 0x20, // Item attributes: visible, blendMode, locked, name, opacity, clipMask ... - ATTRIBUTE: 32, + ATTRIBUTE: 0x40, // Text content - CONTENT: 64, + CONTENT: 0x80, // Raster pixels - PIXELS: 128, + PIXELS: 0x100, // Clipping in one of the child items - CLIPPING: 256 + CLIPPING: 0x200 }; // Shortcuts to often used ChangeFlag values including APPEARANCE @@ -39,6 +42,7 @@ var Change = { HIERARCHY: ChangeFlag.HIERARCHY | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE, GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE, + SEGMENTS: ChangeFlag.SEGMENTS | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE, STROKE: ChangeFlag.STROKE | ChangeFlag.STYLE | ChangeFlag.APPEARANCE, STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE, ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE, diff --git a/src/path/Path.js b/src/path/Path.js index 01220ff4..3382b1fa 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -138,14 +138,19 @@ var Path = PathItem.extend(/** @lends Path# */{ _changed: function _changed(flags) { _changed.base.call(this, flags); if (flags & /*#=*/ ChangeFlag.GEOMETRY) { - // Clear cached native Path - (this._compound ? this._parent : this)._currentPath = undefined; + // Clear cached native Path. Clear on the parent too, for + // CompoundPaths and Groups (ab)used as clipping paths. + this._currentPath = undefined; + var parent = this._parent; + if (parent) + parent._currentPath = undefined; // Clockwise state becomes undefined as soon as geometry changes. this._length = this._clockwise = undefined; - // Curves are no longer valid - if (this._curves) { + // Only notify all curves if we're not told that only one Segment + // has changed and took already care of notifications. + if (this._curves && !(flags & /*#=*/ ChangeFlag.SEGMENTS)) { for (var i = 0, l = this._curves.length; i < l; i++) - this._curves[i]._changed(/*#=*/ Change.GEOMETRY); + this._curves[i]._changed(); } // Clear cached curves used for winding direction and containment // calculation. @@ -327,7 +332,7 @@ var Path = PathItem.extend(/** @lends Path# */{ this._curves[length - 1] = new Curve(this, this._segments[length - 1], this._segments[0]); } - this._changed(/*#=*/ Change.GEOMETRY); + this._changed(/*#=*/ Change.SEGMENTS); } }, @@ -414,7 +419,7 @@ var Path = PathItem.extend(/** @lends Path# */{ // Adjust segments for the curves before and after the removed ones this._adjustCurves(from, to); } - this._changed(/*#=*/ Change.GEOMETRY); + this._changed(/*#=*/ Change.SEGMENTS); return segs; }, @@ -738,7 +743,7 @@ var Path = PathItem.extend(/** @lends Path# */{ // Adjust segments for the curves before and after the removed ones this._adjustCurves(index, index); } - this._changed(/*#=*/ Change.GEOMETRY); + this._changed(/*#=*/ Change.SEGMENTS); return removed; }, @@ -1280,7 +1285,6 @@ var Path = PathItem.extend(/** @lends Path# */{ last1.remove(); this.setClosed(true); } - this._changed(/*#=*/ Change.GEOMETRY); return true; } return false; diff --git a/src/path/Segment.js b/src/path/Segment.js index 6a5d7b85..8407fd2f 100644 --- a/src/path/Segment.js +++ b/src/path/Segment.js @@ -170,7 +170,7 @@ var Segment = Base.extend(/** @lends Segment# */{ && (curveOut = curves[index])) curveOut._changed(); } - path._changed(/*#=*/ Change.GEOMETRY); + path._changed(/*#=*/ Change.SEGMENTS); }, /**