mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-14 19:05:01 +08:00
more tidy up of api for type 1 fonts
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
using Tokenization.Tokens;
|
||||
using Type1;
|
||||
using Type1.Parser;
|
||||
using Util;
|
||||
|
||||
internal class Type1FontHandler : IFontHandler
|
||||
{
|
||||
|
@@ -8,18 +8,52 @@
|
||||
|
||||
internal class Type1CharStrings
|
||||
{
|
||||
private readonly object locker = new object();
|
||||
private readonly Dictionary<string, CommandSequence> charStrings = new Dictionary<string, CommandSequence>();
|
||||
|
||||
public IReadOnlyDictionary<string, CommandSequence> CharStrings { get; }
|
||||
|
||||
public IReadOnlyDictionary<int, CommandSequence> Subroutines { get; }
|
||||
|
||||
|
||||
public Type1CharStrings(IReadOnlyDictionary<string, CommandSequence> charStrings, IReadOnlyDictionary<int, CommandSequence> 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
|
||||
{
|
||||
/// <summary>
|
||||
/// The ordered list of numbers and commands for a Type 1 charstring or subroutine.
|
||||
/// </summary>
|
||||
public IReadOnlyList<DiscriminatedUnion<decimal, LazyType1Command>> Commands { get; }
|
||||
|
||||
public CommandSequence(IReadOnlyList<DiscriminatedUnion<decimal, LazyType1Command>> commands)
|
||||
|
@@ -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<byte> Parse(IReadOnlyList<byte> bytes, bool isLenientParsing)
|
||||
public (Type1PrivateDictionary, Type1CharStrings) Parse(IReadOnlyList<byte> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -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<int, string> encoding, ArrayToken fontMatrix, PdfRectangle boundingBox)
|
||||
public Type1PrivateDictionary PrivateDictionary { get; }
|
||||
|
||||
public Type1Font(string name, IReadOnlyDictionary<int, string> encoding, ArrayToken fontMatrix, PdfRectangle boundingBox,
|
||||
Type1PrivateDictionary privateDictionary)
|
||||
{
|
||||
Name = name;
|
||||
Encoding = encoding;
|
||||
FontMatrix = fontMatrix;
|
||||
BoundingBox = boundingBox;
|
||||
PrivateDictionary = privateDictionary ?? throw new ArgumentNullException(nameof(privateDictionary));
|
||||
}
|
||||
}
|
||||
}
|
@@ -321,6 +321,15 @@
|
||||
/// <see cref="Type1PrivateDictionary.ExpansionFactor"/>.
|
||||
/// </summary>
|
||||
public decimal? ExpansionFactor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Generate a <see cref="Type1PrivateDictionary"/> from the values in this builder.
|
||||
/// </summary>
|
||||
/// <returns>The generated <see cref="Type1PrivateDictionary"/>.</returns>
|
||||
public Type1PrivateDictionary Build()
|
||||
{
|
||||
return new Type1PrivateDictionary(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user