diff --git a/src/UglyToad.Pdf.Tests/Fonts/Parser/AdobeFontMetricsParserTests.cs b/src/UglyToad.Pdf.Tests/Fonts/Parser/AdobeFontMetricsParserTests.cs new file mode 100644 index 00000000..edaeb7ae --- /dev/null +++ b/src/UglyToad.Pdf.Tests/Fonts/Parser/AdobeFontMetricsParserTests.cs @@ -0,0 +1,83 @@ +namespace UglyToad.Pdf.Tests.Fonts.Parser +{ + using Pdf.Fonts.Parser; + using Xunit; + + public class AdobeFontMetricsParserTests + { + private const string CourierAfmSnippet = @" +StartFontMetrics 4.1 + +Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. + +Comment Creation Date: Thu May 1 17:27:09 1997 + +Comment UniqueID 43050 + +Comment VMusage 39754 50779 + +FontName Courier + +FullName Courier + +FamilyName Courier + +Weight Medium + +ItalicAngle 0 + +IsFixedPitch true + +CharacterSet ExtendedRoman + +FontBBox -23 -250 715 805 + +UnderlinePosition -100 + +UnderlineThickness 50 + +Version 003.000 + +Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. + +EncodingScheme AdobeStandardEncoding + +CapHeight 562 + +XHeight 426 + +Ascender 629 + +Descender -157 + +StdHW 51 + +StdVW 51 + +StartCharMetrics 315 + +C 32 ; WX 600 ; N space ; B 0 0 0 0 ; + +C 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ; + +C 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ; + +C 35 ; WX 600 ; N numbersign ; B 93 -32 507 639 ; + +C 36 ; WX 600 ; N dollar ; B 105 -126 496 662 ; + +C 37 ; WX 600 ; N percent ; B 81 -15 518 622 ;"; + + private readonly AdobeFontMetricsParser parser = new AdobeFontMetricsParser(); + + [Fact] + public void CanParseAfmFile() + { + var input = StringBytesTestConverter.Convert(CourierAfmSnippet, false); + + var metrics = parser.Parse(input.Bytes, false); + + Assert.NotNull(metrics); + } + } +} diff --git a/src/UglyToad.Pdf/Fonts/Parser/AdobeFontMetricsParser.cs b/src/UglyToad.Pdf/Fonts/Parser/AdobeFontMetricsParser.cs index 1d095051..c38a4563 100644 --- a/src/UglyToad.Pdf/Fonts/Parser/AdobeFontMetricsParser.cs +++ b/src/UglyToad.Pdf/Fonts/Parser/AdobeFontMetricsParser.cs @@ -1,11 +1,337 @@ namespace UglyToad.Pdf.Fonts.Parser { + using System; using IO; + using Tokenization.Scanner; + using Tokenization.Tokens; internal class AdobeFontMetricsParser : IAdobeFontMetricsParser { + /// + /// This is a comment in a AFM file. + /// + public const string Comment = "Comment"; + + /// + /// This is the constant used in the AFM file to start a font metrics item. + /// + public const string StartFontMetrics = "StartFontMetrics"; + + /// + /// This is the constant used in the AFM file to end a font metrics item. + /// + public const string EndFontMetrics = "EndFontMetrics"; + + /// + /// The font name. + /// + public const string FontName = "FontName"; + + /// + /// The full name. + /// + public const string FullName = "FullName"; + + /// + /// The family name. + /// + public const string FamilyName = "FamilyName"; + + /// + /// The weight. + /// + public const string Weight = "Weight"; + + /// + /// The bounding box. + /// + public const string FontBbox = "FontBBox"; + + /// + /// The version of the font. + /// + public const string Version = "Version"; + + /// + /// The notice. + /// + public const string Notice = "Notice"; + + /// + /// The encoding scheme. + /// + public const string EncodingScheme = "EncodingScheme"; + + /// + /// The mapping scheme. + /// + public const string MappingScheme = "MappingScheme"; + + /// + /// The escape character. + /// + public const string EscChar = "EscChar"; + + /// + /// The character set. + /// + public const string CharacterSet = "CharacterSet"; + + /// + /// The characters attribute. + /// + public const string Characters = "Characters"; + + /// + /// Whether this is a base font. + /// + public const string IsBaseFont = "IsBaseFont"; + + /// + /// The V Vector attribute. + /// + public const string VVector = "VVector"; + + /// + /// Whether V is fixed. + /// + public const string IsFixedV = "IsFixedV"; + + /// + /// The cap height. + /// + public const string CapHeight = "CapHeight"; + + /// + /// The X height. + /// + public const string XHeight = "XHeight"; + + /// + /// The ascender attribute. + /// + public const string Ascender = "Ascender"; + + /// + /// The descender attribute. + /// + public const string Descender = "Descender"; + + /// + /// The underline position. + /// + public const string UnderlinePosition = "UnderlinePosition"; + + /// + /// The underline thickness. + /// + public const string UnderlineThickness = "UnderlineThickness"; + + /// + /// The italic angle. + /// + public const string ItalicAngle = "ItalicAngle"; + + /// + /// The character width. + /// + public const string CharWidth = "CharWidth"; + + /// + /// Determines if fixed pitch. + /// + public const string IsFixedPitch = "IsFixedPitch"; + + /// + /// The start of the character metrics. + /// + public const string StartCharMetrics = "StartCharMetrics"; + + /// + /// The end of the character metrics. + /// + public const string EndCharMetrics = "EndCharMetrics"; + + /// + /// The character metrics c value. + /// + public const string CharmetricsC = "C"; + + /// + /// The character metrics value. + /// + public const string CharmetricsCh = "CH"; + + /// + /// The character metrics value. + /// + public const string CharmetricsWx = "WX"; + + /// + /// The character metrics value. + /// + public const string CharmetricsW0X = "W0X"; + + /// + /// The character metrics value. + /// + public const string CharmetricsW1X = "W1X"; + + /// + /// The character metrics value. + /// + public const string CharmetricsWy = "WY"; + + /// + /// The character metrics value. + /// + public const string CharmetricsW0Y = "W0Y"; + + /// + /// The character metrics value. + /// + public const string CharmetricsW1Y = "W1Y"; + + /// + /// The character metrics value. + /// + public const string CharmetricsW = "W"; + + /// + /// The character metrics value. + /// + public const string CharmetricsW0 = "W0"; + + /// + /// The character metrics value. + /// + public const string CharmetricsW1 = "W1"; + + /// + /// The character metrics value. + /// + public const string CharmetricsVv = "VV"; + + /// + /// The character metrics value. + /// + public const string CharmetricsN = "N"; + + /// + /// The character metrics value. + /// + public const string CharmetricsB = "B"; + + /// + /// The character metrics value. + /// + public const string CharmetricsL = "L"; + + /// + /// The character metrics value. + /// + public const string StdHw = "StdHW"; + + /// + /// The character metrics value. + /// + public const string StdVw = "StdVW"; + + /// + /// This is the start of the track kern data. + /// + public const string StartTrackKern = "StartTrackKern"; + + /// + /// This is the end of the track kern data. + /// + public const string EndTrackKern = "EndTrackKern"; + + /// + /// This is the start of the kern data. + /// + public const string StartKernData = "StartKernData"; + + /// + /// This is the end of the kern data. + /// + public const string EndKernData = "EndKernData"; + + /// + /// This is the start of the kern pairs data. + /// + public const string StartKernPairs = "StartKernPairs"; + + /// + /// This is the end of the kern pairs data. + /// + public const string EndKernPairs = "EndKernPairs"; + + /// + /// This is the start of the kern pairs data. + /// + public const string StartKernPairs0 = "StartKernPairs0"; + + /// + /// This is the start of the kern pairs data. + /// + public const string StartKernPairs1 = "StartKernPairs1"; + + /// + /// This is the start of the composite data section. + /// + public const string StartComposites = "StartComposites"; + + /// + /// This is the end of the composite data section. + /// + public const string EndComposites = "EndComposites"; + + /// + /// This is a composite character. + /// + public const string Cc = "CC"; + + /// + /// This is a composite character part. + /// + public const string Pcc = "PCC"; + + /// + /// This is a kern pair. + /// + public const string KernPairKp = "KP"; + + /// + /// This is a kern pair. + /// + public const string KernPairKph = "KPH"; + + /// + /// This is a kern pair. + /// + public const string KernPairKpx = "KPX"; + + public const string KernPairKpy = "KPY"; + public FontMetrics Parse(IInputBytes bytes, bool useReducedDataSet) { + var tokenizer = new CoreTokenScanner(bytes); + + tokenizer.MoveNext(); + + var current = tokenizer.CurrentToken; + + if (!(current is OperatorToken operatorToken) || operatorToken.Data != StartFontMetrics) + { + throw new InvalidOperationException($"The font metrics file started with {current} rather than {StartFontMetrics}."); + } + + while (tokenizer.MoveNext()) + { + + } + return new FontMetrics(); } }