diff --git a/CHANGELOG.md b/CHANGELOG.md index 128d08b7..13056b9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixed +- Fix drawing with compound path as clip item (#1361). - SVG Export: Fix error when `Item#matrix` is not invertible (#1580). - SVG Import: Fix gradient default values (#1632). - JSON Import: Prevent overriding `Item#insert()` (#1392). diff --git a/src/item/Item.js b/src/item/Item.js index dddb4068..3b969fea 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -4427,8 +4427,10 @@ new function() { // Injection scope for hit-test functions shared with project this._draw(ctx, param, viewMatrix, strokeMatrix); ctx.restore(); matrices.pop(); - if (param.clip && !param.dontFinish) - ctx.clip(); + if (param.clip && !param.dontFinish) { + // Pass fill-rule to handle clipping with compound-paths (#1361). + ctx.clip(this.getFillRule()); + } // If a temporary canvas was created, composite it onto the main canvas: if (!direct) { // Use BlendMode.process even for processing normal blendMode with diff --git a/test/tests/Item.js b/test/tests/Item.js index 28242f69..0f751996 100644 --- a/test/tests/Item.js +++ b/test/tests/Item.js @@ -951,3 +951,27 @@ test('Item#rasterize() with empty bounds', function() { view.update(); expect(0); }); + +test('Item#draw() with CompoundPath as clip item', function() { + function createdClippedGroup(invertedOrder) { + var compound = new CompoundPath({ + children: [ + new Path.Circle(new Point(50, 50), 50), + new Path.Circle(new Point(100, 50), 50) + ], + fillRule: 'evenodd' + }); + + var rectangle = new Shape.Rectangle(new Point(0, 0), new Point(150, 50)); + + var group = new Group(); + group.children = invertedOrder + ? [compound, rectangle] + : [rectangle, compound]; + group.fillColor = 'black'; + group.clipped = true; + return group; + }; + + comparePixels(createdClippedGroup(true), createdClippedGroup(false)); +});