From ab9de799f91e47ef1d59086ab3733ecf56d952c9 Mon Sep 17 00:00:00 2001 From: Eliot Jones Date: Thu, 1 Nov 2018 22:26:10 +0000 Subject: [PATCH] more tidy up of api for type 1 fonts --- .../Fonts/Parser/Handlers/Type1FontHandler.cs | 1 - .../Type1/CharStrings/Type1CharStrings.cs | 36 ++++++++++++++++++- .../Parser/Type1EncryptedPortionParser.cs | 23 ++++++------ .../Fonts/Type1/Parser/Type1FontParser.cs | 4 +-- src/UglyToad.PdfPig/Fonts/Type1/Type1Font.cs | 8 +++-- .../Fonts/Type1/Type1PrivateDictionary.cs | 9 +++++ 6 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/UglyToad.PdfPig/Fonts/Parser/Handlers/Type1FontHandler.cs b/src/UglyToad.PdfPig/Fonts/Parser/Handlers/Type1FontHandler.cs index 59c93414..711f9677 100644 --- a/src/UglyToad.PdfPig/Fonts/Parser/Handlers/Type1FontHandler.cs +++ b/src/UglyToad.PdfPig/Fonts/Parser/Handlers/Type1FontHandler.cs @@ -13,7 +13,6 @@ using Tokenization.Tokens; using Type1; using Type1.Parser; - using Util; internal class Type1FontHandler : IFontHandler { diff --git a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Type1CharStrings.cs b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Type1CharStrings.cs index f27ff52d..2b0a4eb9 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Type1CharStrings.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/CharStrings/Type1CharStrings.cs @@ -8,18 +8,52 @@ internal class Type1CharStrings { + private readonly object locker = new object(); + private readonly Dictionary charStrings = new Dictionary(); + public IReadOnlyDictionary CharStrings { get; } public IReadOnlyDictionary Subroutines { get; } - + public Type1CharStrings(IReadOnlyDictionary charStrings, IReadOnlyDictionary subroutines) { CharStrings = charStrings ?? throw new ArgumentNullException(nameof(charStrings)); Subroutines = subroutines ?? throw new ArgumentNullException(nameof(subroutines)); } + public void Generate(string name) + { + lock (locker) + { + if (charStrings.TryGetValue(name, out var result)) + { + return; + } + } + + if (!CharStrings.TryGetValue(name, out var sequence)) + { + throw new InvalidOperationException($"No charstring sequence with the name /{name} in this font."); + } + + Run(sequence); + + lock (locker) + { + charStrings[name] = sequence; + } + } + + private void Run(CommandSequence sequence) + { + + } + public class CommandSequence { + /// + /// The ordered list of numbers and commands for a Type 1 charstring or subroutine. + /// public IReadOnlyList> Commands { get; } public CommandSequence(IReadOnlyList> commands) diff --git a/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1EncryptedPortionParser.cs b/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1EncryptedPortionParser.cs index 880591d0..9579fa43 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1EncryptedPortionParser.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1EncryptedPortionParser.cs @@ -7,7 +7,6 @@ using IO; using PdfPig.Parser.Parts; using Tokenization.Tokens; - using Util; internal class Type1EncryptedPortionParser { @@ -17,7 +16,7 @@ private const int Password = 5839; private const int CharstringEncryptionKey = 4330; - public IReadOnlyList Parse(IReadOnlyList bytes, bool isLenientParsing) + public (Type1PrivateDictionary, Type1CharStrings) Parse(IReadOnlyList bytes, bool isLenientParsing) { if (!IsBinary(bytes)) { @@ -25,11 +24,9 @@ } var decrypted = Decrypt(bytes, EexecEncryptionKey, EexecRandomBytes); - - // line 461 of type1parser.java - var str = OtherEncodings.BytesAsLatin1String(decrypted.ToArray()); - + var tokenizer = new Type1Tokenizer(new ByteArrayInputBytes(decrypted)); + /* * After 4 random characters follows the /Private dictionary and the /CharString dictionary. * The first defines a number of technical terms involving character construction, and contains also an array of subroutines used in character paths. @@ -54,8 +51,8 @@ var length = next.AsInt(); ReadExpected(tokenizer, Type1Token.TokenType.Name, "dict"); - // actually could also be "/Private 10 dict def Private begin" - // instead of the "dup" + + // Could also be "/Private 10 dict def Private begin" instead of the "dup" ReadExpectedAfterOptional(tokenizer, Type1Token.TokenType.Name, "def", Type1Token.TokenType.Name, "dup"); ReadExpected(tokenizer, Type1Token.TokenType.Name, "begin"); @@ -85,6 +82,7 @@ case Type1Symbols.RdProcedureAlt: { var procedureTokens = ReadProcedure(tokenizer); + builder.Rd = procedureTokens; ReadTillDef(tokenizer); break; } @@ -92,6 +90,7 @@ case Type1Symbols.NoAccessDefAlt: { var procedureTokens = ReadProcedure(tokenizer); + builder.NoAccessDef = procedureTokens; ReadTillDef(tokenizer); break; } @@ -99,6 +98,7 @@ case Type1Symbols.NoAccessPutAlt: { var procedureTokens = ReadProcedure(tokenizer); + builder.NoAccessPut = procedureTokens; ReadTillDef(tokenizer); break; } @@ -290,14 +290,15 @@ charStrings = new Type1CharstringDecryptedBytes[0]; } + var privateDictionary = builder.Build(); + var instructions = Type1CharStringParser.Parse(charStrings, builder.Subroutines ?? new Type1CharstringDecryptedBytes[0]); - return decrypted; + return (privateDictionary, instructions); } /// - /// To distinguish between binary and hex the first 4 bytes (of the ciphertext) for hex must - /// obey these restrictions: + /// To distinguish between binary and hex the first 4 bytes (of the ciphertext) for hex must obey these restrictions: /// The first byte must not be whitespace. /// One of the first four ciphertext bytes must not be an ASCII hex character. /// diff --git a/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs b/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs index e7b0b02b..de518295 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs @@ -146,9 +146,9 @@ var matrix = GetFontMatrix(dictionaries); var boundingBox = GetBoundingBox(dictionaries); - var binaryPortion = encryptedPortionParser.Parse(eexecPortion, false); + var (privateDictionary, charStrings) = encryptedPortionParser.Parse(eexecPortion, false); - return new Type1Font(name, encoding, matrix, boundingBox ?? new PdfRectangle()); + return new Type1Font(name, encoding, matrix, boundingBox ?? new PdfRectangle(), privateDictionary); } /// diff --git a/src/UglyToad.PdfPig/Fonts/Type1/Type1Font.cs b/src/UglyToad.PdfPig/Fonts/Type1/Type1Font.cs index 91de85dd..716621f4 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/Type1Font.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/Type1Font.cs @@ -1,7 +1,7 @@ namespace UglyToad.PdfPig.Fonts.Type1 { + using System; using System.Collections.Generic; - using Cos; using Geometry; using Tokenization.Tokens; using Util.JetBrains.Annotations; @@ -21,12 +21,16 @@ [CanBeNull] public PdfRectangle BoundingBox { get; } - public Type1Font(string name, IReadOnlyDictionary encoding, ArrayToken fontMatrix, PdfRectangle boundingBox) + public Type1PrivateDictionary PrivateDictionary { get; } + + public Type1Font(string name, IReadOnlyDictionary encoding, ArrayToken fontMatrix, PdfRectangle boundingBox, + Type1PrivateDictionary privateDictionary) { Name = name; Encoding = encoding; FontMatrix = fontMatrix; BoundingBox = boundingBox; + PrivateDictionary = privateDictionary ?? throw new ArgumentNullException(nameof(privateDictionary)); } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Fonts/Type1/Type1PrivateDictionary.cs b/src/UglyToad.PdfPig/Fonts/Type1/Type1PrivateDictionary.cs index dd27b3d0..bfcc2e09 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/Type1PrivateDictionary.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/Type1PrivateDictionary.cs @@ -321,6 +321,15 @@ /// . /// public decimal? ExpansionFactor { get; set; } + + /// + /// Generate a from the values in this builder. + /// + /// The generated . + public Type1PrivateDictionary Build() + { + return new Type1PrivateDictionary(this); + } } } }