unoplatform / uno

Open-source platform for building cross-platform native Mobile, Web, Desktop and Embedded apps quickly. Create rich, C#/XAML, single-codebase apps from any IDE. Hot Reload included! 90m+ NuGet Downloads!!
https://platform.uno
Apache License 2.0
8.85k stars 714 forks source link

[Linux] `Path` is not clipping inside a ScrollViewer. #18473

Open ramezgerges opened 2 hours ago

ramezgerges commented 2 hours ago

Current behavior

In the repro below, scrolling the scrollviewer will make the Path inside remain visible even though it should be partially clipped. The shocking part is that this only happens on Linux. The WPF target on Windows clips accurately. Note that the repro seems to be very stable. I've tried a bunch of variations and they all repro 100% of the time.

The problem was originally discovered in SamplesApp (notice the unclipped chevron): image

Expected behavior

The Path should only be visible within the viewport of the ScrollViewer.

How to reproduce it (as minimally and precisely as possible)

    <StackPanel>
        <Border Height="100" HorizontalAlignment="Stretch" Background="Blue" />
        <ScrollViewer Height="30">
            <StackPanel>
                <Path Data="m 0,0 c -0.639,0 -1.276,0.243 -1.765,0.729 -0.977,0.974 -0.98,2.557 -0.006,3.535 L 16.925,23.032 -1.768,41.725 c -0.976,0.976 -0.976,2.559 0,3.535 0.977,0.976 2.559,0.976 3.536,0 L 22.225,24.803 c 0.975,-0.975 0.976,-2.555 0.004,-3.532 L 1.771,0.736 C 1.283,0.245 0.642,0 0,0" Fill="Red" />
            </StackPanel>
        </ScrollViewer>
    </StackPanel>

Workaround

No response

Works on UWP/WinUI

None

Environment

No response

NuGet package version(s)

No response

Affected platforms

No response

IDE

No response

IDE version

No response

Relevant plugins

No response

Anything else we need to know?

No response

ramezgerges commented 2 hours ago

I've reduced the render cycle to drawing the visual of the Path only and it still reproduced. Here are the insane results of this investigation:

  1. The problematic part is
    session.Canvas.DrawPath(geometryWithTransformations, fillPaint)

    inside CompositionSpriteShape.skia.cs, which actually draws the path. The code is accurate and works on WPF as mentioned above, but it somehow completely ignores the SKCanvas's current clipping. The canvas's clip numbers are accurate, they're just ignored as if the clip rect didn't exist.

  2. Changing that line to
    session.Canvas.DrawPath(SKPath.ParseSvgPathData(geometryWithTransformations.ToSvgPathData()), fillPaint);

    which just encodes the SKPath to svg and decodes it again makes things work correctly!!! This, however, doesn't work:

    session.Canvas.DrawPath(new SKPath(geometryWithTransformations), fillPaint);
  3. Another solution is to create a new SKPaint. Replacing the problematic line with
    session.Canvas.DrawPath(SKPath.ParseSvgPathData(geometryWithTransformations.ToSvgPathData()), new SKPaint() { Color: SKColors.Red });

    fixes the bug too.

  4. Yet another solution is to set IsAntiAlias on the SKPaint to false. (╯°□°)╯︵ ┻━┻