diff --git a/src/UglyToad.PdfPig.Core/ClippingRule.cs b/src/UglyToad.PdfPig.Core/ClippingRule.cs
new file mode 100644
index 00000000..72f21f14
--- /dev/null
+++ b/src/UglyToad.PdfPig.Core/ClippingRule.cs
@@ -0,0 +1,32 @@
+namespace UglyToad.PdfPig.Core
+{
+ ///
+ /// Rules for determining which points lie inside/outside a path.
+ ///
+ public enum ClippingRule
+ {
+ ///
+ /// No rule.
+ ///
+ None,
+
+ ///
+ /// This even-odd rule determines whether a point is inside a path by drawing a ray from that point in
+ /// any direction and simply counting the number of path segments that cross the ray, regardless of
+ /// direction. If this number is odd, the point is inside; if even, the point is outside. This yields
+ /// the same results as the nonzero winding number rule for paths with simple shapes, but produces
+ /// different results for more complex shapes.
+ ///
+ EvenOdd,
+
+ ///
+ /// The nonzero winding number rule determines whether a given point is inside a path by conceptually
+ /// drawing a ray from that point to infinity in any direction and then examining the places where a
+ /// segment of the path crosses the ray. Starting with a count of 0, the rule adds 1 each time a path
+ /// segment crosses the ray from left to right and subtracts 1 each time a segment crosses from right
+ /// to left. After counting all the crossings, if the result is 0, the point is outside the path;
+ /// otherwise, it is inside.
+ ///
+ NonZeroWinding
+ }
+}
diff --git a/src/UglyToad.PdfPig.Core/PdfPath.cs b/src/UglyToad.PdfPig.Core/PdfPath.cs
index 339a371f..f99abdde 100644
--- a/src/UglyToad.PdfPig.Core/PdfPath.cs
+++ b/src/UglyToad.PdfPig.Core/PdfPath.cs
@@ -22,6 +22,16 @@
///
public bool IsDrawnAsRectangle { get; internal set; }
+ ///
+ /// Rules for determining which points lie inside/outside the path.
+ ///
+ public ClippingRule ClippingRule { get; private set; }
+
+ ///
+ /// Returns true if this is a clipping path.
+ ///
+ public bool IsClipping { get; private set; }
+
private PdfPoint? currentPosition;
private double shoeLaceSum;
@@ -78,6 +88,16 @@
return new PdfPoint(points.Average(p => p.X), points.Average(p => p.Y));
}
+ ///
+ ///
+ ///
+ ///
+ public void SetClipping(ClippingRule clippingRule)
+ {
+ IsClipping = true;
+ ClippingRule = clippingRule;
+ }
+
internal static PdfPoint GetStartPoint(IPathCommand command)
{
if (command is Line line)
diff --git a/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs b/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs
index 2e6dce19..9dec83ec 100644
--- a/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs
+++ b/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs
@@ -93,12 +93,14 @@
public void BeginMarkedContent(NameToken name, NameToken propertyDictionaryName, DictionaryToken properties)
{
-
}
public void EndMarkedContent()
{
+ }
+ public void ModifyClippingIntersect(ClippingRule clippingRule)
+ {
}
private class TestFontFactory : IFontFactory
diff --git a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs
index a3dc979a..af326ecd 100644
--- a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs
+++ b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs
@@ -565,5 +565,10 @@
TextMatrices.TextMatrix = newMatrix;
}
+
+ public void ModifyClippingIntersect(ClippingRule clippingRule)
+ {
+ CurrentPath.SetClipping(clippingRule);
+ }
}
}
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs
index c81e8af8..740c3a0f 100644
--- a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs
+++ b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs
@@ -127,5 +127,10 @@
/// Indicates that the current inline image is complete.
///
void EndInlineImage(IReadOnlyList bytes);
+
+ ///
+ /// Modify the clipping rule of the current path.
+ ///
+ void ModifyClippingIntersect(ClippingRule clippingRule);
}
}
\ No newline at end of file
diff --git a/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByEvenOddIntersect.cs b/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByEvenOddIntersect.cs
index ac88494d..284614d5 100644
--- a/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByEvenOddIntersect.cs
+++ b/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByEvenOddIntersect.cs
@@ -29,6 +29,7 @@
///
public void Run(IOperationContext operationContext)
{
+ operationContext.ModifyClippingIntersect(PdfPig.Core.ClippingRule.EvenOdd);
}
///
diff --git a/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByNonZeroWindingIntersect.cs b/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByNonZeroWindingIntersect.cs
index fa39bac0..6c5d0459 100644
--- a/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByNonZeroWindingIntersect.cs
+++ b/src/UglyToad.PdfPig/Graphics/Operations/ClippingPaths/ModifyClippingByNonZeroWindingIntersect.cs
@@ -29,6 +29,7 @@
///
public void Run(IOperationContext operationContext)
{
+ operationContext.ModifyClippingIntersect(PdfPig.Core.ClippingRule.NonZeroWinding);
}
///