diff --git a/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs b/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs index 95ceb3ea..6f335aec 100644 --- a/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs +++ b/src/UglyToad.PdfPig.Tests/Graphics/TestOperationContext.cs @@ -65,6 +65,7 @@ public void BeginSubpath() { } + public PdfPoint CloseSubpath() { return new PdfPoint(); @@ -87,6 +88,10 @@ } + public void EndPath() + { + } + public void ClosePath() { } diff --git a/src/UglyToad.PdfPig/Content/IPageFactory.cs b/src/UglyToad.PdfPig/Content/IPageFactory.cs index 17c01447..902fc5a8 100644 --- a/src/UglyToad.PdfPig/Content/IPageFactory.cs +++ b/src/UglyToad.PdfPig/Content/IPageFactory.cs @@ -4,6 +4,6 @@ internal interface IPageFactory { - Page Create(int number, DictionaryToken dictionary, PageTreeMembers pageTreeMembers); + Page Create(int number, DictionaryToken dictionary, PageTreeMembers pageTreeMembers, bool clipPaths); } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Content/Pages.cs b/src/UglyToad.PdfPig/Content/Pages.cs index 10c976c3..06752c6c 100644 --- a/src/UglyToad.PdfPig/Content/Pages.cs +++ b/src/UglyToad.PdfPig/Content/Pages.cs @@ -23,7 +23,7 @@ Count = catalog.PagesDictionary.GetIntOrDefault(NameToken.Count); } - public Page GetPage(int pageNumber) + public Page GetPage(int pageNumber, bool clipPaths) { if (pageNumber <= 0 || pageNumber > Count) { @@ -62,8 +62,8 @@ pageTreeMembers.Rotation = rotateToken.Int; } } - - var page = pageFactory.Create(pageNumber, pageNode.NodeDictionary, pageTreeMembers); + + var page = pageFactory.Create(pageNumber, pageNode.NodeDictionary, pageTreeMembers, clipPaths); return page; } diff --git a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs index d6cf4df5..6fe31edb 100644 --- a/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs +++ b/src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs @@ -48,6 +48,7 @@ private readonly IPageContentParser pageContentParser; private readonly IFilterProvider filterProvider; private readonly ILog log; + private readonly bool clipPaths; private readonly MarkedContentStack markedContentStack = new MarkedContentStack(); private Stack graphicsStack = new Stack(); @@ -86,7 +87,8 @@ IPdfTokenScanner pdfScanner, IPageContentParser pageContentParser, IFilterProvider filterProvider, - ILog log) + ILog log, + bool clipPaths) { this.resourceStore = resourceStore; this.userSpaceUnit = userSpaceUnit; @@ -95,6 +97,7 @@ this.pageContentParser = pageContentParser ?? throw new ArgumentNullException(nameof(pageContentParser)); this.filterProvider = filterProvider ?? throw new ArgumentNullException(nameof(filterProvider)); this.log = log; + this.clipPaths = clipPaths; // initiate CurrentClippingPath to cropBox var clippingSubpath = new PdfSubpath(); @@ -509,12 +512,12 @@ if (CurrentPath.IsClipping) { - /*if (!clipPaths) + if (!clipPaths) { // if we don't clip paths, add clipping paths paths.Add(CurrentPath); markedContentStack.AddPath(CurrentPath); - }*/ + } CurrentPath = null; return; } @@ -549,20 +552,20 @@ CurrentPath.FillColor = currentState.CurrentNonStrokingColor; } - //if (clipPaths) - //{ + if (clipPaths) + { var clippedPath = currentState.CurrentClippingPath.Clip(CurrentPath); if (clippedPath != null) { paths.Add(clippedPath); markedContentStack.AddPath(clippedPath); } - /*} + } else { paths.Add(CurrentPath); markedContentStack.AddPath(CurrentPath); - }*/ + } CurrentPath = null; } diff --git a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs index d4e9ea21..8db0757b 100644 --- a/src/UglyToad.PdfPig/Graphics/IOperationContext.cs +++ b/src/UglyToad.PdfPig/Graphics/IOperationContext.cs @@ -117,6 +117,12 @@ /// Whether to also close the path. void FillStrokePath(FillingRule fillingRule, bool close); + /// + /// End the path object without filling or stroking it. This operator shall be a path-painting no-op, + /// used primarily for the side effect of changing the current clipping path (see 8.5.4, "Clipping Path Operators"). + /// + void EndPath(); + /// /// Close the current path. /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathConstruction/AppendStartControlPointBezierCurve.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathConstruction/AppendStartControlPointBezierCurve.cs index e334d167..61d1dd9b 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathConstruction/AppendStartControlPointBezierCurve.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathConstruction/AppendStartControlPointBezierCurve.cs @@ -56,17 +56,15 @@ /// public void Run(IOperationContext operationContext) { - var controlPoint2 = new PdfPoint(X2, Y2); - var end = new PdfPoint(X3, Y3); - var controlPoint2Transform = operationContext.CurrentTransformationMatrix.Transform(controlPoint2); - var endTransform = operationContext.CurrentTransformationMatrix.Transform(end); + var controlPoint2 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X2, Y2)); + var end = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X3, Y3)); operationContext.CurrentSubpath.BezierCurveTo(operationContext.CurrentPosition.X, operationContext.CurrentPosition.Y, - controlPoint2Transform.X, - controlPoint2Transform.Y, - endTransform.X, - endTransform.Y); - operationContext.CurrentPosition = endTransform; + controlPoint2.X, + controlPoint2.Y, + end.X, + end.Y); + operationContext.CurrentPosition = end; } /// diff --git a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/EndPath.cs b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/EndPath.cs index 4c0b79bf..b86e7627 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/EndPath.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/PathPainting/EndPath.cs @@ -28,6 +28,7 @@ /// public void Run(IOperationContext operationContext) { + operationContext.EndPath(); } /// diff --git a/src/UglyToad.PdfPig/Parser/PageFactory.cs b/src/UglyToad.PdfPig/Parser/PageFactory.cs index 2c48f8bf..49f950aa 100644 --- a/src/UglyToad.PdfPig/Parser/PageFactory.cs +++ b/src/UglyToad.PdfPig/Parser/PageFactory.cs @@ -33,7 +33,7 @@ this.pdfScanner = pdfScanner; } - public Page Create(int number, DictionaryToken dictionary, PageTreeMembers pageTreeMembers) + public Page Create(int number, DictionaryToken dictionary, PageTreeMembers pageTreeMembers, bool clipPaths) { if (dictionary == null) { @@ -107,8 +107,8 @@ bytes.Add((byte)'\n'); } } - - content = GetContent(number, bytes, cropBox, userSpaceUnit, rotation); + + content = GetContent(number, bytes, cropBox, userSpaceUnit, rotation, clipPaths); } else { @@ -121,7 +121,7 @@ var bytes = contentStream.Decode(filterProvider); - content = GetContent(number, bytes, cropBox, userSpaceUnit, rotation); + content = GetContent(number, bytes, cropBox, userSpaceUnit, rotation, clipPaths); } var page = new Page(number, dictionary, mediaBox, cropBox, rotation, content, @@ -137,15 +137,16 @@ } private PageContent GetContent(int pageNumber, IReadOnlyList contentBytes, CropBox cropBox, UserSpaceUnit userSpaceUnit, - PageRotationDegrees rotation) + PageRotationDegrees rotation, bool clipPaths) { var operations = pageContentParser.Parse(pageNumber, new ByteArrayInputBytes(contentBytes), log); - var context = new ContentStreamProcessor(cropBox.Bounds, resourceStore, userSpaceUnit, rotation, pdfScanner, + var context = new ContentStreamProcessor(cropBox.Bounds, resourceStore, userSpaceUnit, rotation, pdfScanner, pageContentParser, - filterProvider, - log); + filterProvider, + log, + clipPaths); return context.Process(pageNumber, operations); } diff --git a/src/UglyToad.PdfPig/PdfDocument.cs b/src/UglyToad.PdfPig/PdfDocument.cs index e63299a3..373d0f28 100644 --- a/src/UglyToad.PdfPig/PdfDocument.cs +++ b/src/UglyToad.PdfPig/PdfDocument.cs @@ -141,8 +141,9 @@ /// Get the page with the specified page number (1 indexed). /// /// The number of the page to return, this starts from 1. + /// Paths will be clipped if set to true. Default is false. /// The page. - public Page GetPage(int pageNumber) + public Page GetPage(int pageNumber, bool clipPaths = false) { if (isDisposed) { @@ -153,7 +154,7 @@ try { - return pages.GetPage(pageNumber); + return pages.GetPage(pageNumber, clipPaths); } catch (Exception ex) {