mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
arrange operations into folders in line with grouping from the specification and start creating a context to mutate through operations.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
namespace UglyToad.Pdf.Tests.Graphics.Operations.General
|
||||
{
|
||||
using Pdf.Graphics.Operations.General;
|
||||
using Xunit;
|
||||
|
||||
public class SetMiterLimitTests
|
||||
{
|
||||
private readonly TestResourceStore resourceStore = new TestResourceStore();
|
||||
private readonly TestOperationContext context = new TestOperationContext();
|
||||
|
||||
[Fact]
|
||||
public void RunSetsMiterLimitOfCurrentState()
|
||||
{
|
||||
var limit = new SetMiterLimit(25);
|
||||
|
||||
limit.Run(context, resourceStore);
|
||||
|
||||
Assert.Equal(25, context.GetCurrentState().MiterLimit);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MiterLimitSymbolCorrect()
|
||||
{
|
||||
Assert.Equal("M", SetMiterLimit.Symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace UglyToad.Pdf.Tests.Graphics.Operations.SpecialGraphicsState
|
||||
{
|
||||
using System;
|
||||
using Pdf.Graphics;
|
||||
using Pdf.Graphics.Operations.SpecialGraphicsState;
|
||||
using Xunit;
|
||||
|
||||
public class PopTests
|
||||
{
|
||||
private readonly TestResourceStore resourceStore = new TestResourceStore();
|
||||
private readonly TestOperationContext context = new TestOperationContext();
|
||||
|
||||
[Fact]
|
||||
public void PopSymbolCorrect()
|
||||
{
|
||||
Assert.Equal("Q", Pop.Symbol);
|
||||
Assert.Equal("Q", Pop.Value.Operator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotPopWithSingleFrame()
|
||||
{
|
||||
Action action = () => Pop.Value.Run(context, resourceStore);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotPopWithNoFrames()
|
||||
{
|
||||
context.StateStack.Pop();
|
||||
|
||||
Action action = () => Pop.Value.Run(context, resourceStore);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopsTopFrame()
|
||||
{
|
||||
context.StateStack.Push(new CurrentGraphicsState
|
||||
{
|
||||
LineWidth = 23
|
||||
});
|
||||
|
||||
Pop.Value.Run(context, resourceStore);
|
||||
|
||||
Assert.Equal(1, context.StackSize);
|
||||
Assert.Equal(1, context.GetCurrentState().LineWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace UglyToad.Pdf.Tests.Graphics.Operations.SpecialGraphicsState
|
||||
{
|
||||
using Pdf.Graphics.Operations.SpecialGraphicsState;
|
||||
using Xunit;
|
||||
|
||||
public class PushTests
|
||||
{
|
||||
private readonly TestResourceStore resourceStore = new TestResourceStore();
|
||||
private readonly TestOperationContext context = new TestOperationContext();
|
||||
|
||||
[Fact]
|
||||
public void PushSymbolCorrect()
|
||||
{
|
||||
Assert.Equal("q", Push.Symbol);
|
||||
Assert.Equal("q", Push.Value.Operator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PushAddsToStack()
|
||||
{
|
||||
Push.Value.Run(context, resourceStore);
|
||||
|
||||
Assert.Equal(2, context.StackSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/UglyToad.Pdf.Tests/Graphics/TestOperationContext.cs
Normal file
42
src/UglyToad.Pdf.Tests/Graphics/TestOperationContext.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace UglyToad.Pdf.Tests.Graphics
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Content;
|
||||
using Pdf.Graphics;
|
||||
|
||||
internal class TestOperationContext : IOperationContext
|
||||
{
|
||||
public Stack<CurrentGraphicsState> StateStack { get; }
|
||||
= new Stack<CurrentGraphicsState>();
|
||||
|
||||
public int StackSize => StateStack.Count;
|
||||
|
||||
public TextMatrices TextMatrices { get; set; }
|
||||
= new TextMatrices();
|
||||
|
||||
public TestOperationContext()
|
||||
{
|
||||
StateStack.Push(new CurrentGraphicsState());
|
||||
}
|
||||
|
||||
public CurrentGraphicsState GetCurrentState()
|
||||
{
|
||||
return StateStack.Peek();
|
||||
}
|
||||
|
||||
public void PopState()
|
||||
{
|
||||
StateStack.Pop();
|
||||
}
|
||||
|
||||
public void PushState()
|
||||
{
|
||||
StateStack.Push(StateStack.Peek().DeepClone());
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestResourceStore : IResourceStore
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
namespace UglyToad.Pdf.Tests.Parser
|
||||
{
|
||||
using Graphics;
|
||||
using Pdf.Cos;
|
||||
using Pdf.Graphics;
|
||||
using Pdf.Graphics.Operations.General;
|
||||
using Pdf.Graphics.Operations.TextObjects;
|
||||
using Pdf.Graphics.Operations.TextPositioning;
|
||||
using Pdf.Graphics.Operations.TextShowing;
|
||||
using Pdf.Graphics.Operations.TextState;
|
||||
using Pdf.Parser;
|
||||
using Xunit;
|
||||
|
||||
public class PageContentParserTests
|
||||
{
|
||||
private readonly PageContentParser parser = new PageContentParser();
|
||||
private readonly IGraphicsStateOperationFactory operationFactory = new ReflectionGraphicsStateOperationFactory();
|
||||
|
||||
[Fact]
|
||||
public void CorrectlyExtractsOperations()
|
||||
@@ -16,6 +23,70 @@
|
||||
var result = parser.Parse(new ReflectionGraphicsStateOperationFactory(), input.Bytes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CorrectlyExtractsOptionsInTextContext()
|
||||
{
|
||||
const string s = @"BT
|
||||
/F13 48 Tf
|
||||
20 38 Td
|
||||
1 Tr
|
||||
2 w
|
||||
(ABC) Tj
|
||||
ET";
|
||||
var input = StringBytesTestConverter.Convert(s, false);
|
||||
|
||||
var result = parser.Parse(operationFactory, input.Bytes);
|
||||
|
||||
Assert.Equal(7, result.GraphicsStateOperations.Count);
|
||||
|
||||
Assert.Equal(BeginText.Value, result.GraphicsStateOperations[0]);
|
||||
|
||||
var font = Assert.IsType<SetFontSize>(result.GraphicsStateOperations[1]);
|
||||
Assert.Equal(CosName.Create("F13"), font.Font);
|
||||
Assert.Equal(48, font.Size);
|
||||
|
||||
var nextLine = Assert.IsType<MoveToNextLineWithOffset>(result.GraphicsStateOperations[2]);
|
||||
Assert.Equal(20, nextLine.Tx);
|
||||
Assert.Equal(38, nextLine.Ty);
|
||||
|
||||
var renderingMode = Assert.IsType<SetTextRenderingMode>(result.GraphicsStateOperations[3]);
|
||||
Assert.Equal(RenderingMode.Stroke, renderingMode.Mode);
|
||||
|
||||
var lineWidth = Assert.IsType<SetLineWidth>(result.GraphicsStateOperations[4]);
|
||||
Assert.Equal(2, lineWidth.Width);
|
||||
|
||||
var text = Assert.IsType<ShowText>(result.GraphicsStateOperations[5]);
|
||||
Assert.Equal("ABC", text.Text);
|
||||
|
||||
Assert.Equal(EndText.Value, result.GraphicsStateOperations[6]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SkipsComments()
|
||||
{
|
||||
const string s = @"BT
|
||||
21 32 Td %A comment here
|
||||
0 Tr
|
||||
ET";
|
||||
|
||||
var input = StringBytesTestConverter.Convert(s, false);
|
||||
|
||||
var result = parser.Parse(operationFactory, input.Bytes);
|
||||
|
||||
Assert.Equal(4, result.GraphicsStateOperations.Count);
|
||||
|
||||
Assert.Equal(BeginText.Value, result.GraphicsStateOperations[0]);
|
||||
|
||||
var moveLine = Assert.IsType<MoveToNextLineWithOffset>(result.GraphicsStateOperations[1]);
|
||||
Assert.Equal(21, moveLine.Tx);
|
||||
Assert.Equal(32, moveLine.Ty);
|
||||
|
||||
var renderingMode = Assert.IsType<SetTextRenderingMode>(result.GraphicsStateOperations[2]);
|
||||
Assert.Equal(RenderingMode.Fill, renderingMode.Mode);
|
||||
|
||||
Assert.Equal(EndText.Value, result.GraphicsStateOperations[3]);
|
||||
}
|
||||
|
||||
private const string SimpleGoogleDocPageContent = @"
|
||||
1 0 0 -1 0 792 cm
|
||||
q
|
||||
|
||||
@@ -7,7 +7,12 @@
|
||||
using Fonts;
|
||||
using Parser;
|
||||
|
||||
public class ResourceContainer
|
||||
public interface IResourceStore
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ResourceContainer : IResourceStore
|
||||
{
|
||||
private readonly Dictionary<CosName, IFont> loadedFonts = new Dictionary<CosName, IFont>();
|
||||
|
||||
|
||||
7
src/UglyToad.Pdf/Core/IDeepCloneable.cs
Normal file
7
src/UglyToad.Pdf/Core/IDeepCloneable.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace UglyToad.Pdf.Core
|
||||
{
|
||||
public interface IDeepCloneable<out T>
|
||||
{
|
||||
T DeepClone();
|
||||
}
|
||||
}
|
||||
84
src/UglyToad.Pdf/Graphics/CurrentFontState.cs
Normal file
84
src/UglyToad.Pdf/Graphics/CurrentFontState.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
// ReSharper disable RedundantDefaultMemberInitializer
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
using Core;
|
||||
using Cos;
|
||||
|
||||
/// <summary>
|
||||
/// The current state of text related parameters for a content stream.
|
||||
/// </summary>
|
||||
internal 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)
|
||||
/// glyph displacement.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In horizontal writing mode a positive value will expand the distance between letters/glyphs.
|
||||
/// Default value 0.
|
||||
/// </remarks>
|
||||
public decimal CharacterSpacing { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// As for <see cref="CharacterSpacing"/> but applies only for the space character (32).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Default value 0.
|
||||
/// </remarks>
|
||||
public decimal WordSpacing { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the width of glyphs/letters by stretching (or compressing) them horizontally.
|
||||
/// Value is a percentage of the normal width.
|
||||
/// </summary>
|
||||
public decimal HorizontalScaling { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// The vertical distance in unscaled text space units between the baselines of lines of text.
|
||||
/// </summary>
|
||||
public decimal Leading { get; set; }
|
||||
|
||||
public CosName FontName { get; set; }
|
||||
|
||||
public decimal FontSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="RenderingMode"/> 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;
|
||||
|
||||
/// <summary>
|
||||
/// The distance in unscaled text space units to move the default baseline either up or down.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Always applies to the vertical coordinate irrespective or writing mode.
|
||||
/// </remarks>
|
||||
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?
|
||||
/// </summary>
|
||||
public bool Knockout { get; set; }
|
||||
|
||||
public CurrentFontState DeepClone()
|
||||
{
|
||||
return new CurrentFontState
|
||||
{
|
||||
CharacterSpacing = CharacterSpacing,
|
||||
RenderingMode = RenderingMode,
|
||||
Rise = Rise,
|
||||
Leading = Leading,
|
||||
WordSpacing = WordSpacing,
|
||||
FontName = FontName,
|
||||
FontSize = FontSize,
|
||||
HorizontalScaling = HorizontalScaling,
|
||||
Knockout = Knockout
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
176
src/UglyToad.Pdf/Graphics/CurrentGraphicsState.cs
Normal file
176
src/UglyToad.Pdf/Graphics/CurrentGraphicsState.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Geometry;
|
||||
using Operations;
|
||||
|
||||
internal class CurrentGraphicsState : IDeepCloneable<CurrentGraphicsState>
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="CurrentFontState"/> for this graphics state.
|
||||
/// </summary>
|
||||
public CurrentFontState FontState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Thickness in user space units of path to be stroked.
|
||||
/// </summary>
|
||||
public decimal LineWidth { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the shape of line ends for open stroked paths.
|
||||
/// </summary>
|
||||
public LineCapStyle CapStyle { get; set; } = LineCapStyle.Butt;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the shape of joins between connected stroked path segments.
|
||||
/// </summary>
|
||||
public LineJoinStyle JoinStyle { get; set; } = LineJoinStyle.Miter;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum length of mitered line joins for paths before becoming a bevel.
|
||||
/// </summary>
|
||||
public decimal MiterLimit { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// The pattern to be used for stroked lines.
|
||||
/// </summary>
|
||||
public LineDashPattern LineDashPattern { get; set; } = LineDashPattern.Solid;
|
||||
|
||||
/// <summary>
|
||||
/// The rendering intent to use when converting CIE-based colors to device colors.
|
||||
/// </summary>
|
||||
public RenderingIntent RenderingIntent { get; set; } = RenderingIntent.RelativeColorimetric;
|
||||
|
||||
/// <summary>
|
||||
/// Should a correction for rasterization effects be applied?
|
||||
/// </summary>
|
||||
public bool StrokeAdjustment { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Opacity value to be used for transparent imaging.
|
||||
/// </summary>
|
||||
public decimal AlphaConstant { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Should soft mask and alpha constant values be interpreted as shape (<see langword="true"/>) or opacity (<see langword="false"/>) values?
|
||||
/// </summary>
|
||||
public bool AlphaSource { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Maps positions from user coordinates to device coordinates.
|
||||
/// </summary>
|
||||
public TransformationMatrix CurrentTransformationMatrix { get; set; } = TransformationMatrix.Default;
|
||||
|
||||
#region Device Dependent
|
||||
|
||||
/// <summary>
|
||||
/// Should painting in a colorant set erase (<see langword="false"/>)
|
||||
/// or leave unchanged (<see langword="true"/>) areas of other colorant sets?
|
||||
/// </summary>
|
||||
public bool Overprint { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// As for <see cref="Overprint"/> but with non-stroking operations.
|
||||
/// </summary>
|
||||
public bool NonStrokingOverprint { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// In DeviceCMYK color space a value of 0 for a component will erase a component (0)
|
||||
/// or leave it unchanged (1) for overprinting.
|
||||
/// </summary>
|
||||
public decimal OverprintMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The precision for rendering curves, smaller numbers give smoother curves.
|
||||
/// </summary>
|
||||
public decimal Flatness { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The precision for rendering color gradients on the output device.
|
||||
/// </summary>
|
||||
public decimal Smoothness { get; set; } = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
public CurrentGraphicsState DeepClone()
|
||||
{
|
||||
return new CurrentGraphicsState
|
||||
{
|
||||
FontState = FontState.DeepClone(),
|
||||
RenderingIntent = RenderingIntent
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal interface IOperationContext
|
||||
{
|
||||
CurrentGraphicsState GetCurrentState();
|
||||
|
||||
TextMatrices TextMatrices { get; }
|
||||
|
||||
int StackSize { get; }
|
||||
|
||||
void PopState();
|
||||
|
||||
void PushState();
|
||||
}
|
||||
|
||||
internal class TextMatrices
|
||||
{
|
||||
public TransformationMatrix TextMatrix { get; set; }
|
||||
|
||||
public TransformationMatrix TextLineMatrix { get; set; }
|
||||
}
|
||||
|
||||
internal class ContentStreamProcessor : IOperationContext
|
||||
{
|
||||
private readonly Stack<CurrentGraphicsState> graphicsStack = new Stack<CurrentGraphicsState>();
|
||||
|
||||
public TextMatrices TextMatrices { get; private set; } = new TextMatrices();
|
||||
|
||||
public int StackSize => graphicsStack.Count;
|
||||
|
||||
|
||||
public ContentStreamProcessor(PdfRectangle cropBox)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Process(IReadOnlyList<IGraphicsStateOperation> operations)
|
||||
{
|
||||
var currentState = CloneAllStates();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void ProcessOperations(IReadOnlyList<IGraphicsStateOperation> operations)
|
||||
{
|
||||
foreach (var stateOperation in operations)
|
||||
{
|
||||
// stateOperation.Run();
|
||||
}
|
||||
}
|
||||
|
||||
private Stack<CurrentGraphicsState> CloneAllStates()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public CurrentGraphicsState GetCurrentState()
|
||||
{
|
||||
return graphicsStack.Peek();
|
||||
}
|
||||
|
||||
public void PopState()
|
||||
{
|
||||
graphicsStack.Pop();
|
||||
}
|
||||
|
||||
public void PushState()
|
||||
{
|
||||
graphicsStack.Push(graphicsStack.Peek().DeepClone());
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/UglyToad.Pdf/Graphics/LineCapStyle.cs
Normal file
9
src/UglyToad.Pdf/Graphics/LineCapStyle.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
internal enum LineCapStyle
|
||||
{
|
||||
Butt = 0,
|
||||
Round = 1,
|
||||
ProjectingSquare = 2
|
||||
}
|
||||
}
|
||||
20
src/UglyToad.Pdf/Graphics/LineDashPattern.cs
Normal file
20
src/UglyToad.Pdf/Graphics/LineDashPattern.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
using System;
|
||||
|
||||
public struct LineDashPattern
|
||||
{
|
||||
public int Phase { get; }
|
||||
|
||||
public decimal[] Array { get; }
|
||||
|
||||
public LineDashPattern(int phase, decimal[] array)
|
||||
{
|
||||
Phase = phase;
|
||||
Array = array ?? throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
public static LineDashPattern Solid { get; }
|
||||
= new LineDashPattern(0, new decimal[0]);
|
||||
}
|
||||
}
|
||||
9
src/UglyToad.Pdf/Graphics/LineJoinStyle.cs
Normal file
9
src/UglyToad.Pdf/Graphics/LineJoinStyle.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
internal enum LineJoinStyle
|
||||
{
|
||||
Miter = 0,
|
||||
Round = 1,
|
||||
Bevel = 2
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
{
|
||||
internal class BeginText : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "BT";
|
||||
public static readonly BeginText Value = new BeginText();
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
private BeginText()
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.ClippingPaths
|
||||
{
|
||||
internal class ModifyClippingByNonZeroWindingIntersect : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
{
|
||||
internal class EndText : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "q";
|
||||
public static readonly EndText Value = new EndText();
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
private EndText()
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.General
|
||||
{
|
||||
internal class SetColorRenderingIntent : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.General
|
||||
{
|
||||
internal class SetFlatnessTolerance : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.General
|
||||
{
|
||||
using System;
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
public Style Cap { get; set; }
|
||||
public LineCapStyle Cap { get; set; }
|
||||
|
||||
public SetLineCap(int cap) : this((Style)cap) { }
|
||||
public SetLineCap(Style cap)
|
||||
public SetLineCap(int cap) : this((LineCapStyle)cap) { }
|
||||
public SetLineCap(LineCapStyle cap)
|
||||
{
|
||||
if (cap < 0 || (int)cap > 2)
|
||||
{
|
||||
@@ -25,12 +25,5 @@
|
||||
{
|
||||
return $"{(int) Cap} {Symbol}";
|
||||
}
|
||||
|
||||
public enum Style
|
||||
{
|
||||
Butt = 0,
|
||||
Round = 1,
|
||||
ProjectingSquare = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations.General
|
||||
{
|
||||
internal class SetLineDashPattern : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "d";
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
public LineDashPattern Pattern { get; }
|
||||
|
||||
|
||||
public SetLineDashPattern(decimal[] array, int phase)
|
||||
{
|
||||
Pattern = new LineDashPattern(phase, array);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Pattern.Array} {Pattern.Phase} {Symbol}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.General
|
||||
{
|
||||
using System;
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
public Style Join { get; set; }
|
||||
public LineJoinStyle Join { get; set; }
|
||||
|
||||
public SetLineJoin(int join) : this((Style)join) { }
|
||||
public SetLineJoin(Style join)
|
||||
public SetLineJoin(int join) : this((LineJoinStyle)join) { }
|
||||
public SetLineJoin(LineJoinStyle join)
|
||||
{
|
||||
if (join < 0 || (int)join > 2)
|
||||
{
|
||||
@@ -25,12 +25,5 @@
|
||||
{
|
||||
return $"{(int)Join} {Symbol}";
|
||||
}
|
||||
|
||||
public enum Style
|
||||
{
|
||||
Miter = 0,
|
||||
Round = 1,
|
||||
Bevel = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.General
|
||||
{
|
||||
using Content;
|
||||
|
||||
internal class SetLineWidth : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "w";
|
||||
@@ -13,6 +15,12 @@
|
||||
Width = width;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
currentState.LineWidth = Width;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Width} {Symbol}";
|
||||
@@ -1,5 +1,7 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.General
|
||||
{
|
||||
using Content;
|
||||
|
||||
internal class SetMiterLimit : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "M";
|
||||
@@ -12,6 +14,13 @@
|
||||
{
|
||||
Limit = limit;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
{
|
||||
var currentState = operationContext.GetCurrentState();
|
||||
|
||||
currentState.MiterLimit = Limit;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using Geometry;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using Geometry;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using Geometry;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using Geometry;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using Geometry;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.PathConstruction
|
||||
{
|
||||
using Geometry;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.PathConstruction
|
||||
{
|
||||
internal class CloseSubpath : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,19 +0,0 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
{
|
||||
internal class Pop : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "Q";
|
||||
public static readonly Pop Value = new Pop();
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
private Pop()
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
{
|
||||
internal class SetLineDashPattern : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "d";
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
public decimal[] Array { get; }
|
||||
|
||||
public decimal Phase { get; }
|
||||
|
||||
public SetLineDashPattern(decimal[] array, decimal phase)
|
||||
{
|
||||
Array = array;
|
||||
Phase = phase;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Array} {Phase} {Symbol}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.SpecialGraphicsState
|
||||
{
|
||||
using System;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations.SpecialGraphicsState
|
||||
{
|
||||
using System;
|
||||
using Content;
|
||||
|
||||
internal class Pop : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "Q";
|
||||
public static readonly Pop Value = new Pop();
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
private Pop()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
{
|
||||
var currentStackSize = operationContext.StackSize;
|
||||
if (currentStackSize > 1)
|
||||
{
|
||||
operationContext.PopState();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot execute a pop of the graphics state stack, it would leave the stack empty.");
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.SpecialGraphicsState
|
||||
{
|
||||
using Content;
|
||||
|
||||
internal class Push : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "q";
|
||||
@@ -15,5 +17,10 @@
|
||||
{
|
||||
return Symbol;
|
||||
}
|
||||
|
||||
public void Run(IOperationContext context, IResourceStore resourceStore)
|
||||
{
|
||||
context.PushState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextObjects
|
||||
{
|
||||
using Content;
|
||||
using Core;
|
||||
|
||||
internal class BeginText : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "BT";
|
||||
public static readonly BeginText Value = new BeginText();
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
private BeginText()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
{
|
||||
operationContext.TextMatrices.TextMatrix = TransformationMatrix.Default;
|
||||
operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Default;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/UglyToad.Pdf/Graphics/Operations/TextObjects/EndText.cs
Normal file
28
src/UglyToad.Pdf/Graphics/Operations/TextObjects/EndText.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextObjects
|
||||
{
|
||||
using Content;
|
||||
using Core;
|
||||
|
||||
internal class EndText : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "ET";
|
||||
public static readonly EndText Value = new EndText();
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
private EndText()
|
||||
{
|
||||
}
|
||||
|
||||
public void Run(IOperationContext operationContext, IResourceStore resourceStore)
|
||||
{
|
||||
operationContext.TextMatrices.TextMatrix = TransformationMatrix.Default;
|
||||
operationContext.TextMatrices.TextLineMatrix = TransformationMatrix.Default;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextPositioning
|
||||
{
|
||||
internal class MoveToNextLine : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextPositioning
|
||||
{
|
||||
internal class MoveToNextLineWithOffset : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextPositioning
|
||||
{
|
||||
internal class MoveToNextLineWithOffsetSetLeading : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextPositioning
|
||||
{
|
||||
using System;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextShowing
|
||||
{
|
||||
internal class MoveToNextLineShowString : IGraphicsStateOperation
|
||||
internal class MoveToNextLineShowText : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "'";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public string Text { get; }
|
||||
|
||||
public MoveToNextLineShowString(string text)
|
||||
public MoveToNextLineShowText(string text)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextShowing
|
||||
{
|
||||
internal class MoveToNextLineShowStringWithSpacing : IGraphicsStateOperation
|
||||
internal class MoveToNextLineShowTextWithSpacing : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "\"";
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
public string Text { get; }
|
||||
|
||||
public MoveToNextLineShowStringWithSpacing(decimal wordSpacing, decimal characterSpacing, string text)
|
||||
public MoveToNextLineShowTextWithSpacing(decimal wordSpacing, decimal characterSpacing, string text)
|
||||
{
|
||||
WordSpacing = wordSpacing;
|
||||
CharacterSpacing = characterSpacing;
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextShowing
|
||||
{
|
||||
internal class ShowString : IGraphicsStateOperation
|
||||
internal class ShowText : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "Tj";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public string Text { get; }
|
||||
|
||||
public ShowString(string text)
|
||||
public ShowText(string text)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextShowing
|
||||
{
|
||||
internal class ShowStringsWithPositioning : IGraphicsStateOperation
|
||||
internal class ShowTextsWithPositioning : IGraphicsStateOperation
|
||||
{
|
||||
public const string Symbol = "TJ";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
public object[] Array { get; }
|
||||
|
||||
public ShowStringsWithPositioning(object[] array)
|
||||
public ShowTextsWithPositioning(object[] array)
|
||||
{
|
||||
Array = array;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextState
|
||||
{
|
||||
internal class SetCharacterSpacing : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextState
|
||||
{
|
||||
using Cos;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextState
|
||||
{
|
||||
internal class SetHorizontalScaling : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextState
|
||||
{
|
||||
internal class SetTextLeading : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextState
|
||||
{
|
||||
internal class SetTextRenderingMode : IGraphicsStateOperation
|
||||
{
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
public string Operator => Symbol;
|
||||
|
||||
public int Mode { get; }
|
||||
public RenderingMode Mode { get; }
|
||||
|
||||
public SetTextRenderingMode(int mode)
|
||||
{
|
||||
Mode = mode;
|
||||
Mode = (RenderingMode)mode;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextState
|
||||
{
|
||||
internal class SetTextRise : IGraphicsStateOperation
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace UglyToad.Pdf.Graphics.Operations
|
||||
namespace UglyToad.Pdf.Graphics.Operations.TextState
|
||||
{
|
||||
internal class SetWordSpacing : IGraphicsStateOperation
|
||||
{
|
||||
44
src/UglyToad.Pdf/Graphics/RenderingIntent.cs
Normal file
44
src/UglyToad.Pdf/Graphics/RenderingIntent.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
internal enum RenderingIntent
|
||||
{
|
||||
/// <summary>
|
||||
/// No correction for the output medium's white point. Colors
|
||||
/// only represented relative to the light source.
|
||||
/// </summary>
|
||||
AbsoluteColorimetric = 0,
|
||||
/// <summary>
|
||||
/// Combines light source and output medium's white point.
|
||||
/// </summary>
|
||||
RelativeColorimetric = 1,
|
||||
/// <summary>
|
||||
/// Emphasises saturation rather than colorimetric accuracy.
|
||||
/// </summary>
|
||||
Saturation = 2,
|
||||
/// <summary>
|
||||
/// Modifies from colorimetric values to provide a "pleasing perceptual appearance".
|
||||
/// </summary>
|
||||
Perceptual = 3
|
||||
}
|
||||
|
||||
internal static class RenderingIntentExtensions
|
||||
{
|
||||
public static RenderingIntent ToRenderingIntent(this string s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case "AbsoluteColorimetric":
|
||||
return RenderingIntent.AbsoluteColorimetric;
|
||||
case "RelativeColorimetric":
|
||||
return RenderingIntent.RelativeColorimetric;
|
||||
case "Saturation":
|
||||
return RenderingIntent.Saturation;
|
||||
case "Perceptual":
|
||||
return RenderingIntent.Perceptual;
|
||||
default:
|
||||
// If the application does not recognise the name it uses RelativeColorimetric by default.
|
||||
return RenderingIntent.RelativeColorimetric;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/UglyToad.Pdf/Graphics/RenderingMode.cs
Normal file
44
src/UglyToad.Pdf/Graphics/RenderingMode.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
internal enum RenderingMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Fill text.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Corresponds to filling the entire letter region.
|
||||
/// </remarks>
|
||||
Fill = 0,
|
||||
/// <summary>
|
||||
/// Stroke text.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Corresponds to drawing the border/outline of the letter.
|
||||
/// </remarks>
|
||||
Stroke = 1,
|
||||
/// <summary>
|
||||
/// Fill then stroke text.
|
||||
/// </summary>
|
||||
FillThenStroke = 2,
|
||||
/// <summary>
|
||||
/// Neither fill nor stroke text thereby causing text to become invisible.
|
||||
/// </summary>
|
||||
Neither = 3,
|
||||
/// <summary>
|
||||
/// Fill the text and add to the clipping path.
|
||||
/// </summary>
|
||||
FillClip = 4,
|
||||
/// <summary>
|
||||
/// Stroke the text and add to the clipping path.
|
||||
/// </summary>
|
||||
StrokeClip = 5,
|
||||
/// <summary>
|
||||
/// Fill then stroke the text and then add to the clipping path.
|
||||
/// </summary>
|
||||
FillThenStrokeClip = 6,
|
||||
/// <summary>
|
||||
/// Neither fill nor stroke but add to the clipping path.
|
||||
/// </summary>
|
||||
NeitherClip = 7
|
||||
}
|
||||
}
|
||||
29
src/UglyToad.Pdf/Graphics/RenderingModeExtensions.cs
Normal file
29
src/UglyToad.Pdf/Graphics/RenderingModeExtensions.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace UglyToad.Pdf.Graphics
|
||||
{
|
||||
internal static class RenderingModeExtensions
|
||||
{
|
||||
public static bool IsFill(this RenderingMode mode)
|
||||
{
|
||||
return mode == RenderingMode.Fill
|
||||
|| mode == RenderingMode.FillThenStroke
|
||||
|| mode == RenderingMode.FillClip
|
||||
|| mode == RenderingMode.FillThenStrokeClip;
|
||||
}
|
||||
|
||||
public static bool IsStroke(this RenderingMode mode)
|
||||
{
|
||||
return mode == RenderingMode.Stroke
|
||||
|| mode == RenderingMode.FillThenStroke
|
||||
|| mode == RenderingMode.StrokeClip
|
||||
|| mode == RenderingMode.FillThenStrokeClip;
|
||||
}
|
||||
|
||||
public static bool IsClip(this RenderingMode mode)
|
||||
{
|
||||
return mode == RenderingMode.FillClip
|
||||
|| mode == RenderingMode.StrokeClip
|
||||
|| mode == RenderingMode.FillThenStrokeClip
|
||||
|| mode == RenderingMode.NeitherClip;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user