PathOperation.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using ChunkyImageLib.DataHolders;
  2. using Drawie.Backend.Core.ColorsImpl;
  3. using Drawie.Backend.Core.ColorsImpl.Paintables;
  4. using Drawie.Backend.Core.Numerics;
  5. using Drawie.Backend.Core.Shaders;
  6. using Drawie.Backend.Core.Surfaces;
  7. using Drawie.Backend.Core.Surfaces.PaintImpl;
  8. using Drawie.Backend.Core.Vector;
  9. using Drawie.Numerics;
  10. namespace ChunkyImageLib.Operations;
  11. internal class PathOperation : IMirroredDrawOperation
  12. {
  13. private readonly VectorPath path;
  14. private readonly Paint paint;
  15. private readonly RectI bounds;
  16. private bool antiAliasing;
  17. public bool IgnoreEmptyChunks => false;
  18. public PathOperation(VectorPath path, Color color, float strokeWidth, StrokeCap cap, BlendMode blendMode, RectI? customBounds = null)
  19. {
  20. this.path = new VectorPath(path);
  21. paint = new() { Color = color, Style = PaintStyle.Stroke, StrokeWidth = strokeWidth, StrokeCap = cap, BlendMode = blendMode };
  22. RectI floatBounds = customBounds ?? (RectI)(path.TightBounds).RoundOutwards();
  23. bounds = floatBounds.Inflate((int)Math.Ceiling(strokeWidth) + 1);
  24. }
  25. public PathOperation(VectorPath path, Color color, float strokeWidth, StrokeCap cap, Blender blender, RectI? customBounds = null)
  26. {
  27. this.path = new VectorPath(path);
  28. paint = new() { Color = color, Style = PaintStyle.Stroke, StrokeWidth = strokeWidth, StrokeCap = cap, Blender = blender };
  29. RectI floatBounds = customBounds ?? (RectI)(path.TightBounds).RoundOutwards();
  30. bounds = floatBounds.Inflate((int)Math.Ceiling(strokeWidth) + 1);
  31. }
  32. public PathOperation(VectorPath path, Paintable paintable, float strokeWidth, StrokeCap cap, BlendMode blendMode,
  33. PaintStyle style, bool antiAliasing, RectI? customBounds = null)
  34. {
  35. this.antiAliasing = antiAliasing;
  36. this.path = new VectorPath(path);
  37. paint = new() { Paintable = paintable, Style = style, StrokeWidth = strokeWidth, StrokeCap = cap, BlendMode = blendMode };
  38. RectI floatBounds = customBounds ?? (RectI)(path.Bounds).RoundOutwards();
  39. bounds = floatBounds.Inflate((int)Math.Ceiling(strokeWidth) + 1);
  40. }
  41. public PathOperation(VectorPath path, Paintable paintable, float strokeWidth, StrokeCap cap, Blender blender, PaintStyle style, bool antiAliasing, RectI? customBounds)
  42. {
  43. this.antiAliasing = antiAliasing;
  44. this.path = new VectorPath(path);
  45. paint = new() { Paintable = paintable, Style = style, StrokeWidth = strokeWidth, StrokeCap = cap, Blender = blender };
  46. RectI floatBounds = customBounds ?? (RectI)(path.Bounds).RoundOutwards();
  47. bounds = floatBounds.Inflate((int)Math.Ceiling(strokeWidth) + 1);
  48. }
  49. public void DrawOnChunk(Chunk targetChunk, VecI chunkPos)
  50. {
  51. paint.IsAntiAliased = antiAliasing || targetChunk.Resolution != ChunkResolution.Full;
  52. var surf = targetChunk.Surface.DrawingSurface;
  53. surf.Canvas.Save();
  54. surf.Canvas.Scale((float)targetChunk.Resolution.Multiplier());
  55. surf.Canvas.Translate(-chunkPos * ChunkyImage.FullChunkSize);
  56. surf.Canvas.DrawPath(path, paint);
  57. surf.Canvas.Restore();
  58. }
  59. public AffectedArea FindAffectedArea(VecI imageSize)
  60. {
  61. return new AffectedArea(OperationHelper.FindChunksTouchingRectangle(bounds, ChunkyImage.FullChunkSize), bounds);
  62. }
  63. public IDrawOperation AsMirrored(double? verAxisX, double? horAxisY)
  64. {
  65. var matrix = Matrix3X3.CreateScale(verAxisX is not null ? -1 : 1, horAxisY is not null ? -1 : 1, (float?)verAxisX ?? 0, (float?)horAxisY ?? 0);
  66. using var copy = new VectorPath(path);
  67. copy.Transform(matrix);
  68. RectI newBounds = bounds;
  69. if (verAxisX is not null)
  70. newBounds = (RectI)newBounds.ReflectX((double)verAxisX).Round();
  71. if (horAxisY is not null)
  72. newBounds = (RectI)newBounds.ReflectY((double)horAxisY).Round();
  73. if (paint.Paintable != null)
  74. {
  75. if( paint.Blender != null)
  76. {
  77. return new PathOperation(copy, paint.Paintable, paint.StrokeWidth, paint.StrokeCap, paint.Blender, paint.Style, antiAliasing, newBounds);
  78. }
  79. else
  80. {
  81. return new PathOperation(copy, paint.Paintable, paint.StrokeWidth, paint.StrokeCap, paint.BlendMode,
  82. paint.Style, antiAliasing, newBounds);
  83. }
  84. }
  85. if (paint.Blender != null)
  86. {
  87. return new PathOperation(copy, paint.Color, paint.StrokeWidth, paint.StrokeCap, paint.Blender, newBounds);
  88. }
  89. return new PathOperation(copy, paint.Color, paint.StrokeWidth, paint.StrokeCap, paint.BlendMode, newBounds);
  90. }
  91. public void Dispose()
  92. {
  93. path.Dispose();
  94. paint.Dispose();
  95. }
  96. }