diff --git a/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs b/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs index 003e9a47..5885ebf4 100644 --- a/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs +++ b/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs @@ -69,8 +69,13 @@ public void StrokePath(bool close) { } - public void FillPath(bool close) + + public void FillPath(FillingRule fillingRule, bool close) { + } + public void FillStrokePath(FillingRule fillingRule, bool close) + { + } public void ClosePath() diff --git a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs index 7bb3df6f..0b480f3f 100644 --- a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs +++ b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs @@ -17,6 +17,7 @@ using Tokenization.Scanner; using Tokens; using XObjects; + using static UglyToad.PdfPig.Core.PdfSubpath; internal class ContentStreamProcessor : IOperationContext { @@ -94,7 +95,14 @@ this.pageContentParser = pageContentParser ?? throw new ArgumentNullException(nameof(pageContentParser)); this.filterProvider = filterProvider ?? throw new ArgumentNullException(nameof(filterProvider)); this.log = log; - graphicsStack.Push(new CurrentGraphicsState()); + + // initiate CurrentClippingPath to cropBox + var clippingSubpath = new PdfSubpath(); + clippingSubpath.Rectangle(cropBox.BottomLeft.X, cropBox.BottomLeft.Y, cropBox.Width, cropBox.Height); + var clippingPath = new PdfPath() { clippingSubpath }; + clippingPath.SetClipping(FillingRule.NonZeroWinding); + + graphicsStack.Push(new CurrentGraphicsState() { CurrentClippingPath = clippingPath }); ColorSpaceContext = new ColorSpaceContext(GetCurrentState, resourceStore); } @@ -399,7 +407,41 @@ public void BeginSubpath() { - + if (CurrentPath == null) + { + CurrentPath = new PdfPath(); + } + + AddSubpath(); + CurrentSubpath = new PdfSubpath(); + } + + public PdfPoint CloseSubpath() + { + PdfPoint point; + if (CurrentSubpath.Commands[0] is Move move) + { + point = move.Location; + } + else + { + throw new ArgumentException("CloseSubpath(): first command not Move."); + } + + CurrentSubpath.ClosePath(); + AddSubpath(); + return point; + } + + public void AddSubpath() + { + if (CurrentSubpath == null) + { + return; + } + + CurrentPath.Add(CurrentSubpath); + CurrentSubpath = null; } public void StrokePath(bool close) @@ -407,11 +449,16 @@ } - public void FillPath(bool close) + public void FillPath(FillingRule fillingRule, bool close) { } + public void FillStrokePath(FillingRule fillingRule, bool close) + { + + } + public void ClosePath() { diff --git a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs index 64eb1744..6482d343 100644 --- a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs +++ b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs @@ -95,8 +95,16 @@ /// /// Fill the current path. /// + /// The filling rule to use. /// Whether to also close the path. - void FillPath(bool close); + void FillPath(FillingRule fillingRule, bool close); + + /// + /// Fill and stroke the current path. + /// + /// The filling rule to use. + /// Whether to also close the path. + void FillStrokePath(FillingRule fillingRule, bool close); /// /// Close the current path. diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathEvenOddRuleAndStroke.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathEvenOddRuleAndStroke.cs index 77e3fe57..b4927b4a 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathEvenOddRuleAndStroke.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathEvenOddRuleAndStroke.cs @@ -28,7 +28,7 @@ /// public void Run(IOperationContext operationContext) { - operationContext.FillPath(true); + operationContext.FillStrokePath(PdfPig.Core.FillingRule.EvenOdd, true); } /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathNonZeroWindingAndStroke.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathNonZeroWindingAndStroke.cs index d9fa07b7..52e30f33 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathNonZeroWindingAndStroke.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/CloseFillPathNonZeroWindingAndStroke.cs @@ -28,7 +28,7 @@ /// public void Run(IOperationContext operationContext) { - operationContext.FillPath(true); + operationContext.FillStrokePath(PdfPig.Core.FillingRule.NonZeroWinding, true); } /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRule.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRule.cs index d475cff5..fa3614d7 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRule.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRule.cs @@ -28,7 +28,7 @@ /// public void Run(IOperationContext operationContext) { - operationContext.FillPath(false); + operationContext.FillPath(PdfPig.Core.FillingRule.EvenOdd, false); } /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRuleAndStroke.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRuleAndStroke.cs index 0f590bfb..92d80bd7 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRuleAndStroke.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathEvenOddRuleAndStroke.cs @@ -28,7 +28,7 @@ /// public void Run(IOperationContext operationContext) { - operationContext.FillPath(false); + operationContext.FillStrokePath(PdfPig.Core.FillingRule.EvenOdd, false); } /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWinding.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWinding.cs index 1fb1a93d..bd0efdc0 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWinding.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWinding.cs @@ -29,7 +29,7 @@ /// public void Run(IOperationContext operationContext) { - operationContext.FillPath(false); + operationContext.FillPath(PdfPig.Core.FillingRule.NonZeroWinding, false); } /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingAndStroke.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingAndStroke.cs index 26f1a2f0..1b254580 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingAndStroke.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingAndStroke.cs @@ -28,7 +28,7 @@ /// public void Run(IOperationContext operationContext) { - operationContext.FillPath(false); + operationContext.FillStrokePath(PdfPig.Core.FillingRule.NonZeroWinding, false); } /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingCompatibility.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingCompatibility.cs index e655ae55..b148ae24 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingCompatibility.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/FillPathNonZeroWindingCompatibility.cs @@ -15,7 +15,7 @@ public const string Symbol = "F"; /// - /// The instance of the operation. + /// The instance of the operation. /// public static readonly FillPathNonZeroWindingCompatibility Value = new FillPathNonZeroWindingCompatibility(); @@ -29,13 +29,14 @@ /// public void Run(IOperationContext operationContext) { - operationContext.FillPath(false); + operationContext.FillPath(PdfPig.Core.FillingRule.NonZeroWinding, false); } /// public void Write(Stream stream) { - stream.WriteText(Symbol); + // Although PDF reader applications shall be able to accept this operator, PDF writer applications should use f instead. + stream.WriteText(FillPathNonZeroWinding.Symbol); stream.WriteNewLine(); }