diff --git a/HEADER.js b/HEADER.js index b3a79c8b7ac..15315a10f2f 100644 --- a/HEADER.js +++ b/HEADER.js @@ -118,6 +118,21 @@ fabric.devicePixelRatio = fabric.window.devicePixelRatio || fabric.window.webkitDevicePixelRatio || fabric.window.mozDevicePixelRatio || 1; +/** + * Browser-specific constant to adjust CanvasRenderingContext2D.shadowBlur value, + * which is unitless and not rendered equally across browsers. + * + * Values that work quite well (as of October 2017) are: + * - Chrome: 1.5 + * - Edge: 1.75 + * - Firefox: 0.9 + * - Safari: 0.95 + * + * @since 2.0.0 + * @type Number + * @default 1 + */ +fabric.browserShadowBlurConstant = 1; fabric.initFilterBackend = function() { if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) { diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index 6c61727154c..f8785f6ad9c 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -1210,7 +1210,7 @@ multY *= fabric.devicePixelRatio; } ctx.shadowColor = this.shadow.color; - ctx.shadowBlur = this.shadow.blur * (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4; + ctx.shadowBlur = this.shadow.blur * fabric.browserShadowBlurConstant * (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4; ctx.shadowOffsetX = this.shadow.offsetX * multX * scaling.scaleX; ctx.shadowOffsetY = this.shadow.offsetY * multY * scaling.scaleY; }, diff --git a/test/unit/object.js b/test/unit/object.js index eb4e7598a4a..22378a776de 100644 --- a/test/unit/object.js +++ b/test/unit/object.js @@ -1197,20 +1197,26 @@ offsetY: 15 }); object._setShadow(context); - assert.equal(context.shadowOffsetX, object.shadow.offsetX); - assert.equal(context.shadowOffsetY, object.shadow.offsetY); - assert.equal(context.shadowBlur, object.shadow.blur); + assert.equal(context.shadowOffsetX, object.shadow.offsetX, 'shadow offsetX is set'); + assert.equal(context.shadowOffsetY, object.shadow.offsetY, 'shadow offsetY is set'); + assert.equal(context.shadowBlur, object.shadow.blur, 'shadow blur is set'); + fabric.browserShadowBlurConstant = 1.5; + object._setShadow(context); + assert.equal(context.shadowOffsetX, object.shadow.offsetX, 'shadow offsetX is unchanged with browserConstant'); + assert.equal(context.shadowOffsetY, object.shadow.offsetY, 'shadow offsetY is unchanged with browserConstant'); + assert.equal(context.shadowBlur, object.shadow.blur * 1.5, 'shadow blur is affected with browserConstant'); + fabric.browserShadowBlurConstant = 1; object.scaleX = 2; object.scaleY = 3; object._setShadow(context); - assert.equal(context.shadowOffsetX, object.shadow.offsetX * object.scaleX); - assert.equal(context.shadowOffsetY, object.shadow.offsetY * object.scaleY); - assert.equal(context.shadowBlur, object.shadow.blur * (object.scaleX + object.scaleY) / 2); + assert.equal(context.shadowOffsetX, object.shadow.offsetX * object.scaleX, 'shadow offsetX is affected by scaleX'); + assert.equal(context.shadowOffsetY, object.shadow.offsetY * object.scaleY, 'shadow offsetY is affected by scaleY'); + assert.equal(context.shadowBlur, object.shadow.blur * (object.scaleX + object.scaleY) / 2, 'shadow blur is affected by scaleY and scaleX'); object.group = group; object._setShadow(context); - assert.equal(context.shadowOffsetX, object.shadow.offsetX * object.scaleX * group.scaleX); - assert.equal(context.shadowOffsetY, object.shadow.offsetY * object.scaleY * group.scaleY); - assert.equal(context.shadowBlur, object.shadow.blur * (object.scaleX * group.scaleX + object.scaleY * group.scaleY) / 2); + assert.equal(context.shadowOffsetX, object.shadow.offsetX * object.scaleX * group.scaleX, 'shadow offsetX is affected by scaleX and group.scaleX'); + assert.equal(context.shadowOffsetY, object.shadow.offsetY * object.scaleY * group.scaleY, 'shadow offsetX is affected by scaleX and group.scaleX'); + assert.equal(context.shadowBlur, object.shadow.blur * (object.scaleX * group.scaleX + object.scaleY * group.scaleY) / 2, 'shadow blur is affected by scales'); }); QUnit.test('willDrawShadow', function(assert) {