Implement CompoundPath#_getWindings() and move #_contains() code for both Path and CompoundPath to PathItem.

This commit is contained in:
Jürg Lehni 2013-10-29 17:57:25 +01:00
parent 04286bc1e0
commit fc9cad009f
3 changed files with 21 additions and 46 deletions

View file

@ -185,40 +185,12 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
return paths.join(' ');
},
/**
* A private method to help with both #contains() and #_hitTest().
* Instead of simply returning a boolean, it returns a children of all the
* children that contain the point. This is required by _hitTest(), and
* Item#contains() is prepared for such a result.
*/
_contains: function(point) {
/*#*/ if (options.nativeContains) {
// To compare with native canvas approach:
var ctx = CanvasProvider.getContext(1, 1),
children = this._children,
param = Base.merge({ compound: true });
// Return early if the compound path doesn't have any children:
if (children.length === 0)
return false;
ctx.beginPath();
for (var i = 0, l = children.length; i < l; i++)
children[i]._draw(ctx, param);
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
CanvasProvider.release(ctx);
return res;
/*#*/ } else { // !options.nativeContains
// Compound paths are a little complex: In order to determine whether a
// point is inside a path or not due to the winding rule, we need to
// check all the children and count how many intersect. If it's an odd
// number, the point is inside the path. Once we know it's inside the
// path, _hitTest also needs access to the first intersecting element,
// for the HitResult, so we return it here.
_getWinding: function(point) {
var children = this._children,
winding = 0;
for (var i = 0, l = children.length; i < l; i++)
winding += children[i]._getWinding(point);
return !!(this.getWindingRule() === 'evenodd' ? winding & 1 : winding);
/*#*/ } // !options.nativeContains
return winding;
},
_hitTest : function _hitTest(point, options) {
@ -242,8 +214,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
},
_draw: function(ctx, param) {
var children = this._children,
style = this._style;
var children = this._children;
// Return early if the compound path doesn't have any children:
if (children.length === 0)
return;
@ -253,6 +224,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
children[i].draw(ctx, param);
if (!param.clip) {
this._setStyles(ctx);
var style = this._style;
if (style.getFillColor())
ctx.fill(style.getWindingRule());
if (style.getStrokeColor())

View file

@ -1727,20 +1727,6 @@ var Path = PathItem.extend(/** @lends Path# */{
return winding;
},
_contains: function(point) {
/*#*/ if (options.nativeContains) {
// To compare with native canvas approach:
var ctx = CanvasProvider.getContext(1, 1);
this._draw(ctx, Base.merge({ clip: true }));
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
CanvasProvider.release(ctx);
return res;
/*#*/ } else { // !options.nativeContains
var winding = this._getWinding(point);
return !!(this.getWindingRule() == 'evenodd' ? winding & 1 : winding);
/*#*/ } // !options.nativeContains
},
_hitTest: function(point, options) {
var style = this.getStyle(),
segments = this._segments,

View file

@ -184,6 +184,23 @@ var PathItem = Item.extend(/** @lends PathItem# */{
// A path with only a fill or a stroke can be directly blended, but if
// it has both, it needs to be drawn into a separate canvas first.
return !(this.hasFill() && this.hasStroke());
},
_contains: function(point) {
// NOTE: point is reverse transformed by _matrix, so we don't need to
// apply here.
/*#*/ if (options.nativeContains) {
// To compare with native canvas approach:
var ctx = CanvasProvider.getContext(1, 1);
// Abuse clip = true to get a shape for ctx.isPointInPath().
this._draw(ctx, Base.merge({ clip: true, transforms: [new Matrix()] }));
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
CanvasProvider.release(ctx);
return res;
/*#*/ } else { // !options.nativeContains
var winding = this._getWinding(point);
return !!(this.getWindingRule() === 'evenodd' ? winding & 1 : winding);
/*#*/ } // !options.nativeContains
}
/**