mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-19 10:47:56 +08:00
Simplify path construction operators
fix 're' operator to reflect documentation Update ContentStreamProcessor with fill, stroke and clip operations Throw errors when currentPosition is null in PdfSubpath
This commit is contained in:
@@ -166,8 +166,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: probably the wrong behaviour here, maybe line starts from (0, 0)?
|
||||
MoveTo(x, y);
|
||||
// PDF Reference 1.7 p226
|
||||
throw new ArgumentNullException("LineTo(): currentPosition is null.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,11 +176,12 @@
|
||||
/// </summary>
|
||||
public void Rectangle(double x, double y, double width, double height)
|
||||
{
|
||||
currentPosition = new PdfPoint(x, y);
|
||||
LineTo(x + width, y);
|
||||
LineTo(x + width, y + height);
|
||||
LineTo(x, y + height);
|
||||
LineTo(x, y);
|
||||
// is equivalent to
|
||||
MoveTo(x, y); // x y m
|
||||
LineTo(x + width, y); // (x + width) y l
|
||||
LineTo(x + width, y + height); // (x + width) (y + height) l
|
||||
LineTo(x, y + height); // x (y + height) l
|
||||
ClosePath(); // h
|
||||
IsDrawnAsRectangle = true;
|
||||
}
|
||||
|
||||
@@ -203,7 +204,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveTo(x3, y3);
|
||||
// PDF Reference 1.7 p226
|
||||
throw new ArgumentNullException("BezierCurveTo(): currentPosition is null.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,15 @@
|
||||
|
||||
public void BeginSubpath()
|
||||
{
|
||||
}
|
||||
public PdfPoint CloseSubpath()
|
||||
{
|
||||
return new PdfPoint();
|
||||
}
|
||||
|
||||
public void AddCurrentSubpath()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void StrokePath(bool close)
|
||||
|
@@ -1,8 +1,9 @@
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using System.Collections.Generic;
|
||||
using Tokens;
|
||||
using UglyToad.PdfPig.Graphics;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
@@ -73,7 +74,7 @@
|
||||
IReadOnlyList<NameToken> attached,
|
||||
IReadOnlyList<MarkedContentElement> children,
|
||||
IReadOnlyList<Letter> letters,
|
||||
IReadOnlyList<PdfSubpath> paths,
|
||||
IReadOnlyList<PdfPath> paths,
|
||||
IReadOnlyList<IPdfImage> images,
|
||||
int index)
|
||||
: base(markedContentIdentifier, tag, properties, language,
|
||||
|
@@ -2,8 +2,8 @@
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Tokens;
|
||||
using UglyToad.PdfPig.Graphics;
|
||||
|
||||
/// <summary>
|
||||
/// A marked content element can be used to provide application specific data in the
|
||||
@@ -50,7 +50,7 @@
|
||||
/// <summary>
|
||||
/// Paths contained in this marked content.
|
||||
/// </summary>
|
||||
public IReadOnlyList<PdfSubpath> Paths { get; }
|
||||
public IReadOnlyList<PdfPath> Paths { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Images contained in this marked content.
|
||||
@@ -88,7 +88,7 @@
|
||||
bool isArtifact,
|
||||
IReadOnlyList<MarkedContentElement> children,
|
||||
IReadOnlyList<Letter> letters,
|
||||
IReadOnlyList<PdfSubpath> paths,
|
||||
IReadOnlyList<PdfPath> paths,
|
||||
IReadOnlyList<IPdfImage> images,
|
||||
int index)
|
||||
{
|
||||
|
@@ -412,7 +412,7 @@
|
||||
CurrentPath = new PdfPath();
|
||||
}
|
||||
|
||||
AddSubpath();
|
||||
AddCurrentSubpath();
|
||||
CurrentSubpath = new PdfSubpath();
|
||||
}
|
||||
|
||||
@@ -429,11 +429,11 @@
|
||||
}
|
||||
|
||||
CurrentSubpath.ClosePath();
|
||||
AddSubpath();
|
||||
AddCurrentSubpath();
|
||||
return point;
|
||||
}
|
||||
|
||||
public void AddSubpath()
|
||||
public void AddCurrentSubpath()
|
||||
{
|
||||
if (CurrentSubpath == null)
|
||||
{
|
||||
@@ -446,22 +446,149 @@
|
||||
|
||||
public void StrokePath(bool close)
|
||||
{
|
||||
if (CurrentPath == null)
|
||||
{
|
||||
throw new ArgumentException("StrokePath(null)");
|
||||
//return;
|
||||
}
|
||||
|
||||
CurrentPath.SetStroked();
|
||||
|
||||
if (close)
|
||||
{
|
||||
CurrentSubpath.ClosePath();
|
||||
}
|
||||
|
||||
ClosePath();
|
||||
}
|
||||
|
||||
public void FillPath(FillingRule fillingRule, bool close)
|
||||
{
|
||||
if (CurrentPath == null)
|
||||
{
|
||||
throw new ArgumentException("FillPath(null)");
|
||||
//return;
|
||||
}
|
||||
|
||||
CurrentPath.SetFilled(fillingRule);
|
||||
|
||||
if (close)
|
||||
{
|
||||
CurrentSubpath.ClosePath();
|
||||
}
|
||||
|
||||
ClosePath();
|
||||
}
|
||||
|
||||
public void FillStrokePath(FillingRule fillingRule, bool close)
|
||||
{
|
||||
|
||||
if (CurrentPath == null)
|
||||
{
|
||||
throw new ArgumentException("FillStrokePath(null)");
|
||||
//return;
|
||||
}
|
||||
|
||||
CurrentPath.SetFilled(fillingRule);
|
||||
CurrentPath.SetStroked();
|
||||
|
||||
if (close)
|
||||
{
|
||||
CurrentSubpath.ClosePath();
|
||||
}
|
||||
|
||||
ClosePath();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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").
|
||||
/// </summary>
|
||||
public void EndPath()
|
||||
{
|
||||
AddCurrentSubpath();
|
||||
|
||||
if (CurrentPath.IsClipping)
|
||||
{
|
||||
/*if (!clipPaths)
|
||||
{
|
||||
// if we don't clip paths, add clipping paths
|
||||
paths.Add(CurrentPath);
|
||||
markedContentStack.AddPath(CurrentPath);
|
||||
}*/
|
||||
CurrentPath = null;
|
||||
return;
|
||||
}
|
||||
|
||||
paths.Add(CurrentPath);
|
||||
markedContentStack.AddPath(CurrentPath);
|
||||
CurrentPath = null;
|
||||
}
|
||||
|
||||
public void ClosePath()
|
||||
{
|
||||
AddCurrentSubpath();
|
||||
|
||||
if (CurrentPath.IsClipping)
|
||||
{
|
||||
EndPath();
|
||||
return;
|
||||
}
|
||||
|
||||
var currentState = this.GetCurrentState();
|
||||
if (CurrentPath.IsStroked)
|
||||
{
|
||||
CurrentPath.LineDashPattern = currentState.LineDashPattern;
|
||||
CurrentPath.StrokeColor = currentState.CurrentStrokingColor;
|
||||
CurrentPath.LineWidth = currentState.LineWidth;
|
||||
CurrentPath.LineCapStyle = currentState.CapStyle;
|
||||
CurrentPath.LineJoinStyle = currentState.JoinStyle;
|
||||
}
|
||||
|
||||
if (CurrentPath.IsFilled)
|
||||
{
|
||||
CurrentPath.FillColor = currentState.CurrentNonStrokingColor;
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
public void ModifyClippingIntersect(FillingRule clippingRule)
|
||||
{
|
||||
if (CurrentPath == null)
|
||||
{
|
||||
throw new ArgumentException("ModifyClippingIntersect(null)");
|
||||
}
|
||||
|
||||
AddCurrentSubpath();
|
||||
|
||||
CurrentPath.SetClipping(clippingRule);
|
||||
var currentClipping = GetCurrentState().CurrentClippingPath;
|
||||
currentClipping.SetClipping(clippingRule);
|
||||
|
||||
var newClippings = CurrentPath.Clip(currentClipping);
|
||||
if (newClippings == null)
|
||||
{
|
||||
Console.WriteLine("ContentStreamProcessor.ModifyClippingIntersect(): Warning, empty clipping path found... Clipping path not updated.");
|
||||
log.Warn("ModifyClippingIntersect(): Warning, empty clipping path found... Clipping path not updated.");
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCurrentState().CurrentClippingPath = newClippings;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNamedGraphicsState(NameToken stateName)
|
||||
@@ -563,15 +690,5 @@
|
||||
|
||||
TextMatrices.TextMatrix = newMatrix;
|
||||
}
|
||||
|
||||
public void ModifyClippingIntersect(FillingRule clippingRule)
|
||||
{
|
||||
if (CurrentSubpath == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -85,6 +85,17 @@
|
||||
/// Start a new sub-path.
|
||||
/// </summary>
|
||||
void BeginSubpath();
|
||||
|
||||
/// <summary>
|
||||
/// Close the current subpath.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
PdfPoint CloseSubpath();
|
||||
|
||||
/// <summary>
|
||||
/// Add the current subpath to the path.
|
||||
/// </summary>
|
||||
void AddCurrentSubpath();
|
||||
|
||||
/// <summary>
|
||||
/// Stroke the current path.
|
||||
|
@@ -57,7 +57,7 @@
|
||||
top?.AddLetter(letter);
|
||||
}
|
||||
|
||||
public void AddPath(PdfSubpath path)
|
||||
public void AddPath(PdfPath path)
|
||||
{
|
||||
top?.AddPath(path);
|
||||
}
|
||||
@@ -86,7 +86,7 @@
|
||||
private readonly DictionaryToken properties;
|
||||
|
||||
private readonly List<Letter> letters = new List<Letter>();
|
||||
private readonly List<PdfSubpath> paths = new List<PdfSubpath>();
|
||||
private readonly List<PdfPath> paths = new List<PdfPath>();
|
||||
private readonly List<IPdfImage> images = new List<IPdfImage>();
|
||||
|
||||
public List<MarkedContentElement> Children { get; } = new List<MarkedContentElement>();
|
||||
@@ -108,7 +108,7 @@
|
||||
images.Add(image);
|
||||
}
|
||||
|
||||
public void AddPath(PdfSubpath path)
|
||||
public void AddPath(PdfPath path)
|
||||
{
|
||||
paths.Add(path);
|
||||
}
|
||||
|
@@ -71,17 +71,12 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var controlPoint1 = new PdfPoint(X1, Y1);
|
||||
var controlPoint2 = new PdfPoint(X2, Y2);
|
||||
var end = new PdfPoint(X3, Y3);
|
||||
|
||||
var controlPoint1Transform = operationContext.CurrentTransformationMatrix.Transform(controlPoint1);
|
||||
var controlPoint2Transform = operationContext.CurrentTransformationMatrix.Transform(controlPoint2);
|
||||
var endTransform = operationContext.CurrentTransformationMatrix.Transform(end);
|
||||
operationContext.CurrentSubpath.BezierCurveTo(controlPoint1Transform.X, controlPoint1Transform.Y,
|
||||
controlPoint2Transform.X, controlPoint2Transform.Y,
|
||||
endTransform.X, endTransform.Y);
|
||||
operationContext.CurrentPosition = endTransform;
|
||||
var controlPoint1 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X1, Y1));
|
||||
var controlPoint2 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X2, Y2));
|
||||
var end = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X3, Y3));
|
||||
operationContext.CurrentSubpath.BezierCurveTo(controlPoint1.X, controlPoint1.Y,
|
||||
controlPoint2.X, controlPoint2.Y, end.X, end.Y);
|
||||
operationContext.CurrentPosition = end;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -56,16 +56,10 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var controlPoint1 = new PdfPoint(X1, Y1);
|
||||
var end = new PdfPoint(X3, Y3);
|
||||
var controlPoint1Transform = operationContext.CurrentTransformationMatrix.Transform(controlPoint1);
|
||||
var endTransform = operationContext.CurrentTransformationMatrix.Transform(end);
|
||||
operationContext.CurrentSubpath.BezierCurveTo(controlPoint1Transform.X, controlPoint1Transform.Y,
|
||||
endTransform.X,
|
||||
endTransform.Y,
|
||||
endTransform.X,
|
||||
endTransform.Y);
|
||||
operationContext.CurrentPosition = endTransform;
|
||||
var controlPoint1 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X1, Y1));
|
||||
var end = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X3, Y3));
|
||||
operationContext.CurrentSubpath.BezierCurveTo(controlPoint1.X, controlPoint1.Y, end.X, end.Y, end.X, end.Y);
|
||||
operationContext.CurrentPosition = end;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -56,14 +56,12 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var lowerLeft = new PdfPoint(LowerLeftX, LowerLeftY);
|
||||
var upperRight = new PdfPoint(LowerLeftX + Width, LowerLeftY + Height);
|
||||
|
||||
operationContext.BeginSubpath();
|
||||
var lowerLeftTransform = operationContext.CurrentTransformationMatrix.Transform(lowerLeft);
|
||||
var upperRightTransform = operationContext.CurrentTransformationMatrix.Transform(upperRight);
|
||||
var lowerLeft = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(LowerLeftX, LowerLeftY));
|
||||
var upperRight = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(LowerLeftX + Width, LowerLeftY + Height));
|
||||
|
||||
operationContext.CurrentSubpath.Rectangle(lowerLeftTransform.X, lowerLeftTransform.Y, upperRightTransform.X - lowerLeftTransform.X, upperRightTransform.Y - lowerLeftTransform.Y);
|
||||
operationContext.CurrentSubpath.Rectangle(lowerLeft.X, lowerLeft.Y, upperRight.X - lowerLeft.X, upperRight.Y - lowerLeft.Y);
|
||||
operationContext.AddCurrentSubpath();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -41,11 +41,10 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var point = new PdfPoint(X, Y);
|
||||
operationContext.BeginSubpath();
|
||||
var pointTransform = operationContext.CurrentTransformationMatrix.Transform(point);
|
||||
operationContext.CurrentPosition = pointTransform;
|
||||
operationContext.CurrentSubpath.MoveTo(pointTransform.X, pointTransform.Y);
|
||||
var point = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X, Y));
|
||||
operationContext.CurrentPosition = point;
|
||||
operationContext.CurrentSubpath.MoveTo(point.X, point.Y);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -29,7 +29,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentSubpath?.ClosePath();
|
||||
operationContext.CurrentPosition = operationContext.CloseSubpath();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -45,7 +45,7 @@
|
||||
/// <summary>
|
||||
/// Thickness in user space units of path to be stroked.
|
||||
/// </summary>
|
||||
public double LineWidth { get; set; } = double.NaN;
|
||||
public decimal LineWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The pattern to be used for stroked lines.
|
||||
|
Reference in New Issue
Block a user