-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor masks, in progress #368
base: refactor-timing
Are you sure you want to change the base?
Changes from all commits
aa9b4fa
987e59c
1705928
24d5377
8eb2285
5d03c50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -744,101 +744,141 @@ Element.prototype._checkSwitcher = function(next) { | |
*/ | ||
// > Element.render % (ctx: Context, gtime: Float, dt: Float) | ||
Element.prototype.render = function(ctx) { | ||
if (this.disabled || !this.active || this.isMask) return; | ||
if (this.disabled || !this.active) return; | ||
|
||
this.rendering = true; | ||
|
||
if (this.visible) { | ||
ctx.save(); | ||
|
||
if (!this.$mask) { | ||
// draw directly to context, if has no mask | ||
if (!this.isMask && !this.$mask) { | ||
|
||
ctx.save(); | ||
|
||
this.transform(ctx); | ||
this.painters(ctx); | ||
this.each(function(child) { | ||
child.render(ctx); | ||
}); | ||
} else { | ||
// FIXME: the complete mask process should be a Painter. | ||
var mask = this.$mask; | ||
|
||
mask.ensureHasMaskCanvas(); | ||
var mcvs = mask.__maskCvs, | ||
mctx = mask.__maskCtx, | ||
bcvs = mask.__backCvs, | ||
bctx = mask.__backCtx; | ||
|
||
// FIXME: test if bounds are not empty | ||
var bounds_pts = mask.bounds().toPoints(); | ||
|
||
var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, | ||
maxX = Number.MIN_VALUE, maxY = Number.MIN_VALUE; | ||
|
||
var pt; | ||
for (var i = 0, il = bounds_pts.length; i < il; i++) { | ||
pt = bounds_pts[i]; | ||
if (pt.x < minX) minX = pt.x; | ||
if (pt.y < minY) minY = pt.y; | ||
if (pt.x > maxX) maxX = pt.x; | ||
if (pt.y > maxY) maxY = pt.y; | ||
} | ||
|
||
var ratio = engine.PX_RATIO, | ||
x = minX, y = minY, | ||
width = Math.round(maxX - minX), | ||
height = Math.round(maxY - minY); | ||
ctx.restore(); | ||
|
||
var last_cvs_size = this._maskCvsSize || engine.getCanvasSize(mcvs); | ||
} else if (this.isMask) { // this element is a mask | ||
|
||
if ((last_cvs_size[0] < width) || | ||
(last_cvs_size[1] < height)) { | ||
// mcvs/bcvs both always have the same size, so we save/check only one of them | ||
this._maskCvsSize = engine.setCanvasSize(mcvs, width, height); | ||
engine.setCanvasSize(bcvs, width, height); | ||
} else { | ||
this._maskCvsSize = last_cvs_size; | ||
} | ||
this._renderAsMask(); | ||
|
||
var scale = ratio; // multiple by global scale when it's known | ||
} else if (this.$mask) { // this element is masked | ||
|
||
bctx.clearRect(0, 0, width*scale, height*scale); | ||
mctx.clearRect(0, 0, width*scale, height*scale); | ||
ctx.save(); | ||
this._renderAsMasked(ctx); | ||
ctx.restore(); | ||
|
||
bctx.save(); | ||
mctx.save(); | ||
} | ||
|
||
bctx.setTransform(scale, 0, 0, scale, -x*scale, -y*scale); | ||
mctx.setTransform(scale, 0, 0, scale, -x*scale, -y*scale); | ||
} | ||
|
||
this.transform(bctx); | ||
this.painters(bctx); | ||
this.each(function(child) { | ||
child.render(bctx, dt); | ||
}); | ||
this.__postRender(); | ||
this.rendering = false; | ||
return this; | ||
}; | ||
|
||
// FIXME: this should be performed one time for all masked elements! | ||
mask.transform(mctx); | ||
mask.painters(mctx); | ||
mask.each(function(child) { | ||
child.render(mctx); | ||
}); | ||
Element.prototype._renderAsMask = function() { | ||
this.ensureHasMaskCanvas(); | ||
|
||
bctx.globalCompositeOperation = 'destination-in'; | ||
bctx.setTransform(1, 0, 0, 1, 0, 0); | ||
bctx.drawImage(mcvs, 0, 0); | ||
var mcvs = this.__maskCvs, | ||
mctx = this.__maskCtx, | ||
bcvs = this.__backCvs; | ||
|
||
ctx.drawImage(bcvs, | ||
0, 0, Math.floor(width * scale), Math.floor(height * scale), | ||
x, y, width, height); | ||
// FIXME: test if bounds are not empty | ||
var bounds_pts = this.bounds().toPoints(); | ||
|
||
mctx.restore(); | ||
bctx.restore(); | ||
} | ||
ctx.restore(); | ||
var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, | ||
maxX = Number.MIN_VALUE, maxY = Number.MIN_VALUE; | ||
|
||
var pt; | ||
for (var i = 0, il = bounds_pts.length; i < il; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does it do exactly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If masking element was rotated, mask canvas bounds should fit it completely (like "bounding rectangle"). It could be an artefact now, but I am not sure yet. See |
||
pt = bounds_pts[i]; | ||
if (pt.x < minX) minX = pt.x; | ||
if (pt.y < minY) minY = pt.y; | ||
if (pt.x > maxX) maxX = pt.x; | ||
if (pt.y > maxY) maxY = pt.y; | ||
} | ||
this.__postRender(); | ||
this.rendering = false; | ||
return this; | ||
|
||
var ratio = engine.PX_RATIO, | ||
x = minX, y = minY, | ||
width = Math.round(maxX - minX), | ||
height = Math.round(maxY - minY); | ||
|
||
var last_cvs_size = this._maskCvsSize || engine.getCanvasSize(mcvs); | ||
|
||
var scale = ratio; // multiple by global scale when it's known | ||
|
||
if ((last_cvs_size[0] < width) || | ||
(last_cvs_size[1] < height)) { | ||
// mcvs/bcvs both always have the same size, so we save/check only one of them | ||
this._maskCvsSize = engine.setCanvasSize(mcvs, width, height); | ||
engine.setCanvasSize(bcvs, width, height); | ||
} else { | ||
this._maskCvsSize = last_cvs_size; | ||
} | ||
|
||
this._maskCvsPos = [ x, y ]; | ||
|
||
mctx.clearRect(0, 0, width*scale, height*scale); | ||
|
||
mctx.save(); | ||
mctx.setTransform(scale, 0, 0, scale, -x*scale, -y*scale); | ||
|
||
// FIXME: this should be performed one time for all masked elements! | ||
this.transform(mctx); | ||
this.painters(mctx); | ||
this.each(function(child) { | ||
child.render(mctx); | ||
}); | ||
|
||
mctx.restore(); | ||
}; | ||
|
||
Element.prototype._renderAsMasked = function(ctx) { | ||
// FIXME: the complete mask process should be a Painter. | ||
var mask = this.$mask; | ||
|
||
var ratio = engine.PX_RATIO; | ||
|
||
if (!mask.__maskCvs) throw new Error('Mask canvas is not ready!'); | ||
|
||
var mcvs = mask.__maskCvs, | ||
bcvs = mask.__backCvs, | ||
bctx = mask.__backCtx; | ||
|
||
var maskSize = mask._maskCvsSize, | ||
maskPos = mask._maskCvsPos; | ||
|
||
var width = maskSize[0], | ||
height = maskSize[1], | ||
x = maskPos[0], y = maskPos[1]; | ||
|
||
var scale = ratio; // multiple by global scale when it's known | ||
|
||
bctx.clearRect(0, 0, width*scale, height*scale); | ||
|
||
bctx.save(); | ||
bctx.setTransform(scale, 0, 0, scale, -x*scale, -y*scale); | ||
|
||
this.transform(bctx); | ||
this.painters(bctx); | ||
this.each(function(child) { | ||
child.render(bctx); | ||
}); | ||
|
||
bctx.globalCompositeOperation = 'destination-in'; | ||
bctx.setTransform(1, 0, 0, 1, 0, 0); | ||
bctx.drawImage(mcvs, 0, 0); | ||
|
||
ctx.drawImage(bcvs, | ||
0, 0, Math.floor(width * scale), Math.floor(height * scale), | ||
x, y, width, height); | ||
|
||
bctx.restore(); | ||
}; | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be helpful to rename those variable like: isMask and isMasked