Start implementing bounds caching the new way.

Work in progress still.
This commit is contained in:
Jürg Lehni 2011-11-24 15:37:44 +01:00
parent c989d3ee3f
commit 569c415b2f
3 changed files with 37 additions and 40 deletions

View file

@ -1256,11 +1256,34 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
// faster processing // faster processing
if (matrix && matrix.isIdentity()) if (matrix && matrix.isIdentity())
matrix = null; matrix = null;
// TODO: Caching! // See if we can cache these bounds. We only cache non-transformed
// bounds on items without children, as we do not receive hierarchy
// change notifiers from children, and walking up the parents and
// merging cache bounds is not expensive.
var cache = !this._children && !matrix
&& (this._boundsName[name] || name);
if (cache && this._bounds && this._bounds[cache])
return this._bounds[cache];
var bounds = this._getBounds(name, matrix); var bounds = this._getBounds(name, matrix);
return name == 'bounds' ? this._createBounds(bounds) : bounds; // TODO:
if (name == 'bounds')
bounds = this._createBounds(bounds);
// If we can cache the result, update the _bounds cache structure
// before returning
if (cache) {
if (!this._bounds)
this._bounds = {};
this._bounds[cache] = bounds;
}
return bounds;
}; };
}, /** @lends Item# */{ }, /** @lends Item# */{
/**
* Used internally to override caching names, so bound types can share their
* cache, in case they return the same results.
*/
_boundsName: {},
/** /**
* Internal method used in all the bounds getters. It loops through all the * Internal method used in all the bounds getters. It loops through all the
* children, gets their bounds and finds the bounds around all of them. * children, gets their bounds and finds the bounds around all of them.
@ -1301,17 +1324,6 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
rect.x, rect.y, rect.width, rect.height); rect.x, rect.y, rect.width, rect.height);
}, },
/**
* {@grouptitle Bounding Rectangles}
*
* The bounding rectangle of the item excluding stroke width.
* @type Rectangle
* @bean
*/
// getBounds: function(/* matrix */) {
// return this._getBounds('getBounds', '_bounds', arguments[0]);
// },
setBounds: function(rect) { setBounds: function(rect) {
rect = Rectangle.read(arguments); rect = Rectangle.read(arguments);
var bounds = this.getBounds(), var bounds = this.getBounds(),
@ -1333,26 +1345,25 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
this.transform(matrix); this.transform(matrix);
} }
/**
* {@grouptitle Bounding Rectangles}
*
* The bounding rectangle of the item excluding stroke width.
* @type Rectangle
* @bean
*/
/** /**
* The bounding rectangle of the item including stroke width. * The bounding rectangle of the item including stroke width.
* *
* @type Rectangle * @type Rectangle
* @bean * @bean
*/ */
// getStrokeBounds: function(/* matrix */) {
// return this._getBounds('getStrokeBounds', '_strokeBounds', arguments[0]);
// },
/** /**
* The bounding rectangle of the item including handles. * The bounding rectangle of the item including handles.
* *
* @type Rectangle * @type Rectangle
* @bean * @bean
*/ */
// getHandleBounds: function(/* matrix */) {
// return this._getBounds('getHandleBounds', '_handleBounds', arguments[0]);
// },
/** /**
* The rough bounding rectangle of the item that is shure to include all of * The rough bounding rectangle of the item that is shure to include all of
* the drawing, including stroke width. * the drawing, including stroke width.
@ -1361,9 +1372,6 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
* @bean * @bean
* @ignore * @ignore
*/ */
// getRoughBounds: function(/* matrix */) {
// return this._getBounds('getRoughBounds', '_roughBounds', arguments[0]);
// },
}), /** @lends Item# */{ }), /** @lends Item# */{
/** /**
* {@grouptitle Stroke Style} * {@grouptitle Stroke Style}
@ -1698,7 +1706,7 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
// TODO: Call transform on chidren only if 'children' flag is provided. // TODO: Call transform on chidren only if 'children' flag is provided.
// Calling _changed will clear _bounds and _position, but depending // Calling _changed will clear _bounds and _position, but depending
// on matrix we can calculate and set them again. // on matrix we can calculate and set them again.
var bounds = this._bounds, var bounds = null,// this._bounds,
position = this._position, position = this._position,
children = this._children; children = this._children;
if (this._transform) { if (this._transform) {
@ -1709,6 +1717,7 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
// and transform the cached _bounds and _position without having to // and transform the cached _bounds and _position without having to
// fully recalculate each time. // fully recalculate each time.
if (bounds && matrix.getRotation() % 90 === 0) { if (bounds && matrix.getRotation() % 90 === 0) {
// XXX: Bounds transition
// Transform the old _bounds without notifying it of changes // Transform the old _bounds without notifying it of changes
this._bounds = matrix._transformBounds(bounds, bounds, true); this._bounds = matrix._transformBounds(bounds, bounds, true);
// Update _position again, by linking it to _bounds // Update _position again, by linking it to _bounds

View file

@ -32,17 +32,6 @@ var PlacedItem = this.PlacedItem = Item.extend(/** @lends PlacedItem# */{
this._matrix.preConcatenate(matrix); this._matrix.preConcatenate(matrix);
}, },
_changed: function(flags) {
// Don't use base() for reasons of performance.
Item.prototype._changed.call(this, flags);
if (flags & ChangeFlag.GEOMETRY) {
delete this._strokeBounds;
// TODO: These are not used in Raster. Do we mind?
delete this._handleBounds;
delete this._roughBounds;
}
},
/** /**
* The item's transformation matrix, defining position and dimensions in the * The item's transformation matrix, defining position and dimensions in the
* document. * document.

View file

@ -64,14 +64,13 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
// Don't use base() for reasons of performance. // Don't use base() for reasons of performance.
Item.prototype._changed.call(this, flags); Item.prototype._changed.call(this, flags);
if (flags & ChangeFlag.GEOMETRY) { if (flags & ChangeFlag.GEOMETRY) {
delete this._strokeBounds;
delete this._handleBounds;
delete this._roughBounds;
delete this._length; delete this._length;
// Clockwise state becomes undefined as soon as geometry changes. // Clockwise state becomes undefined as soon as geometry changes.
delete this._clockwise; delete this._clockwise;
} else if (flags & ChangeFlag.STROKE) { } else if (flags & ChangeFlag.STROKE) {
delete this._strokeBounds; // TODO: We could preserve the purely geometric bounds that are not
// affected by stroke: _bounds.bounds and _bounds.handleBounds
delete this._bounds;
} }
}, },