diff --git a/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFont.cs b/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFont.cs index f41d06c8..ea32c9fe 100644 --- a/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFont.cs +++ b/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFont.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig.Fonts.CidFonts { using Core; + using Geometry; using Tokenization.Tokens; /// @@ -39,8 +40,8 @@ FontDescriptor Descriptor { get; } - decimal GetWidthFromFont(int characterCode); - decimal GetWidthFromDictionary(int cid); + + PdfRectangle GetBoundingBox(int characterCode); } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFontProgram.cs b/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFontProgram.cs index 6faa49b6..09748282 100644 --- a/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFontProgram.cs +++ b/src/UglyToad.PdfPig/Fonts/CidFonts/ICidFontProgram.cs @@ -1,10 +1,12 @@ namespace UglyToad.PdfPig.Fonts.CidFonts { + using Geometry; + /// /// Represents either an Adobe Type 1 or TrueType font program for a CIDFont. /// internal interface ICidFontProgram { - + bool TryGetBoundingBox(int characterCode, out PdfRectangle boundingBox); } } diff --git a/src/UglyToad.PdfPig/Fonts/CidFonts/Type0CidFont.cs b/src/UglyToad.PdfPig/Fonts/CidFonts/Type0CidFont.cs index 25170101..1b9ca2a3 100644 --- a/src/UglyToad.PdfPig/Fonts/CidFonts/Type0CidFont.cs +++ b/src/UglyToad.PdfPig/Fonts/CidFonts/Type0CidFont.cs @@ -1,6 +1,7 @@ namespace UglyToad.PdfPig.Fonts.CidFonts { using Core; + using Geometry; using Tokenization.Tokens; /// @@ -32,5 +33,10 @@ { throw new System.NotImplementedException(); } + + public PdfRectangle GetBoundingBox(int characterCode) + { + throw new System.NotImplementedException(); + } } } diff --git a/src/UglyToad.PdfPig/Fonts/CidFonts/Type2CidFont.cs b/src/UglyToad.PdfPig/Fonts/CidFonts/Type2CidFont.cs index 28fda9ad..1825cc38 100644 --- a/src/UglyToad.PdfPig/Fonts/CidFonts/Type2CidFont.cs +++ b/src/UglyToad.PdfPig/Fonts/CidFonts/Type2CidFont.cs @@ -2,6 +2,7 @@ { using System.Collections.Generic; using Core; + using Geometry; using Tokenization.Tokens; /// @@ -57,5 +58,20 @@ return Descriptor.MissingWidth; } + + public PdfRectangle GetBoundingBox(int characterCode) + { + if (fontProgram == null) + { + return Descriptor.BoundingBox; + } + + if (fontProgram.TryGetBoundingBox(characterCode, out var result)) + { + return result; + } + + return Descriptor.BoundingBox; + } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Fonts/Composite/Type0Font.cs b/src/UglyToad.PdfPig/Fonts/Composite/Type0Font.cs index 003d4ef1..ea486a6b 100644 --- a/src/UglyToad.PdfPig/Fonts/Composite/Type0Font.cs +++ b/src/UglyToad.PdfPig/Fonts/Composite/Type0Font.cs @@ -88,7 +88,7 @@ public PdfRectangle GetBoundingBox(int characterCode) { - throw new NotImplementedException(); + return CidFont.GetBoundingBox(characterCode); } public TransformationMatrix GetFontMatrix() diff --git a/src/UglyToad.PdfPig/Fonts/Simple/TrueTypeSimpleFont.cs b/src/UglyToad.PdfPig/Fonts/Simple/TrueTypeSimpleFont.cs index bd6053d4..4f4effd9 100644 --- a/src/UglyToad.PdfPig/Fonts/Simple/TrueTypeSimpleFont.cs +++ b/src/UglyToad.PdfPig/Fonts/Simple/TrueTypeSimpleFont.cs @@ -107,19 +107,17 @@ public PdfRectangle GetBoundingBox(int characterCode) { - if (font?.CMapTable == null) + if (font == null) { return descriptor.BoundingBox; } - if (!font.CMapTable.TryGetGlyphIndex(characterCode, out var index)) + if (font.TryGetBoundingBox(characterCode, out var bounds)) { - return descriptor.BoundingBox; + return bounds; } - var glyph = font.GlyphTable.Glyphs[index]; - - return glyph?.GlyphBounds ?? descriptor.BoundingBox; + return descriptor.BoundingBox; } public TransformationMatrix GetFontMatrix() diff --git a/src/UglyToad.PdfPig/Fonts/TrueType/TrueTypeFont.cs b/src/UglyToad.PdfPig/Fonts/TrueType/TrueTypeFont.cs index 69b9efd7..549ca9d4 100644 --- a/src/UglyToad.PdfPig/Fonts/TrueType/TrueTypeFont.cs +++ b/src/UglyToad.PdfPig/Fonts/TrueType/TrueTypeFont.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using CidFonts; + using Geometry; using Parser; using Tables; @@ -29,5 +30,31 @@ CMapTable = tableRegister.CMapTable; GlyphTable = tableRegister.GlyphDataTable; } + + public bool TryGetBoundingBox(int characterCode, out PdfRectangle boundingBox) + { + boundingBox = default(PdfRectangle); + + if (CMapTable == null) + { + return false; + } + + if (!CMapTable.TryGetGlyphIndex(characterCode, out var index)) + { + return false; + } + + var glyph = GlyphTable.Glyphs[index]; + + if (glyph?.GlyphBounds == null) + { + return false; + } + + boundingBox = glyph.GlyphBounds; + + return true; + } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs b/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs index c2490fbd..10298b6c 100644 --- a/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs +++ b/src/UglyToad.PdfPig/Fonts/Type1/Parser/Type1FontParser.cs @@ -31,6 +31,7 @@ /// The parsed type 1 font. public Type1Font Parse(IInputBytes inputBytes, int length1, int length2) { + // Sometimes the entire PFB file including the header bytes can be included which prevents parsing in the normal way. var isEntirePfbFile = inputBytes.Peek() == PfbFileIndicator; IReadOnlyList eexecPortion = new byte[0]; @@ -155,6 +156,14 @@ /// private static (byte[] ascii, byte[] binary) ReadPfbHeader(IInputBytes bytes) { + /* + * The header is a 6 byte sequence. The first byte is 0x80 followed by 0x01 for the ASCII record indicator. + * The following 4 bytes determine the size/length of the ASCII part of the PFB file. + * After the ASCII part another 6 byte sequence is present, this time 0x80 0x02 for the Binary part length. + * A 3rd sequence is present at the end re-stating the ASCII length but this is surplus to requirements. + */ + + // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local int ReadSize(byte recordType) { bytes.MoveNext();