From 569c415b2f3b49a988133c05f3b992ca4acf7397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Thu, 24 Nov 2011 15:37:44 +0100 Subject: [PATCH] Start implementing bounds caching the new way. Work in progress still. --- src/item/Item.js | 59 ++++++++++++++++++++++++------------------ src/item/PlacedItem.js | 11 -------- src/path/Path.js | 7 +++-- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/src/item/Item.js b/src/item/Item.js index 61985d38..75db1c23 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -1256,11 +1256,34 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{ // faster processing if (matrix && matrix.isIdentity()) 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); - 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# */{ + /** + * 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 * 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); }, - /** - * {@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) { rect = Rectangle.read(arguments); var bounds = this.getBounds(), @@ -1333,26 +1345,25 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{ 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. * * @type Rectangle * @bean */ -// getStrokeBounds: function(/* matrix */) { -// return this._getBounds('getStrokeBounds', '_strokeBounds', arguments[0]); -// }, - /** * The bounding rectangle of the item including handles. * * @type Rectangle * @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 drawing, including stroke width. @@ -1361,9 +1372,6 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{ * @bean * @ignore */ -// getRoughBounds: function(/* matrix */) { -// return this._getBounds('getRoughBounds', '_roughBounds', arguments[0]); -// }, }), /** @lends Item# */{ /** * {@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. // Calling _changed will clear _bounds and _position, but depending // on matrix we can calculate and set them again. - var bounds = this._bounds, + var bounds = null,// this._bounds, position = this._position, children = this._children; 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 // fully recalculate each time. if (bounds && matrix.getRotation() % 90 === 0) { + // XXX: Bounds transition // Transform the old _bounds without notifying it of changes this._bounds = matrix._transformBounds(bounds, bounds, true); // Update _position again, by linking it to _bounds diff --git a/src/item/PlacedItem.js b/src/item/PlacedItem.js index 1e237823..7b237e79 100644 --- a/src/item/PlacedItem.js +++ b/src/item/PlacedItem.js @@ -32,17 +32,6 @@ var PlacedItem = this.PlacedItem = Item.extend(/** @lends PlacedItem# */{ 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 * document. diff --git a/src/path/Path.js b/src/path/Path.js index 50cb03c5..9ee95f02 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -64,14 +64,13 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ // Don't use base() for reasons of performance. Item.prototype._changed.call(this, flags); if (flags & ChangeFlag.GEOMETRY) { - delete this._strokeBounds; - delete this._handleBounds; - delete this._roughBounds; delete this._length; // Clockwise state becomes undefined as soon as geometry changes. delete this._clockwise; } 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; } },