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:
BobLd
2020-04-02 17:21:51 +01:00
committed by Eliot Jones
parent 3ee9ac7915
commit 983cfcb2f6
13 changed files with 189 additions and 63 deletions

View File

@@ -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.");
}
}

View File

@@ -64,6 +64,15 @@
public void BeginSubpath()
{
}
public PdfPoint CloseSubpath()
{
return new PdfPoint();
}
public void AddCurrentSubpath()
{
}
public void StrokePath(bool close)

View File

@@ -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,

View File

@@ -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)
{

View File

@@ -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;
}
}
}
}

View File

@@ -86,6 +86,17 @@
/// </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.
/// </summary>

View File

@@ -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);
}

View File

@@ -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 />

View File

@@ -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 />

View File

@@ -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 />

View File

@@ -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 />

View File

@@ -29,7 +29,7 @@
/// <inheritdoc />
public void Run(IOperationContext operationContext)
{
operationContext.CurrentSubpath?.ClosePath();
operationContext.CurrentPosition = operationContext.CloseSubpath();
}
/// <inheritdoc />

View File

@@ -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.