-
-
Notifications
You must be signed in to change notification settings - Fork 46
Backport improvements from TechPizzaDev fork. #366
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4561a3c
52c5312
bed3722
558de97
7527241
3c8b5d3
319b80d
0a70463
2152cec
4fdddc4
99a6283
4569fe7
0285e5d
4bfa88b
0dbfc38
5703f58
0e0d9bf
975c453
5448713
9b91ee4
d3ec07c
d819f81
70da339
f8a963b
c5c823c
018962b
9e8c991
72bd892
c40f450
1e06414
539e09d
f71184b
4cf8fa3
b976617
ea766fd
fdbb390
9c877af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,6 @@ | ||
| // Copyright (c) Six Labors. | ||
| // Licensed under the Six Labors Split License. | ||
|
|
||
| using System.Numerics; | ||
|
|
||
| namespace SixLabors.ImageSharp.Drawing; | ||
|
|
||
| /// <summary> | ||
|
|
@@ -28,20 +26,19 @@ public static bool IsOpaqueColorWithoutBlending(this GraphicsOptions options, Co | |
| return false; | ||
| } | ||
|
|
||
| if (options.AlphaCompositionMode != PixelAlphaCompositionMode.SrcOver | ||
| && options.AlphaCompositionMode != PixelAlphaCompositionMode.Src) | ||
| if (options.AlphaCompositionMode is not PixelAlphaCompositionMode.SrcOver and not PixelAlphaCompositionMode.Src) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| const float Opaque = 1F; | ||
| const float opaque = 1f; | ||
|
|
||
| if (options.BlendPercentage != Opaque) | ||
| if (options.BlendPercentage != opaque) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| if (color.ToScaledVector4().W != Opaque) | ||
| if (color.ToScaledVector4().W != opaque) | ||
|
||
| { | ||
| return false; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -292,7 +292,7 @@ protected override void EndGlyph() | |
| } | ||
|
|
||
| // Path has already been added to the collection via the base class. | ||
| IPath path = this.Paths.Last(); | ||
| IPath path = this.PathList[^1]; | ||
|
||
| Point renderLocation = ClampToPixel(path.Bounds.Location); | ||
| if (this.noCache || this.rasterizationRequired) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |||||
| // Licensed under the Six Labors Split License. | ||||||
|
|
||||||
| using System.Buffers; | ||||||
| using System.Diagnostics.CodeAnalysis; | ||||||
| using System.Numerics; | ||||||
|
|
||||||
| namespace SixLabors.ImageSharp.Drawing; | ||||||
|
|
@@ -14,8 +15,9 @@ namespace SixLabors.ImageSharp.Drawing; | |||||
| public sealed class ComplexPolygon : IPath, IPathInternals, IInternalPathOwner | ||||||
| { | ||||||
| private readonly IPath[] paths; | ||||||
| private readonly List<InternalPath> internalPaths; | ||||||
| private readonly float length; | ||||||
| private List<InternalPath>? internalPaths; | ||||||
| private float length; | ||||||
| private RectangleF? bounds; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Initializes a new instance of the <see cref="ComplexPolygon"/> class. | ||||||
|
|
@@ -45,53 +47,10 @@ public ComplexPolygon(params IPath[] paths) | |||||
| Guard.NotNull(paths, nameof(paths)); | ||||||
|
|
||||||
| this.paths = paths; | ||||||
| this.internalPaths = new List<InternalPath>(this.paths.Length); | ||||||
|
|
||||||
| if (paths.Length > 0) | ||||||
| { | ||||||
| float minX = float.MaxValue; | ||||||
| float maxX = float.MinValue; | ||||||
| float minY = float.MaxValue; | ||||||
| float maxY = float.MinValue; | ||||||
| float length = 0; | ||||||
|
|
||||||
| foreach (IPath p in this.paths) | ||||||
| { | ||||||
| if (p.Bounds.Left < minX) | ||||||
| { | ||||||
| minX = p.Bounds.Left; | ||||||
| } | ||||||
|
|
||||||
| if (p.Bounds.Right > maxX) | ||||||
| { | ||||||
| maxX = p.Bounds.Right; | ||||||
| } | ||||||
|
|
||||||
| if (p.Bounds.Top < minY) | ||||||
| { | ||||||
| minY = p.Bounds.Top; | ||||||
| } | ||||||
|
|
||||||
| if (p.Bounds.Bottom > maxY) | ||||||
| { | ||||||
| maxY = p.Bounds.Bottom; | ||||||
| } | ||||||
|
|
||||||
| foreach (ISimplePath s in p.Flatten()) | ||||||
| { | ||||||
| InternalPath ip = new(s.Points, s.IsClosed); | ||||||
| length += ip.Length; | ||||||
| this.internalPaths.Add(ip); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| this.length = length; | ||||||
| this.Bounds = new RectangleF(minX, minY, maxX - minX, maxY - minY); | ||||||
| } | ||||||
| else | ||||||
| if (paths.Length == 0) | ||||||
| { | ||||||
| this.length = 0; | ||||||
| this.Bounds = RectangleF.Empty; | ||||||
| this.bounds = RectangleF.Empty; | ||||||
| } | ||||||
|
|
||||||
| this.PathType = PathTypes.Mixed; | ||||||
|
|
@@ -106,7 +65,7 @@ public ComplexPolygon(params IPath[] paths) | |||||
| public IEnumerable<IPath> Paths => this.paths; | ||||||
|
|
||||||
| /// <inheritdoc/> | ||||||
| public RectangleF Bounds { get; } | ||||||
| public RectangleF Bounds => this.bounds ??= this.CalcBounds(); | ||||||
|
|
||||||
| /// <inheritdoc/> | ||||||
| public IPath Transform(Matrix3x2 matrix) | ||||||
|
|
@@ -118,10 +77,10 @@ public IPath Transform(Matrix3x2 matrix) | |||||
| } | ||||||
|
|
||||||
| IPath[] shapes = new IPath[this.paths.Length]; | ||||||
| int i = 0; | ||||||
| foreach (IPath s in this.Paths) | ||||||
|
|
||||||
| for (int i = 0; i < shapes.Length; i++) | ||||||
| { | ||||||
| shapes[i++] = s.Transform(matrix); | ||||||
| shapes[i] = this.paths[i].Transform(matrix); | ||||||
| } | ||||||
|
|
||||||
| return new ComplexPolygon(shapes); | ||||||
|
|
@@ -159,6 +118,11 @@ public IPath AsClosedPath() | |||||
| /// <inheritdoc/> | ||||||
| SegmentInfo IPathInternals.PointAlongPath(float distance) | ||||||
| { | ||||||
| if (this.internalPaths == null) | ||||||
| { | ||||||
| this.InitInternalPaths(); | ||||||
| } | ||||||
|
|
||||||
| distance %= this.length; | ||||||
| foreach (InternalPath p in this.internalPaths) | ||||||
| { | ||||||
|
|
@@ -177,7 +141,49 @@ SegmentInfo IPathInternals.PointAlongPath(float distance) | |||||
|
|
||||||
| /// <inheritdoc/> | ||||||
| IReadOnlyList<InternalPath> IInternalPathOwner.GetRingsAsInternalPath() | ||||||
| => this.internalPaths; | ||||||
| { | ||||||
| this.InitInternalPaths(); | ||||||
| return this.internalPaths; | ||||||
|
||||||
| return this.internalPaths; | |
| return this.internalPaths!; |
Copilot
AI
Oct 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This foreach loop immediately maps its iteration variable to another variable - consider mapping the sequence explicitly using '.Select(...)'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Equality checks on floating point values can yield unexpected results.