mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-04-05 20:55:01 +08:00
fix clipping error when trying to fill a single line; add log; set EvenOdd as default in initiate CurrentClippingPath; add tests
This commit is contained in:
parent
e41ae7d3a2
commit
8f0f7769a6
19
src/UglyToad.PdfPig.Tests/Geometry/ClippingTests.cs
Normal file
19
src/UglyToad.PdfPig.Tests/Geometry/ClippingTests.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using UglyToad.PdfPig.Tests.Integration;
|
||||
using Xunit;
|
||||
|
||||
namespace UglyToad.PdfPig.Tests.Geometry
|
||||
{
|
||||
public class ClippingTests
|
||||
{
|
||||
[Fact]
|
||||
public void ContainsRectangleEvenOdd()
|
||||
{
|
||||
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("SPARC - v9 Architecture Manual"),
|
||||
new ParsingOptions() { ClipPaths = true }))
|
||||
{
|
||||
var page = document.GetPage(45);
|
||||
Assert.Equal(28, page.ExperimentalAccess.Paths.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
@ -6,6 +6,7 @@
|
||||
using ClipperLibrary;
|
||||
using Core;
|
||||
using Graphics;
|
||||
using UglyToad.PdfPig.Logging;
|
||||
using static Core.PdfSubpath;
|
||||
|
||||
/// <summary>
|
||||
@ -23,7 +24,7 @@
|
||||
/// <summary>
|
||||
/// Generates the result of applying a clipping path to another path.
|
||||
/// </summary>
|
||||
public static PdfPath Clip(this PdfPath clipping, PdfPath subject)
|
||||
public static PdfPath Clip(this PdfPath clipping, PdfPath subject, ILog log = null)
|
||||
{
|
||||
if (clipping == null)
|
||||
{
|
||||
@ -61,7 +62,10 @@
|
||||
subPathClipping.CloseSubpath();
|
||||
}
|
||||
|
||||
clipper.AddPath(subPathClipping.ToClipperPolygon().ToList(), ClipperPolyType.Clip, true);
|
||||
if (!clipper.AddPath(subPathClipping.ToClipperPolygon().ToList(), ClipperPolyType.Clip, true))
|
||||
{
|
||||
log?.Error("ClippingExtensions.Clip(): failed to add clipping subpath.");
|
||||
}
|
||||
}
|
||||
|
||||
// Subject path
|
||||
@ -74,13 +78,27 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
if (subjectClose && !subPathSubject.IsClosed()
|
||||
&& subPathSubject.Commands.Count(sp => sp is Line) < 2
|
||||
&& subPathSubject.Commands.Count(sp => sp is BezierCurve) == 0)
|
||||
{
|
||||
// strange here:
|
||||
// the subpath contains maximum 1 line and no curves
|
||||
// it cannot be filled or a be clipping path
|
||||
// cancel closing the path/subpath
|
||||
subjectClose = false;
|
||||
}
|
||||
|
||||
// Force close subject if need be
|
||||
if (subjectClose && !subPathSubject.IsClosed())
|
||||
{
|
||||
subPathSubject.CloseSubpath();
|
||||
}
|
||||
|
||||
clipper.AddPath(subPathSubject.ToClipperPolygon().ToList(), ClipperPolyType.Subject, subjectClose);
|
||||
if (!clipper.AddPath(subPathSubject.ToClipperPolygon().ToList(), ClipperPolyType.Subject, subjectClose))
|
||||
{
|
||||
log?.Error("ClippingExtensions.Clip(): failed to add subject subpath for clipping.");
|
||||
}
|
||||
}
|
||||
|
||||
var clippingFillType = clipping.FillingRule == FillingRule.NonZeroWinding ? ClipperPolyFillType.NonZero : ClipperPolyFillType.EvenOdd;
|
||||
@ -164,11 +182,12 @@
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (pdfPath.Commands[0] is Move currentMove)
|
||||
ClipperIntPoint movePoint;
|
||||
if (pdfPath.Commands[0] is Move move)
|
||||
{
|
||||
var previous = currentMove.Location.ToClipperIntPoint();
|
||||
movePoint = move.Location.ToClipperIntPoint();
|
||||
|
||||
yield return previous;
|
||||
yield return movePoint;
|
||||
|
||||
if (pdfPath.Commands.Count == 1)
|
||||
{
|
||||
@ -185,7 +204,7 @@
|
||||
var command = pdfPath.Commands[i];
|
||||
if (command is Move)
|
||||
{
|
||||
throw new ArgumentException("ToClipperPolygon():only one move allowed per subpath.", nameof(pdfPath));
|
||||
throw new ArgumentException("ToClipperPolygon(): only one move allowed per subpath.", nameof(pdfPath));
|
||||
}
|
||||
|
||||
if (command is Line line)
|
||||
@ -203,7 +222,11 @@
|
||||
}
|
||||
else if (command is Close)
|
||||
{
|
||||
yield return currentMove.Location.ToClipperIntPoint();
|
||||
if (movePoint == null)
|
||||
{
|
||||
throw new ArgumentException("ToClipperPolygon(): Move command was null, cannot close the subpath.");
|
||||
}
|
||||
yield return movePoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@
|
||||
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);
|
||||
clippingPath.SetClipping(FillingRule.EvenOdd);
|
||||
|
||||
graphicsStack.Push(new CurrentGraphicsState()
|
||||
{
|
||||
@ -627,7 +627,7 @@
|
||||
|
||||
if (clipPaths)
|
||||
{
|
||||
var clippedPath = currentState.CurrentClippingPath.Clip(CurrentPath);
|
||||
var clippedPath = currentState.CurrentClippingPath.Clip(CurrentPath, log);
|
||||
if (clippedPath != null)
|
||||
{
|
||||
paths.Add(clippedPath);
|
||||
@ -658,7 +658,7 @@
|
||||
var currentClipping = GetCurrentState().CurrentClippingPath;
|
||||
currentClipping.SetClipping(clippingRule);
|
||||
|
||||
var newClippings = CurrentPath.Clip(currentClipping);
|
||||
var newClippings = CurrentPath.Clip(currentClipping, log);
|
||||
if (newClippings == null)
|
||||
{
|
||||
log.Warn("Empty clipping path found. Clipping path not updated.");
|
||||
|
Loading…
Reference in New Issue
Block a user