Merge pull request #40 from adroitwhiz/fix-gradient-stroke-scaling

Properly render gradients when strokeScaling = false
This commit is contained in:
adroitwhiz 2020-07-28 15:52:11 -04:00 committed by GitHub
commit 16d5ff0267
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 9 deletions

View file

@ -4281,16 +4281,16 @@ new function() { // Injection scope for hit-test functions shared with project
* Not defined in Path as it is required by other classes too, * Not defined in Path as it is required by other classes too,
* e.g. PointText. * e.g. PointText.
*/ */
_setStyles: function(ctx, param, viewMatrix) { _setStyles: function(ctx, param, viewMatrix, strokeMatrix) {
// We can access internal properties since we're only using this on // We can access internal properties since we're only using this on
// items without children, where styles would be merged. // items without children, where styles would be merged.
var style = this._style, var style = this._style,
matrix = this._matrix; matrix = this._matrix;
if (style.hasFill()) { if (style.hasFill()) {
ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx, matrix); ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx, matrix, strokeMatrix);
} }
if (style.hasStroke()) { if (style.hasStroke()) {
ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx, matrix); ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx, matrix, strokeMatrix);
ctx.lineWidth = style.getStrokeWidth(); ctx.lineWidth = style.getStrokeWidth();
var strokeJoin = style.getStrokeJoin(), var strokeJoin = style.getStrokeJoin(),
strokeCap = style.getStrokeCap(), strokeCap = style.getStrokeCap(),

View file

@ -261,7 +261,7 @@ var Shape = Item.extend(/** @lends Shape# */{
ctx.closePath(); ctx.closePath();
} }
if (!dontPaint && (hasFill || hasStroke)) { if (!dontPaint && (hasFill || hasStroke)) {
this._setStyles(ctx, param, viewMatrix); this._setStyles(ctx, param, viewMatrix, strokeMatrix);
if (hasFill) { if (hasFill) {
ctx.fill(style.getFillRule()); ctx.fill(style.getFillRule());
ctx.shadowColor = 'rgba(0,0,0,0)'; ctx.shadowColor = 'rgba(0,0,0,0)';

View file

@ -311,7 +311,7 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
children[i].draw(ctx, param, strokeMatrix); children[i].draw(ctx, param, strokeMatrix);
if (!param.clip) { if (!param.clip) {
this._setStyles(ctx, param, viewMatrix); this._setStyles(ctx, param, viewMatrix, strokeMatrix);
var style = this._style; var style = this._style;
if (style.hasFill()) { if (style.hasFill()) {
ctx.fill(style.getFillRule()); ctx.fill(style.getFillRule());

View file

@ -2320,7 +2320,7 @@ new function() { // Scope for drawing
if (!dontPaint && (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, param, viewMatrix); this._setStyles(ctx, param, viewMatrix, strokeMatrix);
if (hasFill) { if (hasFill) {
ctx.fill(style.getFillRule()); ctx.fill(style.getFillRule());
// If shadowColor is defined, clear it after fill, so it // If shadowColor is defined, clear it after fill, so it

View file

@ -899,8 +899,11 @@ var Color = Base.extend(new function() {
+ components.join(',') + ')'; + components.join(',') + ')';
}, },
toCanvasStyle: function(ctx, matrix) { toCanvasStyle: function(ctx, matrix, strokeMatrix) {
if (this._canvasStyle) // strokeMatrix can change without triggering _changed here, so we
// can't use a cached gradient here.
var strokeMayChange = this._type === 'gradient' && strokeMatrix;
if (this._canvasStyle && !strokeMayChange)
return this._canvasStyle; return this._canvasStyle;
// Normal colors are simply represented by their CSS string. // Normal colors are simply represented by their CSS string.
if (this._type !== 'gradient') if (this._type !== 'gradient')
@ -923,6 +926,12 @@ var Color = Base.extend(new function() {
if (highlight) if (highlight)
highlight = inverse._transformPoint(highlight); highlight = inverse._transformPoint(highlight);
} }
if (strokeMatrix) {
origin = strokeMatrix._transformPoint(origin);
destination = strokeMatrix._transformPoint(destination);
if (highlight)
highlight = strokeMatrix._transformPoint(highlight);
}
if (gradient._radial) { if (gradient._radial) {
var radius = destination.getDistance(origin); var radius = destination.getDistance(origin);
if (highlight) { if (highlight) {
@ -948,7 +957,12 @@ var Color = Base.extend(new function() {
offset == null ? i / (l - 1) : offset, offset == null ? i / (l - 1) : offset,
stop._color.toCanvasStyle()); stop._color.toCanvasStyle());
} }
return this._canvasStyle = canvasGradient; // Don't store gradients that may change in the cache.
// If we cached a gradient that was transformed by strokeMatrix
// then set strokeScaling to true, then the transformed gradient
// could get "stuck" in the cache.
if (!strokeMayChange) this._canvasStyle = canvasGradient;
return canvasGradient;
}, },
/** /**

View file

@ -306,6 +306,41 @@ test('Gradients with applyMatrix', function() {
comparePixels(path, shape); comparePixels(path, shape);
}); });
test('Gradients with strokeScaling: false', function() {
var topLeft = [100, 100];
var bottomRight = [400, 400];
var gradientColor = {
gradient: {
stops: ['yellow', 'red', 'blue']
},
origin: topLeft,
destination: bottomRight
}
var path = new Shape.Rectangle({
topLeft: topLeft,
bottomRight: bottomRight,
fillColor: gradientColor,
strokeScaling: true
});
var shape = new Shape.Rectangle({
topLeft: topLeft,
bottomRight: bottomRight,
fillColor: gradientColor,
strokeScaling: false
});
comparePixels(path, shape);
path.scale(2);
path.rotate(45);
shape.scale(2);
shape.rotate(45);
comparePixels(path, shape);
})
test('Modifying group.strokeColor for multiple children', function() { test('Modifying group.strokeColor for multiple children', function() {
var item = new Group(new Path(), new Path()); var item = new Group(new Path(), new Path());
item.strokeColor = 'red'; item.strokeColor = 'red';