ソースを参照

Merge pull request #791 from PixiEditor/fixes/antialiasing

Fixed anti aliasing pen
Krzysztof Krysiński 4 ヶ月 前
コミット
bfb597f637

+ 1 - 1
src/ChunkyImageLib/ChunkyImage.cs

@@ -611,7 +611,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
     }
     }
 
 
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
-    public void EnqueueDrawEllipse(RectD location, Paintable strokeColor, Paintable fillColor, float strokeWidth,
+    public void EnqueueDrawEllipse(RectD location, Paintable? strokeColor, Paintable? fillColor, float strokeWidth,
         double rotationRad = 0, bool antiAliased = false,
         double rotationRad = 0, bool antiAliased = false,
         Paint? paint = null)
         Paint? paint = null)
     {
     {

+ 2 - 2
src/ChunkyImageLib/Operations/EllipseOperation.cs

@@ -175,7 +175,7 @@ internal class EllipseOperation : IMirroredDrawOperation
         RectD fillRect = ((RectD)location).Inflate(-strokeWidth / 2f);
         RectD fillRect = ((RectD)location).Inflate(-strokeWidth / 2f);
         
         
         surf.Canvas.DrawOval(fillRect.Center, fillRect.Size / 2f, paint);
         surf.Canvas.DrawOval(fillRect.Center, fillRect.Size / 2f, paint);
-        
+
         paint.IsAntiAliased = true;
         paint.IsAntiAliased = true;
         paint.SetPaintable(strokeWidth <= 0 ? fillPaintable : strokePaintable);
         paint.SetPaintable(strokeWidth <= 0 ? fillPaintable : strokePaintable);
         paint.Style = PaintStyle.Stroke;
         paint.Style = PaintStyle.Stroke;
@@ -195,7 +195,7 @@ internal class EllipseOperation : IMirroredDrawOperation
         RectI bounds = (RectI)corners.AABBBounds.RoundOutwards();
         RectI bounds = (RectI)corners.AABBBounds.RoundOutwards();
         
         
         var chunks = OperationHelper.FindChunksTouchingRectangle(bounds, ChunkyImage.FullChunkSize);
         var chunks = OperationHelper.FindChunksTouchingRectangle(bounds, ChunkyImage.FullChunkSize);
-        if (!fillPaintable.AnythingVisible)
+        if (!fillPaintable?.AnythingVisible ?? false)
         {
         {
              chunks.ExceptWith(OperationHelper.FindChunksFullyInsideEllipse
              chunks.ExceptWith(OperationHelper.FindChunksFullyInsideEllipse
                 (location.Center, location.Width / 2.0 - strokeWidth * 2, location.Height / 2.0 - strokeWidth * 2, ChunkyImage.FullChunkSize, rotation));
                 (location.Center, location.Width / 2.0 - strokeWidth * 2, location.Height / 2.0 - strokeWidth * 2, ChunkyImage.FullChunkSize, rotation));

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit 4a2fdd1c8cd368b24a512033b5935cf3ee758b8f
+Subproject commit 92082eb78437163d5e94e9aa57281f1971419cca

+ 25 - 19
src/PixiEditor.ChangeableDocument/Changes/Drawing/LineBasedPen_UpdateableChange.cs

@@ -1,5 +1,6 @@
 using ChunkyImageLib.Operations;
 using ChunkyImageLib.Operations;
 using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.ColorsImpl;
+using Drawie.Backend.Core.ColorsImpl.Paintables;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Shaders;
 using Drawie.Backend.Core.Shaders;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
@@ -43,10 +44,10 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
         this.spacing = spacing;
         this.spacing = spacing;
         points.Add(pos);
         points.Add(pos);
         this.frame = frame;
         this.frame = frame;
-        
+
         srcPaint.Shader?.Dispose();
         srcPaint.Shader?.Dispose();
         srcPaint.Shader = null;
         srcPaint.Shader = null;
-        
+
         if (this.antiAliasing && !erasing)
         if (this.antiAliasing && !erasing)
         {
         {
             srcPaint.BlendMode = BlendMode.SrcOver;
             srcPaint.BlendMode = BlendMode.SrcOver;
@@ -65,7 +66,7 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
             var bresenham = BresenhamLineHelper.GetBresenhamLine(points[^1], pos);
             var bresenham = BresenhamLineHelper.GetBresenhamLine(points[^1], pos);
             points.AddRange(bresenham);
             points.AddRange(bresenham);
         }
         }
-        
+
         this.strokeWidth = strokeWidth;
         this.strokeWidth = strokeWidth;
     }
     }
 
 
@@ -90,8 +91,8 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
         int opCount = image.QueueLength;
         int opCount = image.QueueLength;
 
 
         float spacingPixels = strokeWidth * spacing;
         float spacingPixels = strokeWidth * spacing;
-        
-        for(int i = Math.Max(lastAppliedPointIndex, 0); i < points.Count; i++)
+
+        for (int i = Math.Max(lastAppliedPointIndex, 0); i < points.Count; i++)
         {
         {
             var point = points[i];
             var point = points[i];
             if (points.Count > 1 && VecF.Distance(lastPos, point) < spacingPixels)
             if (points.Count > 1 && VecF.Distance(lastPos, point) < spacingPixels)
@@ -99,14 +100,15 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
 
 
             lastPos = point;
             lastPos = point;
             var rect = new RectI(point - new VecI((int)(strokeWidth / 2f)), new VecI((int)strokeWidth));
             var rect = new RectI(point - new VecI((int)(strokeWidth / 2f)), new VecI((int)strokeWidth));
+            Paintable finalPaintable = color;
             if (antiAliasing)
             if (antiAliasing)
             {
             {
-                ApplySoftnessGradient((VecD)point);
+                finalPaintable = ApplySoftnessGradient((VecD)point);
             }
             }
 
 
-            image.EnqueueDrawEllipse((RectD)rect, color, color, 0, 0, antiAliasing, srcPaint);
+            image.EnqueueDrawEllipse((RectD)rect, finalPaintable, finalPaintable, 0, 0, antiAliasing, srcPaint);
         }
         }
-        
+
         lastAppliedPointIndex = points.Count - 1;
         lastAppliedPointIndex = points.Count - 1;
 
 
         var affChunks = image.FindAffectedArea(opCount);
         var affChunks = image.FindAffectedArea(opCount);
@@ -119,19 +121,20 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
         if (points.Count == 1)
         if (points.Count == 1)
         {
         {
             var rect = new RectI(points[0] - new VecI((int)(strokeWidth / 2f)), new VecI((int)strokeWidth));
             var rect = new RectI(points[0] - new VecI((int)(strokeWidth / 2f)), new VecI((int)strokeWidth));
+            Paintable finalPaintable = color;
             if (antiAliasing)
             if (antiAliasing)
             {
             {
-                ApplySoftnessGradient(points[0]);
+                finalPaintable = ApplySoftnessGradient(points[0]);
             }
             }
 
 
-            targetImage.EnqueueDrawEllipse((RectD)rect, color, color, 0, 0, antiAliasing, srcPaint);
+            targetImage.EnqueueDrawEllipse((RectD)rect, finalPaintable, finalPaintable, 0, 0, antiAliasing, srcPaint);
             return;
             return;
         }
         }
 
 
         VecF lastPos = points[0];
         VecF lastPos = points[0];
 
 
         float spacingInPixels = strokeWidth * this.spacing;
         float spacingInPixels = strokeWidth * this.spacing;
-        
+
         for (int i = 0; i < points.Count; i++)
         for (int i = 0; i < points.Count; i++)
         {
         {
             if (i > 0 && VecF.Distance(lastPos, points[i]) < spacingInPixels)
             if (i > 0 && VecF.Distance(lastPos, points[i]) < spacingInPixels)
@@ -139,24 +142,27 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
 
 
             lastPos = points[i];
             lastPos = points[i];
             var rect = new RectI(points[i] - new VecI((int)(strokeWidth / 2f)), new VecI((int)strokeWidth));
             var rect = new RectI(points[i] - new VecI((int)(strokeWidth / 2f)), new VecI((int)strokeWidth));
+            Paintable? finalPaintable = color;
             if (antiAliasing)
             if (antiAliasing)
             {
             {
-                ApplySoftnessGradient(points[i]);
+                finalPaintable = ApplySoftnessGradient(points[i]);
             }
             }
 
 
-            targetImage.EnqueueDrawEllipse((RectD)rect, color, color, 0, 0, antiAliasing, srcPaint);
+            targetImage.EnqueueDrawEllipse((RectD)rect, finalPaintable, finalPaintable, 0, 0, antiAliasing, srcPaint);
         }
         }
     }
     }
 
 
-    private void ApplySoftnessGradient(VecD pos)
+    private RadialGradientPaintable? ApplySoftnessGradient(VecD pos)
     {
     {
-        if (hardness >= 1) return;
-        srcPaint.Shader?.Dispose();
+        if (hardness >= 1) return null;
+        srcPaint.Paintable?.Dispose();
         float radius = strokeWidth / 2f;
         float radius = strokeWidth / 2f;
         radius = MathF.Max(1, radius);
         radius = MathF.Max(1, radius);
-        srcPaint.Shader = Shader.CreateRadialGradient(
-            pos, radius, [color, color.WithAlpha(0)],
-            [Math.Max(hardness - 0.05f, 0), 0.95f], ShaderTileMode.Clamp);
+        return new RadialGradientPaintable(pos, radius,
+        [
+            new GradientStop(color, Math.Max(hardness - 0.05f, 0)),
+            new GradientStop(color.WithAlpha(0), 0.95f)
+        ]) { AbsoluteValues = true };
     }
     }
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,