diff --git a/src/UglyToad.Pdf/Fonts/CidFonts/CharacterIdentifierFont.cs b/src/UglyToad.Pdf/Fonts/CidFonts/CharacterIdentifierFont.cs deleted file mode 100644 index fbf62c5f..00000000 --- a/src/UglyToad.Pdf/Fonts/CidFonts/CharacterIdentifierFont.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace UglyToad.Pdf.Fonts.CidFonts -{ - using Cmap; - using Cos; - - internal class CharacterIdentifierFont - { - public const int DefaultWidthWhenUndeclared = 1000; - - public CidFontType Subtype { get; } - - public CosName BaseFont { get; } - - public CharacterIdentifierSystemInfo SystemInfo { get; set; } - - public CosObjectKey FontDescriptor { get; set; } - - public int DefaultWidth { get; } - - public COSArray Widths { get; set; } - - public VerticalVectorComponents VerticalVectors { get; } = VerticalVectorComponents.Default; - - public CharacterIdentifierToGlyphIdentifierMap CidToGidMap { get; } - - public CharacterIdentifierFont(CidFontType subtype, CosName baseFont, CharacterIdentifierSystemInfo systemInfo, - CosObjectKey fontDescriptor, - int defaultWidth, - COSArray widths, - CharacterIdentifierToGlyphIdentifierMap cidToGidMap) - { - Subtype = subtype; - BaseFont = baseFont; - SystemInfo = systemInfo; - FontDescriptor = fontDescriptor; - DefaultWidth = defaultWidth; - Widths = widths; - CidToGidMap = cidToGidMap; - } - - - } -} \ No newline at end of file diff --git a/src/UglyToad.Pdf/Fonts/CidFonts/CharacterIdentifierFontBuilder.cs b/src/UglyToad.Pdf/Fonts/CidFonts/CharacterIdentifierFontBuilder.cs deleted file mode 100644 index 67683719..00000000 --- a/src/UglyToad.Pdf/Fonts/CidFonts/CharacterIdentifierFontBuilder.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace UglyToad.Pdf.Fonts.CidFonts -{ - using System; - using System.Collections.Generic; - using Cmap; - using Cos; - - internal class CharacterIdentifierFontBuilder - { - private static readonly IReadOnlyDictionary NameTypeMap = new Dictionary - { - { CosName.CID_FONT_TYPE0, CidFontType.Type0 }, - { CosName.CID_FONT_TYPE2, CidFontType.Type2 } - }; - - private readonly CidFontType subType; - private readonly CosName baseFont; - private int defaultWidth = CharacterIdentifierFont.DefaultWidthWhenUndeclared; - private readonly CharacterIdentifierSystemInfo systemInfo; - private readonly CosObjectKey fontDescriptorKey; - - public CharacterIdentifierFontBuilder(CosName subType, CosName baseFont, - CharacterIdentifierSystemInfo systemInfo, - CosObjectKey fontDescriptorKey) - { - if (!NameTypeMap.TryGetValue(subType, out var subTypeValue)) - { - throw new InvalidOperationException("The subType of the CIDFont was not valid: " + subType); - } - - this.subType = subTypeValue; - this.baseFont = baseFont; - this.systemInfo = systemInfo; - this.fontDescriptorKey = fontDescriptorKey; - } - - public void WithDefaultWidth(int width) - { - defaultWidth = width; - } - - public CharacterIdentifierFont Build() - { - return new CharacterIdentifierFont(subType, baseFont, systemInfo, fontDescriptorKey, defaultWidth, null, null); - } - } -} \ No newline at end of file diff --git a/src/UglyToad.Pdf/Fonts/CidFonts/Type2CidFont.cs b/src/UglyToad.Pdf/Fonts/CidFonts/Type2CidFont.cs index 38291454..59dde2f7 100644 --- a/src/UglyToad.Pdf/Fonts/CidFonts/Type2CidFont.cs +++ b/src/UglyToad.Pdf/Fonts/CidFonts/Type2CidFont.cs @@ -1,7 +1,7 @@ namespace UglyToad.Pdf.Fonts.CidFonts { + using System.Collections.Generic; using Cos; - using TrueType.Parser; /// /// @@ -10,7 +10,10 @@ /// internal class Type2CidFont : ICidFont { - private readonly TrueTypeFont fontProgram; + private readonly ICidFontProgram fontProgram; + private readonly VerticalWritingMetrics verticalWritingMetrics; + private readonly IReadOnlyDictionary widths; + public CosName Type { get; } public CosName SubType { get; } public CosName BaseFont { get; } @@ -18,7 +21,10 @@ public CidFontType CidFontType => CidFontType.Type2; public FontDescriptor Descriptor { get; } - public Type2CidFont(CosName type, CosName subType, CosName baseFont, CharacterIdentifierSystemInfo systemInfo, FontDescriptor descriptor, TrueTypeFont fontProgram) + public Type2CidFont(CosName type, CosName subType, CosName baseFont, CharacterIdentifierSystemInfo systemInfo, + FontDescriptor descriptor, ICidFontProgram fontProgram, + VerticalWritingMetrics verticalWritingMetrics, + IReadOnlyDictionary widths) { Type = type; SubType = subType; @@ -26,6 +32,8 @@ SystemInfo = systemInfo; Descriptor = descriptor; this.fontProgram = fontProgram; + this.verticalWritingMetrics = verticalWritingMetrics; + this.widths = widths; } } } \ No newline at end of file diff --git a/src/UglyToad.Pdf/Fonts/Parser/CharacterIdentifierFontParser.cs b/src/UglyToad.Pdf/Fonts/Parser/CharacterIdentifierFontParser.cs deleted file mode 100644 index 4fe32d4e..00000000 --- a/src/UglyToad.Pdf/Fonts/Parser/CharacterIdentifierFontParser.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace UglyToad.Pdf.Fonts.Parser -{ - using System; - using CidFonts; - using ContentStream; - using ContentStream.TypedAccessors; - using Cos; - - internal class CharacterIdentifierFontParser - { - public CharacterIdentifierFont Parse(PdfDictionary dictionary, bool isLenientParsing) - { - if (dictionary == null) - { - throw new ArgumentNullException(nameof(dictionary)); - } - - var isFont = dictionary.IsType(CosName.FONT); - - if (!isFont && !isLenientParsing) - { - throw new InvalidOperationException("The font dictionary was not of type 'Font': " + dictionary); - } - - var systemInfo = new CharacterIdentifierSystemInfo(null, null, 0); - - var builder = new CharacterIdentifierFontBuilder(dictionary.GetName(CosName.SUBTYPE), - dictionary.GetName(CosName.BASE_FONT), systemInfo, dictionary.GetObjectKey(CosName.FONT_DESC)); - - return builder.Build(); - } - } -} diff --git a/src/UglyToad.Pdf/Fonts/Parser/Handlers/Type0FontHandler.cs b/src/UglyToad.Pdf/Fonts/Parser/Handlers/Type0FontHandler.cs index 0dd61444..9ebfc28a 100644 --- a/src/UglyToad.Pdf/Fonts/Parser/Handlers/Type0FontHandler.cs +++ b/src/UglyToad.Pdf/Fonts/Parser/Handlers/Type0FontHandler.cs @@ -33,13 +33,15 @@ var cMap = ReadEncoding(dictionary, out var isCMapPredefined); + ICidFont cidFont; + if (TryGetFirstDescendant(dictionary, out var descendantObject)) { var parsed = pdfObjectParser.Parse(descendantObject.ToIndirectReference(), reader, isLenientParsing); if (parsed is PdfDictionary descendantFontDictionary) { - ParseDescendant(descendantFontDictionary, reader, isLenientParsing); + cidFont = ParseDescendant(descendantFontDictionary, reader, isLenientParsing); } else { @@ -68,7 +70,7 @@ } } - var font = new Type0Font(baseFont, new Type0CidFont(), cMap, toUnicodeCMap); + var font = new Type0Font(baseFont, cidFont, cMap, toUnicodeCMap); return font; } @@ -97,15 +99,17 @@ return false; } - private void ParseDescendant(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) + private ICidFont ParseDescendant(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) { var type = dictionary.GetName(CosName.TYPE); if (!CosName.FONT.Equals(type)) { - throw new InvalidOperationException($"Expected \'Font\' dictionary but found \'{type.Name}\'"); + throw new InvalidFontFormatException($"Expected \'Font\' dictionary but found \'{type.Name}\'"); } - cidFontFactory.Generate(dictionary, reader, isLenientParsing); + var result = cidFontFactory.Generate(dictionary, reader, isLenientParsing); + + return result; } private CMap ReadEncoding(PdfDictionary dictionary, out bool isCMapPredefined) diff --git a/src/UglyToad.Pdf/Fonts/Parser/Parts/CidFontFactory.cs b/src/UglyToad.Pdf/Fonts/Parser/Parts/CidFontFactory.cs index 9c28af20..c0e138ff 100644 --- a/src/UglyToad.Pdf/Fonts/Parser/Parts/CidFontFactory.cs +++ b/src/UglyToad.Pdf/Fonts/Parser/Parts/CidFontFactory.cs @@ -4,7 +4,9 @@ using System.Collections.Generic; using CidFonts; using ContentStream; + using ContentStream.TypedAccessors; using Cos; + using Exceptions; using Filters; using Geometry; using IO; @@ -34,7 +36,7 @@ var type = dictionary.GetName(CosName.TYPE); if (!CosName.FONT.Equals(type)) { - throw new InvalidOperationException($"Expected \'Font\' dictionary but found \'{type.Name}\'"); + throw new InvalidFontFormatException($"Expected \'Font\' dictionary but found \'{type.Name}\'"); } var widths = ReadWidths(dictionary); @@ -46,7 +48,11 @@ descriptor = descriptorFactory.Generate(descriptorDictionary, isLenientParsing); } - ReadDescriptorFile(descriptor, reader, isLenientParsing); + var fontProgram = ReadDescriptorFile(descriptor, reader, isLenientParsing); + + var baseFont = dictionary.GetName(CosName.BASE_FONT); + + var systemInfo = GetSystemInfo(dictionary); var subType = dictionary.GetName(CosName.SUBTYPE); if (CosName.CID_FONT_TYPE0.Equals(subType)) @@ -56,7 +62,7 @@ if (CosName.CID_FONT_TYPE2.Equals(subType)) { - //return new PDCIDFontType2(dictionary, parent); + return new Type2CidFont(type, subType, baseFont, systemInfo, descriptor, fontProgram, verticalWritingMetrics, widths); } return null; @@ -83,18 +89,18 @@ return true; } - private void ReadDescriptorFile(FontDescriptor descriptor, IRandomAccessRead reader, bool isLenientParsing) + private ICidFontProgram ReadDescriptorFile(FontDescriptor descriptor, IRandomAccessRead reader, bool isLenientParsing) { if (descriptor?.FontFile == null) { - return; + return null; } var fontFileStream = pdfObjectParser.Parse(descriptor.FontFile.ObjectKey, reader, isLenientParsing) as PdfRawStream; if (fontFileStream == null) { - return; + return null; } var fontFile = fontFileStream.Decode(filterProvider); @@ -103,8 +109,7 @@ { case DescriptorFontFile.FontFileType.TrueType: var input = new TrueTypeDataBytes(new ByteArrayInputBytes(fontFile)); - trueTypeFontParser.Parse(input); - break; + return trueTypeFontParser.Parse(input); default: throw new NotSupportedException("Currently only TrueType fonts are supported."); } @@ -211,5 +216,19 @@ return new VerticalWritingMetrics(dw2, verticalDisplacements, positionVectors); } + + private static CharacterIdentifierSystemInfo GetSystemInfo(PdfDictionary dictionary) + { + if(!dictionary.TryGetItemOfType(CosName.CIDSYSTEMINFO, out PdfDictionary cidDictionary)) + { + throw new InvalidFontFormatException($"No CID System Info was found in the CID Font dictionary: " + dictionary); + } + + var registry = (CosString) cidDictionary.GetItemOrDefault(CosName.REGISTRY); + var ordering = (CosString)cidDictionary.GetItemOrDefault(CosName.ORDERING); + var supplement = cidDictionary.GetIntOrDefault(CosName.SUPPLEMENT, 0); + + return new CharacterIdentifierSystemInfo(registry.GetAscii(), ordering.GetAscii(), supplement); + } } } diff --git a/src/UglyToad.Pdf/Fonts/TrueType/Parser/TrueTypeFont.cs b/src/UglyToad.Pdf/Fonts/TrueType/TrueTypeFont.cs similarity index 81% rename from src/UglyToad.Pdf/Fonts/TrueType/Parser/TrueTypeFont.cs rename to src/UglyToad.Pdf/Fonts/TrueType/TrueTypeFont.cs index 6e567851..8c4005b7 100644 --- a/src/UglyToad.Pdf/Fonts/TrueType/Parser/TrueTypeFont.cs +++ b/src/UglyToad.Pdf/Fonts/TrueType/TrueTypeFont.cs @@ -1,9 +1,10 @@ -namespace UglyToad.Pdf.Fonts.TrueType.Parser +namespace UglyToad.Pdf.Fonts.TrueType { using System.Collections.Generic; + using CidFonts; using Tables; - internal class TrueTypeFont + internal class TrueTypeFont : ICidFontProgram { public decimal Version { get; } diff --git a/src/UglyToad.Pdf/Parser/ObjectStreamParser.cs b/src/UglyToad.Pdf/Parser/ObjectStreamParser.cs index 4a9df069..4df2c988 100644 --- a/src/UglyToad.Pdf/Parser/ObjectStreamParser.cs +++ b/src/UglyToad.Pdf/Parser/ObjectStreamParser.cs @@ -38,6 +38,8 @@ var bytes = stream.Decode(filterProvider); + var text = UglyToad.Pdf.Util.OtherEncodings.BytesAsLatin1String(bytes); + var reader = new RandomAccessBuffer(bytes); for (int i = 0; i < numberOfObjects; i++) diff --git a/src/UglyToad.Pdf/Parser/Parts/CosStringParser.cs b/src/UglyToad.Pdf/Parser/Parts/CosStringParser.cs index b4eadaea..00beaad4 100644 --- a/src/UglyToad.Pdf/Parser/Parts/CosStringParser.cs +++ b/src/UglyToad.Pdf/Parser/Parts/CosStringParser.cs @@ -168,6 +168,7 @@ { seqSource.Unread(c); } + writer.Flush(); return new CosString(memoryStream.ToArray()); } }