Merge pull request #237 from BobLd/operationcontext-refactor

Using `byte[]` for `IPageImageRenderer` and keeping the point on `ModifyCurrentTransformationMatrix.cs` in mind.
This commit is contained in:
BobLd 2020-11-27 11:29:45 +00:00 committed by GitHub
commit 6e69160b4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 505 additions and 122 deletions

View File

@ -162,7 +162,7 @@
} }
/// <summary> /// <summary>
/// Adds 4 <see cref="Line"/>s forming a rectangle to the path. /// Add a rectangle following the pdf specification (m, l, l, l, c) path. A new subpath is created.
/// </summary> /// </summary>
public void Rectangle(double x, double y, double width, double height) public void Rectangle(double x, double y, double width, double height)
{ {
@ -175,8 +175,6 @@
IsDrawnAsRectangle = true; IsDrawnAsRectangle = true;
} }
internal void QuadraticCurveTo(double x1, double y1, double x2, double y2) { }
/// <summary> /// <summary>
/// Add a <see cref="BezierCurve"/> to the path. /// Add a <see cref="BezierCurve"/> to the path.
/// </summary> /// </summary>

View File

@ -7,6 +7,8 @@
using PdfPig.Tokens; using PdfPig.Tokens;
using PdfPig.Core; using PdfPig.Core;
using Tokens; using Tokens;
using UglyToad.PdfPig.Graphics.Core;
using UglyToad.PdfPig.Graphics.Operations.TextPositioning;
internal class TestOperationContext : IOperationContext internal class TestOperationContext : IOperationContext
{ {
@ -88,6 +90,66 @@
} }
public void MoveTo(double x, double y)
{
BeginSubpath();
var point = CurrentTransformationMatrix.Transform(new PdfPoint(x, y));
CurrentPosition = point;
CurrentSubpath.MoveTo(point.X, point.Y);
}
public void BezierCurveTo(double x2, double y2, double x3, double y3)
{
if (CurrentSubpath == null)
{
return;
}
var controlPoint2 = CurrentTransformationMatrix.Transform(new PdfPoint(x2, y2));
var end = CurrentTransformationMatrix.Transform(new PdfPoint(x3, y3));
CurrentSubpath.BezierCurveTo(CurrentPosition.X, CurrentPosition.Y, controlPoint2.X, controlPoint2.Y, end.X, end.Y);
CurrentPosition = end;
}
public void BezierCurveTo(double x1, double y1, double x2, double y2, double x3, double y3)
{
if (CurrentSubpath == null)
{
return;
}
var controlPoint1 = CurrentTransformationMatrix.Transform(new PdfPoint(x1, y1));
var controlPoint2 = CurrentTransformationMatrix.Transform(new PdfPoint(x2, y2));
var end = CurrentTransformationMatrix.Transform(new PdfPoint(x3, y3));
CurrentSubpath.BezierCurveTo(controlPoint1.X, controlPoint1.Y, controlPoint2.X, controlPoint2.Y, end.X, end.Y);
CurrentPosition = end;
}
public void LineTo(double x, double y)
{
if (CurrentSubpath == null)
{
return;
}
var endPoint = CurrentTransformationMatrix.Transform(new PdfPoint(x, y));
CurrentSubpath.LineTo(endPoint.X, endPoint.Y);
CurrentPosition = endPoint;
}
public void Rectangle(double x, double y, double width, double height)
{
BeginSubpath();
var lowerLeft = CurrentTransformationMatrix.Transform(new PdfPoint(x, y));
var upperRight = CurrentTransformationMatrix.Transform(new PdfPoint(x + width, y + height));
CurrentSubpath.Rectangle(lowerLeft.X, lowerLeft.Y, upperRight.X - lowerLeft.X, upperRight.Y - lowerLeft.Y);
AddCurrentSubpath();
}
public void EndPath() public void EndPath()
{ {
} }
@ -124,6 +186,91 @@
{ {
} }
private void AdjustTextMatrix(double tx, double ty)
{
var matrix = TransformationMatrix.GetTranslationMatrix(tx, ty);
TextMatrices.TextMatrix = matrix.Multiply(TextMatrices.TextMatrix);
}
public void SetFlatnessTolerance(decimal tolerance)
{
GetCurrentState().Flatness = tolerance;
}
public void SetLineCap(LineCapStyle cap)
{
GetCurrentState().CapStyle = cap;
}
public void SetLineDashPattern(LineDashPattern pattern)
{
GetCurrentState().LineDashPattern = pattern;
}
public void SetLineJoin(LineJoinStyle join)
{
GetCurrentState().JoinStyle = join;
}
public void SetLineWidth(decimal width)
{
GetCurrentState().LineWidth = width;
}
public void SetMiterLimit(decimal limit)
{
GetCurrentState().MiterLimit = limit;
}
public void MoveToNextLineWithOffset()
{
var tdOperation = new MoveToNextLineWithOffset(0, -1 * (decimal)GetCurrentState().FontState.Leading);
tdOperation.Run(this);
}
public void SetFontAndSize(NameToken font, double size)
{
var currentState = GetCurrentState();
currentState.FontState.FontSize = size;
currentState.FontState.FontName = font;
}
public void SetHorizontalScaling(double scale)
{
GetCurrentState().FontState.HorizontalScaling = scale;
}
public void SetTextLeading(double leading)
{
GetCurrentState().FontState.Leading = leading;
}
public void SetTextRenderingMode(TextRenderingMode mode)
{
GetCurrentState().FontState.TextRenderingMode = mode;
}
public void SetTextRise(double rise)
{
GetCurrentState().FontState.Rise = rise;
}
public void SetWordSpacing(double spacing)
{
GetCurrentState().FontState.WordSpacing = spacing;
}
public void ModifyCurrentTransformationMatrix(double[] value)
{
var ctm = GetCurrentState().CurrentTransformationMatrix;
GetCurrentState().CurrentTransformationMatrix = TransformationMatrix.FromArray(value).Multiply(ctm);
}
public void SetCharacterSpacing(double spacing)
{
GetCurrentState().FontState.CharacterSpacing = spacing;
}
private class TestFontFactory : IFontFactory private class TestFontFactory : IFontFactory
{ {
public IFont Get(DictionaryToken dictionary) public IFont Get(DictionaryToken dictionary)

View File

@ -74,6 +74,7 @@
"UglyToad.PdfPig.Content.IPdfImage", "UglyToad.PdfPig.Content.IPdfImage",
"UglyToad.PdfPig.Content.Letter", "UglyToad.PdfPig.Content.Letter",
"UglyToad.PdfPig.Content.MarkedContentElement", "UglyToad.PdfPig.Content.MarkedContentElement",
"UglyToad.PdfPig.Content.MediaBox",
"UglyToad.PdfPig.Content.Page", "UglyToad.PdfPig.Content.Page",
"UglyToad.PdfPig.Content.PageRotationDegrees", "UglyToad.PdfPig.Content.PageRotationDegrees",
"UglyToad.PdfPig.Content.PageSize", "UglyToad.PdfPig.Content.PageSize",
@ -197,6 +198,8 @@
"UglyToad.PdfPig.ParsingOptions", "UglyToad.PdfPig.ParsingOptions",
"UglyToad.PdfPig.PdfDocument", "UglyToad.PdfPig.PdfDocument",
"UglyToad.PdfPig.PdfExtensions", "UglyToad.PdfPig.PdfExtensions",
"UglyToad.PdfPig.Rendering.IPageImageRenderer",
"UglyToad.PdfPig.Rendering.PdfRendererImageFormat",
"UglyToad.PdfPig.Structure", "UglyToad.PdfPig.Structure",
"UglyToad.PdfPig.Util.Adler32Checksum", "UglyToad.PdfPig.Util.Adler32Checksum",
"UglyToad.PdfPig.Util.IWordExtractor", "UglyToad.PdfPig.Util.IWordExtractor",

View File

@ -338,6 +338,7 @@
public static readonly NameToken MarkInfo = new NameToken("MarkInfo"); public static readonly NameToken MarkInfo = new NameToken("MarkInfo");
public static readonly NameToken Mask = new NameToken("Mask"); public static readonly NameToken Mask = new NameToken("Mask");
public static readonly NameToken Matrix = new NameToken("Matrix"); public static readonly NameToken Matrix = new NameToken("Matrix");
public static readonly NameToken Matte = new NameToken("Matte");
public static readonly NameToken MaxLen = new NameToken("MaxLen"); public static readonly NameToken MaxLen = new NameToken("MaxLen");
public static readonly NameToken MaxWidth = new NameToken("MaxWidth"); public static readonly NameToken MaxWidth = new NameToken("MaxWidth");
public static readonly NameToken Mcid = new NameToken("MCID"); public static readonly NameToken Mcid = new NameToken("MCID");

View File

@ -9,7 +9,7 @@
/// <remarks> /// <remarks>
/// See table 3.27 from the PDF specification version 1.7. /// See table 3.27 from the PDF specification version 1.7.
/// </remarks> /// </remarks>
internal class MediaBox public class MediaBox
{ {
///<summary> ///<summary>
/// User space units per inch. /// User space units per inch.
@ -66,8 +66,14 @@
/// </summary> /// </summary>
public static readonly MediaBox A6 = new MediaBox(new PdfRectangle(0, 0, 105 * PointsPerMm, 148 * PointsPerMm)); public static readonly MediaBox A6 = new MediaBox(new PdfRectangle(0, 0, 105 * PointsPerMm, 148 * PointsPerMm));
/// <summary>
/// A rectangle, expressed in default user space units, that defines the boundaries of the physical medium on which the page shall be displayed or printed.
/// </summary>
public PdfRectangle Bounds { get; } public PdfRectangle Bounds { get; }
/// <summary>
/// Create a new <see cref="MediaBox"/>.
/// </summary>
public MediaBox(PdfRectangle? bounds) public MediaBox(PdfRectangle? bounds)
{ {
Bounds = bounds ?? throw new ArgumentNullException(nameof(bounds)); Bounds = bounds ?? throw new ArgumentNullException(nameof(bounds));

View File

@ -35,7 +35,10 @@
/// </summary> /// </summary>
public CropBox CropBox { get; } public CropBox CropBox { get; }
internal MediaBox MediaBox { get; } /// <summary>
/// Defines the boundaries of the physical medium on which the page shall be displayed or printed.
/// </summary>
public MediaBox MediaBox { get; }
internal PageContent Content { get; } internal PageContent Content { get; }

View File

@ -1,9 +1,5 @@
namespace UglyToad.PdfPig.Graphics namespace UglyToad.PdfPig.Graphics
{ {
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Colors; using Colors;
using Content; using Content;
using Core; using Core;
@ -14,8 +10,13 @@
using Parser; using Parser;
using PdfFonts; using PdfFonts;
using PdfPig.Core; using PdfPig.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Tokenization.Scanner; using Tokenization.Scanner;
using Tokens; using Tokens;
using UglyToad.PdfPig.Graphics.Operations.TextPositioning;
using XObjects; using XObjects;
using static PdfPig.Core.PdfSubpath; using static PdfPig.Core.PdfSubpath;
@ -561,6 +562,66 @@
ClosePath(); ClosePath();
} }
public void MoveTo(double x, double y)
{
BeginSubpath();
var point = CurrentTransformationMatrix.Transform(new PdfPoint(x, y));
CurrentPosition = point;
CurrentSubpath.MoveTo(point.X, point.Y);
}
public void BezierCurveTo(double x2, double y2, double x3, double y3)
{
if (CurrentSubpath == null)
{
return;
}
var controlPoint2 = CurrentTransformationMatrix.Transform(new PdfPoint(x2, y2));
var end = CurrentTransformationMatrix.Transform(new PdfPoint(x3, y3));
CurrentSubpath.BezierCurveTo(CurrentPosition.X, CurrentPosition.Y, controlPoint2.X, controlPoint2.Y, end.X, end.Y);
CurrentPosition = end;
}
public void BezierCurveTo(double x1, double y1, double x2, double y2, double x3, double y3)
{
if (CurrentSubpath == null)
{
return;
}
var controlPoint1 = CurrentTransformationMatrix.Transform(new PdfPoint(x1, y1));
var controlPoint2 = CurrentTransformationMatrix.Transform(new PdfPoint(x2, y2));
var end = CurrentTransformationMatrix.Transform(new PdfPoint(x3, y3));
CurrentSubpath.BezierCurveTo(controlPoint1.X, controlPoint1.Y, controlPoint2.X, controlPoint2.Y, end.X, end.Y);
CurrentPosition = end;
}
public void LineTo(double x, double y)
{
if (CurrentSubpath == null)
{
return;
}
var endPoint = CurrentTransformationMatrix.Transform(new PdfPoint(x, y));
CurrentSubpath.LineTo(endPoint.X, endPoint.Y);
CurrentPosition = endPoint;
}
public void Rectangle(double x, double y, double width, double height)
{
BeginSubpath();
var lowerLeft = CurrentTransformationMatrix.Transform(new PdfPoint(x, y));
var upperRight = CurrentTransformationMatrix.Transform(new PdfPoint(x + width, y + height));
CurrentSubpath.Rectangle(lowerLeft.X, lowerLeft.Y, upperRight.X - lowerLeft.X, upperRight.Y - lowerLeft.Y);
AddCurrentSubpath();
}
public void EndPath() public void EndPath()
{ {
if (CurrentPath == null) if (CurrentPath == null)
@ -744,7 +805,10 @@
if (markedContentStack.CanPop) if (markedContentStack.CanPop)
{ {
var mc = markedContentStack.Pop(pdfScanner); var mc = markedContentStack.Pop(pdfScanner);
if (mc != null) markedContents.Add(mc); if (mc != null)
{
markedContents.Add(mc);
}
} }
} }
@ -752,9 +816,86 @@
{ {
var matrix = TransformationMatrix.GetTranslationMatrix(tx, ty); var matrix = TransformationMatrix.GetTranslationMatrix(tx, ty);
var newMatrix = matrix.Multiply(TextMatrices.TextMatrix); TextMatrices.TextMatrix = matrix.Multiply(TextMatrices.TextMatrix);
}
TextMatrices.TextMatrix = newMatrix; public void SetFlatnessTolerance(decimal tolerance)
{
GetCurrentState().Flatness = tolerance;
}
public void SetLineCap(LineCapStyle cap)
{
GetCurrentState().CapStyle = cap;
}
public void SetLineDashPattern(LineDashPattern pattern)
{
GetCurrentState().LineDashPattern = pattern;
}
public void SetLineJoin(LineJoinStyle join)
{
GetCurrentState().JoinStyle = join;
}
public void SetLineWidth(decimal width)
{
GetCurrentState().LineWidth = width;
}
public void SetMiterLimit(decimal limit)
{
GetCurrentState().MiterLimit = limit;
}
public void MoveToNextLineWithOffset()
{
var tdOperation = new MoveToNextLineWithOffset(0, -1 * (decimal)GetCurrentState().FontState.Leading);
tdOperation.Run(this);
}
public void SetFontAndSize(NameToken font, double size)
{
var currentState = GetCurrentState();
currentState.FontState.FontSize = size;
currentState.FontState.FontName = font;
}
public void SetHorizontalScaling(double scale)
{
GetCurrentState().FontState.HorizontalScaling = scale;
}
public void SetTextLeading(double leading)
{
GetCurrentState().FontState.Leading = leading;
}
public void SetTextRenderingMode(TextRenderingMode mode)
{
GetCurrentState().FontState.TextRenderingMode = mode;
}
public void SetTextRise(double rise)
{
GetCurrentState().FontState.Rise = rise;
}
public void SetWordSpacing(double spacing)
{
GetCurrentState().FontState.WordSpacing = spacing;
}
public void ModifyCurrentTransformationMatrix(double[] value)
{
var ctm = GetCurrentState().CurrentTransformationMatrix;
GetCurrentState().CurrentTransformationMatrix = TransformationMatrix.FromArray(value).Multiply(ctm);
}
public void SetCharacterSpacing(double spacing)
{
GetCurrentState().FontState.CharacterSpacing = spacing;
} }
} }
} }

View File

@ -3,25 +3,13 @@
using PdfPig.Core; using PdfPig.Core;
using System.Collections.Generic; using System.Collections.Generic;
using Tokens; using Tokens;
using Util.JetBrains.Annotations; using UglyToad.PdfPig.Graphics.Core;
/// <summary> /// <summary>
/// The current graphics state context when running a PDF content stream. /// The current graphics state context when running a PDF content stream.
/// </summary> /// </summary>
public interface IOperationContext public interface IOperationContext
{ {
/// <summary>
/// The current subpath being drawn if applicable.
/// </summary>
[CanBeNull]
PdfSubpath CurrentSubpath { get; }
/// <summary>
/// The current path being drawn if applicable.
/// </summary>
[CanBeNull]
PdfPath CurrentPath { get; }
/// <summary> /// <summary>
/// The active colorspaces for this content stream. /// The active colorspaces for this content stream.
/// </summary> /// </summary>
@ -32,22 +20,11 @@
/// </summary> /// </summary>
PdfPoint CurrentPosition { get; set; } 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> /// <summary>
/// The matrices for the current text state. /// The matrices for the current text state.
/// </summary> /// </summary>
TextMatrices TextMatrices { get; } TextMatrices TextMatrices { get; }
/// <summary>
/// The current transformation matrix
/// </summary>
TransformationMatrix CurrentTransformationMatrix { get; }
/// <summary> /// <summary>
/// The number of graphics states on the stack. /// The number of graphics states on the stack.
/// </summary> /// </summary>
@ -116,6 +93,36 @@
/// <param name="close">Whether to also close the path.</param> /// <param name="close">Whether to also close the path.</param>
void FillStrokePath(FillingRule fillingRule, bool close); void FillStrokePath(FillingRule fillingRule, bool close);
/// <summary>
/// Add a move command to the path.
/// <para>Should implement matrix transformations.</para>
/// </summary>
void MoveTo(double x, double y);
/// <summary>
/// Add a bezier curve to the current subpath.
/// <para>Should implement matrix transformations.</para>
/// </summary>
void BezierCurveTo(double x1, double y1, double x2, double y2, double x3, double y3);
/// <summary>
/// Add a bezier curve to the current subpath.
/// <para>Should implement matrix transformations.</para>
/// </summary>
void BezierCurveTo(double x2, double y2, double x3, double y3);
/// <summary>
/// Add a line command to the subpath.
/// <para>Should implement matrix transformations.</para>
/// </summary>
void LineTo(double x, double y);
/// <summary>
/// Add a rectangle following the pdf specification (m, l, l, l, c) path. A new subpath will be created.
/// <para>Should implement matrix transformations.</para>
/// </summary>
void Rectangle(double x, double y, double width, double height);
/// <summary> /// <summary>
/// End the path object without filling or stroking it. This operator shall be a path-painting no-op, /// End the path object without filling or stroking it. This operator shall be a path-painting no-op,
/// used primarily for the side effect of changing the current clipping path (see 8.5.4, "Clipping Path Operators"). /// used primarily for the side effect of changing the current clipping path (see 8.5.4, "Clipping Path Operators").
@ -162,5 +169,90 @@
/// Modify the clipping rule of the current path. /// Modify the clipping rule of the current path.
/// </summary> /// </summary>
void ModifyClippingIntersect(FillingRule clippingRule); void ModifyClippingIntersect(FillingRule clippingRule);
/// <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>
/// <param name="tolerance"></param>
void SetFlatnessTolerance(decimal tolerance);
/// <summary>
/// Set the line cap style in the graphics state.
/// </summary>
void SetLineCap(LineCapStyle cap);
/// <summary>
/// Set the line dash pattern in the graphics state.
/// </summary>
void SetLineDashPattern(LineDashPattern pattern);
/// <summary>
/// Set the line join style in the graphics state.
/// </summary>
void SetLineJoin(LineJoinStyle join);
/// <summary>
/// Set the line width in the graphics state.
/// </summary>
void SetLineWidth(decimal width);
/// <summary>
/// Set the miter limit in the graphics state.
/// </summary>
void SetMiterLimit(decimal limit);
/// <summary>
/// Move to the start of the next line.
/// </summary>
/// <remarks>
/// This performs this operation: 0 -Tl Td
/// The offset is negative leading text (Tl) value, this is incorrect in the specification.
/// </remarks>
void MoveToNextLineWithOffset();
/// <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>
void SetFontAndSize(NameToken font, double size);
/// <summary>
/// Set the horizontal scaling.
/// </summary>
/// <param name="scale"></param>
void SetHorizontalScaling(double scale);
/// <summary>
/// Set the text leading.
/// </summary>
void SetTextLeading(double leading);
/// <summary>
/// Set the text rendering mode.
/// </summary>
void SetTextRenderingMode(TextRenderingMode mode);
/// <summary>
/// Set text rise.
/// </summary>
void SetTextRise(double rise);
/// <summary>
/// Sets the word spacing.
/// </summary>
void SetWordSpacing(double spacing);
/// <summary>
/// Modify the current transformation matrix by concatenating the specified matrix.
/// </summary>
void ModifyCurrentTransformationMatrix(double[] value);
/// <summary>
/// Set the character spacing to a number expressed in unscaled text space units.
/// Initial value: 0.
/// </summary>
void SetCharacterSpacing(double spacing);
} }
} }

View File

@ -35,7 +35,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
operationContext.GetCurrentState().Flatness = Tolerance; operationContext.SetFlatnessTolerance(Tolerance);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -45,7 +45,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
operationContext.GetCurrentState().CapStyle = Cap; operationContext.SetLineCap(Cap);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -33,7 +33,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
operationContext.GetCurrentState().LineDashPattern = Pattern; operationContext.SetLineDashPattern(Pattern);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -40,7 +40,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
operationContext.GetCurrentState().JoinStyle = Join; operationContext.SetLineJoin(Join);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -33,9 +33,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetLineWidth(Width);
currentState.LineWidth = Width;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -33,9 +33,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetMiterLimit(Limit);
currentState.MiterLimit = Limit;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -20,6 +20,7 @@
/// <summary> /// <summary>
/// Applies the operation to the current context with the provided resources. /// Applies the operation to the current context with the provided resources.
/// <para>Matrix transformations should be implemented in <see cref="IOperationContext"/>.</para>
/// </summary> /// </summary>
/// <param name="operationContext"></param> /// <param name="operationContext"></param>
void Run(IOperationContext operationContext); void Run(IOperationContext operationContext);

View File

@ -71,14 +71,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
if (operationContext.CurrentSubpath == null) return; operationContext.BezierCurveTo((double)X1, (double)Y1, (double)X2, (double)Y2, (double)X3, (double)Y3);
var controlPoint1 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X1, Y1));
var controlPoint2 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X2, Y2));
var end = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X3, Y3));
operationContext.CurrentSubpath.BezierCurveTo(controlPoint1.X, controlPoint1.Y,
controlPoint2.X, controlPoint2.Y, end.X, end.Y);
operationContext.CurrentPosition = end;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -56,12 +56,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
if (operationContext.CurrentSubpath == null) return; operationContext.BezierCurveTo((double)X1, (double)Y1, (double)X3, (double)Y3, (double)X3, (double)Y3);
var controlPoint1 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X1, Y1));
var end = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X3, Y3));
operationContext.CurrentSubpath.BezierCurveTo(controlPoint1.X, controlPoint1.Y, end.X, end.Y, end.X, end.Y);
operationContext.CurrentPosition = end;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -56,12 +56,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
operationContext.BeginSubpath(); operationContext.Rectangle((double)LowerLeftX, (double)LowerLeftY, (double)Width, (double)Height);
var lowerLeft = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(LowerLeftX, LowerLeftY));
var upperRight = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(LowerLeftX + Width, LowerLeftY + Height));
operationContext.CurrentSubpath.Rectangle(lowerLeft.X, lowerLeft.Y, upperRight.X - lowerLeft.X, upperRight.Y - lowerLeft.Y);
operationContext.AddCurrentSubpath();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -56,17 +56,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
if (operationContext.CurrentSubpath == null) return; operationContext.BezierCurveTo((double)X2, (double)Y2, (double)X3, (double)Y3);
var controlPoint2 = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X2, Y2));
var end = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X3, Y3));
operationContext.CurrentSubpath.BezierCurveTo(operationContext.CurrentPosition.X,
operationContext.CurrentPosition.Y,
controlPoint2.X,
controlPoint2.Y,
end.X,
end.Y);
operationContext.CurrentPosition = end;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -41,11 +41,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
if (operationContext.CurrentSubpath == null) return; operationContext.LineTo((double)X, (double)Y);
var endPoint = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X, Y));
operationContext.CurrentSubpath.LineTo(endPoint.X, endPoint.Y);
operationContext.CurrentPosition = endPoint;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -41,10 +41,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
operationContext.BeginSubpath(); operationContext.MoveTo((double)X, (double)Y);
var point = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(X, Y));
operationContext.CurrentPosition = point;
operationContext.CurrentSubpath.MoveTo(point.X, point.Y);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -44,13 +44,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var newMatrix = TransformationMatrix.FromArray(Value); operationContext.ModifyCurrentTransformationMatrix(Array.ConvertAll(Value, x => (double)x));
var ctm = operationContext.GetCurrentState().CurrentTransformationMatrix;
var newCtm = newMatrix.Multiply(ctm);
operationContext.GetCurrentState().CurrentTransformationMatrix = newCtm;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -32,9 +32,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var tdOperation = new MoveToNextLineWithOffset(0, -1 * (decimal)operationContext.GetCurrentState().FontState.Leading); operationContext.MoveToNextLineWithOffset();
tdOperation.Run(operationContext);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -34,9 +34,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetCharacterSpacing((double)Spacing);
currentState.FontState.CharacterSpacing = (double)Spacing;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -48,10 +48,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetFontAndSize(Font, (double)Size);
currentState.FontState.FontSize = (double)Size;
currentState.FontState.FontName = Font;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -30,9 +30,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetHorizontalScaling((double)Scale);
currentState.FontState.HorizontalScaling = (double)Scale;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -33,9 +33,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetTextLeading((double)Leading);
currentState.FontState.Leading = (double)Leading;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -33,9 +33,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetTextRenderingMode(Mode);
currentState.FontState.TextRenderingMode = Mode;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -33,9 +33,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetTextRise((double)Rise);
currentState.FontState.Rise = (double)Rise;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -34,9 +34,7 @@
/// <inheritdoc /> /// <inheritdoc />
public void Run(IOperationContext operationContext) public void Run(IOperationContext operationContext)
{ {
var currentState = operationContext.GetCurrentState(); operationContext.SetWordSpacing((double)Spacing);
currentState.FontState.WordSpacing = (double)Spacing;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -0,0 +1,19 @@
using UglyToad.PdfPig.Content;
namespace UglyToad.PdfPig.Rendering
{
/// <summary>
/// Render page as an image.
/// </summary>
public interface IPageImageRenderer
{
/// <summary>
/// Render page as an image.
/// </summary>
/// <param name="page">The pdf page.</param>
/// <param name="scale">The scale to apply to the page (i.e. zoom level).</param>
/// <param name="imageFormat">The output image format, if supported.</param>
/// <returns>The image as a memory stream.</returns>
byte[] Render(Page page, double scale, PdfRendererImageFormat imageFormat);
}
}

View File

@ -0,0 +1,33 @@
namespace UglyToad.PdfPig.Rendering
{
/// <summary>
/// The output image format of the <see cref="IPageImageRenderer"/>.
/// </summary>
public enum PdfRendererImageFormat : byte
{
/// <summary>
/// Bitmap image format.
/// </summary>
Bmp,
/// <summary>
/// Jpeg/Jpg image format.
/// </summary>
Jpeg,
/// <summary>
/// Png image format.
/// </summary>
Png,
/// <summary>
/// Tiff image format.
/// </summary>
Tiff,
/// <summary>
/// Gif image format.
/// </summary>
Gif
}
}