mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
#26 make almost all operators public
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
public class SetMiterLimitTests
|
||||
{
|
||||
private readonly TestResourceStore resourceStore = new TestResourceStore();
|
||||
private readonly TestOperationContext context = new TestOperationContext();
|
||||
|
||||
[Fact]
|
||||
@@ -13,7 +12,7 @@
|
||||
{
|
||||
var limit = new SetMiterLimit(25);
|
||||
|
||||
limit.Run(context, resourceStore);
|
||||
limit.Run(context);
|
||||
|
||||
Assert.Equal(25, context.GetCurrentState().MiterLimit);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
public class PopTests
|
||||
{
|
||||
private readonly TestResourceStore resourceStore = new TestResourceStore();
|
||||
private readonly TestOperationContext context = new TestOperationContext();
|
||||
|
||||
[Fact]
|
||||
@@ -20,7 +19,7 @@
|
||||
[Fact]
|
||||
public void CannotPopWithSingleFrame()
|
||||
{
|
||||
Action action = () => Pop.Value.Run(context, resourceStore);
|
||||
Action action = () => Pop.Value.Run(context);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(action);
|
||||
}
|
||||
@@ -30,7 +29,7 @@
|
||||
{
|
||||
context.StateStack.Pop();
|
||||
|
||||
Action action = () => Pop.Value.Run(context, resourceStore);
|
||||
Action action = () => Pop.Value.Run(context);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(action);
|
||||
}
|
||||
@@ -43,7 +42,7 @@
|
||||
LineWidth = 23
|
||||
});
|
||||
|
||||
Pop.Value.Run(context, resourceStore);
|
||||
Pop.Value.Run(context);
|
||||
|
||||
Assert.Equal(1, context.StackSize);
|
||||
Assert.Equal(1, context.GetCurrentState().LineWidth);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
public class PushTests
|
||||
{
|
||||
private readonly TestResourceStore resourceStore = new TestResourceStore();
|
||||
private readonly TestOperationContext context = new TestOperationContext();
|
||||
|
||||
[Fact]
|
||||
@@ -18,7 +17,7 @@
|
||||
[Fact]
|
||||
public void PushAddsToStack()
|
||||
{
|
||||
Push.Value.Run(context, resourceStore);
|
||||
Push.Value.Run(context);
|
||||
|
||||
Assert.Equal(2, context.StackSize);
|
||||
}
|
||||
|
||||
@@ -57,9 +57,8 @@
|
||||
var setFontAndSize = new SetFontAndSize(Font1Name, 69.42m);
|
||||
|
||||
var context = new TestOperationContext();
|
||||
var store = new TestResourceStore();
|
||||
|
||||
setFontAndSize.Run(context, store);
|
||||
setFontAndSize.Run(context);
|
||||
|
||||
var state = context.GetCurrentState();
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyXObject(StreamToken xObjectStream)
|
||||
public void ApplyXObject(NameToken xObjectName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ ET";
|
||||
Assert.Equal(38, nextLine.Ty);
|
||||
|
||||
var renderingMode = Assert.IsType<SetTextRenderingMode>(result[3]);
|
||||
Assert.Equal(RenderingMode.Stroke, renderingMode.Mode);
|
||||
Assert.Equal(TextRenderingMode.Stroke, renderingMode.Mode);
|
||||
|
||||
var lineWidth = Assert.IsType<SetLineWidth>(result[4]);
|
||||
Assert.Equal(2, lineWidth.Width);
|
||||
@@ -88,7 +88,7 @@ ET";
|
||||
Assert.Equal(32, moveLine.Ty);
|
||||
|
||||
var renderingMode = Assert.IsType<SetTextRenderingMode>(result[2]);
|
||||
Assert.Equal(RenderingMode.Fill, renderingMode.Mode);
|
||||
Assert.Equal(TextRenderingMode.Fill, renderingMode.Mode);
|
||||
|
||||
Assert.Equal(EndText.Value, result[3]);
|
||||
}
|
||||
|
||||
@@ -24,33 +24,89 @@
|
||||
|
||||
var expected = new List<string>
|
||||
{
|
||||
"UglyToad.PdfPig.IndirectReference",
|
||||
"UglyToad.PdfPig.PdfDocument",
|
||||
"UglyToad.PdfPig.ParsingOptions",
|
||||
"UglyToad.PdfPig.Structure",
|
||||
"UglyToad.PdfPig.Annotations.Annotation",
|
||||
"UglyToad.PdfPig.Annotations.AnnotationType",
|
||||
"UglyToad.PdfPig.Annotations.AnnotationBorder",
|
||||
"UglyToad.PdfPig.Annotations.AnnotationFlags",
|
||||
"UglyToad.PdfPig.Logging.ILog",
|
||||
"UglyToad.PdfPig.Geometry.PdfPoint",
|
||||
"UglyToad.PdfPig.Geometry.PdfRectangle",
|
||||
"UglyToad.PdfPig.Fonts.Exceptions.InvalidFontFormatException",
|
||||
"UglyToad.PdfPig.Exceptions.PdfDocumentFormatException",
|
||||
"UglyToad.PdfPig.Annotations.AnnotationType",
|
||||
"UglyToad.PdfPig.Content.Catalog",
|
||||
"UglyToad.PdfPig.Content.DocumentInformation",
|
||||
"UglyToad.PdfPig.Content.Letter",
|
||||
"UglyToad.PdfPig.Content.Page",
|
||||
"UglyToad.PdfPig.Content.PageSize",
|
||||
"UglyToad.PdfPig.Content.Word",
|
||||
"UglyToad.PdfPig.Core.TransformationMatrix",
|
||||
"UglyToad.PdfPig.CrossReference.CrossReferenceTable",
|
||||
"UglyToad.PdfPig.CrossReference.CrossReferenceType",
|
||||
"UglyToad.PdfPig.CrossReference.TrailerDictionary",
|
||||
"UglyToad.PdfPig.Exceptions.PdfDocumentFormatException",
|
||||
"UglyToad.PdfPig.Fonts.DescriptorFontFile",
|
||||
"UglyToad.PdfPig.Fonts.Exceptions.InvalidFontFormatException",
|
||||
"UglyToad.PdfPig.Fonts.FontDescriptor",
|
||||
"UglyToad.PdfPig.Fonts.FontDescriptorFlags",
|
||||
"UglyToad.PdfPig.Fonts.FontStretch",
|
||||
"UglyToad.PdfPig.Fonts.Standard14Font",
|
||||
"UglyToad.PdfPig.Geometry.PdfPath",
|
||||
"UglyToad.PdfPig.Geometry.PdfPoint",
|
||||
"UglyToad.PdfPig.Geometry.PdfRectangle",
|
||||
"UglyToad.PdfPig.Graphics.Core.LineCapStyle",
|
||||
"UglyToad.PdfPig.Graphics.Core.LineDashPattern",
|
||||
"UglyToad.PdfPig.Graphics.Core.LineJoinStyle",
|
||||
"UglyToad.PdfPig.Graphics.Core.RenderingIntent",
|
||||
"UglyToad.PdfPig.Graphics.Core.TextRenderingMode",
|
||||
"UglyToad.PdfPig.Graphics.CurrentFontState",
|
||||
"UglyToad.PdfPig.Graphics.CurrentGraphicsState",
|
||||
"UglyToad.PdfPig.Graphics.IOperationContext",
|
||||
"UglyToad.PdfPig.Graphics.Operations.ClippingPaths.ModifyClippingByEvenOddIntersect",
|
||||
"UglyToad.PdfPig.Graphics.Operations.ClippingPaths.ModifyClippingByNonZeroWindingIntersect",
|
||||
"UglyToad.PdfPig.Graphics.Operations.CloseAndStrokePath",
|
||||
"UglyToad.PdfPig.Graphics.Operations.EndPath",
|
||||
"UglyToad.PdfPig.Graphics.Operations.FillPathEvenOddRule",
|
||||
"UglyToad.PdfPig.Graphics.Operations.FillPathNonZeroWinding",
|
||||
"UglyToad.PdfPig.Graphics.Operations.FillPathNonZeroWindingAndStroke",
|
||||
"UglyToad.PdfPig.Graphics.Operations.FillPathNonZeroWindingCompatibility",
|
||||
"UglyToad.PdfPig.Graphics.Operations.General.SetColorRenderingIntent",
|
||||
"UglyToad.PdfPig.Graphics.Operations.General.SetFlatnessTolerance",
|
||||
"UglyToad.PdfPig.Graphics.Operations.General.SetLineCap",
|
||||
"UglyToad.PdfPig.Graphics.Operations.General.SetLineDashPattern",
|
||||
"UglyToad.PdfPig.Graphics.Operations.General.SetLineJoin",
|
||||
"UglyToad.PdfPig.Graphics.Operations.General.SetLineWidth",
|
||||
"UglyToad.PdfPig.Graphics.Operations.General.SetMiterLimit",
|
||||
"UglyToad.PdfPig.Graphics.Operations.IGraphicsStateOperation",
|
||||
"UglyToad.PdfPig.Graphics.Operations.InvokeNamedXObject",
|
||||
"UglyToad.PdfPig.Graphics.Operations.PathConstruction.AppendDualControlPointBezierCurve",
|
||||
"UglyToad.PdfPig.Graphics.Operations.PathConstruction.AppendEndControlPointBezierCurve",
|
||||
"UglyToad.PdfPig.Graphics.Operations.PathConstruction.AppendRectangle",
|
||||
"UglyToad.PdfPig.Graphics.Operations.PathConstruction.AppendStartControlPointBezierCurve",
|
||||
"UglyToad.PdfPig.Graphics.Operations.PathConstruction.AppendStraightLineSegment",
|
||||
"UglyToad.PdfPig.Graphics.Operations.PathConstruction.BeginNewSubpath",
|
||||
"UglyToad.PdfPig.Graphics.Operations.PathConstruction.CloseSubpath",
|
||||
"UglyToad.PdfPig.Graphics.Operations.SetNonStrokeColorDeviceCmyk",
|
||||
"UglyToad.PdfPig.Graphics.Operations.SetNonStrokeColorDeviceRgb",
|
||||
"UglyToad.PdfPig.Graphics.Operations.SetStrokeColorDeviceRgb",
|
||||
"UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState.ModifyCurrentTransformationMatrix",
|
||||
"UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState.Pop",
|
||||
"UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState.Push",
|
||||
"UglyToad.PdfPig.Graphics.Operations.StrokePath",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextObjects.BeginText",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextObjects.EndText",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextPositioning.MoveToNextLine",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextShowing.MoveToNextLineShowText",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextShowing.MoveToNextLineShowTextWithSpacing",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextShowing.ShowText",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextState.SetCharacterSpacing",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextState.SetFontAndSize",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextState.SetHorizontalScaling",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextState.SetTextLeading",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextState.SetTextRenderingMode",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextState.SetTextRise",
|
||||
"UglyToad.PdfPig.Graphics.Operations.TextState.SetWordSpacing",
|
||||
"UglyToad.PdfPig.Graphics.TextMatrices",
|
||||
"UglyToad.PdfPig.IndirectReference",
|
||||
"UglyToad.PdfPig.IO.IInputBytes",
|
||||
"UglyToad.PdfPig.Logging.ILog",
|
||||
"UglyToad.PdfPig.ParsingOptions",
|
||||
"UglyToad.PdfPig.PdfDocument",
|
||||
"UglyToad.PdfPig.Structure",
|
||||
"UglyToad.PdfPig.Tokens.ArrayToken",
|
||||
"UglyToad.PdfPig.Tokens.BooleanToken",
|
||||
"UglyToad.PdfPig.Tokens.CommentToken",
|
||||
@@ -71,7 +127,7 @@
|
||||
"UglyToad.PdfPig.Writer.TokenWriter",
|
||||
"UglyToad.PdfPig.XObjects.XObjectImage"
|
||||
};
|
||||
|
||||
|
||||
foreach (var publicTypeName in publicTypeNames)
|
||||
{
|
||||
Assert.True(expected.Contains(publicTypeName), $"Type should not be public: {publicTypeName}.");
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
/// <summary>
|
||||
/// Specifies the conversion from the transformed coordinate space to the original untransformed coordinate space.
|
||||
/// </summary>
|
||||
internal struct TransformationMatrix
|
||||
public struct TransformationMatrix
|
||||
{
|
||||
/// <summary>
|
||||
/// The default <see cref="TransformationMatrix"/>.
|
||||
/// </summary>
|
||||
public static TransformationMatrix Identity = new TransformationMatrix(new decimal[]
|
||||
{
|
||||
1,0,0,
|
||||
@@ -23,37 +26,52 @@
|
||||
/// The scale for the X dimension.
|
||||
/// </summary>
|
||||
public decimal A => value[0];
|
||||
/// <summary>
|
||||
/// The value at (0, 1).
|
||||
/// </summary>
|
||||
public decimal B => value[1];
|
||||
/// <summary>
|
||||
/// The value at (1, 0).
|
||||
/// </summary>
|
||||
public decimal C => value[3];
|
||||
/// <summary>
|
||||
/// The scale for the Y dimension.
|
||||
/// </summary>
|
||||
public decimal D => value[4];
|
||||
/// <summary>
|
||||
/// The value at (2, 0) - translation in X.
|
||||
/// </summary>
|
||||
public decimal E => value[6];
|
||||
/// <summary>
|
||||
/// The value at (2, 1) - translation in Y.
|
||||
/// </summary>
|
||||
public decimal F => value[7];
|
||||
|
||||
/// <summary>
|
||||
/// Get the value at the specific row and column.
|
||||
/// </summary>
|
||||
public decimal this[int row, int col]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (row >= Rows)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"The transformation matrix only contains {Rows} rows and is zero indexed, you tried to access row {row}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(row), $"The transformation matrix only contains {Rows} rows and is zero indexed, you tried to access row {row}.");
|
||||
}
|
||||
|
||||
if (row < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Cannot access negative rows in a matrix.");
|
||||
throw new ArgumentOutOfRangeException(nameof(row), "Cannot access negative rows in a matrix.");
|
||||
}
|
||||
|
||||
if (col >= Columns)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"The transformation matrix only contains {Columns} columns and is zero indexed, you tried to access column {col}.");
|
||||
throw new ArgumentOutOfRangeException(nameof(col), $"The transformation matrix only contains {Columns} columns and is zero indexed, you tried to access column {col}.");
|
||||
}
|
||||
|
||||
if (col < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Cannot access negative columns in a matrix.");
|
||||
throw new ArgumentOutOfRangeException(nameof(col), "Cannot access negative columns in a matrix.");
|
||||
}
|
||||
|
||||
var resultIndex = row * Rows + col;
|
||||
@@ -67,9 +85,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of rows in the matrix.
|
||||
/// </summary>
|
||||
public const int Rows = 3;
|
||||
/// <summary>
|
||||
/// The number of columns in the matrix.
|
||||
/// </summary>
|
||||
public const int Columns = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TransformationMatrix"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The 9 values of the matrix.</param>
|
||||
public TransformationMatrix(decimal[] value)
|
||||
{
|
||||
if (value == null)
|
||||
@@ -85,6 +113,12 @@
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a point using this transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="original">The original point.</param>
|
||||
/// <returns>A new point which is the result of applying this transformation matrix.</returns>
|
||||
[Pure]
|
||||
public PdfPoint Transform(PdfPoint original)
|
||||
{
|
||||
var x = A * original.X + C * original.Y + E;
|
||||
@@ -93,16 +127,26 @@
|
||||
return new PdfPoint(x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform an X coordinate using this transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="x">The X coordinate.</param>
|
||||
/// <returns>The transformed X coordinate.</returns>
|
||||
[Pure]
|
||||
public decimal TransformX(decimal x)
|
||||
internal decimal TransformX(decimal x)
|
||||
{
|
||||
var xt = A * x + C * 0 + E;
|
||||
|
||||
return xt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a vector using this transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="original">The original vector.</param>
|
||||
/// <returns>A new vector which is the result of applying this transformation matrix.</returns>
|
||||
[Pure]
|
||||
public PdfVector Transform(PdfVector original)
|
||||
internal PdfVector Transform(PdfVector original)
|
||||
{
|
||||
var x = A * original.X + C * original.Y + E;
|
||||
var y = B * original.X + D * original.Y + F;
|
||||
@@ -110,6 +154,11 @@
|
||||
return new PdfVector(x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a rectangle using this transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="original">The original rectangle.</param>
|
||||
/// <returns>A new rectangle which is the result of applying this transformation matrix.</returns>
|
||||
[Pure]
|
||||
public PdfRectangle Transform(PdfRectangle original)
|
||||
{
|
||||
@@ -121,8 +170,17 @@
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TransformationMatrix"/> from the 6 values provided in the default PDF order.
|
||||
/// </summary>
|
||||
public static TransformationMatrix FromValues(decimal a, decimal b, decimal c, decimal d, decimal e, decimal f)
|
||||
=> FromArray(new[] {a, b, c, d, e, f});
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TransformationMatrix"/> from the values.
|
||||
/// </summary>
|
||||
/// <param name="values">Either all 9 values of the matrix, 6 values in the default PDF order or the 4 values of the top left square.</param>
|
||||
/// <returns></returns>
|
||||
public static TransformationMatrix FromArray(decimal[] values)
|
||||
{
|
||||
if (values.Length == 9)
|
||||
@@ -153,19 +211,25 @@
|
||||
throw new ArgumentException("The array must either define all 9 elements of the matrix or all 6 key elements. Instead array was: " + values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies one transformation matrix by another without modifying either matrix. Order is: (this * matrix).
|
||||
/// </summary>
|
||||
/// <param name="matrix">The matrix to multiply</param>
|
||||
/// <returns>The resulting matrix.</returns>
|
||||
[Pure]
|
||||
public TransformationMatrix Multiply(TransformationMatrix matrix)
|
||||
{
|
||||
var result = new decimal[9];
|
||||
|
||||
for (int i = 0; i < Rows; i++)
|
||||
for (var i = 0; i < Rows; i++)
|
||||
{
|
||||
var rowIndexPart = i * Rows;
|
||||
|
||||
for (int j = 0; j < Columns; j++)
|
||||
for (var j = 0; j < Columns; j++)
|
||||
{
|
||||
var index = rowIndexPart + j;
|
||||
|
||||
for (int x = 0; x < Rows; x++)
|
||||
for (var x = 0; x < Rows; x++)
|
||||
{
|
||||
result[index] += this[i, x] * matrix[x, j];
|
||||
}
|
||||
@@ -175,17 +239,23 @@
|
||||
return new TransformationMatrix(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the matrix by a scalar value without modifying this matrix.
|
||||
/// </summary>
|
||||
/// <param name="scalar">The value to multiply.</param>
|
||||
/// <returns>A new matrix which is multiplied by the scalar value.</returns>
|
||||
[Pure]
|
||||
public TransformationMatrix Multiply(decimal scalar)
|
||||
{
|
||||
var result = new decimal[9];
|
||||
|
||||
for (int i = 0; i < Rows; i++)
|
||||
for (var i = 0; i < Rows; i++)
|
||||
{
|
||||
for (int j = 0; j < Columns; j++)
|
||||
for (var j = 0; j < Columns; j++)
|
||||
{
|
||||
var index = (i * Rows) + j;
|
||||
|
||||
for (int x = 0; x < Rows; x++)
|
||||
for (var x = 0; x < Rows; x++)
|
||||
{
|
||||
result[index] += this[i, x] * scalar;
|
||||
}
|
||||
@@ -195,7 +265,11 @@
|
||||
return new TransformationMatrix(result);
|
||||
}
|
||||
|
||||
public decimal GetScalingFactorX()
|
||||
/// <summary>
|
||||
/// Get the X scaling component of the current matrix.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal decimal GetScalingFactorX()
|
||||
{
|
||||
var xScale = A;
|
||||
|
||||
@@ -224,6 +298,7 @@
|
||||
return xScale;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is TransformationMatrix m))
|
||||
@@ -234,11 +309,14 @@
|
||||
return Equals(this, m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether 2 transformation matrices are equal.
|
||||
/// </summary>
|
||||
public static bool Equals(TransformationMatrix a, TransformationMatrix b)
|
||||
{
|
||||
for (int i = 0; i < Rows; i++)
|
||||
for (var i = 0; i < Rows; i++)
|
||||
{
|
||||
for (int j = 0; j < Columns; j++)
|
||||
for (var j = 0; j < Columns; j++)
|
||||
{
|
||||
if (a[i, j] != b[i, j])
|
||||
{
|
||||
@@ -250,6 +328,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = 1113510858;
|
||||
@@ -258,11 +337,15 @@
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{A}, {B}, 0\r\n{C}, {D}, 0\r\n{E}, {F}, 1";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TransformationMatrix"/> with the X and Y translation values set.
|
||||
/// </summary>
|
||||
public static TransformationMatrix GetTranslationMatrix(decimal x, decimal y)
|
||||
{
|
||||
return new TransformationMatrix(new []
|
||||
|
||||
@@ -6,18 +6,21 @@ namespace UglyToad.PdfPig.Geometry
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
internal class PdfPath
|
||||
/// <summary>
|
||||
/// A path in a PDF document, used by glyphs and page content.
|
||||
/// </summary>
|
||||
public class PdfPath
|
||||
{
|
||||
private readonly List<IPathCommand> commands = new List<IPathCommand>();
|
||||
private PdfPoint? currentPosition;
|
||||
|
||||
public void MoveTo(decimal x, decimal y)
|
||||
internal void MoveTo(decimal x, decimal y)
|
||||
{
|
||||
currentPosition = new PdfPoint(x, y);
|
||||
commands.Add(new Move(currentPosition.Value));
|
||||
}
|
||||
|
||||
public void LineTo(decimal x, decimal y)
|
||||
internal void LineTo(decimal x, decimal y)
|
||||
{
|
||||
if (currentPosition.HasValue)
|
||||
{
|
||||
@@ -31,9 +34,9 @@ namespace UglyToad.PdfPig.Geometry
|
||||
}
|
||||
}
|
||||
|
||||
public void QuadraticCurveTo(decimal x1, decimal y1, decimal x2, decimal y2) { }
|
||||
internal void QuadraticCurveTo(decimal x1, decimal y1, decimal x2, decimal y2) { }
|
||||
|
||||
public void BezierCurveTo(decimal x1, decimal y1, decimal x2, decimal y2, decimal x3, decimal y3)
|
||||
internal void BezierCurveTo(decimal x1, decimal y1, decimal x2, decimal y2, decimal x3, decimal y3)
|
||||
{
|
||||
if (currentPosition.HasValue)
|
||||
{
|
||||
@@ -48,14 +51,14 @@ namespace UglyToad.PdfPig.Geometry
|
||||
}
|
||||
}
|
||||
|
||||
public void SetWindingRuleMode(int windingRule) { }
|
||||
internal void SetWindingRuleMode(int windingRule) { }
|
||||
|
||||
public void ClosePath()
|
||||
internal void ClosePath()
|
||||
{
|
||||
commands.Add(new Close());
|
||||
}
|
||||
|
||||
public PdfRectangle? GetBoundingRectangle()
|
||||
internal PdfRectangle? GetBoundingRectangle()
|
||||
{
|
||||
if (commands.Count == 0)
|
||||
{
|
||||
@@ -100,7 +103,7 @@ namespace UglyToad.PdfPig.Geometry
|
||||
return new PdfRectangle(minX, minY, maxX, maxY);
|
||||
}
|
||||
|
||||
public string ToSvg()
|
||||
internal string ToSvg()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
foreach (var pathCommand in commands)
|
||||
@@ -121,7 +124,7 @@ namespace UglyToad.PdfPig.Geometry
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public string ToFullSvg()
|
||||
internal string ToFullSvg()
|
||||
{
|
||||
string BboxToRect(PdfRectangle box, string stroke)
|
||||
{
|
||||
@@ -150,7 +153,7 @@ namespace UglyToad.PdfPig.Geometry
|
||||
return result;
|
||||
}
|
||||
|
||||
public interface IPathCommand
|
||||
internal interface IPathCommand
|
||||
{
|
||||
PdfRectangle? GetBoundingRectangle();
|
||||
|
||||
@@ -213,7 +216,7 @@ namespace UglyToad.PdfPig.Geometry
|
||||
}
|
||||
}
|
||||
|
||||
public class BezierCurve : IPathCommand
|
||||
internal class BezierCurve : IPathCommand
|
||||
{
|
||||
public PdfPoint StartPoint { get; }
|
||||
|
||||
@@ -374,7 +377,7 @@ namespace UglyToad.PdfPig.Geometry
|
||||
}
|
||||
}
|
||||
|
||||
public void Rectangle(decimal x, decimal y, decimal width, decimal height)
|
||||
internal void Rectangle(decimal x, decimal y, decimal width, decimal height)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
{
|
||||
foreach (var stateOperation in operations)
|
||||
{
|
||||
stateOperation.Run(this, resourceStore);
|
||||
stateOperation.Run(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,8 +221,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyXObject(StreamToken xObjectStream)
|
||||
public void ApplyXObject(NameToken xObjectName)
|
||||
{
|
||||
var xObjectStream = resourceStore.GetXObject(xObjectName);
|
||||
|
||||
// For now we will determine the type and store the object with the graphics state information preceding it.
|
||||
// Then consumers of the page can request the object/s to be retrieved by type.
|
||||
var subType = (NameToken)xObjectStream.StreamDictionary.Data[NameToken.Subtype.Data];
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Core
|
||||
{
|
||||
internal enum LineCapStyle
|
||||
/// <summary>
|
||||
/// The line cap style specifies the shape to be used at the ends of open subpaths (and dashes, if any) when they are stroked.
|
||||
/// </summary>
|
||||
public enum LineCapStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// The stroke is squared off at the endpoint of the path. There is no projection beyond the end of the path.
|
||||
/// </summary>
|
||||
Butt = 0,
|
||||
/// <summary>
|
||||
/// A semicircular arc with a diameter equal to the line width is drawn around the endpoint and filled in.
|
||||
/// </summary>
|
||||
Round = 1,
|
||||
/// <summary>
|
||||
/// The stroke continues beyond the endpoint of the path for a distance equal to half the line width and is squared off.
|
||||
/// </summary>
|
||||
ProjectingSquare = 2
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,49 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Core
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal struct LineDashPattern
|
||||
/// <summary>
|
||||
/// The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
|
||||
/// It is specified by a dash array and a dash phase.
|
||||
/// </summary>
|
||||
public struct LineDashPattern
|
||||
{
|
||||
/// <summary>
|
||||
/// The distance into the dash pattern at which to start the dash.
|
||||
/// </summary>
|
||||
public int Phase { get; }
|
||||
|
||||
public decimal[] Array { get; }
|
||||
/// <summary>
|
||||
/// The numbers that specify the lengths of alternating dashes and gaps.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public IReadOnlyList<decimal> Array { get; }
|
||||
|
||||
public LineDashPattern(int phase, decimal[] array)
|
||||
/// <summary>
|
||||
/// Create a new <see cref="LineDashPattern"/>.
|
||||
/// </summary>
|
||||
/// <param name="phase">The phase. <see cref="Phase"/>.</param>
|
||||
/// <param name="array">The array. <see cref="Array"/>.</param>
|
||||
public LineDashPattern(int phase, [NotNull]IReadOnlyList<decimal> array)
|
||||
{
|
||||
Phase = phase;
|
||||
Array = array ?? throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The default solid line.
|
||||
/// </summary>
|
||||
public static LineDashPattern Solid { get; }
|
||||
= new LineDashPattern(0, new decimal[0]);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
var arrayStr = string.Join(" ", Array.Select(x => x.ToString("N")));
|
||||
return $"[{arrayStr}] {Phase}.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Core
|
||||
{
|
||||
internal enum LineJoinStyle
|
||||
/// <summary>
|
||||
/// The line join style specifies the shape to be used at the corners of paths that are stroked.
|
||||
/// </summary>
|
||||
public enum LineJoinStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// The outer edges of the strokes for the two segments are extended until they meet at an angle, as in a picture frame.
|
||||
/// If the segments meet at too sharp an angle (as defined by the miter limit parameter), a bevel join is used instead.
|
||||
/// </summary>
|
||||
Miter = 0,
|
||||
/// <summary>
|
||||
/// An arc of a circle with a diameter equal to the line width is drawn around the point where the two segments meet,
|
||||
/// connecting the outer edges of the strokes for the two segments
|
||||
/// </summary>
|
||||
Round = 1,
|
||||
/// <summary>
|
||||
/// The two segments are finished with butt caps and the resulting notch beyond the ends of the segments is filled with a triangle.
|
||||
/// </summary>
|
||||
Bevel = 2
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Core
|
||||
{
|
||||
internal enum RenderingIntent
|
||||
/// <summary>
|
||||
/// Specifying a rendering intent allows a PDF file to set priorities regarding which properties to preserve and which to sacrifice for CIE colors.
|
||||
/// </summary>
|
||||
public enum RenderingIntent
|
||||
{
|
||||
/// <summary>
|
||||
/// No correction for the output medium's white point. Colors
|
||||
|
||||
@@ -2,28 +2,28 @@
|
||||
{
|
||||
internal static class RenderingModeExtensions
|
||||
{
|
||||
public static bool IsFill(this RenderingMode mode)
|
||||
public static bool IsFill(this TextRenderingMode mode)
|
||||
{
|
||||
return mode == RenderingMode.Fill
|
||||
|| mode == RenderingMode.FillThenStroke
|
||||
|| mode == RenderingMode.FillClip
|
||||
|| mode == RenderingMode.FillThenStrokeClip;
|
||||
return mode == TextRenderingMode.Fill
|
||||
|| mode == TextRenderingMode.FillThenStroke
|
||||
|| mode == TextRenderingMode.FillClip
|
||||
|| mode == TextRenderingMode.FillThenStrokeClip;
|
||||
}
|
||||
|
||||
public static bool IsStroke(this RenderingMode mode)
|
||||
public static bool IsStroke(this TextRenderingMode mode)
|
||||
{
|
||||
return mode == RenderingMode.Stroke
|
||||
|| mode == RenderingMode.FillThenStroke
|
||||
|| mode == RenderingMode.StrokeClip
|
||||
|| mode == RenderingMode.FillThenStrokeClip;
|
||||
return mode == TextRenderingMode.Stroke
|
||||
|| mode == TextRenderingMode.FillThenStroke
|
||||
|| mode == TextRenderingMode.StrokeClip
|
||||
|| mode == TextRenderingMode.FillThenStrokeClip;
|
||||
}
|
||||
|
||||
public static bool IsClip(this RenderingMode mode)
|
||||
public static bool IsClip(this TextRenderingMode mode)
|
||||
{
|
||||
return mode == RenderingMode.FillClip
|
||||
|| mode == RenderingMode.StrokeClip
|
||||
|| mode == RenderingMode.FillThenStrokeClip
|
||||
|| mode == RenderingMode.NeitherClip;
|
||||
return mode == TextRenderingMode.FillClip
|
||||
|| mode == TextRenderingMode.StrokeClip
|
||||
|| mode == TextRenderingMode.FillThenStrokeClip
|
||||
|| mode == TextRenderingMode.NeitherClip;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Core
|
||||
{
|
||||
internal enum RenderingMode
|
||||
/// <summary>
|
||||
/// The text rendering mode determines whether showing text causes glyph outlines to be stroked, filled, used as a clipping boundary,
|
||||
/// or some combination of the three.
|
||||
/// </summary>
|
||||
public enum TextRenderingMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Fill text.
|
||||
@@ -8,7 +8,7 @@ namespace UglyToad.PdfPig.Graphics
|
||||
/// <summary>
|
||||
/// The current state of text related parameters for a content stream.
|
||||
/// </summary>
|
||||
internal class CurrentFontState : IDeepCloneable<CurrentFontState>
|
||||
public class CurrentFontState : IDeepCloneable<CurrentFontState>
|
||||
{
|
||||
/// <summary>
|
||||
/// A value in unscaled text space units which is added to the horizontal (or vertical if in vertical writing mode)
|
||||
@@ -39,19 +39,25 @@ namespace UglyToad.PdfPig.Graphics
|
||||
/// </summary>
|
||||
public decimal Leading { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the currently active font.
|
||||
/// </summary>
|
||||
public NameToken FontName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current font size.
|
||||
/// </summary>
|
||||
public decimal FontSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="RenderingMode"/> for glyph outlines.
|
||||
/// The <see cref="TextRenderingMode"/> for glyph outlines.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the rendering mode requires filling the current non-stroking color in the state is used.<br/>
|
||||
/// When the rendering mode requires stroking the current stroking color in the state is used.<br/>
|
||||
/// The rendering mode has no impact on Type 3 fonts.
|
||||
/// </remarks>
|
||||
public RenderingMode RenderingMode { get; set; } = RenderingMode.Fill;
|
||||
public TextRenderingMode TextRenderingMode { get; set; } = TextRenderingMode.Fill;
|
||||
|
||||
/// <summary>
|
||||
/// The distance in unscaled text space units to move the default baseline either up or down.
|
||||
@@ -62,16 +68,17 @@ namespace UglyToad.PdfPig.Graphics
|
||||
public decimal Rise { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Are all glpyhs in a text object treated as a single elementary object for the purpose of the transparent imaging model?
|
||||
/// Are all glyphs in a text object treated as a single elementary object for the purpose of the transparent imaging model?
|
||||
/// </summary>
|
||||
public bool Knockout { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public CurrentFontState DeepClone()
|
||||
{
|
||||
return new CurrentFontState
|
||||
{
|
||||
CharacterSpacing = CharacterSpacing,
|
||||
RenderingMode = RenderingMode,
|
||||
TextRenderingMode = TextRenderingMode,
|
||||
Rise = Rise,
|
||||
Leading = Leading,
|
||||
WordSpacing = WordSpacing,
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
// ReSharper disable RedundantDefaultMemberInitializer
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using Core;
|
||||
using PdfPig.Core;
|
||||
|
||||
/// <summary>
|
||||
/// The state of the current graphics control parameters.
|
||||
/// The state of the current graphics control parameters set by operations in the content stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initialized per page.
|
||||
/// </remarks>
|
||||
internal class CurrentGraphicsState : IDeepCloneable<CurrentGraphicsState>
|
||||
public class CurrentGraphicsState : IDeepCloneable<CurrentGraphicsState>
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="CurrentFontState"/> for this graphics state.
|
||||
@@ -97,6 +98,7 @@
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
public CurrentGraphicsState DeepClone()
|
||||
{
|
||||
return new CurrentGraphicsState
|
||||
|
||||
@@ -1,39 +1,85 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Fonts;
|
||||
using Geometry;
|
||||
using IO;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal interface IOperationContext
|
||||
/// <summary>
|
||||
/// The current graphics state context when running a PDF content stream.
|
||||
/// </summary>
|
||||
public interface IOperationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The current path being drawn if applicable.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
PdfPath CurrentPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The current p
|
||||
/// </summary>
|
||||
PdfPoint CurrentPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the currently active <see cref="CurrentGraphicsState"/>. States are stored on a stack structure.
|
||||
/// </summary>
|
||||
/// <returns>The currently active graphics state.</returns>
|
||||
CurrentGraphicsState GetCurrentState();
|
||||
|
||||
/// <summary>
|
||||
/// The matrices for the current text state.
|
||||
/// </summary>
|
||||
TextMatrices TextMatrices { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of graphics states on the stack.
|
||||
/// </summary>
|
||||
int StackSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current graphics state to the state from the top of the stack.
|
||||
/// </summary>
|
||||
void PopState();
|
||||
|
||||
/// <summary>
|
||||
/// Saves a copy of the current graphics state on the stack.
|
||||
/// </summary>
|
||||
void PushState();
|
||||
|
||||
/// <summary>
|
||||
/// Shows the text represented by the provided bytes using the current graphics state.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The bytes of the text.</param>
|
||||
void ShowText(IInputBytes bytes);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets the tokens to draw text at positions.
|
||||
/// </summary>
|
||||
/// <param name="tokens">The tokens to show.</param>
|
||||
void ShowPositionedText(IReadOnlyList<IToken> tokens);
|
||||
|
||||
void ApplyXObject(StreamToken xObjectStream);
|
||||
/// <summary>
|
||||
/// Retrieves the named XObject and applies it to the current state.
|
||||
/// </summary>
|
||||
/// <param name="xObjectName">The name of the XObject.</param>
|
||||
void ApplyXObject(NameToken xObjectName);
|
||||
|
||||
/// <summary>
|
||||
/// Start a new sub-path.
|
||||
/// </summary>
|
||||
void BeginSubpath();
|
||||
|
||||
/// <summary>
|
||||
/// Stroke the current path.
|
||||
/// </summary>
|
||||
/// <param name="close">Whether to also close the path.</param>
|
||||
void StrokePath(bool close);
|
||||
|
||||
/// <summary>
|
||||
/// Close the current path.
|
||||
/// </summary>
|
||||
void ClosePath();
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,44 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.ClippingPaths
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class ModifyClippingByEvenOddIntersect : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Modify the current clipping path by intersecting it with the current path, using the
|
||||
/// even-odd rule to determine which regions lie inside the clipping path.
|
||||
/// </summary>
|
||||
public class ModifyClippingByEvenOddIntersect : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "W*";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="ModifyClippingByEvenOddIntersect"/> operation.
|
||||
/// </summary>
|
||||
public static readonly ModifyClippingByEvenOddIntersect Value = new ModifyClippingByEvenOddIntersect();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private ModifyClippingByEvenOddIntersect()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,29 +1,44 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.ClippingPaths
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class ModifyClippingByNonZeroWindingIntersect : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Modify the current clipping path by intersecting it with the current path, using the
|
||||
/// nonzero winding number rule to determine which regions lie inside the clipping path.
|
||||
/// </summary>
|
||||
public class ModifyClippingByNonZeroWindingIntersect : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "W";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="EndPath"/> operation.
|
||||
/// </summary>
|
||||
public static readonly ModifyClippingByNonZeroWindingIntersect Value = new ModifyClippingByNonZeroWindingIntersect();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private ModifyClippingByNonZeroWindingIntersect()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Close and stroke the path.
|
||||
/// </summary>
|
||||
internal class CloseAndStrokePath : IGraphicsStateOperation
|
||||
public class CloseAndStrokePath : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.StrokePath(true);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Close, fill, and then stroke the path, using the even-odd rule to determine the region to fill.
|
||||
/// </summary>
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Close, fill, and then stroke the path, using the nonzero winding number rule to determine the region to fill.
|
||||
/// </summary>
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// End path without filling or stroking.
|
||||
/// </summary>
|
||||
internal class EndPath : IGraphicsStateOperation
|
||||
public class EndPath : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Fill the path, using the even-odd rule to determine the region to fill.
|
||||
/// </summary>
|
||||
internal class FillPathEvenOddRule : IGraphicsStateOperation
|
||||
public class FillPathEvenOddRule : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Fill and then stroke the path, using the even-odd rule to determine the region to fill.
|
||||
/// </summary>
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Fill the path, using the nonzero winding number rule to determine the region to fill.
|
||||
/// Any subpaths that are open are implicitly closed before being filled.
|
||||
/// </summary>
|
||||
internal class FillPathNonZeroWinding : IGraphicsStateOperation
|
||||
public class FillPathNonZeroWinding : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -27,7 +27,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Fill and then stroke the path, using the nonzero winding number rule to determine the region to fill.
|
||||
/// </summary>
|
||||
internal class FillPathNonZeroWindingAndStroke : IGraphicsStateOperation
|
||||
public class FillPathNonZeroWindingAndStroke : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Equivalent to <see cref="FillPathNonZeroWinding"/> included only for compatibility.
|
||||
/// Although PDF consumer applications must be able to accept this operator, PDF producer applications should use <see cref="FillPathNonZeroWinding"/> instead.
|
||||
/// </summary>
|
||||
internal class FillPathNonZeroWindingCompatibility : IGraphicsStateOperation
|
||||
public class FillPathNonZeroWindingCompatibility : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -27,7 +27,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,54 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.General
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Tokens;
|
||||
|
||||
internal class SetColorRenderingIntent : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the color rendering intent in the graphics state.
|
||||
/// </summary>
|
||||
public class SetColorRenderingIntent : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "ri";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <summary>
|
||||
/// The rendering intent for CIE-based colors.
|
||||
/// </summary>
|
||||
public NameToken RenderingIntent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create new <see cref="SetColorRenderingIntent"/>.
|
||||
/// </summary>
|
||||
/// <param name="renderingIntent">The rendering intent.</param>
|
||||
public SetColorRenderingIntent(NameToken renderingIntent)
|
||||
{
|
||||
RenderingIntent = renderingIntent ?? throw new ArgumentNullException(nameof(renderingIntent));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteText($"/{RenderingIntent.Data} {Symbol}");
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{RenderingIntent} {Symbol}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,50 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.General
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class SetFlatnessTolerance : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the flatness tolerance in the graphics state.
|
||||
/// Flatness is a number in the range 0 to 100; a value of 0 specifies the output device’s default flatness tolerance.
|
||||
/// </summary>
|
||||
public class SetFlatnessTolerance : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "i";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The flatness tolerance controls the maximum permitted distance in device pixels
|
||||
/// between the mathematically correct path and an approximation constructed from straight line segments.
|
||||
/// </summary>
|
||||
public decimal Tolerance { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create new <see cref="SetFlatnessTolerance"/>.
|
||||
/// </summary>
|
||||
/// <param name="tolerance">The flatness tolerance.</param>
|
||||
public SetFlatnessTolerance(decimal tolerance)
|
||||
{
|
||||
Tolerance = tolerance;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.GetCurrentState().Flatness = Tolerance;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteNumberText(Tolerance, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Tolerance} {Symbol}";
|
||||
|
||||
@@ -2,18 +2,36 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Core;
|
||||
|
||||
internal class SetLineCap : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the line cap style in the graphics state.
|
||||
/// </summary>
|
||||
public class SetLineCap : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "J";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The cap style.
|
||||
/// </summary>
|
||||
public LineCapStyle Cap { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Create a new <see cref="T:UglyToad.PdfPig.Graphics.Operations.General.SetLineCap" />.
|
||||
/// </summary>
|
||||
public SetLineCap(int cap) : this((LineCapStyle)cap) { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetLineCap"/>.
|
||||
/// </summary>
|
||||
public SetLineCap(LineCapStyle cap)
|
||||
{
|
||||
if (cap < 0 || (int)cap > 2)
|
||||
@@ -24,19 +42,19 @@
|
||||
Cap = cap;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.GetCurrentState().CapStyle = Cap;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal((int)Cap);
|
||||
stream.WriteWhiteSpace();
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
stream.WriteNumberText((int)Cap, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{(int) Cap} {Symbol}";
|
||||
|
||||
@@ -1,32 +1,71 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.General
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Core;
|
||||
|
||||
internal class SetLineDashPattern : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the line dash pattern in the graphics state.
|
||||
/// </summary>
|
||||
public class SetLineDashPattern : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "d";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The line dash pattern.
|
||||
/// </summary>
|
||||
public LineDashPattern Pattern { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetLineDashPattern"/>.
|
||||
/// </summary>
|
||||
public SetLineDashPattern(decimal[] array, int phase)
|
||||
{
|
||||
Pattern = new LineDashPattern(phase, array);
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.GetCurrentState().LineDashPattern = Pattern;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteText("[");
|
||||
|
||||
for (var i = 0; i < Pattern.Array.Count; i++)
|
||||
{
|
||||
var value = Pattern.Array[i];
|
||||
stream.WriteDecimal(value);
|
||||
|
||||
if (i < Pattern.Array.Count - 1)
|
||||
{
|
||||
stream.WriteWhiteSpace();
|
||||
}
|
||||
}
|
||||
|
||||
stream.WriteText("]");
|
||||
|
||||
stream.WriteWhiteSpace();
|
||||
|
||||
stream.WriteDecimal(Pattern.Phase);
|
||||
|
||||
stream.WriteWhiteSpace();
|
||||
|
||||
stream.WriteText(Symbol);
|
||||
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Pattern.Array} {Pattern.Phase} {Symbol}";
|
||||
|
||||
@@ -2,18 +2,31 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Core;
|
||||
|
||||
internal class SetLineJoin : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
public class SetLineJoin : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "j";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The line join style.
|
||||
/// </summary>
|
||||
public LineJoinStyle Join { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetLineJoin"/>.
|
||||
/// </summary>
|
||||
public SetLineJoin(int join) : this((LineJoinStyle)join) { }
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetLineJoin"/>.
|
||||
/// </summary>
|
||||
public SetLineJoin(LineJoinStyle join)
|
||||
{
|
||||
if (join < 0 || (int)join > 2)
|
||||
@@ -24,19 +37,19 @@
|
||||
Join = join;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.GetCurrentState().JoinStyle = Join;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal((int)Join);
|
||||
stream.WriteWhiteSpace();
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
stream.WriteNumberText((int)Join, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{(int)Join} {Symbol}";
|
||||
|
||||
@@ -1,36 +1,50 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.General
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class SetLineWidth : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the line width in the graphics state.
|
||||
/// </summary>
|
||||
public class SetLineWidth : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "w";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The line width.
|
||||
/// </summary>
|
||||
public decimal Width { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetLineWidth"/>.
|
||||
/// </summary>
|
||||
/// <param name="width">The line width.</param>
|
||||
public SetLineWidth(decimal width)
|
||||
{
|
||||
Width = width;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
currentState.LineWidth = Width;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(Width);
|
||||
stream.WriteWhiteSpace();
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
stream.WriteNumberText(Width, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Width} {Symbol}";
|
||||
|
||||
@@ -1,33 +1,50 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.General
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class SetMiterLimit : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the miter limit in the graphics state.
|
||||
/// </summary>
|
||||
public class SetMiterLimit : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "M";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The miter limit. The miter limit imposes a maximum on the ratio of the miter length to the line width.
|
||||
/// When the limit is exceeded, the join is converted from a miter to a bevel.
|
||||
/// </summary>
|
||||
public decimal Limit { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetMiterLimit"/>.
|
||||
/// </summary>
|
||||
public SetMiterLimit(decimal limit)
|
||||
{
|
||||
Limit = limit;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
currentState.MiterLimit = Limit;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteNumberText(Limit, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Limit} {Symbol}";
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal interface IGraphicsStateOperation
|
||||
/// <summary>
|
||||
/// An operation with associated data from a content stream.
|
||||
/// </summary>
|
||||
public interface IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol representing the operator in the content stream.
|
||||
/// </summary>
|
||||
string Operator { get; }
|
||||
|
||||
void Run(IOperationContext operationContext, IResourceStore resourceStore);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the operator and any operands as valid PDF content to the stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to write to.</param>
|
||||
void Write(Stream stream);
|
||||
|
||||
/// <summary>
|
||||
/// Applies the operation to the current context with the provided resources.
|
||||
/// </summary>
|
||||
/// <param name="operationContext"></param>
|
||||
void Run(IOperationContext operationContext);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Tokens;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Paint the specified XObject.
|
||||
/// The operand name must appear as a key in the XObject subdictionary of the current resource dictionary.
|
||||
/// The associated value must be a stream whose Type entry, if present, is XObject.
|
||||
/// The effect of <see cref="InvokeNamedXObject"/> depends on the value of the XObject's Subtype entry, which may be Image, Form or PS.
|
||||
/// The effect of <see cref="T:UglyToad.PdfPig.Graphics.Operations.InvokeNamedXObject" /> depends on the value of the XObject's Subtype entry, which may be Image, Form or PS.
|
||||
/// </summary>
|
||||
internal class InvokeNamedXObject : IGraphicsStateOperation
|
||||
public class InvokeNamedXObject : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -31,15 +32,13 @@
|
||||
/// <param name="name">The name of the XObject.</param>
|
||||
public InvokeNamedXObject(NameToken name)
|
||||
{
|
||||
Name = name;
|
||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var xobject = resourceStore.GetXObject(Name);
|
||||
|
||||
operationContext.ApplyXObject(xobject);
|
||||
operationContext.ApplyXObject(Name);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -1,21 +1,47 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Geometry;
|
||||
|
||||
internal class AppendDualControlPointBezierCurve : IGraphicsStateOperation
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Append a cubic Bezier curve to the current path.
|
||||
/// The curve extends from the current point to the point (x3, y3), using (x1, y1) and (x2, y2) as the Bezier control points
|
||||
/// </summary>
|
||||
public class AppendDualControlPointBezierCurve : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "c";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The first control point.
|
||||
/// </summary>
|
||||
public PdfPoint ControlPoint1 { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The second control point.
|
||||
/// </summary>
|
||||
public PdfPoint ControlPoint2 { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The end point.
|
||||
/// </summary>
|
||||
public PdfPoint End { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AppendDualControlPointBezierCurve"/>.
|
||||
/// </summary>
|
||||
/// <param name="x1">Control point 1 x coordinate.</param>
|
||||
/// <param name="y1">Control point 1 y coordinate.</param>
|
||||
/// <param name="x2">Control point 2 x coordinate.</param>
|
||||
/// <param name="y2">Control point 2 y coordinate.</param>
|
||||
/// <param name="x3">End point x coordinate.</param>
|
||||
/// <param name="y3">End point y coordinate.</param>
|
||||
public AppendDualControlPointBezierCurve(decimal x1, decimal y1, decimal x2, decimal y2, decimal x3, decimal y3)
|
||||
{
|
||||
ControlPoint1 = new PdfPoint(x1, y1);
|
||||
@@ -23,7 +49,8 @@
|
||||
End = new PdfPoint(x3, y3);
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.BezierCurveTo(ControlPoint1.X, ControlPoint1.Y,
|
||||
ControlPoint2.X, ControlPoint2.Y,
|
||||
@@ -31,6 +58,7 @@
|
||||
operationContext.CurrentPosition = End;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(ControlPoint1.X);
|
||||
@@ -49,6 +77,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ControlPoint1.X} {ControlPoint1.Y} {ControlPoint2.X} {ControlPoint2.Y} {End.X} {End.Y} {Symbol}";
|
||||
|
||||
@@ -1,26 +1,48 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Geometry;
|
||||
|
||||
internal class AppendEndControlPointBezierCurve : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Append a cubic Bezier curve to the current path.
|
||||
/// The curve extends from the current point to the point (x3, y3), using (x1, y1) and (x3, y3) as the Bezier control points
|
||||
/// </summary>
|
||||
public class AppendEndControlPointBezierCurve : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "y";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The first control point.
|
||||
/// </summary>
|
||||
public PdfPoint ControlPoint1 { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The end point and second control point.
|
||||
/// </summary>
|
||||
public PdfPoint End { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AppendEndControlPointBezierCurve"/>.
|
||||
/// </summary>
|
||||
/// <param name="x1">Control point 1 x coordinate.</param>
|
||||
/// <param name="y1">Control point 1 y coordinate.</param>
|
||||
/// <param name="x3">Control point 2/End x coordinate.</param>
|
||||
/// <param name="y3">Control point 2/End y coordinate.</param>
|
||||
public AppendEndControlPointBezierCurve(decimal x1, decimal y1, decimal x3, decimal y3)
|
||||
{
|
||||
ControlPoint1 = new PdfPoint(x1, y1);
|
||||
End = new PdfPoint(x3, y3);
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.BezierCurveTo(ControlPoint1.X, ControlPoint1.Y,
|
||||
End.X,
|
||||
@@ -30,6 +52,7 @@
|
||||
operationContext.CurrentPosition = End;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(ControlPoint1.X);
|
||||
@@ -44,6 +67,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ControlPoint1.X} {ControlPoint1.Y} {End.X} {End.Y} {Symbol}";
|
||||
|
||||
@@ -1,21 +1,44 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Geometry;
|
||||
|
||||
internal class AppendRectangle : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// Append a rectangle to the current path as a complete subpath.
|
||||
/// </remarks>
|
||||
public class AppendRectangle : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "re";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The lower left corner.
|
||||
/// </summary>
|
||||
public PdfPoint LowerLeft { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The width of the rectangle.
|
||||
/// </summary>
|
||||
public decimal Width { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of the rectangle.
|
||||
/// </summary>
|
||||
public decimal Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AppendRectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate of the lower left corner.</param>
|
||||
/// <param name="y">The y coordinate of the lower left corner.</param>
|
||||
/// <param name="width">The width of the rectangle.</param>
|
||||
/// <param name="height">The height of the rectangle.</param>
|
||||
public AppendRectangle(decimal x, decimal y, decimal width, decimal height)
|
||||
{
|
||||
LowerLeft = new PdfPoint(x, y);
|
||||
@@ -24,13 +47,15 @@
|
||||
Height = height;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.BeginSubpath();
|
||||
operationContext.CurrentPath.Rectangle(LowerLeft.X, LowerLeft.Y, Width, Height);
|
||||
operationContext.CurrentPath.ClosePath();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(LowerLeft.X);
|
||||
@@ -45,6 +70,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{LowerLeft.X} {LowerLeft.Y} {Width} {Height} {Symbol}";
|
||||
|
||||
@@ -1,26 +1,48 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Geometry;
|
||||
|
||||
internal class AppendStartControlPointBezierCurve : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Append a cubic Bezier curve to the current path.
|
||||
/// The curve extends from the current point to the point (x3, y3), using the current point and (x2, y2) as the Bezier control points
|
||||
/// </summary>
|
||||
public class AppendStartControlPointBezierCurve : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "v";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The second control point.
|
||||
/// </summary>
|
||||
public PdfPoint ControlPoint2 { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The last point on the curve.
|
||||
/// </summary>
|
||||
public PdfPoint End { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AppendStartControlPointBezierCurve"/>.
|
||||
/// </summary>
|
||||
/// <param name="x2">The x coordinate of the second control point.</param>
|
||||
/// <param name="y2">The y coordinate of the second control point.</param>
|
||||
/// <param name="x3">The x coordinate of the end point.</param>
|
||||
/// <param name="y3">The y coordinate of the end point.</param>
|
||||
public AppendStartControlPointBezierCurve(decimal x2, decimal y2, decimal x3, decimal y3)
|
||||
{
|
||||
ControlPoint2 = new PdfPoint(x2, y2);
|
||||
End = new PdfPoint(x3, y3);
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.BezierCurveTo(operationContext.CurrentPosition.X,
|
||||
operationContext.CurrentPosition.Y,
|
||||
@@ -31,6 +53,7 @@
|
||||
operationContext.CurrentPosition = End;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(ControlPoint2.X);
|
||||
@@ -45,6 +68,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ControlPoint2.X} {ControlPoint2.Y} {End.X} {End.Y} {Symbol}";
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Geometry;
|
||||
|
||||
internal class AppendStraightLineSegment : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Append a straight line segment from the current point to the point (x, y).
|
||||
/// </summary>
|
||||
public class AppendStraightLineSegment : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "l";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The end point of the line.
|
||||
/// </summary>
|
||||
public PdfPoint End { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="AppendStraightLineSegment"/>.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate of the line's end point.</param>
|
||||
/// <param name="y">The y coordinate of the line's end point.</param>
|
||||
public AppendStraightLineSegment(decimal x, decimal y)
|
||||
{
|
||||
End = new PdfPoint(x, y);
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.LineTo(End.X, End.Y);
|
||||
operationContext.CurrentPosition = End;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(End.X);
|
||||
@@ -33,6 +50,7 @@
|
||||
stream.WriteWhiteSpace();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{End.X} {End.Y} {Symbol}";
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Geometry;
|
||||
|
||||
internal class BeginNewSubpath : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Begin a new subpath by moving the current point to coordinates (x, y), omitting any connecting line segment.
|
||||
/// </summary>
|
||||
public class BeginNewSubpath : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "m";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The point to begin the new subpath at.
|
||||
/// </summary>
|
||||
public PdfPoint Point { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="BeginNewSubpath"/>.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate.</param>
|
||||
/// <param name="y">The y coordinate.</param>
|
||||
public BeginNewSubpath(decimal x, decimal y)
|
||||
{
|
||||
Point = new PdfPoint(x, y);
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.BeginSubpath();
|
||||
operationContext.CurrentPosition = Point;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(Point.X);
|
||||
@@ -33,6 +50,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Point.X} {Point.Y} {Symbol}";
|
||||
|
||||
@@ -1,31 +1,45 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class CloseSubpath : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Close the current subpath by appending a straight line segment from the current point to the starting point of the subpath.
|
||||
/// If the current subpath is already closed, this does nothing.
|
||||
/// </summary>
|
||||
public class CloseSubpath : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "h";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="CloseSubpath"/> operation.
|
||||
/// </summary>
|
||||
public static readonly CloseSubpath Value = new CloseSubpath();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private CloseSubpath()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.ClosePath();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the non-stroking color space to DeviceCMYK and set the color to use for stroking operations.
|
||||
/// </summary>
|
||||
internal class SetNonStrokeColorDeviceCmyk : IGraphicsStateOperation
|
||||
public class SetNonStrokeColorDeviceCmyk : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the gray level for non-stroking operations.
|
||||
/// </summary>
|
||||
@@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set RGB color for non-stroking operations.
|
||||
/// </summary>
|
||||
internal class SetNonStrokeColorDeviceRgb : IGraphicsStateOperation
|
||||
public class SetNonStrokeColorDeviceRgb : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -45,7 +45,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the stroking color space to DeviceCMYK and set the color to use for stroking operations.
|
||||
/// </summary>
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the gray level for stroking operations.
|
||||
/// </summary>
|
||||
@@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set RGB color for stroking operations.
|
||||
/// </summary>
|
||||
internal class SetStrokeColorDeviceRgb : IGraphicsStateOperation
|
||||
public class SetStrokeColorDeviceRgb : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -45,7 +45,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,31 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using PdfPig.Core;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Modify the current transformation matrix by concatenating the specified matrix.
|
||||
/// </summary>
|
||||
internal class ModifyCurrentTransformationMatrix : IGraphicsStateOperation
|
||||
public class ModifyCurrentTransformationMatrix : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "cm";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The 6 values for the transformation matrix.
|
||||
/// </summary>
|
||||
public decimal[] Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ModifyCurrentTransformationMatrix"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The 6 transformation matrix values.</param>
|
||||
public ModifyCurrentTransformationMatrix(decimal[] value)
|
||||
{
|
||||
if (value == null)
|
||||
@@ -30,7 +41,8 @@
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var newMatrix = TransformationMatrix.FromArray(Value);
|
||||
|
||||
@@ -41,6 +53,7 @@
|
||||
operationContext.GetCurrentState().CurrentTransformationMatrix = newCtm;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(Value[0]);
|
||||
@@ -59,6 +72,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Value[0]} {Value[1]} {Value[2]} {Value[3]} {Value[4]} {Value[5]} {Symbol}";
|
||||
|
||||
@@ -2,24 +2,32 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Restore the graphics state by removing the most recently saved state from the stack and making it the current state.
|
||||
/// </summary>
|
||||
internal class Pop : IGraphicsStateOperation
|
||||
public class Pop : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Q";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="Pop"/> operation.
|
||||
/// </summary>
|
||||
public static readonly Pop Value = new Pop();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private Pop()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentStackSize = operationContext.StackSize;
|
||||
if (currentStackSize > 1)
|
||||
@@ -32,12 +40,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,33 +1,44 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Save the current graphics state on the graphics state stack.
|
||||
/// </summary>
|
||||
internal class Push : IGraphicsStateOperation
|
||||
public class Push : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "q";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="Push"/> operation.
|
||||
/// </summary>
|
||||
public static readonly Push Value = new Push();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private Push()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext context, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext context)
|
||||
{
|
||||
context.PushState();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,31 +1,44 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class StrokePath : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Stroke the path.
|
||||
/// </summary>
|
||||
public class StrokePath : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "S";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="StrokePath"/> operation.
|
||||
/// </summary>
|
||||
public static readonly StrokePath Value = new StrokePath();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private StrokePath()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.StrokePath(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,35 +1,46 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextObjects
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using PdfPig.Core;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Begin a text object, initializing the text matrix and the text line matrix to the identity matrix. Text objects cannot be nested.
|
||||
/// </summary>
|
||||
internal class BeginText : IGraphicsStateOperation
|
||||
public class BeginText : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "BT";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="BeginText"/> operation.
|
||||
/// </summary>
|
||||
public static readonly BeginText Value = new BeginText();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private BeginText()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.TextMatrices.TextMatrix = TransformationMatrix.Identity;
|
||||
operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Identity;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,35 +1,46 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextObjects
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using PdfPig.Core;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// End a text object, discarding the text matrix.
|
||||
/// </summary>
|
||||
internal class EndText : IGraphicsStateOperation
|
||||
public class EndText : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "ET";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="EndText"/> operation.
|
||||
/// </summary>
|
||||
public static readonly EndText Value = new EndText();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private EndText()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.TextMatrices.TextMatrix = TransformationMatrix.Identity;
|
||||
operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Identity;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Move to the start of the next line.
|
||||
/// </summary>
|
||||
@@ -10,30 +10,41 @@
|
||||
/// This performs this operation: 0 -Tl Td
|
||||
/// The offset is negative leading text (Tl) value, this is incorrect in the specification.
|
||||
/// </remarks>
|
||||
internal class MoveToNextLine : IGraphicsStateOperation
|
||||
public class MoveToNextLine : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "T*";
|
||||
|
||||
/// <summary>
|
||||
/// The instance of the <see cref="MoveToNextLine"/> operation.
|
||||
/// </summary>
|
||||
public static readonly MoveToNextLine Value = new MoveToNextLine();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
private MoveToNextLine()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var tdOperation = new MoveToNextLineWithOffset(0, -1 * operationContext.GetCurrentState().FontState.Leading);
|
||||
|
||||
tdOperation.Run(operationContext, resourceStore);
|
||||
tdOperation.Run(operationContext);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
|
||||
@@ -1,35 +1,51 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using PdfPig.Core;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Move to the start of the next line offset by Tx Ty.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Performs the following operation:
|
||||
/// 1 0 0<br/>
|
||||
/// Tm = Tlm = 0 1 0 * Tlm<br/>
|
||||
/// 1 0 0<br />
|
||||
/// Tm = Tlm = 0 1 0 * Tlm<br />
|
||||
/// tx ty 1
|
||||
/// </remarks>
|
||||
internal class MoveToNextLineWithOffset : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Td";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The x value of the offset.
|
||||
/// </summary>
|
||||
public decimal Tx { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The y value of the offset.
|
||||
/// </summary>
|
||||
public decimal Ty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="MoveToNextLineWithOffset"/>.
|
||||
/// </summary>
|
||||
/// <param name="tx">The x offset.</param>
|
||||
/// <param name="ty">The y offset.</param>
|
||||
public MoveToNextLineWithOffset(decimal tx, decimal ty)
|
||||
{
|
||||
Tx = tx;
|
||||
Ty = ty;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentTextLineMatrix = operationContext.TextMatrices.TextLineMatrix;
|
||||
|
||||
@@ -41,6 +57,7 @@
|
||||
operationContext.TextMatrices.TextMatrix = transformed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(Tx);
|
||||
@@ -51,6 +68,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Tx} {Ty} {Symbol}";
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextPositioning
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using TextState;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Move to the start of the next line, offset from the start of the current line by (tx, ty).
|
||||
/// This operator also sets the leading parameter in the text state.
|
||||
/// </summary>
|
||||
internal class MoveToNextLineWithOffsetSetLeading : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "TD";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
public decimal Tx { get; }
|
||||
@@ -24,17 +28,19 @@
|
||||
Ty = ty;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var tlOperation = new SetTextLeading(-Ty);
|
||||
|
||||
tlOperation.Run(operationContext, resourceStore);
|
||||
tlOperation.Run(operationContext);
|
||||
|
||||
var tdOperation = new MoveToNextLineWithOffset(Tx, Ty);
|
||||
|
||||
tdOperation.Run(operationContext, resourceStore);
|
||||
tdOperation.Run(operationContext);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(Tx);
|
||||
@@ -45,6 +51,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Tx} {Ty} {Symbol}";
|
||||
|
||||
@@ -2,16 +2,20 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using PdfPig.Core;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the text matrix and the text line matrix.
|
||||
/// </summary>
|
||||
internal class SetTextMatrix : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Tm";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
public decimal[] Value { get; }
|
||||
@@ -25,8 +29,9 @@
|
||||
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var newMatrix = TransformationMatrix.FromArray(Value);
|
||||
|
||||
@@ -34,6 +39,7 @@
|
||||
operationContext.TextMatrices.TextLineMatrix = newMatrix;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(Value[0]);
|
||||
@@ -52,6 +58,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Value[0]} {Value[1]} {Value[2]} {Value[3]} {Value[4]} {Value[5]} {Symbol}";
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Content;
|
||||
using TextPositioning;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Move to the next line and show a text string.
|
||||
/// </summary>
|
||||
internal class MoveToNextLineShowText : IGraphicsStateOperation
|
||||
public class MoveToNextLineShowText : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -51,14 +51,14 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var move = MoveToNextLine.Value;
|
||||
|
||||
var showText = Text != null ? new ShowText(Text) : new ShowText(Bytes);
|
||||
|
||||
move.Run(operationContext, resourceStore);
|
||||
showText.Run(operationContext, resourceStore);
|
||||
move.Run(operationContext);
|
||||
showText.Run(operationContext);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -1,27 +1,52 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextShowing
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using TextPositioning;
|
||||
using TextState;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal class MoveToNextLineShowTextWithSpacing : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Move to the next line and show a text string, using the first number as the word spacing and the second as the character spacing
|
||||
/// </summary>
|
||||
public class MoveToNextLineShowTextWithSpacing : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "\"";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The word spacing.
|
||||
/// </summary>
|
||||
public decimal WordSpacing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The character spacing.
|
||||
/// </summary>
|
||||
public decimal CharacterSpacing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The bytes of the text.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public byte[] Bytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The text to show.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="MoveToNextLineShowTextWithSpacing"/>.
|
||||
/// </summary>
|
||||
/// <param name="wordSpacing">The word spacing.</param>
|
||||
/// <param name="characterSpacing">The character spacing.</param>
|
||||
/// <param name="text">The text to show.</param>
|
||||
public MoveToNextLineShowTextWithSpacing(decimal wordSpacing, decimal characterSpacing, string text)
|
||||
{
|
||||
WordSpacing = wordSpacing;
|
||||
@@ -29,6 +54,12 @@
|
||||
Text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="MoveToNextLineShowTextWithSpacing"/>.
|
||||
/// </summary>
|
||||
/// <param name="wordSpacing">The word spacing.</param>
|
||||
/// <param name="characterSpacing">The character spacing.</param>
|
||||
/// <param name="hexBytes">The bytes of the text to show.</param>
|
||||
public MoveToNextLineShowTextWithSpacing(decimal wordSpacing, decimal characterSpacing, byte[] hexBytes)
|
||||
{
|
||||
WordSpacing = wordSpacing;
|
||||
@@ -36,24 +67,27 @@
|
||||
Bytes = hexBytes;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var setWordSpacing = new SetWordSpacing(WordSpacing);
|
||||
var setCharacterSpacing = new SetCharacterSpacing(CharacterSpacing);
|
||||
var moveToNextLine = MoveToNextLine.Value;
|
||||
var showText = Text != null ? new ShowText(Text) : new ShowText(Bytes);
|
||||
|
||||
setWordSpacing.Run(operationContext, resourceStore);
|
||||
setCharacterSpacing.Run(operationContext, resourceStore);
|
||||
moveToNextLine.Run(operationContext, resourceStore);
|
||||
showText.Run(operationContext, resourceStore);
|
||||
setWordSpacing.Run(operationContext);
|
||||
setCharacterSpacing.Run(operationContext);
|
||||
moveToNextLine.Run(operationContext);
|
||||
showText.Run(operationContext);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{WordSpacing} {CharacterSpacing} {Text} {Symbol}";
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using IO;
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Show a text string
|
||||
/// </summary>
|
||||
@@ -15,43 +15,61 @@
|
||||
/// <para>
|
||||
/// Generally each byte represents a single character code, however starting in version 1.2+
|
||||
/// a composite font might use multi-byte character codes to map to glyphs.
|
||||
/// For these composite fonts, the <see cref="Fonts.Cmap.CMap"/> of the font defines the mapping from code to glyph.
|
||||
/// For these composite fonts, the <see cref="T:UglyToad.PdfPig.Fonts.Cmap.CMap" /> of the font defines the mapping from code to glyph.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The grouping of character codes in arguments to this operator does not have any impact on the meaning; for example:<br/>
|
||||
/// (Abc) Tj is equivalent to (A) Tj (b) Tj (c) Tj<br/>
|
||||
/// The grouping of character codes in arguments to this operator does not have any impact on the meaning; for example:<br />
|
||||
/// (Abc) Tj is equivalent to (A) Tj (b) Tj (c) Tj<br />
|
||||
/// However grouping character codes makes the document easier to search and extract text from.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal class ShowText : IGraphicsStateOperation
|
||||
public class ShowText : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Tj";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The text string to show.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public string Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The bytes of the string to show.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public byte[] Bytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ShowText"/>.
|
||||
/// </summary>
|
||||
public ShowText(string text)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ShowText"/>.
|
||||
/// </summary>
|
||||
public ShowText(byte[] hexBytes)
|
||||
{
|
||||
Bytes = hexBytes;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var input = new ByteArrayInputBytes(Text != null ? OtherEncodings.StringAsLatin1Bytes(Text) : Bytes);
|
||||
|
||||
operationContext.ShowText(input);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
if (Text == null && Bytes != null)
|
||||
@@ -65,6 +83,7 @@
|
||||
stream.WriteNewLine();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Text} {Symbol}";
|
||||
|
||||
@@ -3,17 +3,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Tokens;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Show one or more text strings, allowing individual glyph positioning.
|
||||
/// Each element of array can be a string or a number.
|
||||
/// If the element is a string, this operator shows the string.
|
||||
/// If it is a number, the operator adjusts the text position by that amount
|
||||
/// </summary>
|
||||
internal class ShowTextsWithPositioning : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "TJ";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The array elements.
|
||||
/// </summary>
|
||||
public IReadOnlyList<IToken> Array { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="ShowTextsWithPositioning"/>.
|
||||
/// </summary>
|
||||
/// <param name="array">The array elements.</param>
|
||||
public ShowTextsWithPositioning(IReadOnlyList<IToken> array)
|
||||
{
|
||||
if (array == null)
|
||||
@@ -33,11 +50,13 @@
|
||||
Array = array;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ShowPositionedText(Array);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -1,40 +1,51 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextState
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the character spacing to a number expressed in unscaled text space units.
|
||||
/// Initial value: 0.
|
||||
/// </summary>
|
||||
internal class SetCharacterSpacing : IGraphicsStateOperation
|
||||
public class SetCharacterSpacing : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Tc";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The character spacing.
|
||||
/// </summary>
|
||||
public decimal Spacing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetCharacterSpacing"/>.
|
||||
/// </summary>
|
||||
/// <param name="spacing">The character spacing.</param>
|
||||
public SetCharacterSpacing(decimal spacing)
|
||||
{
|
||||
Spacing = spacing;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
currentState.FontState.CharacterSpacing = Spacing;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteDecimal(Spacing);
|
||||
stream.WriteWhiteSpace();
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
stream.WriteNumberText(Spacing, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Spacing} {Symbol}";
|
||||
|
||||
@@ -2,14 +2,23 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal class SetFontAndSize : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the font and the font size.
|
||||
/// Font is the name of a font resource in the Font subdictionary of the current resource dictionary.
|
||||
/// Size is a number representing a scale factor.
|
||||
/// </summary>
|
||||
public class SetFontAndSize : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Tf";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
@@ -24,13 +33,19 @@
|
||||
/// </summary>
|
||||
public decimal Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetFontAndSize"/>.
|
||||
/// </summary>
|
||||
/// <param name="font">The font name.</param>
|
||||
/// <param name="size">The font size.</param>
|
||||
public SetFontAndSize(NameToken font, decimal size)
|
||||
{
|
||||
Font = font ?? throw new ArgumentNullException(nameof(font));
|
||||
Size = size;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
@@ -38,16 +53,15 @@
|
||||
currentState.FontState.FontName = Font;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
stream.WriteText(Font.ToString());
|
||||
stream.WriteWhiteSpace();
|
||||
stream.WriteDecimal(Size);
|
||||
stream.WriteWhiteSpace();
|
||||
stream.WriteText(Symbol);
|
||||
stream.WriteNewLine();
|
||||
stream.WriteNumberText(Size, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Font} {Size} {Symbol}";
|
||||
|
||||
@@ -1,33 +1,47 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextState
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class SetHorizontalScaling : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
public class SetHorizontalScaling : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Tz";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// A number specifying the percentage of the normal width.
|
||||
/// </summary>
|
||||
public decimal Scale { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetHorizontalScaling"/>.
|
||||
/// </summary>
|
||||
/// <param name="scale">The horizontal scaling percentage.</param>
|
||||
public SetHorizontalScaling(decimal scale)
|
||||
{
|
||||
Scale = scale;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
currentState.FontState.HorizontalScaling = Scale;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteNumberText(Scale, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Scale} {Symbol}";
|
||||
|
||||
@@ -1,33 +1,50 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextState
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
internal class SetTextLeading : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the text leading.
|
||||
/// </summary>
|
||||
public class SetTextLeading : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "TL";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
/// <summary>
|
||||
/// The text leading in unscaled text space units.
|
||||
/// </summary>
|
||||
public decimal Leading { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetTextLeading"/>.
|
||||
/// </summary>
|
||||
/// <param name="leading">The text leading.</param>
|
||||
public SetTextLeading(decimal leading)
|
||||
{
|
||||
Leading = leading;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
currentState.FontState.Leading = Leading;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteNumberText(Leading, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Leading} {Symbol}";
|
||||
|
||||
@@ -1,34 +1,50 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextState
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
using Core;
|
||||
|
||||
internal class SetTextRenderingMode : IGraphicsStateOperation
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set the text rendering mode.
|
||||
/// </summary>
|
||||
public class SetTextRenderingMode : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
/// </summary>
|
||||
public const string Symbol = "Tr";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Operator => Symbol;
|
||||
|
||||
public RenderingMode Mode { get; }
|
||||
/// <summary>
|
||||
/// The text rendering mode to set.
|
||||
/// </summary>
|
||||
public TextRenderingMode Mode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetTextRenderingMode"/>.
|
||||
/// </summary>
|
||||
public SetTextRenderingMode(int mode)
|
||||
{
|
||||
Mode = (RenderingMode)mode;
|
||||
Mode = (TextRenderingMode)mode;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
currentState.FontState.RenderingMode = Mode;
|
||||
currentState.FontState.TextRenderingMode = Mode;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
stream.WriteNumberText((int)Mode, Symbol);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Mode} {Symbol}";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextState
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Set text rise.
|
||||
/// </summary>
|
||||
internal class SetTextRise : IGraphicsStateOperation
|
||||
public class SetTextRise : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Operations.TextState
|
||||
{
|
||||
using System.IO;
|
||||
using Content;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the word spacing.
|
||||
/// </summary>
|
||||
internal class SetWordSpacing : IGraphicsStateOperation
|
||||
public class SetWordSpacing : IGraphicsStateOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// The symbol for this operation in a stream.
|
||||
@@ -33,7 +32,7 @@
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
using PdfPig.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Manages the Text Matrix (Tm), Text line matrix (Tlm) and Text Rendering Matrix (Trm).
|
||||
/// Manages the Text Matrix (Tm), Text line matrix (Tlm) and used to generate the Text Rendering Matrix (Trm).
|
||||
/// </summary>
|
||||
internal class TextMatrices
|
||||
public class TextMatrices
|
||||
{
|
||||
/// <summary>
|
||||
/// The current text matrix (Tm).
|
||||
/// </summary>
|
||||
public TransformationMatrix TextMatrix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Captures the value of the <see cref="TextMatrix"/> at the beginning of a line of text.
|
||||
/// This is convenient for aligning evenly spaced lines of text.
|
||||
/// </summary>
|
||||
public TransformationMatrix TextLineMatrix { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,45 @@
|
||||
{
|
||||
using System;
|
||||
|
||||
internal interface IInputBytes : IDisposable
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// The input bytes for a PDF document.
|
||||
/// </summary>
|
||||
public interface IInputBytes : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The current offset in bytes.
|
||||
/// </summary>
|
||||
long CurrentOffset { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Moves to the next byte if available.
|
||||
/// </summary>
|
||||
bool MoveNext();
|
||||
|
||||
/// <summary>
|
||||
/// The current byte.
|
||||
/// </summary>
|
||||
byte CurrentByte { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of the data in bytes.
|
||||
/// </summary>
|
||||
long Length { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the next byte if available.
|
||||
/// </summary>
|
||||
byte? Peek();
|
||||
|
||||
/// <summary>
|
||||
/// Whether we are at the end of the available data.
|
||||
/// </summary>
|
||||
bool IsAtEnd();
|
||||
|
||||
/// <summary>
|
||||
/// Move to a given position.
|
||||
/// </summary>
|
||||
void Seek(long position);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user