From b477b3b56028dea25758fdca630a73b78bc7fe1f Mon Sep 17 00:00:00 2001 From: Eliot Jones Date: Tue, 13 Nov 2018 22:22:24 +0000 Subject: [PATCH] implement more type 1 commands to modify the context --- .../Fonts/Type1/CharStrings/CharacterPath.cs | 10 ++++++ .../Arithmetic/CallOtherSubrCommand.cs | 31 ++++++++++++++++--- .../Commands/Arithmetic/ReturnCommand.cs | 2 +- .../Arithmetic/SetCurrentPointCommand.cs | 4 +++ .../Commands/Hint/DotSectionCommand.cs | 1 + .../Commands/Hint/HStem3Command.cs | 5 ++- .../CharStrings/Commands/Hint/HStemCommand.cs | 5 ++- .../Commands/Hint/VStem3Command.cs | 5 ++- .../CharStrings/Commands/Hint/VStemCommand.cs | 5 ++- .../CharStrings/Commands/LazyType1Command.cs | 10 ++++++ .../PathConstruction/HMoveToCommand.cs | 15 +++++++++ .../PathConstruction/HvCurveToCommand.cs | 22 ++++++++++--- .../PathConstruction/VMoveToCommand.cs | 15 +++++++++ .../PathConstruction/VhCurveToCommand.cs | 22 ++++++++++--- .../StartFinishOutline/HsbwCommand.cs | 4 +-- .../Commands/StartFinishOutline/SbwCommand.cs | 10 ++++++ .../StartFinishOutline/SeacCommand.cs | 8 +++++ .../Commands/Type1BuildCharContext.cs | 26 ++++++++++++++-- src/UglyToad.PdfPig/UglyToad.PdfPig.csproj | 4 --- 19 files changed, 178 insertions(+), 26 deletions(-) diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/CharacterPath.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/CharacterPath.cs index 68ab535d..0e293a85 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/CharacterPath.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/CharacterPath.cs @@ -53,6 +53,11 @@ commands.Add(new Close()); } + public PdfRectangle GetBoundingRectangle() + { + return new PdfRectangle(); + } + public string ToSvg() { var builder = new StringBuilder(); @@ -61,6 +66,11 @@ pathCommand.WriteSvg(builder); } + if (builder.Length == 0) + { + return string.Empty; + } + if (builder[builder.Length - 1] == ' ') { builder.Remove(builder.Length - 1, 1); diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/CallOtherSubrCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/CallOtherSubrCommand.cs index 89654d8d..bb816108 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/CallOtherSubrCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/CallOtherSubrCommand.cs @@ -1,5 +1,6 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Arithmetic { + using System; using System.Collections.Generic; /// @@ -21,12 +22,32 @@ public static void Run(Type1BuildCharContext context) { - var index = (int)context.Stack.PopTop(); - var numberOfArguments = (int)context.Stack.PopTop(); - var otherSubroutineArguments = new List(numberOfArguments); - for (int j = 0; j < numberOfArguments; j++) + var index = (int) context.Stack.PopTop(); + + // What it should do + //var numberOfArguments = (int)context.Stack.PopTop(); + //var otherSubroutineArguments = new List(numberOfArguments); + //for (int j = 0; j < numberOfArguments; j++) + //{ + // otherSubroutineArguments.Add(context.Stack.PopTop()); + //} + + switch (index) { - otherSubroutineArguments.Add(context.Stack.PopTop()); + case 0: + { + context.IsFlexing = false; + if (context.FlexPoints.Count < 7) + { + throw new NotSupportedException("There must be at least 7 flex points defined by an other subroutine."); + } + + context.ClearFlexPoints(); + break; + } + case 1: + context.IsFlexing = true; + break; } } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/ReturnCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/ReturnCommand.cs index c1b0f94c..7033be68 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/ReturnCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/ReturnCommand.cs @@ -17,7 +17,7 @@ public static void Run(Type1BuildCharContext context) { - + // Do nothing } } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/SetCurrentPointCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/SetCurrentPointCommand.cs index 9f25dac7..56607c2c 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/SetCurrentPointCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Arithmetic/SetCurrentPointCommand.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Arithmetic { + using Geometry; + /// /// Sets the current point to (x, y) in absolute character space coordinates without performing a charstring moveto command. /// @@ -20,6 +22,8 @@ var x = context.Stack.PopBottom(); var y = context.Stack.PopBottom(); + context.CurrentPosition = new PdfPoint(x, y); + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/DotSectionCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/DotSectionCommand.cs index 67fc47ad..8c034cb4 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/DotSectionCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/DotSectionCommand.cs @@ -17,6 +17,7 @@ public static void Run(Type1BuildCharContext context) { + // Ignored. context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStem3Command.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStem3Command.cs index 8cef1dab..52c721e0 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStem3Command.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStem3Command.cs @@ -1,4 +1,5 @@ -namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint +// ReSharper disable UnusedVariable +namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint { /// /// Declares the vertical ranges of three horizontal stem zones: @@ -31,6 +32,8 @@ var y2 = context.Stack.PopBottom(); var dy2 = context.Stack.PopBottom(); + // Ignored + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStemCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStemCommand.cs index f2898c93..62eca87b 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStemCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/HStemCommand.cs @@ -1,4 +1,5 @@ -namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint +// ReSharper disable UnusedVariable +namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint { /// /// Declares the vertical range of a horizontal stem zone between the y coordinates y and y+dy, @@ -21,6 +22,8 @@ var y = context.Stack.PopBottom(); var dy = context.Stack.PopBottom(); + // Ignored + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStem3Command.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStem3Command.cs index b2bcb1cf..67fed29a 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStem3Command.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStem3Command.cs @@ -1,4 +1,5 @@ -namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint +// ReSharper disable UnusedVariable +namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint { /// /// Declares the horizontal ranges of three vertical stem zones. @@ -31,6 +32,8 @@ var x2 = context.Stack.PopBottom(); var dx2 = context.Stack.PopBottom(); + // Ignored + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStemCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStemCommand.cs index 237a7e2e..94df5b3a 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStemCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Hint/VStemCommand.cs @@ -1,4 +1,5 @@ -namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint +// ReSharper disable UnusedVariable +namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.Hint { /// /// Declares the horizontal range of a vertical stem zone between the x coordinates x and x+dx, @@ -21,6 +22,8 @@ var x = context.Stack.PopBottom(); var dx = context.Stack.PopBottom(); + // Ignored + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/LazyType1Command.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/LazyType1Command.cs index 71847e5c..c5843800 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/LazyType1Command.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/LazyType1Command.cs @@ -36,6 +36,11 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands public decimal PopTop() { + if (stack.Count == 0) + { + throw new InvalidOperationException("Cannot pop from the top of an empty stack, invalid charstring parsed."); + } + var result = stack[stack.Count - 1]; stack.RemoveAt(stack.Count - 1); return result; @@ -43,6 +48,11 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands public decimal PopBottom() { + if (stack.Count == 0) + { + throw new InvalidOperationException("Cannot pop from the bottom of an empty stack, invalid charstring parsed."); + } + var result = stack[0]; stack.RemoveAt(0); return result; diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HMoveToCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HMoveToCommand.cs index ebb5f8d4..e50f9f8d 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HMoveToCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HMoveToCommand.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.PathConstruction { + using Geometry; + /// /// Relative move to for horizontal dimension only. /// @@ -19,6 +21,19 @@ { var x = context.Stack.PopBottom(); + var actualX = context.CurrentPosition.X + x; + var y = context.CurrentPosition.Y; + + if (context.IsFlexing) + { + // TODO: flex support + } + else + { + context.CurrentPosition = new PdfPoint(actualX, y); + context.Path.MoveTo(actualX, y); + } + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HvCurveToCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HvCurveToCommand.cs index 8367e377..24bdb297 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HvCurveToCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/HvCurveToCommand.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.PathConstruction { + using Geometry; + /// /// Horizontal vertical curve to command. Draws a Bézier curve when the first Bézier tangent is horizontal and the second Bézier tangent is vertical. /// Equivalent to dx1 0 dx2 dy2 0 dy3 rrcurveto. @@ -18,10 +20,22 @@ public static void Run(Type1BuildCharContext context) { - var postControlPointDeltaX = context.Stack.PopBottom(); - var preControlPointDeltaX = context.Stack.PopBottom(); - var preControlPointDeltaY = context.Stack.PopBottom(); - var endPointDeltaY = context.Stack.PopBottom(); + var dx1 = context.Stack.PopBottom(); + var dx2 = context.Stack.PopBottom(); + var dy2 = context.Stack.PopBottom(); + var dy3 = context.Stack.PopBottom(); + + var x1 = context.CurrentPosition.X + dx1; + var y1 = context.CurrentPosition.Y; + + var x2 = x1 + dx2; + var y2 = y1 + dy2; + + var x3 = x2; + var y3 = y2 + dy3; + + context.Path.BezierCurveTo(x1, y1, x2, y2, x3, y3); + context.CurrentPosition = new PdfPoint(x3, y3); context.Stack.Clear(); } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VMoveToCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VMoveToCommand.cs index 64344f4b..4964fdcd 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VMoveToCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VMoveToCommand.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.PathConstruction { + using Geometry; + /// /// Vertical move to. Moves relative to the current point. /// @@ -19,6 +21,19 @@ { var deltaY = context.Stack.PopBottom(); + if (context.IsFlexing) + { + // TODO: flex commands + } + else + { + var y = context.CurrentPosition.Y + deltaY; + var x = context.CurrentPosition.X; + + context.CurrentPosition = new PdfPoint(x, y); + context.Path.MoveTo(x, y); + } + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VhCurveToCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VhCurveToCommand.cs index 7a712506..1c08615e 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VhCurveToCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/PathConstruction/VhCurveToCommand.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.PathConstruction { + using Geometry; + /// /// Vertical-horizontal curveto. /// Equivalent to 0 dy1 dx2 dy2 dx3 0 rrcurveto. @@ -19,10 +21,22 @@ public static void Run(Type1BuildCharContext context) { - var postControlPointDeltaY = context.Stack.PopBottom(); - var preControlPointDeltaX = context.Stack.PopBottom(); - var preControlPointDeltaY = context.Stack.PopBottom(); - var endPointDeltaX = context.Stack.PopBottom(); + var dy1 = context.Stack.PopBottom(); + var dx2 = context.Stack.PopBottom(); + var dy2 = context.Stack.PopBottom(); + var dx3 = context.Stack.PopBottom(); + + var x1 = context.CurrentPosition.X; + var y1 = context.CurrentPosition.Y + dy1; + + var x2 = x1 + dx2; + var y2 = y1 + dy2; + + var x3 = x2 + dx3; + var y3 = y2; + + context.Path.BezierCurveTo(x1, y1, x2, y2, x3, y3); + context.CurrentPosition = new PdfPoint(x3, y3); context.Stack.Clear(); } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/HsbwCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/HsbwCommand.cs index 9c8697eb..8837ebb0 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/HsbwCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/HsbwCommand.cs @@ -25,8 +25,8 @@ var leftSidebearingPointX = context.Stack.PopBottom(); var characterWidthVectorX = context.Stack.PopBottom(); - context.LeftSideBearing = leftSidebearingPointX; - context.Width = characterWidthVectorX; + context.LeftSideBearingX = leftSidebearingPointX; + context.WidthX = characterWidthVectorX; context.CurrentPosition = new PdfPoint(leftSidebearingPointX, 0); diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SbwCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SbwCommand.cs index 0a869681..106173d4 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SbwCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SbwCommand.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.StartFinishOutline { + using Geometry; + /// /// Sets left sidebearing and the character width vector. /// This command also sets the current point to(sbx, sby), but does not place the point in the character path. @@ -23,6 +25,14 @@ var characterWidthX = context.Stack.PopBottom(); var characterWidthY = context.Stack.PopBottom(); + context.LeftSideBearingX = leftSidebearingX; + context.LeftSideBearingY = leftSidebearingY; + + context.WidthX = characterWidthX; + context.WidthY = characterWidthY; + + context.CurrentPosition = new PdfPoint(leftSidebearingX, leftSidebearingY); + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SeacCommand.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SeacCommand.cs index 18df53e8..899c684b 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SeacCommand.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/StartFinishOutline/SeacCommand.cs @@ -1,5 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands.StartFinishOutline { + using System; + /// /// Standard encoding accented character. /// Makes an accented character from two other characters in the font program. @@ -24,6 +26,12 @@ var baseCharacterCode = context.Stack.PopBottom(); var accentCharacterCode = context.Stack.PopBottom(); + var baseCharacter = context.GetCharacter((int)baseCharacterCode); + var accentCharacter = context.GetCharacter((int) accentCharacterCode); + + // TODO + throw new NotImplementedException("Not done yet..."); + context.Stack.Clear(); } } diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Type1BuildCharContext.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Type1BuildCharContext.cs index b03ba18a..04a93855 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Type1BuildCharContext.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Commands/Type1BuildCharContext.cs @@ -1,12 +1,17 @@ namespace UglyToad.PdfPig.Fonts.Type1.CharStrings.Commands { + using System.Collections.Generic; using Geometry; internal class Type1BuildCharContext { - public decimal Width { get; set; } + public decimal WidthX { get; set; } - public decimal LeftSideBearing { get; set; } + public decimal WidthY { get; set; } + + public decimal LeftSideBearingX { get; set; } + + public decimal LeftSideBearingY { get; set; } public bool IsFlexing { get; set; } @@ -17,5 +22,22 @@ public Type1Stack Stack { get; } = new Type1Stack(); public Type1Stack PostscriptStack { get; } = new Type1Stack(); + + public IReadOnlyList FlexPoints { get; } + + public void AddFlexPoint(PdfPoint point) + { + + } + + public CharacterPath GetCharacter(int characterCode) + { + return null; + } + + public void ClearFlexPoints() + { + + } } } diff --git a/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj b/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj index 7272a579..14382ee4 100644 --- a/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj +++ b/src/UglyToad.PdfPig/UglyToad.PdfPig.csproj @@ -36,9 +36,5 @@ - - - -