From 40dc80c28128931443df98fd1c2ec2e6c983f3aa Mon Sep 17 00:00:00 2001 From: Eliot Jones Date: Wed, 5 Feb 2020 10:46:39 +0000 Subject: [PATCH] handle type 1 font with no descriptor information #132 though required by the spec an adobe type 1 font may be missing all width data. in this case we default to empty values and treat it like a normal adobe type 1 font. --- .../Parser/Handlers/Type1FontHandler.cs | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs index 6b3c3d58..7bdc6386 100644 --- a/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs +++ b/src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type1FontHandler.cs @@ -23,8 +23,8 @@ private readonly FontDescriptorFactory fontDescriptorFactory; private readonly IEncodingReader encodingReader; - public Type1FontHandler(IPdfTokenScanner pdfScanner, IFilterProvider filterProvider, - FontDescriptorFactory fontDescriptorFactory, + public Type1FontHandler(IPdfTokenScanner pdfScanner, IFilterProvider filterProvider, + FontDescriptorFactory fontDescriptorFactory, IEncodingReader encodingReader) { this.pdfScanner = pdfScanner; @@ -40,7 +40,7 @@ if (usingStandard14Only) { // TODO: some fonts combine standard 14 font with other metrics. - if (!dictionary.TryGet(NameToken.BaseFont, out var baseFontToken) + if (!dictionary.TryGet(NameToken.BaseFont, out var baseFontToken) || !(baseFontToken is NameToken standard14Name)) { throw new InvalidFontFormatException($"The Type 1 font did not contain a first character entry but also did not reference a standard 14 font: {dictionary}"); @@ -48,20 +48,34 @@ var metrics = Standard14.GetAdobeFontMetrics(standard14Name.Data); - var overrideEncoding = encodingReader.Read(dictionary, isLenientParsing); + if (metrics != null) + { + var overrideEncoding = encodingReader.Read(dictionary, isLenientParsing); - return new Type1Standard14Font(metrics, overrideEncoding); + return new Type1Standard14Font(metrics, overrideEncoding); + } } - var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary); + int firstCharacter, lastCharacter; + double[] widths; + if (!usingStandard14Only) + { + firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary); - var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary); + lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary); - var widths = FontDictionaryAccessHelper.GetWidths(pdfScanner, dictionary, isLenientParsing); + widths = FontDictionaryAccessHelper.GetWidths(pdfScanner, dictionary, isLenientParsing); + } + else + { + firstCharacter = 0; + lastCharacter = 0; + widths = EmptyArray.Instance; + } if (!dictionary.TryGet(NameToken.FontDescriptor, out var _)) { - if (dictionary.TryGet(NameToken.BaseFont, out var baseFontToken) && + if (dictionary.TryGet(NameToken.BaseFont, out var baseFontToken) && DirectObjectFinder.TryGet(baseFontToken, pdfScanner, out NameToken baseFontName)) { var metrics = Standard14.GetAdobeFontMetrics(baseFontName.Data); @@ -77,7 +91,7 @@ var font = ParseFontProgram(descriptor, isLenientParsing); var name = FontDictionaryAccessHelper.GetName(pdfScanner, dictionary, descriptor, isLenientParsing); - + CMap toUnicodeCMap = null; if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj)) { @@ -105,7 +119,7 @@ if (encoding == null) { - font?.Match(x => encoding = new BuiltInEncoding(x.Encoding), _ => {}); + font?.Match(x => encoding = new BuiltInEncoding(x.Encoding), _ => { }); } return new Type1FontSimple(name, firstCharacter, lastCharacter, widths, descriptor, encoding, toUnicodeCMap, font); @@ -122,7 +136,7 @@ { return null; } - + try { if (!(pdfScanner.Get(descriptor.FontFile.ObjectKey.Data).Data is StreamToken stream)) @@ -139,10 +153,10 @@ var cffFont = CompactFontFormatParser.Parse(new CompactFontFormatData(bytes)); return Union.Two(cffFont); } - + var length1 = stream.StreamDictionary.Get(NameToken.Length1, pdfScanner); var length2 = stream.StreamDictionary.Get(NameToken.Length2, pdfScanner); - + var font = Type1FontParser.Parse(new ByteArrayInputBytes(bytes), length1.Int, length2.Int); return Union.One(font);