Explorar el Código

Fix gradient stop reordeing (#18907)

Benedikt Stebner hace 4 meses
padre
commit
0b87d23935

+ 11 - 2
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<ImmutableGradientStop> 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;
         }
     }
 }

+ 9 - 2
src/Avalonia.Base/Media/Immutable/ImmutableGradientStop.cs

@@ -1,4 +1,6 @@
-namespace Avalonia.Media.Immutable
+using Avalonia.Utilities;
+
+namespace Avalonia.Media.Immutable
 {
     /// <summary>
     /// 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;
         }
 

+ 25 - 21
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;
                             }