#26 make almost all operators public

This commit is contained in:
Eliot Jones
2019-01-03 22:20:53 +00:00
parent 29daeb5806
commit 5c8a77bf33
75 changed files with 1196 additions and 304 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -51,7 +51,7 @@
{
}
public void ApplyXObject(StreamToken xObjectStream)
public void ApplyXObject(NameToken xObjectName)
{
}

View File

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

View File

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

View File

@@ -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 []

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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