Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue21983.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue21983"
Title="Issue21983">

<ContentPage.Resources>
<ResourceDictionary>
<LinearGradientBrush x:Key="LinearGradient">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="0.5" Color="Blue" />
<GradientStop Offset="0.9" Color="Purple" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>

<RadialGradientBrush x:Key="RadialGradient">
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="0.5" Color="Blue" />
<GradientStop Offset="0.9" Color="Purple" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</ResourceDictionary>
</ContentPage.Resources>

<VerticalStackLayout Margin="30,0" Spacing="35">
<Path
AutomationId="path"
Fill="Red"
Stroke="{StaticResource LinearGradient}"
StrokeThickness="20">
<Path.Data>
<PathGeometry>
<PathFigureCollection>
<PathFigure StartPoint="0,0">
<ArcSegment
IsLargeArc="False"
Point="120,140"
Size="100,100"
SweepDirection="Clockwise" />
</PathFigure>
</PathFigureCollection>
</PathGeometry>
</Path.Data>
</Path>

<Ellipse
Fill="Red"
HeightRequest="50"
Stroke="{StaticResource RadialGradient}"
StrokeThickness="10"
WidthRequest="50" />

<Ellipse
Fill="{StaticResource RadialGradient}"
HeightRequest="50"
Stroke="Red"
StrokeThickness="10"
WidthRequest="50" />
</VerticalStackLayout>
</ContentPage>
15 changes: 15 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue21983.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;

namespace Maui.Controls.Sample.Issues;

[XamlCompilation(XamlCompilationOptions.Compile)]
[Issue(IssueTracker.Github, 21983, "GradientBrushes are not supported on Shape.Stroke", PlatformAffected.All)]

public partial class Issue21983 : ContentPage
{
public Issue21983()
{
InitializeComponent();
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#if !WINDOWS
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue21983 : _IssuesUITest
{
public override string Issue => "GradientBrushes are not supported on Shape.Stroke";

public Issue21983(TestDevice device) : base(device)
{
}

[Test]
[Category(UITestCategories.Shape)]
public void GradientShouldBeAppliedToStrokes()
{
_ = App.WaitForElement("path");

VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2));
}
}
}
#endif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions src/Core/src/Graphics/ShapeDrawable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ void DrawStrokePath(ICanvas canvas, RectF dirtyRect, PathF path)
// Set Stroke
var stroke = ShapeView.Stroke;

// TODO: Add Paint support for Stroke in Microsoft.Maui.Graphics.
// For now, only support a solid color.
// TODO: Add Paint support for Stroke in Microsoft.Maui.Graphics for Windows
canvas.StrokeColor = stroke.ToColor();

// Set StrokeLineCap
Expand All @@ -108,6 +107,12 @@ void DrawStrokePath(ICanvas canvas, RectF dirtyRect, PathF path)
var strokeMiterLimit = ShapeView.StrokeMiterLimit;
canvas.MiterLimit = strokeMiterLimit;

// Use SetFillPaint to configure gradient state (shader/CGGradient)
// which PlatformDrawPath will apply to the stroke rendering.
// Use path.Bounds so the gradient maps to the shape geometry,
// not the full dirty rect (which would misalign gradients on
// shapes that don't fill the entire view).
canvas.SetFillPaint(stroke, path.Bounds);
canvas.DrawPath(path);

canvas.RestoreState();
Expand Down
16 changes: 15 additions & 1 deletion src/Graphics/src/Graphics/Platforms/Android/PlatformCanvas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,21 @@ public override void SubtractFromClip(float x, float y, float width, float heigh
protected override void PlatformDrawPath(PathF aPath)
{
var platformPath = aPath.AsAndroidPath();
_canvas.DrawPath(platformPath, CurrentState.StrokePaintWithAlpha);

if (_shader != null)
{
// Mirror iOS ReplacePathWithStrokedPath: convert stroke geometry into a fill path
var strokedOutline = new Path();
CurrentState.StrokePaintWithAlpha.GetFillPath(platformPath, strokedOutline);
// FillPaintWithAlpha already has the gradient shader from SetFillPaint
_canvas.DrawPath(strokedOutline, CurrentState.FillPaintWithAlpha);
strokedOutline.Dispose();
}
else
{
_canvas.DrawPath(platformPath, CurrentState.StrokePaintWithAlpha);
}

platformPath.Dispose();
}

Expand Down
17 changes: 15 additions & 2 deletions src/Graphics/src/Graphics/Platforms/MaciOS/PlatformCanvas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -884,8 +884,21 @@ private CGPath GetPlatformPath(PathF path)
protected override void PlatformDrawPath(PathF path)
{
var platformPath = GetPlatformPath(path);
_context.AddPath(platformPath);
_context.DrawPath(CGPathDrawingMode.Stroke);

if (_gradient != null)
{
FillWithGradient(() =>
{
_context.AddPath(platformPath);
_context.ReplacePathWithStrokedPath();
return true;
});
}
else
{
_context.AddPath(platformPath);
_context.DrawPath(CGPathDrawingMode.Stroke);
}
}

public override void ClipPath(PathF path, WindingMode windingMode = WindingMode.NonZero)
Expand Down
Loading