Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 6678d9c

Browse files
authored
clipPath to use fillType param (#38956)
Co-authored-by: alanwutang11 <[email protected]>
1 parent bb7b700 commit 6678d9c

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ SVGSVGElement pathToSvgClipPath(ui.Path path,
5151
clipPath.setAttribute('clipPathUnits', 'objectBoundingBox');
5252
svgPath.setAttribute('transform', 'scale($scaleX, $scaleY)');
5353
}
54-
54+
if (path.fillType == ui.PathFillType.evenOdd) {
55+
svgPath.setAttribute('clip-rule', 'evenodd');
56+
} else {
57+
svgPath.setAttribute('clip-rule', 'nonzero');
58+
}
5559
svgPath.setAttribute('d', pathToSvg((path as SurfacePath).pathRef, offsetX: offsetX, offsetY: offsetY));
5660
return root;
5761
}

lib/web_ui/test/html/canvas_clip_path_golden_test.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,50 @@ Future<void> testMain() async {
119119
await canvasScreenshot(rc, 'image_clipped_by_oval_path',
120120
region: const Rect.fromLTWH(0, 0, 600, 800));
121121
});
122+
123+
test('Clips with fillType evenOdd', () async {
124+
final engine.RecordingCanvas rc = engine.RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500));
125+
rc.save();
126+
const double testWidth = 400;
127+
const double testHeight = 350;
128+
129+
// draw RGB test image
130+
rc.drawImageRect(createTestImage(), const Rect.fromLTRB(0, 0, testWidth, testHeight),
131+
const Rect.fromLTWH(0, 0, testWidth, testHeight), engine.SurfacePaint());
132+
133+
// draw a clipping path with:
134+
// 1) an outside larger rectangle
135+
// 2) a smaller inner rectangle specified by a path
136+
final Path path = Path();
137+
path.addRect(const Rect.fromLTWH(0, 0, testWidth, testHeight));
138+
const double left = 25;
139+
const double top = 30;
140+
const double right = 300;
141+
const double bottom = 250;
142+
path
143+
..moveTo(left, top)
144+
..lineTo(right,top)
145+
..lineTo(right,bottom)
146+
..lineTo(left, bottom)
147+
..close();
148+
path.fillType = PathFillType.evenOdd;
149+
rc.clipPath(path);
150+
151+
// draw an orange paint path of size testWidth and testHeight
152+
final Path paintPath = Path();
153+
paintPath.addRect(const Rect.fromLTWH(0, 0, testWidth, testHeight));
154+
paintPath.close();
155+
rc.drawPath(paintPath,
156+
engine.SurfacePaint()
157+
..color = const Color(0xFFFF9800)
158+
..style = PaintingStyle.fill);
159+
rc.restore();
160+
161+
// when fillType is set to evenOdd from the clipping path, expect the inner
162+
// rectangle should clip some of the orange painted portion, revealing the RGB testImage
163+
await canvasScreenshot(rc, 'clipPath_uses_fillType_evenOdd',
164+
region: const Rect.fromLTWH(0, 0, 600, 800));
165+
});
122166
}
123167

124168
engine.HtmlImage createTestImage({int width = 200, int height = 150}) {

0 commit comments

Comments
 (0)