mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-19 14:10:14 -05:00
Big refactoring of the way bounds are handled and cached, properly supporting Groups inside Symbols, and also adding #roughBounds, to be used by upcoming hit testing code.
This commit is contained in:
parent
10b0062ce2
commit
45a3e7f873
5 changed files with 94 additions and 35 deletions
|
@ -1042,8 +1042,8 @@ var Item = this.Item = Base.extend(/** @lends Item# */{
|
|||
* @type Rectangle
|
||||
* @bean
|
||||
*/
|
||||
getBounds: function() {
|
||||
return this._getBounds('getBounds');
|
||||
getBounds: function(/* matrix */) {
|
||||
return this._getBounds('getBounds', '_bounds', arguments);
|
||||
},
|
||||
|
||||
setBounds: function(rect) {
|
||||
|
@ -1073,8 +1073,8 @@ var Item = this.Item = Base.extend(/** @lends Item# */{
|
|||
* @type Rectangle
|
||||
* @bean
|
||||
*/
|
||||
getStrokeBounds: function() {
|
||||
return this._getBounds('getStrokeBounds');
|
||||
getStrokeBounds: function(/* matrix */) {
|
||||
return this._getBounds('getStrokeBounds', '_strokeBounds', arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1083,15 +1083,30 @@ var Item = this.Item = Base.extend(/** @lends Item# */{
|
|||
* @type Rectangle
|
||||
* @bean
|
||||
*/
|
||||
getHandleBounds: function() {
|
||||
return this._getBounds('getHandleBounds');
|
||||
getHandleBounds: function(/* matrix */) {
|
||||
return this._getBounds('getHandleBounds', '_handleBounds', arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* The rough bounding rectangle of the item that is shure to include all of
|
||||
* the drawing, including stroke width.
|
||||
*
|
||||
* @type Rectangle
|
||||
* @bean
|
||||
* @ignore
|
||||
*/
|
||||
getRoughBounds: function(/* matrix */) {
|
||||
return this._getBounds('getRoughBounds', '_roughBounds', arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* Loops through all children, gets their bounds and finds the bounds around
|
||||
* all of them.
|
||||
*/
|
||||
_getBounds: function(getter) {
|
||||
_getBounds: function(getter, cacheName, args) {
|
||||
// Note: We cannot cache these results here, since we do not get
|
||||
// _changed() notifications here for changing geometry in children.
|
||||
// But cacheName is used in sub-classes such as PlacedItem.
|
||||
var children = this._children;
|
||||
// TODO: What to return if nothing is defined, e.g. empty Groups?
|
||||
// Scriptographer behaves weirdly then too.
|
||||
|
@ -1104,7 +1119,7 @@ var Item = this.Item = Base.extend(/** @lends Item# */{
|
|||
for (var i = 0, l = children.length; i < l; i++) {
|
||||
var child = children[i];
|
||||
if (child._visible) {
|
||||
var rect = child[getter]();
|
||||
var rect = child[getter](args[0]);
|
||||
x1 = Math.min(rect.x, x1);
|
||||
y1 = Math.min(rect.y, y1);
|
||||
x2 = Math.max(rect.x + rect.width, x2);
|
||||
|
@ -1535,6 +1550,8 @@ var Item = this.Item = Base.extend(/** @lends Item# */{
|
|||
* path.fitBounds(view.bounds);
|
||||
*/
|
||||
fitBounds: function(rectangle, fill) {
|
||||
// TODO: Think about passing options with various ways of defining
|
||||
// fitting.
|
||||
rectangle = Rectangle.read(arguments);
|
||||
var bounds = this.getBounds(),
|
||||
itemRatio = bounds.height / bounds.width,
|
||||
|
|
|
@ -32,6 +32,17 @@ 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.
|
||||
|
@ -48,7 +59,30 @@ var PlacedItem = this.PlacedItem = Item.extend(/** @lends PlacedItem# */{
|
|||
this._changed(Change.GEOMETRY);
|
||||
},
|
||||
|
||||
getStrokeBounds: function() {
|
||||
return this.getBounds();
|
||||
getBounds: function(/* matrix */) {
|
||||
// The bounds of PlacedItems are the same as the strokeBounds, but are
|
||||
// wrapped in a LinkedRectangle that catch changes for us.
|
||||
var useCache = arguments[0] === undefined;
|
||||
if (useCache && this._bounds)
|
||||
return this._bounds;
|
||||
var bounds = this.getStrokeBounds(arguments[0]);
|
||||
if (useCache)
|
||||
bounds = this._bounds = this._createBounds(bounds);
|
||||
return bounds;
|
||||
},
|
||||
|
||||
_getBounds: function(getter, cacheName, args) {
|
||||
var matrix = args[0],
|
||||
useCache = matrix === undefined;
|
||||
if (useCache && this[cacheName])
|
||||
return this[cacheName];
|
||||
matrix = matrix ? matrix.clone().concatenate(this._matrix)
|
||||
: this._matrix;
|
||||
// Call _calculateBounds, which needs to be defined in the subclasses:
|
||||
var bounds = this._calculateBounds(getter, matrix);
|
||||
// TODO: Clear cache
|
||||
if (useCache)
|
||||
this[cacheName] = bounds;
|
||||
return bounds;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -71,6 +71,9 @@ var PlacedSymbol = this.PlacedSymbol = PlacedItem.extend(/** @lends PlacedSymbol
|
|||
: new Matrix();
|
||||
},
|
||||
|
||||
// TODO: Symbols need to register their placed instances, so whenever a
|
||||
// symbol definition changes, all instances are notified through _changed()
|
||||
|
||||
/**
|
||||
* The symbol that the placed symbol refers to:
|
||||
*
|
||||
|
@ -82,12 +85,9 @@ var PlacedSymbol = this.PlacedSymbol = PlacedItem.extend(/** @lends PlacedSymbol
|
|||
return this._clone(new PlacedSymbol(this.symbol, this._matrix.clone()));
|
||||
},
|
||||
|
||||
getBounds: function() {
|
||||
if (!this._bounds) {
|
||||
this._bounds = this._createBounds(
|
||||
this.symbol._definition.getStrokeBounds(this._matrix));
|
||||
}
|
||||
return this._bounds;
|
||||
_calculateBounds: function(getter, matrix) {
|
||||
// Ask the symbol definition to calculate the bounds for us
|
||||
return this.symbol._definition[getter](matrix);
|
||||
},
|
||||
|
||||
draw: function(ctx, param) {
|
||||
|
|
|
@ -368,11 +368,21 @@ var Raster = this.Raster = PlacedItem.extend(/** @lends Raster# */{
|
|||
this.getContext(true).putImageData(data, point.x, point.y);
|
||||
},
|
||||
|
||||
getBounds: function() {
|
||||
if (!this._bounds)
|
||||
this._bounds = this._createBounds(this._matrix._transformBounds(
|
||||
new Rectangle(this._size).setCenter(0, 0)));
|
||||
return this._bounds;
|
||||
_calculateBounds: function(getter, matrix) {
|
||||
// The getter is only used for PlacedSymbol, not Raster
|
||||
return matrix._transformBounds(
|
||||
new Rectangle(this._size).setCenter(0, 0));
|
||||
},
|
||||
|
||||
// Since Raster doesn't make the distinction between the different bounds,
|
||||
// simply redirect to strokeBounds so the cached values can be reused.
|
||||
|
||||
getHandleBounds: function(/* matrix */) {
|
||||
return this.getStrokeBounds(arguments[0]);
|
||||
},
|
||||
|
||||
getRoughBounds: function(/* matrix */) {
|
||||
return this.getStrokeBounds(arguments[0]);
|
||||
},
|
||||
|
||||
draw: function(ctx, param) {
|
||||
|
|
|
@ -1787,16 +1787,15 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
* @ignore
|
||||
*/
|
||||
getBounds: function(/* matrix */) {
|
||||
var useCache = arguments.length == 0;
|
||||
var useCache = arguments[0] === undefined;
|
||||
// Pass the matrix hidden from Bootstrap, so it still inject
|
||||
// getBounds as bean too.
|
||||
if (!useCache || !this._bounds) {
|
||||
var bounds = this._createBounds(getBounds(this, arguments[0]));
|
||||
if (useCache)
|
||||
this._bounds = bounds;
|
||||
return bounds;
|
||||
}
|
||||
return this._bounds;
|
||||
if (useCache && this._bounds)
|
||||
return this._bounds;
|
||||
var bounds = this._createBounds(getBounds(this, arguments[0]));
|
||||
if (useCache)
|
||||
this._bounds = bounds;
|
||||
return bounds;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1807,8 +1806,8 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
getStrokeBounds: function(/* matrix */) {
|
||||
if (!this._style._strokeColor || !this._style._strokeWidth)
|
||||
return this.getBounds.apply(this, arguments);
|
||||
var useCache = arguments.length == 0;
|
||||
if (this._strokeBounds && useCache)
|
||||
var useCache = arguments[0] === undefined;
|
||||
if (useCache && this._strokeBounds)
|
||||
return this._strokeBounds;
|
||||
var matrix = arguments[0], // set #getBounds()
|
||||
width = this.getStrokeWidth(),
|
||||
|
@ -1915,7 +1914,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
getHandleBounds: function(/* matrix, stroke, join */) {
|
||||
var matrix = arguments[0],
|
||||
useCache = matrix === undefined;
|
||||
if (this._handleBounds && useCache)
|
||||
if (useCache && this._handleBounds)
|
||||
return this._handleBounds;
|
||||
var coords = new Array(6),
|
||||
stroke = arguments[1] / 2 || 0, // Stroke padding
|
||||
|
@ -1963,9 +1962,8 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
|
|||
* @ignore
|
||||
*/
|
||||
getRoughBounds: function(/* matrix */) {
|
||||
var matrix = arguments[0],
|
||||
useCache = matrix === undefined;
|
||||
if (this._roughBounds && useCache)
|
||||
var useCache = arguments[0] === undefined;
|
||||
if (useCache && this._roughBounds)
|
||||
return this._roughBounds;
|
||||
// Delegate to #getHandleBounds(), but pass on radius values for
|
||||
// stroke and joins. Hanlde miter joins specially, by passing the
|
||||
|
|
Loading…
Reference in a new issue