mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
parent
0fe52a7d39
commit
438de7013a
6 changed files with 64 additions and 44 deletions
|
@ -106,18 +106,22 @@ var Group = Item.extend(/** @lends Group# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
_getClipItem: function() {
|
_getClipItem: function() {
|
||||||
// Allow us to set _clipItem to null when none is found and still return
|
// NOTE: _clipItem is the child that has _clipMask set to true.
|
||||||
// it as a defined value without searching again
|
var clipItem = this._clipItem;
|
||||||
if (this._clipItem !== undefined)
|
// Distinguish null (no clipItem set) and undefined (clipItem was not
|
||||||
return this._clipItem;
|
// looked for yet).
|
||||||
for (var i = 0, l = this._children.length; i < l; i++) {
|
if (clipItem === undefined) {
|
||||||
var child = this._children[i];
|
clipItem = null;
|
||||||
if (child._clipMask)
|
for (var i = 0, l = this._children.length; i < l; i++) {
|
||||||
return this._clipItem = child;
|
var child = this._children[i];
|
||||||
|
if (child._clipMask) {
|
||||||
|
clipItem = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._clipItem = clipItem;
|
||||||
}
|
}
|
||||||
// Make sure we're setting _clipItem to null so it won't be searched for
|
return clipItem;
|
||||||
// nex time.
|
|
||||||
return this._clipItem = null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,14 +168,33 @@ var Group = Item.extend(/** @lends Group# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
_draw: function(ctx, param) {
|
_draw: function(ctx, param) {
|
||||||
var clipItem = param.clipItem = this._getClipItem();
|
var clip = param.clip,
|
||||||
if (clipItem)
|
clipItem = !clip && this._getClipItem(),
|
||||||
|
draw = true;
|
||||||
|
param = param.extend({ clipItem: clipItem, clip: false });
|
||||||
|
if (clip) {
|
||||||
|
// If told to clip with a group, we start our own path and draw each
|
||||||
|
// child just like in a compound-path. We also cache the resulting
|
||||||
|
// path in _currentPath.
|
||||||
|
if (this._currentPath) {
|
||||||
|
ctx.currentPath = this._currentPath;
|
||||||
|
draw = false;
|
||||||
|
} else {
|
||||||
|
ctx.beginPath();
|
||||||
|
param.dontStart = param.dontFinish = true;
|
||||||
|
}
|
||||||
|
} else if (clipItem) {
|
||||||
clipItem.draw(ctx, param.extend({ clip: true }));
|
clipItem.draw(ctx, param.extend({ clip: true }));
|
||||||
for (var i = 0, l = this._children.length; i < l; i++) {
|
|
||||||
var item = this._children[i];
|
|
||||||
if (item !== clipItem)
|
|
||||||
item.draw(ctx, param);
|
|
||||||
}
|
}
|
||||||
param.clipItem = null;
|
if (draw) {
|
||||||
|
for (var i = 0, l = this._children.length; i < l; i++) {
|
||||||
|
var item = this._children[i];
|
||||||
|
if (item !== clipItem)
|
||||||
|
item.draw(ctx, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (clip) {
|
||||||
|
this._currentPath = ctx.currentPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -238,9 +238,11 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
cacheParent = this._parent || symbol,
|
cacheParent = this._parent || symbol,
|
||||||
project = this._project;
|
project = this._project;
|
||||||
if (flags & /*#=*/ ChangeFlag.GEOMETRY) {
|
if (flags & /*#=*/ ChangeFlag.GEOMETRY) {
|
||||||
// Clear cached bounds and position whenever geometry changes
|
// Clear cached bounds, position and decomposed matrix whenever
|
||||||
|
// geometry changes. Also clear _currentPath since it can be used
|
||||||
|
// both on compound-paths and clipping groups.
|
||||||
this._bounds = this._position = this._decomposed =
|
this._bounds = this._position = this._decomposed =
|
||||||
this._globalMatrix = undefined;
|
this._globalMatrix = this._currentPath = undefined;
|
||||||
}
|
}
|
||||||
if (cacheParent && (flags
|
if (cacheParent && (flags
|
||||||
& (/*#=*/ ChangeFlag.GEOMETRY | /*#=*/ ChangeFlag.STROKE))) {
|
& (/*#=*/ ChangeFlag.GEOMETRY | /*#=*/ ChangeFlag.STROKE))) {
|
||||||
|
@ -3509,6 +3511,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
// Determine if we can draw directly, or if we need to draw into a
|
// Determine if we can draw directly, or if we need to draw into a
|
||||||
// separate canvas and then composite onto the main canvas.
|
// separate canvas and then composite onto the main canvas.
|
||||||
direct = normalBlend && opacity === 1
|
direct = normalBlend && opacity === 1
|
||||||
|
|| param.clip
|
||||||
// If native blending is possible, see if the item allows it
|
// If native blending is possible, see if the item allows it
|
||||||
|| (nativeBlend || normalBlend && opacity < 1)
|
|| (nativeBlend || normalBlend && opacity < 1)
|
||||||
&& this._canComposite(),
|
&& this._canComposite(),
|
||||||
|
@ -3554,7 +3557,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
if (trackTransforms)
|
if (trackTransforms)
|
||||||
transforms.pop();
|
transforms.pop();
|
||||||
if (param.clip)
|
if (param.clip && !param.dontFinish)
|
||||||
ctx.clip();
|
ctx.clip();
|
||||||
// If a temporary canvas was created, composite it onto the main canvas:
|
// If a temporary canvas was created, composite it onto the main canvas:
|
||||||
if (!direct) {
|
if (!direct) {
|
||||||
|
|
|
@ -169,11 +169,12 @@ var Shape = Item.extend(/** @lends Shape# */{
|
||||||
var style = this._style,
|
var style = this._style,
|
||||||
hasFill = style.hasFill(),
|
hasFill = style.hasFill(),
|
||||||
hasStroke = style.hasStroke(),
|
hasStroke = style.hasStroke(),
|
||||||
clip = param.clip;
|
dontPaint = param.dontFinish || param.clip;
|
||||||
if (hasFill || hasStroke || clip) {
|
if (hasFill || hasStroke || dontPaint) {
|
||||||
var radius = this._radius,
|
var radius = this._radius,
|
||||||
shape = this._shape;
|
shape = this._shape;
|
||||||
ctx.beginPath();
|
if (!param.dontStart)
|
||||||
|
ctx.beginPath();
|
||||||
if (shape === 'circle') {
|
if (shape === 'circle') {
|
||||||
ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
|
ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -217,7 +218,7 @@ var Shape = Item.extend(/** @lends Shape# */{
|
||||||
}
|
}
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
}
|
}
|
||||||
if (!clip && (hasFill || hasStroke)) {
|
if (!dontPaint && (hasFill || hasStroke)) {
|
||||||
this._setStyles(ctx);
|
this._setStyles(ctx);
|
||||||
if (hasFill) {
|
if (hasFill) {
|
||||||
ctx.fill(style.getWindingRule());
|
ctx.fill(style.getWindingRule());
|
||||||
|
|
|
@ -101,13 +101,6 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_changed: function _changed(flags) {
|
|
||||||
_changed.base.call(this, flags);
|
|
||||||
// Clear cached native Path
|
|
||||||
if (flags & (/*#=*/ ChangeFlag.HIERARCHY | /*#=*/ ChangeFlag.GEOMETRY))
|
|
||||||
this._currentPath = undefined;
|
|
||||||
},
|
|
||||||
|
|
||||||
insertChildren: function insertChildren(index, items, _preserve) {
|
insertChildren: function insertChildren(index, items, _preserve) {
|
||||||
// Pass on 'path' for _type, to make sure that only paths are added as
|
// Pass on 'path' for _type, to make sure that only paths are added as
|
||||||
// children.
|
// children.
|
||||||
|
@ -254,8 +247,8 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
|
||||||
if (this._currentPath) {
|
if (this._currentPath) {
|
||||||
ctx.currentPath = this._currentPath;
|
ctx.currentPath = this._currentPath;
|
||||||
} else {
|
} else {
|
||||||
|
param = param.extend({ dontStart: true, dontFinish: true });
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
param = param.extend({ compound: true });
|
|
||||||
for (var i = 0, l = children.length; i < l; i++)
|
for (var i = 0, l = children.length; i < l; i++)
|
||||||
children[i].draw(ctx, param);
|
children[i].draw(ctx, param);
|
||||||
this._currentPath = ctx.currentPath;
|
this._currentPath = ctx.currentPath;
|
||||||
|
|
|
@ -2008,10 +2008,9 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_draw: function(ctx, param) {
|
_draw: function(ctx, param) {
|
||||||
var clip = param.clip,
|
var dontStart = param.dontStart,
|
||||||
// Also mark this Path as _compound so _changed() knows about it
|
dontPaint = param.dontFinish || param.clip;
|
||||||
compound = this._compound = param.compound;
|
if (!dontStart)
|
||||||
if (!compound)
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
|
||||||
var style = this.getStyle(),
|
var style = this.getStyle(),
|
||||||
|
@ -2028,20 +2027,20 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
return dashArray[((i % dashLength) + dashLength) % dashLength];
|
return dashArray[((i % dashLength) + dashLength) % dashLength];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._currentPath) {
|
if (!dontStart && this._currentPath) {
|
||||||
ctx.currentPath = this._currentPath;
|
ctx.currentPath = this._currentPath;
|
||||||
} else if (hasFill || hasStroke && !dashLength || compound || clip){
|
} else if (hasFill || hasStroke && !dashLength || dontPaint) {
|
||||||
// Prepare the canvas path if we have any situation that
|
// Prepare the canvas path if we have any situation that
|
||||||
// requires it to be defined.
|
// requires it to be defined.
|
||||||
drawSegments(ctx, this);
|
drawSegments(ctx, this);
|
||||||
if (this._closed)
|
if (this._closed)
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
// CompoundPath collects its own _currentPath
|
// CompoundPath collects its own _currentPath
|
||||||
if (!compound)
|
if (!dontStart)
|
||||||
this._currentPath = ctx.currentPath;
|
this._currentPath = ctx.currentPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clip && !compound && (hasFill || hasStroke)) {
|
if (!dontPaint && (hasFill || hasStroke)) {
|
||||||
// If the path is part of a compound path or doesn't have a fill
|
// If the path is part of a compound path or doesn't have a fill
|
||||||
// or stroke, there is no need to continue.
|
// or stroke, there is no need to continue.
|
||||||
this._setStyles(ctx);
|
this._setStyles(ctx);
|
||||||
|
@ -2059,7 +2058,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
// NOTE: We don't cache this path in another currentPath
|
// NOTE: We don't cache this path in another currentPath
|
||||||
// since browsers that support currentPath also support
|
// since browsers that support currentPath also support
|
||||||
// native dashes.
|
// native dashes.
|
||||||
ctx.beginPath();
|
if (!dontStart)
|
||||||
|
ctx.beginPath();
|
||||||
var flattener = new PathFlattener(this),
|
var flattener = new PathFlattener(this),
|
||||||
length = flattener.length,
|
length = flattener.length,
|
||||||
from = -style.getDashOffset(), to,
|
from = -style.getDashOffset(), to,
|
||||||
|
|
|
@ -309,8 +309,8 @@ var PathItem = Item.extend(/** @lends PathItem# */{
|
||||||
/*#*/ if (__options.nativeContains || !__options.booleanOperations) {
|
/*#*/ if (__options.nativeContains || !__options.booleanOperations) {
|
||||||
// To compare with native canvas approach:
|
// To compare with native canvas approach:
|
||||||
var ctx = CanvasProvider.getContext(1, 1);
|
var ctx = CanvasProvider.getContext(1, 1);
|
||||||
// Abuse clip = true to get a shape for ctx.isPointInPath().
|
// Use dontFinish to tell _draw to only produce geometries for hit-test.
|
||||||
this._draw(ctx, new Base({ clip: true }));
|
this._draw(ctx, new Base({ dontFinish: true }));
|
||||||
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
|
var res = ctx.isPointInPath(point.x, point.y, this.getWindingRule());
|
||||||
CanvasProvider.release(ctx);
|
CanvasProvider.release(ctx);
|
||||||
return res;
|
return res;
|
||||||
|
|
Loading…
Reference in a new issue