Skip to content

fix: PolyLineSegment not rendering on Skia backend#22757

Open
Copilot wants to merge 3 commits intomasterfrom
copilot/fix-polyline-segment-display
Open

fix: PolyLineSegment not rendering on Skia backend#22757
Copilot wants to merge 3 commits intomasterfrom
copilot/fix-polyline-segment-display

Conversation

Copy link
Contributor

Copilot AI commented Mar 2, 2026

PolyLineSegment (and any stroke-only path segment beyond the first) was silently dropped on the Skia backend. A PathGeometry with a LineSegment followed by a PolyLineSegment would only render the LineSegment.

Root cause

In CompositionSpriteShape.Paint() (Skia), the stroke rendering block applied ClipPathPaintRestore without a matching Save. The fill block correctly wrapped its clip in a Save/Restore pair, but the stroke block was missing the Save.

With no prior Save, the Restore call either popped the wrong level from the enclosing canvas save-stack (corrupting clip/transform state for the recorded picture during playback) or was a no-op, leaving a persistent clip that affected subsequent rendering. Either way, stroke-only shapes rendered incorrectly.

Fix

  • CompositionSpriteShape.skia.cs: Add session.Canvas.Save() immediately before session.Canvas.ClipPath(strokeFillPath, …) in the stroke block, matching the established pattern in the fill block.
// Before (unbalanced):
session.Canvas.ClipPath(strokeFillPath, antialias: true);
stroke.Paint(session.Canvas, session.Opacity, strokeFillPath.Bounds);
session.Canvas.Restore();

// After (balanced):
session.Canvas.Save();
session.Canvas.ClipPath(strokeFillPath, antialias: true);
stroke.Paint(session.Canvas, session.Opacity, strokeFillPath.Bounds);
session.Canvas.Restore();

PR Type:

  • 🐞 Bugfix

What is the current behavior? 🤔

PolyLineSegment segments in a PathGeometry do not render on the Skia (desktop) backend. Only the first segment (LineSegment) is visible.

What is the new behavior? 🚀

All segments in a PathGeometry—including PolyLineSegment—render correctly on Skia, matching WinUI behavior.

PR Checklist ✅

Please check if your PR fulfills the following requirements:

Other information ℹ️

The CompositionSpriteShape.Paint fill block already had the correct Save/Restore pattern. The stroke block was simply missing the Save, which is a one-line addition.

A runtime test When_PolyLineSegment_Is_Stroked_Renders_All_Points has been added to Given_Path.cs. It builds a stroke-only PathGeometry with a LineSegment followed by a PolyLineSegment (the exact scenario from the issue), takes a screenshot, and asserts that pixels along both the LineSegment and PolyLineSegment portions are rendered with the stroke color. The test runs on Skia and WinUI.

Original prompt

This section details on the original issue you should resolve

<issue_title>PolyLineSegment does not display in UNO (but does in WinUI)</issue_title>
<issue_description>### Current behavior

Good morning!

I have experienced ar bug when drawing: I have drawn 3 black lines onto the green field. This first line is a LineSegment, the other two are one PolyLineSegment. Under WinUI, all 3 lines are drawn

Image

But under UNO, the PolyLineSegment is not drawn, see below:
Image

Best, Michael:)

Expected behavior

No response

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

No response

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

19957.zip</issue_description>

Comments on the Issue (you are @copilot in this section)

@jeromelaban @MichaelJachan thanks for the report. Would you mind [posting a repro](https://platform.uno/docs/articles/uno-howto-create-a-repro.html?tabs=windows-vs) for this specific issue? Thanks!

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI requested review from Copilot and removed request for Copilot March 2, 2026 08:34
…priteShape

Co-authored-by: MartinZikmund <1075116+MartinZikmund@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot March 2, 2026 09:26
Copilot AI changed the title [WIP] Fix PolyLineSegment display issue in UNO fix: PolyLineSegment not rendering on Skia backend Mar 2, 2026
@MartinZikmund
Copy link
Member

@copilot add runtime test coverage

…9957)

Co-authored-by: MartinZikmund <1075116+MartinZikmund@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot March 2, 2026 09:44
Copy link
Contributor Author

Copilot AI commented Mar 2, 2026

@copilot add runtime test coverage

Added When_PolyLineSegment_Is_Stroked_Renders_All_Points in Given_Path.cs (commit 81c687af). The test builds a PathGeometry with a LineSegment followed by a PolyLineSegment (stroke only, no fill — the exact broken scenario), loads it, takes a screenshot, and asserts that pixels along both the LineSegment portion and the PolyLineSegment portion are black, while pixels away from the line are not.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@unodevops
Copy link
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22757/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22757/wasm-skia-net9/index.html

@nventive-devops
Copy link
Contributor

The build 199072 found UI Test snapshots differences: android-28-net9: 15, android-28-net9-Snap: 29, ios: 5, ios-Snap: 45, skia-linux-screenshots: 59, skia-windows-screenshots: 60, wasm: 102, wasm-automated-net10.0-WinUI-Benchmarks-automated: 0, wasm-automated-net10.0-WinUI-Default-automated: 13, wasm-automated-net10.0-WinUI-RuntimeTests-0: 0, wasm-automated-net10.0-WinUI-RuntimeTests-1: 0, wasm-automated-net10.0-WinUI-RuntimeTests-2: 1

Details
  • android-28-net9: 15 changed over 758

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • DecimalFormatterTest_UITests_Shared_Microsoft_UI_Xaml_Controls_NumberBoxTests_NumberBoxPage
    • Detereminate_ProgressRing_Validation75_[#FF0000_#008000_#008000_#008000]_Progress-Ring-Value-75
    • NativeCommandBar_Size_Uno_UI_Samples_Content_UITests_CommandBar_CommandBar_Dynamic
    • ListView_ListViewWithHeader_InitializesTest_SamplesApp_Windows_UI_Xaml_Controls_ListView_HorizontalListViewGrouped
    • ProgressRing_IsEnabled_Running_UITests_Windows_UI_Xaml_Controls_ProgressRing_WindowsProgressRing_GH1220
    • Popup_PlacementTest_1Default_HSVS_Uno_UI_Samples_Content_UITests_Popup_Popup_HVAlignments
    • SequentialAnimations_SamplesApp_Windows_UI_Xaml_Media_Animation_SequentialAnimationsPage
    • UpDownEnabledTest_UITests_Shared_Microsoft_UI_Xaml_Controls_NumberBoxTests_NumberBoxPage
    • When_SingleSelectionWithItemClick_Then_PointersEvents_UITests_Windows_UI_Xaml_Controls_ListView_ListView_Selection_Pointers
    • WebView_NavigateToAnchor_Initial
    • When_Parent_PointerMoved_After_drag_on_non-scrolling_ScrollViewer
    • When_Parent_PointerMoved_After_drag_on_ScrollViewer_-_touch
    • When_NoSelectionWithItemClick_Then_PointersEvents_UITests_Windows_UI_Xaml_Controls_ListView_ListView_Selection_Pointers
    • When_NoSelection_Then_PointersEvents_UITests_Windows_UI_Xaml_Controls_ListView_ListView_Selection_Pointers
    • ProgressRing_Visibility_Collapsed_UITests_Windows_UI_Xaml_Controls_ProgressRing_WindowsProgressRing_GH1220
  • android-28-net9-Snap: 29 changed over 1067

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • CommandBar_Examples_Uno_UI_Samples_Content_UITests_CommandBar_CommandBar_Examples
    • TabView_MUXControlsTestApp_TabViewPage_MUXControlsTestApp_TabViewPage
    • Buttons_UITests_Microsoft_UI_Xaml_Controls_RadioButtonsTests_RadioButtonsPage_UITests_Microsoft_UI_Xaml_Controls_RadioButtonsTests_RadioButtonsPage
    • CommandBarFlyout_MUXControlsTestApp_CommandBarFlyoutPage_MUXControlsTestApp_CommandBarFlyoutPage
    • MUX_UITests_Shared_Microsoft_UI_Xaml_Controls_TreeViewTests_TreeViewPage_UITests_Shared_Microsoft_UI_Xaml_Controls_TreeViewTests_TreeViewPage
    • Projection_PlaneProjection_Basic_UITests_Shared_Windows_UI_Xaml_Media_Projection_PlaneProjection_Basic
    • Automation_Accessibility_ScreenReader_UITests_Shared_Windows_UI_Xaml_Automation_AccessibilityScreenReaderPage
    • Icons_UITests_Microsoft_UI_Xaml_Controls_ImageIconTests_ImageIconPage_UITests_Microsoft_UI_Xaml_Controls_ImageIconTests_ImageIconPage
    • MUX_NumberBox_UITests_Shared_Microsoft_UI_Xaml_Controls_NumberBoxTests_NumberBoxPage
    • ListView_ListView_With_ListViews_Count_Measure_UITests_Shared_Windows_UI_Xaml_Controls_ListView_ListView_With_ListViews_Count_Measure
    • TeachingTip_UITests_Microsoft_UI_Xaml_Controls_TeachingTipTests_TeachingTipPage_UITests_Microsoft_UI_Xaml_Controls_TeachingTipTests_TeachingTipPage
    • GridView_Uno_UI_Samples_Content_UITests_GridView_GridViewVariableItemHeightFromSelector_Uno_UI_Samples_Content_UITests_GridView_GridViewVariableItemHeightFromSelector
    • Image_UITests_Windows_UI_Xaml_Controls_ImageTests_SvgImageSource_FromMsAppData_UITests_Windows_UI_Xaml_Controls_ImageTests_SvgImageSource_FromMsAppData
    • Scrolling_MUXControlsTestApp_ScrollViewDynamicPage_MUXControlsTestApp_ScrollViewDynamicPage
    • Transform_Basics_UITests_Shared_Windows_UI_Xaml_Media_Transform_Basics
    • NavigationView_MUXControlsTestApp_NavigationViewRS4Page_MUXControlsTestApp_NavigationViewRS4Page
    • SwipeControl_MUXControlsTestApp_SwipeControlPage2_MUXControlsTestApp_SwipeControlPage2
    • WebView_WebView2_Mailto_SamplesApp_Microsoft_UI_Xaml_Controls_WebView2Tests_WebView2_Mailto
    • WebView_UITests_Microsoft_UI_Xaml_Controls_WebView2Tests_WebView2_NavigationProperties_UITests_Microsoft_UI_Xaml_Controls_WebView2Tests_WebView2_NavigationProperties
    • ListView_ListViewSelectedItems_SamplesApp_Windows_UI_Xaml_Controls_ListView_ListViewSelectedItems
  • ios: 5 changed over 213

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ListView_SelectedItems_SamplesApp_Windows_UI_Xaml_Controls_ListView_ListViewSelectedItems
    • Check_ListView_Swallows_Measure_UITests_Shared_Windows_UI_Xaml_Controls_ListView_ListView_With_ListViews_Count_Measure
    • ProgressRing_Visibility_Collapsed_UITests_Windows_UI_Xaml_Controls_ProgressRing_WindowsProgressRing_GH1220
    • ProgressRing_IsEnabled_Running_UITests_Windows_UI_Xaml_Controls_ProgressRing_WindowsProgressRing_GH1220
    • When_SingleSelectionWithoutItemClick_Then_PointersEvents_UITests_Windows_UI_Xaml_Controls_ListView_ListView_Selection_Pointers
  • ios-Snap: 45 changed over 986

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Brushes_PanelImageBrush_Uno_UI_Samples_UITests_ImageBrushTestControl_PanelImageBrush
    • Brushes_RectangleStretchFill_Uno_UI_Samples_UITests_ImageBrushTestControl_RectangleStretchFill
    • Brushes_GenericApp_Views_Content_UITests_ImageBrushTestControl_BorderImageBrushRelativeTransform_GenericApp_Views_Content_UITests_ImageBrushTestControl_BorderImageBrushRelativeTransform
    • Image_EmptyImageFixedWidth_Uno_UI_Samples_UITests_ImageTestsControl_EmptyImageFixedWidth
    • NavigationView_MUXControlsTestApp_NavigationViewMinimalPage_MUXControlsTestApp_NavigationViewMinimalPage
    • Brushes_ImageBrush_Stretch_None_Uno_UI_Samples_UITests_ImageBrushTestControl_ImageBrush_Stretch_None
    • Image_Uno_UI_Samples_UITests_Image_Image_Stretch_Alignment_Bigger_Uno_UI_Samples_UITests_Image_Image_Stretch_Alignment_Bigger
    • Image_Image_Stretch_None_Uno_UI_Samples_UITests_ImageTestsControl_Image_Stretch_None
    • MediaPlayerElement_Mini_player_UITests_Shared_Windows_UI_Xaml_Controls_MediaPlayerElement_MediaPlayerElement_Minimal
    • MediaPlayerElement_Using_ogg_UITests_Shared_Windows_UI_Xaml_Controls_MediaPlayerElement_MediaPlayerElement_Ogg_Extension
    • Scrolling_MUXControlsTestApp_ScrollViewsWithSimpleContentsPage_MUXControlsTestApp_ScrollViewsWithSimpleContentsPage
    • ColorPicker_WinUIColorPickerPage_UITests_Shared_Microsoft_UI_Xaml_Controls_ColorPickerTests_WinUIColorPickerPage
    • Default_UITests_Windows_UI_Xaml_Controls_Canvas_Grid_ZIndex_UITests_Windows_UI_Xaml_Controls_Canvas_Grid_ZIndex
    • Image_UITests_Windows_UI_Xaml_Controls_ImageTests_Image_Formats_UITests_Windows_UI_Xaml_Controls_ImageTests_Image_Formats
    • Brushes_ImageBrushStretch_Uno_UI_Samples_UITests_ImageBrushTestControl_ImageBrushStretch
    • WebView_UITests_Microsoft_UI_Xaml_Controls_WebView2Tests_WebView2_NavigationProperties_UITests_Microsoft_UI_Xaml_Controls_WebView2Tests_WebView2_NavigationProperties
    • Grid_CenteredGridinGridwiththreefixedsizechildren_Uno_UI_Samples_Content_UITests_GridTestsControl_CenteredGridinGridwiththreefixedsizechildren
    • x_Bind_PhaseBinding_StartOne_Uno_UI_Samples_Content_UITests_XBind_PhaseBinding_StartOne
    • Default_UITests_Shared_Windows_UI_Xaml_Controls_Canvas_Canvas_ZIndex_UITests_Shared_Windows_UI_Xaml_Controls_Canvas_Canvas_ZIndex
    • Performance_UITests_Windows_UI_Xaml_Performance_Performance_1000ButtonsContinuousRendering_UITests_Windows_UI_Xaml_Performance_Performance_1000ButtonsContinuousRendering
  • skia-linux-screenshots: 59 changed over 2314

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Focus_FocusVisual_Properties.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_CurrentReading.png
    • BitmapIcon_Monochromatic.png
    • Examples.png-dark
    • Examples.png
    • ImageIconPage.png-dark
    • ImageIconPage.png
    • Buttons.png
    • DisplayInformation.png-dark
    • ListViewHeaderUpdate.png-dark
    • ButtonClippingTestsControl.png
    • DynamicFont.png-dark
    • DynamicFont.png
    • Buttons.png-dark
    • ClipboardTests.png-dark
    • ButtonClippingTestsControl.png-dark
    • DropDownButtonPage.png-dark
    • Gamepad_Enumeration.png-dark
    • Gamepad_Enumeration.png
  • skia-windows-screenshots: 60 changed over 2316

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • DisplayInformation.png-dark
    • CalendarView_Theming.png
    • ClipboardTests.png
    • DropDownButtonPage.png-dark
    • DropDownButtonPage.png
    • Buttons.png
    • Gamepad_Enumeration.png-dark
    • Gamepad_Enumeration.png
    • ContentPresenter_NativeEmbedding_Android_FillType.png-dark
    • ContentPresenter_NativeEmbedding_Android_FillType.png
    • Focus_FocusVisual_Properties.png-dark
    • ButtonClippingTestsControl.png
    • Examples.png-dark
    • Examples.png
    • ButtonClippingTestsControl.png-dark
    • CalendarView_Theming.png-dark
    • ClipboardTests.png-dark
    • Buttons.png-dark
    • Gamepad_CurrentReading.png-dark
    • Gamepad_CurrentReading.png
  • wasm: 102 changed over 1066

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • MUXControlsTestApp.SwipeControlPage
    • SamplesApp.Wasm.Windows_UI_Xaml_Controls.ListView.ListView_IsSelected
    • SamplesApp.Windows_UI_Xaml_Controls.ListView.ListView_Expandable_Item_Large
    • SamplesApp.Windows_UI_Xaml_Controls.ListView.ListView_Image
    • UITests.Shared.Windows_Devices.Midi.MidiDeviceOutputTests
    • UITests.Shared.Windows_UI_Xaml_Controls.Buttons_Native
    • UITests.Shared.Windows_UI_Xaml_Controls.ListView.ListView_ObservableCollection_Unused_Space
    • UITests.Windows_ApplicationModel.DataTransfer.DataTransferManagerTests
    • UITests.Windows_Devices.Midi.MidiDeviceInput
    • UITests.Windows_UI_Xaml_Controls.ImageTests.SvgImageSource_Basic
    • UITests.Windows_UI_Xaml_Controls.ImageTests.SvgImageSource_FromStream
    • UITests.Windows_UI_Xaml_Controls.TextBlockControl.TextBlock_LayoutAlignment
    • UITests.Windows_UI_Xaml_Controls.TextBlockControl.TextBlock_MeasureCache
    • UITests.Windows_UI_Xaml_Controls.TextBlockControl.TextBlock_RelativeTextSize
    • SamplesApp.Windows_UI_Xaml_Controls.ListView.ListViewHeaderFooter_ImplicitlyBinded
    • UITests.Shared.Windows_UI_Xaml_Controls.AutoSuggestBoxTests.AutoSuggestBoxChosenSuggestion
    • UITests.Shared.Windows_UI_Xaml_Controls.MediaPlayerElement.MediaPlayerElement_Minimal
    • UITests.Shared.Windows_UI_Xaml_Controls.MediaPlayerElement.MediaPlayerElement_Ogg_Extension
    • UITests.Windows_UI_Xaml_Controls.ListView.ListView_Selection_Events
    • MUXControlsTestApp.ExtraCommandBarFlyoutPage
  • wasm-automated-net10.0-WinUI-Benchmarks-automated: 0 changed over 1

  • wasm-automated-net10.0-WinUI-Default-automated: 13 changed over 877

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Default_StrokeThickness_MyLine
    • ListView_SelectedItems_SamplesApp_Windows_UI_Xaml_Controls_ListView_ListViewSelectedItems
    • Default_StrokeThickness_MyRect
    • When_SingleSelectionWithoutItemClick_Then_PointersEvents_UITests_Windows_UI_Xaml_Controls_ListView_ListView_Selection_Pointers
    • Default_StrokeThickness_MyEllipse
    • When_StretchAndAlignmentNone_ImageBrush-50-50-None-XLeft-YBottom
    • Default_StrokeThickness_MyPolyline
    • Default_StrokeThickness_MyPolygon
    • When_NoSelectionWithItemClick_Then_PointersEvents_UITests_Windows_UI_Xaml_Controls_ListView_ListView_Selection_Pointers
    • TestProgressRing_InitialState_UITests_Microsoft_UI_Xaml_Controls_ProgressRing_WinUIProgressRing_Features
    • When_MultipleSelectionWithoutItemClick_Then_PointersEvents_UITests_Windows_UI_Xaml_Controls_ListView_ListView_Selection_Pointers
    • Default_StrokeThickness_MyPath
    • SequentialAnimations_SamplesApp_Windows_UI_Xaml_Media_Animation_SequentialAnimationsPage
  • wasm-automated-net10.0-WinUI-RuntimeTests-0: 0 changed over 1

  • wasm-automated-net10.0-WinUI-RuntimeTests-1: 0 changed over 1

  • wasm-automated-net10.0-WinUI-RuntimeTests-2: 1 changed over 1

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • RunRuntimeTests_SamplesApp_Samples_UnitTests_UnitTestsPage

@unodevops
Copy link
Contributor

⚠️⚠️ The build 199072 has failed on Uno.UI - CI.

@MartinZikmund MartinZikmund marked this pull request as ready for review March 2, 2026 13:07
@github-actions github-actions bot added the area/skia ✏️ Categorizes an issue or PR as relevant to Skia label Mar 2, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Skia rendering of stroke-only PathGeometry segments (e.g., PolyLineSegment after the first segment) by balancing the canvas save/restore stack around stroke clipping, and adds a runtime test to prevent regressions.

Changes:

  • Balance Skia stroke rendering clip state by adding a missing Canvas.Save() before ClipPath().
  • Add a runtime screenshot test validating that both LineSegment and subsequent PolyLineSegment portions render when stroked.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Uno.UI.Composition/Composition/CompositionSpriteShape.skia.cs Fixes unbalanced Skia canvas state management in the stroke paint path by adding Save() before ClipPath().
src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Shapes/Given_Path.cs Adds a regression runtime test ensuring stroked PolyLineSegment points render (Skia + WinUI).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@unodevops
Copy link
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22757/wasm-skia-net9/index.html

@MartinZikmund MartinZikmund enabled auto-merge March 2, 2026 13:29
@MartinZikmund MartinZikmund added the ready-to-merge Automatically merge the PR once all '.mergify.yml' policies are met label Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/skia ✏️ Categorizes an issue or PR as relevant to Skia ready-to-merge Automatically merge the PR once all '.mergify.yml' policies are met

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PolyLineSegment does not display in UNO (but does in WinUI)

7 participants