diff --git a/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart b/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart
index 24f5fe5eb044e..4bc0bff9c33bb 100644
--- a/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart
+++ b/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart
@@ -51,7 +51,11 @@ SVGSVGElement pathToSvgClipPath(ui.Path path,
clipPath.setAttribute('clipPathUnits', 'objectBoundingBox');
svgPath.setAttribute('transform', 'scale($scaleX, $scaleY)');
}
-
+ if (path.fillType == ui.PathFillType.evenOdd) {
+ svgPath.setAttribute('clip-rule', 'evenodd');
+ } else {
+ svgPath.setAttribute('clip-rule', 'nonzero');
+ }
svgPath.setAttribute('d', pathToSvg((path as SurfacePath).pathRef, offsetX: offsetX, offsetY: offsetY));
return root;
}
diff --git a/lib/web_ui/test/html/canvas_clip_path_golden_test.dart b/lib/web_ui/test/html/canvas_clip_path_golden_test.dart
index a4643c3a97359..7242600b361e6 100644
--- a/lib/web_ui/test/html/canvas_clip_path_golden_test.dart
+++ b/lib/web_ui/test/html/canvas_clip_path_golden_test.dart
@@ -119,6 +119,50 @@ Future testMain() async {
await canvasScreenshot(rc, 'image_clipped_by_oval_path',
region: const Rect.fromLTWH(0, 0, 600, 800));
});
+
+ test('Clips with fillType evenOdd', () async {
+ final engine.RecordingCanvas rc = engine.RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500));
+ rc.save();
+ const double testWidth = 400;
+ const double testHeight = 350;
+
+ // draw RGB test image
+ rc.drawImageRect(createTestImage(), const Rect.fromLTRB(0, 0, testWidth, testHeight),
+ const Rect.fromLTWH(0, 0, testWidth, testHeight), engine.SurfacePaint());
+
+ // draw a clipping path with:
+ // 1) an outside larger rectangle
+ // 2) a smaller inner rectangle specified by a path
+ final Path path = Path();
+ path.addRect(const Rect.fromLTWH(0, 0, testWidth, testHeight));
+ const double left = 25;
+ const double top = 30;
+ const double right = 300;
+ const double bottom = 250;
+ path
+ ..moveTo(left, top)
+ ..lineTo(right,top)
+ ..lineTo(right,bottom)
+ ..lineTo(left, bottom)
+ ..close();
+ path.fillType = PathFillType.evenOdd;
+ rc.clipPath(path);
+
+ // draw an orange paint path of size testWidth and testHeight
+ final Path paintPath = Path();
+ paintPath.addRect(const Rect.fromLTWH(0, 0, testWidth, testHeight));
+ paintPath.close();
+ rc.drawPath(paintPath,
+ engine.SurfacePaint()
+ ..color = const Color(0xFFFF9800)
+ ..style = PaintingStyle.fill);
+ rc.restore();
+
+ // when fillType is set to evenOdd from the clipping path, expect the inner
+ // rectangle should clip some of the orange painted portion, revealing the RGB testImage
+ await canvasScreenshot(rc, 'clipPath_uses_fillType_evenOdd',
+ region: const Rect.fromLTWH(0, 0, 600, 800));
+ });
}
engine.HtmlImage createTestImage({int width = 200, int height = 150}) {