Skip to content

Support clipPath in Svg.Controls.Avalonia#502

Merged
wieslawsoltes merged 2 commits into
masterfrom
issue-438-avalonia-clip-path
May 9, 2026
Merged

Support clipPath in Svg.Controls.Avalonia#502
wieslawsoltes merged 2 commits into
masterfrom
issue-438-avalonia-clip-path

Conversation

@wieslawsoltes
Copy link
Copy Markdown
Owner

PR Summary: Fix Avalonia clip-path rendering

Summary

Fixes Svg.Controls.Avalonia clip-path rendering for SVGs loaded through the pure Avalonia control path. Previously, Skia picture recording preserved ClipPathCanvasCommand entries, but the Avalonia conversion layer returned null for ClipPath.ToGeometry, so clip-path="url(#...)" was effectively ignored by the Avalonia drawing command recorder.

This change converts retained clip-path payloads into Avalonia geometries and records them as geometry clips, allowing clipped SVG content to render correctly in Svg.Controls.Avalonia.

Issue

Addresses GitHub issue #438: Svg.Controls.Avalonia did not honor a simple SVG clip path:

<clipPath id="clip">
  <rect width="10" height="10" />
</clipPath>
<rect fill="#F00" width="24" height="24" rx="12" clip-path="url(#clip)" />

The reported behavior showed the rounded rectangle rendered without the expected 10x10 clip. The expected result is that only the clipped upper-left portion is visible.

Implementation Details

  • Implemented ClipPath to Avalonia Geometry conversion in AvaloniaModelExtensions.
  • Added conversion for PathClip entries, including nested clips.
  • Combined local clip entries with GeometryCombineMode.Union, matching SVG clip-path behavior where child clip shapes contribute to the clipping region.
  • Combined referenced/nested clips with GeometryCombineMode.Intersect, preserving nested clip constraints.
  • Preserved clip transforms and composed them with any existing geometry transforms.
  • Extended SKPath.ToGeometry to handle compact single-command shape paths:
    • AddRectPathCommand
    • AddRoundRectPathCommand
    • AddOvalPathCommand
    • AddCirclePathCommand
    • AddPolyPathCommand
  • Updated AvaloniaPicture clip recording to request filled geometry for clip paths.

Tests

Added a regression test using the issue SVG sample:

  • Loads the SVG through SvgSource.LoadFromSvg.
  • Records the SKPicture into an AvaloniaPicture.
  • Asserts that a GeometryClipDrawCommand is emitted.
  • Asserts that the clip geometry bounds are 0,0,10,10.
  • Asserts that the clipped rectangle draw command is still recorded.

Validation

Validated locally with:

dotnet build src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj -f net8.0 -c Release --no-restore
dotnet build src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj -f net10.0 -c Release --no-restore
dotnet test tests/Svg.Controls.Avalonia.UnitTests/Svg.Controls.Avalonia.UnitTests.csproj -f net10.0 -c Release --no-restore

The net10.0 package build passed cleanly. The net8.0 package build passed with existing warnings from dependency projects. The affected Avalonia unit-test project passed all 11 tests.

Notes

The full solution build was not used as the final validation target because this checkout initially lacked restored assets and, before submodule initialization, could not compile Svg.Custom. After running git submodule update --init --recursive and restoring the affected test project, the targeted package and unit-test validation completed successfully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant