diff --git a/src/Avalonia.Base/Media/GradientStops.cs b/src/Avalonia.Base/Media/GradientStops.cs index c3d0bb5ceb..9befb4f1d3 100644 --- a/src/Avalonia.Base/Media/GradientStops.cs +++ b/src/Avalonia.Base/Media/GradientStops.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using Avalonia.Collections; using Avalonia.Media.Immutable; @@ -17,7 +16,17 @@ namespace Avalonia.Media public IReadOnlyList ToImmutable() { - return this.Select(x => new ImmutableGradientStop(x.Offset, x.Color)).ToArray(); + var count = Count; + var stops = new ImmutableGradientStop[count]; + + for (var i = 0; i < count; i++) + { + var currentStop = this[i]; + + stops[i] = new ImmutableGradientStop(currentStop.Offset, currentStop.Color); + } + + return stops; } } } diff --git a/src/Avalonia.Base/Media/Immutable/ImmutableGradientStop.cs b/src/Avalonia.Base/Media/Immutable/ImmutableGradientStop.cs index f3e2e52fd0..5c8c908cf7 100644 --- a/src/Avalonia.Base/Media/Immutable/ImmutableGradientStop.cs +++ b/src/Avalonia.Base/Media/Immutable/ImmutableGradientStop.cs @@ -1,4 +1,6 @@ -namespace Avalonia.Media.Immutable +using Avalonia.Utilities; + +namespace Avalonia.Media.Immutable { /// /// Describes the location and color of a transition point in a gradient. @@ -7,7 +9,12 @@ { public ImmutableGradientStop(double offset, Color color) { - Offset = offset; + if (MathUtilities.IsZero(offset)) + { + offset = 0; + } + + Offset = (offset < 0) ? 0 : (offset > 1) ? 1 : offset; Color = color; } diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 46c06d2672..ce5b59a86d 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -963,39 +963,43 @@ namespace Avalonia.Skia (originPoint.Y - centerPoint.Y) * radiusX / radiusY + centerPoint.Y); var origin = originPoint.ToSKPoint(); - var endOffset = 0.0; - // and then reverse the reference point of the stops - var reversedStops = new float[stopOffsets.Length]; - - for (var i = 0; i < stopOffsets.Length; i++) - { - var offset = stopOffsets[i]; - if (endOffset < offset) - { - endOffset = offset; - } - reversedStops[i] = offset; - if (reversedStops[i] > 0 && reversedStops[i] < 1) - { - reversedStops[i] = Math.Abs(1 - offset); - } - } + var endOffset = stopOffsets[stopOffsets.Length - 1]; var start = origin; var radiusStart = 0f; var end = center; var radiusEnd = (float)radiusX; - var reverse = MathUtilities.AreClose(1, endOffset); + var reverse = (centerPoint.X != originPoint.X || centerPoint.Y != originPoint.Y) && endOffset == 1; if (reverse) { + // reverse the order of the stops to match D2D (start, radiusStart, end, radiusEnd) = (end, radiusEnd, start, radiusStart); - // reverse the order of the stops to match D2D + var count = stopOffsets.Length; + var reversedColors = new SKColor[stopColors.Length]; - Array.Copy(stopColors, reversedColors, stopColors.Length); - Array.Reverse(reversedColors); + // and then reverse the reference point of the stops + var reversedStops = new float[count]; + + for (var i = 0; i < count; i++) + { + var offset = radialGradient.GradientStops[i].Offset; + + offset = 1 - offset; + + if (MathUtilities.IsZero(offset)) + { + offset = 0; + } + + var reversedIndex = count - 1 - i; + + reversedStops[reversedIndex] = (float)offset; + reversedColors[reversedIndex] = stopColors[i]; + } + stopColors = reversedColors; stopOffsets = reversedStops; }