Skip to content
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

Inline Clipper #265

Merged
merged 21 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ private Buffer2D<float> Render(IPath path)
0,
size.Height,
subpixelCount,
IntersectionRule.Nonzero,
IntersectionRule.NonZero,
this.memoryAllocator);

try
Expand Down
19 changes: 15 additions & 4 deletions src/ImageSharp.Drawing/Processing/ShapeOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,25 @@ public ShapeOptions()
{
}

private ShapeOptions(ShapeOptions source) => this.IntersectionRule = source.IntersectionRule;
private ShapeOptions(ShapeOptions source)
{
this.IntersectionRule = source.IntersectionRule;
this.ClippingOperation = source.ClippingOperation;
}

/// <summary>
/// Gets or sets the clipping operation.
/// <para/>
/// Defaults to <see cref="ClippingOperation.Difference"/>.
/// </summary>
public ClippingOperation ClippingOperation { get; set; } = ClippingOperation.Difference;

/// <summary>
/// Gets or sets a value indicating whether antialiasing should be applied.
/// Gets or sets the rule for calculating intersection points.
/// <para/>
/// Defaults to <see cref="IntersectionRule.OddEven"/>.
/// Defaults to <see cref="IntersectionRule.EvenOdd"/>.
/// </summary>
public IntersectionRule IntersectionRule { get; set; } = IntersectionRule.OddEven;
public IntersectionRule IntersectionRule { get; set; } = IntersectionRule.EvenOdd;

/// <inheritdoc/>
public ShapeOptions DeepClone() => new(this);
Expand Down
73 changes: 51 additions & 22 deletions src/ImageSharp.Drawing/Shapes/ClipPathExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,71 @@
// Licensed under the Apache License, Version 2.0.

using System.Collections.Generic;
using SixLabors.ImageSharp.Drawing.PolygonClipper;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Drawing.Shapes.PolygonClipper;

namespace SixLabors.ImageSharp.Drawing
{
/// <summary>
/// Path extensions to clip paths.
/// Provides extension methods to <see cref="IPath"/> that allow the clipping of shapes.
/// </summary>
public static class ClipPathExtensions
{
/// <summary>
/// Clips the specified holes.
/// Clips the specified subject path with the provided clipping paths.
/// </summary>
/// <param name="shape">The shape.</param>
/// <param name="holes">The holes.</param>
/// <returns>Returns a new shape with the holes clipped out of the shape.</returns>
/// <exception cref="ClipperException">Open paths have been disabled.</exception>
public static IPath Clip(this IPath shape, IEnumerable<IPath> holes)
/// <param name="subjectPath">The subject path.</param>
/// <param name="clipPaths">The clipping paths.</param>
/// <returns>The clipped <see cref="IPath"/>.</returns>
/// <exception cref="ClipperException">Thrown when an error occured while attempting to clip the polygon.</exception>
public static IPath Clip(this IPath subjectPath, params IPath[] clipPaths)
=> subjectPath.Clip((IEnumerable<IPath>)clipPaths);

/// <summary>
/// Clips the specified subject path with the provided clipping paths.
/// </summary>
/// <param name="subjectPath">The subject path.</param>
/// <param name="options">The shape options.</param>
/// <param name="clipPaths">The clipping paths.</param>
/// <returns>The clipped <see cref="IPath"/>.</returns>
/// <exception cref="ClipperException">Thrown when an error occured while attempting to clip the polygon.</exception>
public static IPath Clip(
this IPath subjectPath,
ShapeOptions options,
params IPath[] clipPaths)
=> subjectPath.Clip(options, (IEnumerable<IPath>)clipPaths);

/// <summary>
/// Clips the specified subject path with the provided clipping paths.
/// </summary>
/// <param name="subjectPath">The subject path.</param>
/// <param name="clipPaths">The clipping paths.</param>
/// <returns>The clipped <see cref="IPath"/>.</returns>
/// <exception cref="ClipperException">Thrown when an error occured while attempting to clip the polygon.</exception>
public static IPath Clip(this IPath subjectPath, IEnumerable<IPath> clipPaths)
=> subjectPath.Clip(new(), clipPaths);

/// <summary>
/// Clips the specified subject path with the provided clipping paths.
/// </summary>
/// <param name="subjectPath">The subject path.</param>
/// <param name="options">The shape options.</param>
/// <param name="clipPaths">The clipping paths.</param>
/// <returns>The clipped <see cref="IPath"/>.</returns>
/// <exception cref="ClipperException">Thrown when an error occured while attempting to clip the polygon.</exception>
public static IPath Clip(
this IPath subjectPath,
ShapeOptions options,
IEnumerable<IPath> clipPaths)
{
var clipper = new Clipper();
Clipper clipper = new();

clipper.AddPath(shape, ClippingType.Subject);
clipper.AddPaths(holes, ClippingType.Clip);
clipper.AddPath(subjectPath, ClippingType.Subject);
clipper.AddPaths(clipPaths, ClippingType.Clip);

IPath[] result = clipper.GenerateClippedShapes();
IPath[] result = clipper.GenerateClippedShapes(options.ClippingOperation, options.IntersectionRule);

return new ComplexPolygon(result);
}

/// <summary>
/// Clips the specified holes.
/// </summary>
/// <param name="shape">The shape.</param>
/// <param name="holes">The holes.</param>
/// <returns>Returns a new shape with the holes clipped out of the shape.</returns>
/// <exception cref="ClipperException">Open paths have been disabled.</exception>
public static IPath Clip(this IPath shape, params IPath[] holes)
=> shape.Clip((IEnumerable<IPath>)holes);
}
}
Loading