mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-19 02:37:56 +08:00
Merge pull request #220 from BobLd/fix-clip-line-fill
fix clipping error when trying to fill a single line
This commit is contained in:
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 ClipperLibrary;
|
||||||
using Core;
|
using Core;
|
||||||
using Graphics;
|
using Graphics;
|
||||||
|
using UglyToad.PdfPig.Logging;
|
||||||
using static Core.PdfSubpath;
|
using static Core.PdfSubpath;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates the result of applying a clipping path to another path.
|
/// Generates the result of applying a clipping path to another path.
|
||||||
/// </summary>
|
/// </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)
|
if (clipping == null)
|
||||||
{
|
{
|
||||||
@@ -61,7 +62,10 @@
|
|||||||
subPathClipping.CloseSubpath();
|
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
|
// Subject path
|
||||||
@@ -74,13 +78,27 @@
|
|||||||
continue;
|
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
|
// Force close subject if need be
|
||||||
if (subjectClose && !subPathSubject.IsClosed())
|
if (subjectClose && !subPathSubject.IsClosed())
|
||||||
{
|
{
|
||||||
subPathSubject.CloseSubpath();
|
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;
|
var clippingFillType = clipping.FillingRule == FillingRule.NonZeroWinding ? ClipperPolyFillType.NonZero : ClipperPolyFillType.EvenOdd;
|
||||||
@@ -164,11 +182,12 @@
|
|||||||
yield break;
|
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)
|
if (pdfPath.Commands.Count == 1)
|
||||||
{
|
{
|
||||||
@@ -185,7 +204,7 @@
|
|||||||
var command = pdfPath.Commands[i];
|
var command = pdfPath.Commands[i];
|
||||||
if (command is Move)
|
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)
|
if (command is Line line)
|
||||||
@@ -203,7 +222,11 @@
|
|||||||
}
|
}
|
||||||
else if (command is Close)
|
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();
|
var clippingSubpath = new PdfSubpath();
|
||||||
clippingSubpath.Rectangle(cropBox.BottomLeft.X, cropBox.BottomLeft.Y, cropBox.Width, cropBox.Height);
|
clippingSubpath.Rectangle(cropBox.BottomLeft.X, cropBox.BottomLeft.Y, cropBox.Width, cropBox.Height);
|
||||||
var clippingPath = new PdfPath() { clippingSubpath };
|
var clippingPath = new PdfPath() { clippingSubpath };
|
||||||
clippingPath.SetClipping(FillingRule.NonZeroWinding);
|
clippingPath.SetClipping(FillingRule.EvenOdd);
|
||||||
|
|
||||||
graphicsStack.Push(new CurrentGraphicsState()
|
graphicsStack.Push(new CurrentGraphicsState()
|
||||||
{
|
{
|
||||||
@@ -627,7 +627,7 @@
|
|||||||
|
|
||||||
if (clipPaths)
|
if (clipPaths)
|
||||||
{
|
{
|
||||||
var clippedPath = currentState.CurrentClippingPath.Clip(CurrentPath);
|
var clippedPath = currentState.CurrentClippingPath.Clip(CurrentPath, log);
|
||||||
if (clippedPath != null)
|
if (clippedPath != null)
|
||||||
{
|
{
|
||||||
paths.Add(clippedPath);
|
paths.Add(clippedPath);
|
||||||
@@ -658,7 +658,7 @@
|
|||||||
var currentClipping = GetCurrentState().CurrentClippingPath;
|
var currentClipping = GetCurrentState().CurrentClippingPath;
|
||||||
currentClipping.SetClipping(clippingRule);
|
currentClipping.SetClipping(clippingRule);
|
||||||
|
|
||||||
var newClippings = CurrentPath.Clip(currentClipping);
|
var newClippings = CurrentPath.Clip(currentClipping, log);
|
||||||
if (newClippings == null)
|
if (newClippings == null)
|
||||||
{
|
{
|
||||||
log.Warn("Empty clipping path found. Clipping path not updated.");
|
log.Warn("Empty clipping path found. Clipping path not updated.");
|
||||||
|
Reference in New Issue
Block a user