Implement an optimization in _changed() notifications where not all curves need to updated if only segments change that already have told their curves about the change.

This commit is contained in:
Jürg Lehni 2014-03-17 14:35:33 +01:00
parent 72ba453ba2
commit 0fe52a7d39
3 changed files with 27 additions and 19 deletions

View file

@ -13,23 +13,26 @@
var ChangeFlag = { var ChangeFlag = {
// Anything affecting the appearance of an item, including GEOMETRY, // Anything affecting the appearance of an item, including GEOMETRY,
// STROKE, STYLE and ATTRIBUTE (except for the invisible ones: locked, name) // STROKE, STYLE and ATTRIBUTE (except for the invisible ones: locked, name)
APPEARANCE: 1, APPEARANCE: 0x1,
// Change in item hierarchy // Change in item hierarchy
HIERARCHY: 2, HIERARCHY: 0x2,
// Item geometry (path, bounds) // 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 geometry (excluding color)
STROKE: 8, STROKE: 0x10,
// Fill style or stroke color / dash // Fill style or stroke color / dash
STYLE: 16, STYLE: 0x20,
// Item attributes: visible, blendMode, locked, name, opacity, clipMask ... // Item attributes: visible, blendMode, locked, name, opacity, clipMask ...
ATTRIBUTE: 32, ATTRIBUTE: 0x40,
// Text content // Text content
CONTENT: 64, CONTENT: 0x80,
// Raster pixels // Raster pixels
PIXELS: 128, PIXELS: 0x100,
// Clipping in one of the child items // Clipping in one of the child items
CLIPPING: 256 CLIPPING: 0x200
}; };
// Shortcuts to often used ChangeFlag values including APPEARANCE // Shortcuts to often used ChangeFlag values including APPEARANCE
@ -39,6 +42,7 @@ var Change = {
HIERARCHY: ChangeFlag.HIERARCHY | ChangeFlag.GEOMETRY HIERARCHY: ChangeFlag.HIERARCHY | ChangeFlag.GEOMETRY
| ChangeFlag.APPEARANCE, | ChangeFlag.APPEARANCE,
GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE, GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
SEGMENTS: ChangeFlag.SEGMENTS | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
STROKE: ChangeFlag.STROKE | ChangeFlag.STYLE | ChangeFlag.APPEARANCE, STROKE: ChangeFlag.STROKE | ChangeFlag.STYLE | ChangeFlag.APPEARANCE,
STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE, STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE,
ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE, ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE,

View file

@ -138,14 +138,19 @@ var Path = PathItem.extend(/** @lends Path# */{
_changed: function _changed(flags) { _changed: function _changed(flags) {
_changed.base.call(this, flags); _changed.base.call(this, flags);
if (flags & /*#=*/ ChangeFlag.GEOMETRY) { if (flags & /*#=*/ ChangeFlag.GEOMETRY) {
// Clear cached native Path // Clear cached native Path. Clear on the parent too, for
(this._compound ? this._parent : this)._currentPath = undefined; // 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. // Clockwise state becomes undefined as soon as geometry changes.
this._length = this._clockwise = undefined; this._length = this._clockwise = undefined;
// Curves are no longer valid // Only notify all curves if we're not told that only one Segment
if (this._curves) { // 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++) 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 // Clear cached curves used for winding direction and containment
// calculation. // calculation.
@ -327,7 +332,7 @@ var Path = PathItem.extend(/** @lends Path# */{
this._curves[length - 1] = new Curve(this, this._curves[length - 1] = new Curve(this,
this._segments[length - 1], this._segments[0]); 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 // Adjust segments for the curves before and after the removed ones
this._adjustCurves(from, to); this._adjustCurves(from, to);
} }
this._changed(/*#=*/ Change.GEOMETRY); this._changed(/*#=*/ Change.SEGMENTS);
return segs; return segs;
}, },
@ -738,7 +743,7 @@ var Path = PathItem.extend(/** @lends Path# */{
// Adjust segments for the curves before and after the removed ones // Adjust segments for the curves before and after the removed ones
this._adjustCurves(index, index); this._adjustCurves(index, index);
} }
this._changed(/*#=*/ Change.GEOMETRY); this._changed(/*#=*/ Change.SEGMENTS);
return removed; return removed;
}, },
@ -1280,7 +1285,6 @@ var Path = PathItem.extend(/** @lends Path# */{
last1.remove(); last1.remove();
this.setClosed(true); this.setClosed(true);
} }
this._changed(/*#=*/ Change.GEOMETRY);
return true; return true;
} }
return false; return false;

View file

@ -170,7 +170,7 @@ var Segment = Base.extend(/** @lends Segment# */{
&& (curveOut = curves[index])) && (curveOut = curves[index]))
curveOut._changed(); curveOut._changed();
} }
path._changed(/*#=*/ Change.GEOMETRY); path._changed(/*#=*/ Change.SEGMENTS);
}, },
/** /**