Skip to content

Commit fc9cad0

Browse files
committed
Implement CompoundPath#_getWindings() and move #_contains() code for both Path and CompoundPath to PathItem.
1 parent 04286bc commit fc9cad0

3 files changed

Lines changed: 21 additions & 46 deletions

File tree

src/path/CompoundPath.js

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -185,40 +185,12 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
185185
return paths.join(' ');
186186
},
187187

188-
/**
189-
* A private method to help with both #contains() and #_hitTest().
190-
* Instead of simply returning a boolean, it returns a children of all the
191-
* children that contain the point. This is required by _hitTest(), and
192-
* Item#contains() is prepared for such a result.
193-
*/
194-
_contains: function(point) {
195-
/*#*/ if (options.nativeContains) {
196-
// To compare with native canvas approach:
197-
var ctx = CanvasProvider.getContext(1, 1),
198-
children = this._children,
199-
param = Base.merge({ compound: true });
200-
// Return early if the compound path doesn't have any children:
201-
if (children.length === 0)
202-
return false;
203-
ctx.beginPath();
204-
for (var i = 0, l = children.length; i < l; i++)
205-
children[i]._draw(ctx, param);
206-
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
207-
CanvasProvider.release(ctx);
208-
return res;
209-
/*#*/ } else { // !options.nativeContains
210-
// Compound paths are a little complex: In order to determine whether a
211-
// point is inside a path or not due to the winding rule, we need to
212-
// check all the children and count how many intersect. If it's an odd
213-
// number, the point is inside the path. Once we know it's inside the
214-
// path, _hitTest also needs access to the first intersecting element,
215-
// for the HitResult, so we return it here.
188+
_getWinding: function(point) {
216189
var children = this._children,
217190
winding = 0;
218191
for (var i = 0, l = children.length; i < l; i++)
219192
winding += children[i]._getWinding(point);
220-
return !!(this.getWindingRule() === 'evenodd' ? winding & 1 : winding);
221-
/*#*/ } // !options.nativeContains
193+
return winding;
222194
},
223195

224196
_hitTest : function _hitTest(point, options) {
@@ -242,8 +214,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
242214
},
243215

244216
_draw: function(ctx, param) {
245-
var children = this._children,
246-
style = this._style;
217+
var children = this._children;
247218
// Return early if the compound path doesn't have any children:
248219
if (children.length === 0)
249220
return;
@@ -253,6 +224,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
253224
children[i].draw(ctx, param);
254225
if (!param.clip) {
255226
this._setStyles(ctx);
227+
var style = this._style;
256228
if (style.getFillColor())
257229
ctx.fill(style.getWindingRule());
258230
if (style.getStrokeColor())

src/path/Path.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,20 +1727,6 @@ var Path = PathItem.extend(/** @lends Path# */{
17271727
return winding;
17281728
},
17291729

1730-
_contains: function(point) {
1731-
/*#*/ if (options.nativeContains) {
1732-
// To compare with native canvas approach:
1733-
var ctx = CanvasProvider.getContext(1, 1);
1734-
this._draw(ctx, Base.merge({ clip: true }));
1735-
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
1736-
CanvasProvider.release(ctx);
1737-
return res;
1738-
/*#*/ } else { // !options.nativeContains
1739-
var winding = this._getWinding(point);
1740-
return !!(this.getWindingRule() == 'evenodd' ? winding & 1 : winding);
1741-
/*#*/ } // !options.nativeContains
1742-
},
1743-
17441730
_hitTest: function(point, options) {
17451731
var style = this.getStyle(),
17461732
segments = this._segments,

src/path/PathItem.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,23 @@ var PathItem = Item.extend(/** @lends PathItem# */{
184184
// A path with only a fill or a stroke can be directly blended, but if
185185
// it has both, it needs to be drawn into a separate canvas first.
186186
return !(this.hasFill() && this.hasStroke());
187+
},
188+
189+
_contains: function(point) {
190+
// NOTE: point is reverse transformed by _matrix, so we don't need to
191+
// apply here.
192+
/*#*/ if (options.nativeContains) {
193+
// To compare with native canvas approach:
194+
var ctx = CanvasProvider.getContext(1, 1);
195+
// Abuse clip = true to get a shape for ctx.isPointInPath().
196+
this._draw(ctx, Base.merge({ clip: true, transforms: [new Matrix()] }));
197+
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
198+
CanvasProvider.release(ctx);
199+
return res;
200+
/*#*/ } else { // !options.nativeContains
201+
var winding = this._getWinding(point);
202+
return !!(this.getWindingRule() === 'evenodd' ? winding & 1 : winding);
203+
/*#*/ } // !options.nativeContains
187204
}
188205

189206
/**

0 commit comments

Comments
 (0)