test letter positions with truetype standard14 mutant. fix truetype table overflow. read compact font format encodings

This commit is contained in:
Eliot Jones
2019-01-12 18:07:53 +00:00
parent 245efae8ed
commit a4305cc86c
25 changed files with 892 additions and 16 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

View File

@@ -7,6 +7,7 @@
public class GenerateLetterBoundingBoxImages
{
private const string ByzantineGenerals = "byz";
private const string NonLatinAcrobatDistiller = "Single Page Non Latin - from acrobat distiller";
private const string SingleGoogleDrivePage = "Single Page Simple - from google drive";
private const string SinglePageFormattedType0Content = "Type0 Font";
@@ -87,6 +88,12 @@
Run(MotorInsuranceClaim, 841);
}
[Fact]
public void ByzantineGeneralsTrueTypeStandard14()
{
Run(ByzantineGenerals, 702);
}
private static void Run(string file, int imageHeight = 792)
{
var pdfFileName = GetFilename(file);

View File

@@ -1,5 +1,6 @@
namespace UglyToad.PdfPig.Fonts.CidFonts
{
using System;
using System.Collections.Generic;
using Core;
using Geometry;
@@ -44,12 +45,33 @@
public decimal GetWidthFromDictionary(int cid)
{
return Widths[cid];
if (cid < 0)
{
throw new ArgumentException($"The provided character code was negative: {cid}.");
}
if (cid < Widths.Count)
{
return Widths[cid];
}
// TODO: correct values
return 250;
}
public PdfRectangle GetBoundingBox(int characterIdentifier)
{
return new PdfRectangle(0, 0, Widths[characterIdentifier], 0);
// TODO: correct values
if (characterIdentifier < 0)
{
throw new ArgumentException($"The provided character identifier was negative: {characterIdentifier}.");
}
if (characterIdentifier < Widths.Count)
{
return new PdfRectangle(0, 0, Widths[characterIdentifier], 0);
}
if (fontProgram.TryGetBoundingBox(characterIdentifier, out var boundingBox))
{
return boundingBox;

View File

@@ -39,9 +39,14 @@
throw new NotImplementedException();
}
public virtual string GetStringIdByGlyphId(int glyphId)
public virtual int GetStringIdByGlyphId(int glyphId)
{
throw new NotImplementedException();
if (GlyphIdToStringIdAndName.TryGetValue(glyphId, out var strings))
{
return strings.stringId;
}
return 0;
}
}
}

View File

@@ -26,7 +26,7 @@
throw new NotSupportedException("Cid Charsets do not support named glyphs.");
}
public string GetStringIdByGlyphId(int glyphId)
public int GetStringIdByGlyphId(int glyphId)
{
throw new NotSupportedException("Cid Charsets do not support named glyphs.");
}

View File

@@ -205,7 +205,7 @@
throw new System.NotImplementedException();
}
public string GetStringIdByGlyphId(int glyphId)
public int GetStringIdByGlyphId(int glyphId)
{
throw new System.NotImplementedException();
}

View File

@@ -126,7 +126,7 @@
throw new System.NotImplementedException();
}
public string GetStringIdByGlyphId(int glyphId)
public int GetStringIdByGlyphId(int glyphId)
{
throw new System.NotImplementedException();
}

View File

@@ -268,7 +268,7 @@
throw new System.NotImplementedException();
}
public string GetStringIdByGlyphId(int glyphId)
public int GetStringIdByGlyphId(int glyphId)
{
throw new System.NotImplementedException();
}

View File

@@ -8,6 +8,6 @@
string GetNameByStringId(int stringId);
string GetStringIdByGlyphId(int glyphId);
int GetStringIdByGlyphId(int glyphId);
}
}

View File

@@ -0,0 +1,106 @@
namespace UglyToad.PdfPig.Fonts.CompactFontFormat
{
using System;
using System.Collections.Generic;
using Charsets;
using Encodings;
using Exceptions;
internal static class CompactFontFormatEncodingReader
{
public static Encoding ReadEncoding(CompactFontFormatData data, ICompactFontFormatCharset charset, IReadOnlyList<string> stringIndex)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var format = data.ReadCard8();
switch (format)
{
case 0:
return ReadFormat0Encoding(data, charset, stringIndex);
case 1:
return ReadFormat1Encoding(data, charset, stringIndex);
default:
throw new InvalidFontFormatException($"The provided format {format} for this Compact Font Format encoding was invalid.");
}
}
private static CompactFontFormatFormat0Encoding ReadFormat0Encoding(CompactFontFormatData data, ICompactFontFormatCharset charset, IReadOnlyList<string> stringIndex)
{
var numberOfCodes = data.ReadCard8();
var values = new List<(int code, int sid, string str)>();
for (var i = 1; i <= numberOfCodes; i++)
{
var code = data.ReadCard8();
var sid = charset.GetStringIdByGlyphId(i);
var str = ReadString(sid, stringIndex);
values.Add((code, sid, str));
}
return new CompactFontFormatFormat0Encoding(values);
}
private static CompactFontFormatFormat1Encoding ReadFormat1Encoding(CompactFontFormatData data, ICompactFontFormatCharset charset, IReadOnlyList<string> stringIndex)
{
var numberOfRanges = data.ReadCard8();
var fromRanges = new List<(int code, int sid, string str)>();
var gid = 1;
for (var i = 0; i < numberOfRanges; i++)
{
int rangeFirst = data.ReadCard8();
int rangeLeft = data.ReadCard8();
for (var j = 0; j < 1 + rangeLeft; j++)
{
var sid = charset.GetStringIdByGlyphId(gid);
var code = rangeFirst + j;
var str = ReadString(sid, stringIndex);
fromRanges.Add((code, sid, str));
gid++;
}
}
var supplements = ReadSupplement(data, stringIndex);
return new CompactFontFormatFormat1Encoding(numberOfRanges, fromRanges, supplements);
}
private static IReadOnlyList<CompactFontFormatBuiltInEncoding.Supplement> ReadSupplement(CompactFontFormatData dataInput,
IReadOnlyList<string> stringIndex)
{
var numberOfSupplements = dataInput.ReadCard8();
var supplements = new CompactFontFormatBuiltInEncoding.Supplement[numberOfSupplements];
for (var i = 0; i < supplements.Length; i++)
{
var code = dataInput.ReadCard8();
var sid = dataInput.ReadSid();
var name = ReadString(sid, stringIndex);
supplements[i] = new CompactFontFormatBuiltInEncoding.Supplement(code, sid, name);
}
return supplements;
}
private static string ReadString(int index, IReadOnlyList<string> stringIndex)
{
if (index >= 0 && index <= 390)
{
return CompactFontFormatStandardStrings.GetName(index);
}
if (index - 391 < stringIndex.Count)
{
return stringIndex[index - 391];
}
// technically this maps to .notdef, but we need a unique sid name
return "SID" + index;
}
}
}

View File

@@ -5,6 +5,7 @@
using Charsets;
using CharStrings;
using Dictionaries;
using Encodings;
using Geometry;
using Type1.CharStrings;
using Util;
@@ -15,19 +16,26 @@
public CompactFontFormatPrivateDictionary PrivateDictionary { get; }
public ICompactFontFormatCharset Charset { get; }
public Union<Type1CharStrings, Type2CharStrings> CharStrings { get; }
public Encoding Encoding { get; }
public CompactFontFormatFont(CompactFontFormatTopLevelDictionary topDictionary, CompactFontFormatPrivateDictionary privateDictionary,
ICompactFontFormatCharset charset,
Union<Type1CharStrings, Type2CharStrings> charStrings)
public CompactFontFormatFont(CompactFontFormatTopLevelDictionary topDictionary, CompactFontFormatPrivateDictionary privateDictionary,
ICompactFontFormatCharset charset,
Union<Type1CharStrings, Type2CharStrings> charStrings, Encoding fontEncoding)
{
TopDictionary = topDictionary;
PrivateDictionary = privateDictionary;
Charset = charset;
CharStrings = charStrings;
Encoding = fontEncoding;
}
public PdfRectangle? GetCharacterBoundingBox(string characterName)
{
if (characterName == ".notdef")
{
return new PdfRectangle(0, 0, 0, 0);
}
var result = default(PdfRectangle?);
CharStrings.Match(x => throw new NotImplementedException("Type 1 CharStrings in a CFF font are currently unsupported."),
x => { result = x.Generate(characterName).Path.GetBoundingRectangle(); });
@@ -49,7 +57,7 @@
IReadOnlyList<CompactFontFormatTopLevelDictionary> fontDictionaries,
IReadOnlyList<CompactFontFormatPrivateDictionary> privateDictionaries,
IReadOnlyList<CompactFontFormatIndex> localSubroutines,
ICompactFontFormatFdSelect fdSelect) : base(topDictionary, privateDictionary, charset, charStrings)
ICompactFontFormatFdSelect fdSelect) : base(topDictionary, privateDictionary, charset, charStrings, null)
{
FontDictionaries = fontDictionaries;
PrivateDictionaries = privateDictionaries;

View File

@@ -85,5 +85,17 @@
{
return 1000;
}
public string GetCharacterName(int characterCode)
{
var font = GetFont();
if (font.Encoding != null)
{
return font.Encoding.GetName(characterCode);
}
return ".notdef";
}
}
}

View File

@@ -6,6 +6,7 @@
using Charsets;
using CharStrings;
using Dictionaries;
using Encodings;
using Exceptions;
using Type1.CharStrings;
using Util;
@@ -113,7 +114,27 @@
return ReadCidFont(data, topDictionary, charStringIndex.Count, stringIndex, privateDictionary, charset, Union<Type1CharStrings, Type2CharStrings>.Two(charStrings));
}
return new CompactFontFormatFont(topDictionary, privateDictionary, charset, Union<Type1CharStrings, Type2CharStrings>.Two(charStrings));
var encoding = topDictionary.EncodingOffset;
Encoding fontEncoding = null;
if (encoding != CompactFontFormatTopLevelDictionary.UnsetOffset)
{
if (encoding == 0)
{
fontEncoding = CompactFontFormatStandardEncoding.Instance;
}
else if (encoding == 1)
{
fontEncoding = CompactFontFormatExpertEncoding.Instance;
}
else
{
data.Seek(encoding);
fontEncoding = CompactFontFormatEncodingReader.ReadEncoding(data, charset, stringIndex);
}
}
return new CompactFontFormatFont(topDictionary, privateDictionary, charset, Union<Type1CharStrings, Type2CharStrings>.Two(charStrings), fontEncoding);
}
private static ICompactFontFormatCharset ReadCharset(CompactFontFormatData data, CompactFontFormatTopLevelDictionary topDictionary,

View File

@@ -83,6 +83,11 @@
{
var index = indexReader.ReadIndex(data);
if (index.Length == 0)
{
return EmptyArray<string>.Instance;
}
var count = index.Length - 1;
var result = new string[count];

View File

@@ -0,0 +1,38 @@
namespace UglyToad.PdfPig.Fonts.Encodings
{
using System.Collections.Generic;
using CompactFontFormat;
internal abstract class CompactFontFormatBaseEncoding : Encoding
{
private readonly Dictionary<int, string> codeToNameMap = new Dictionary<int, string>(250);
public override string EncodingName { get; } = "CFF";
/// <summary>
/// Returns the PostScript name of the glyph for the given character code.
/// </summary>
public override string GetName(int code)
{
if (!codeToNameMap.TryGetValue(code, out var name))
{
return ".notdef";
}
return name;
}
public void Add(int code, int sid, string name)
{
codeToNameMap[code] = name;
Add(code, name);
}
protected void Add(int code, int sid)
{
var name = CompactFontFormatStandardStrings.GetName(sid);
codeToNameMap[code] = name;
Add(code, name);
}
}
}

View File

@@ -0,0 +1,34 @@
namespace UglyToad.PdfPig.Fonts.Encodings
{
using System.Collections.Generic;
internal abstract class CompactFontFormatBuiltInEncoding : CompactFontFormatBaseEncoding
{
public IReadOnlyList<Supplement> Supplements { get; }
protected CompactFontFormatBuiltInEncoding(IReadOnlyList<Supplement> supplements)
{
Supplements = supplements;
foreach (var supplement in supplements)
{
Add(supplement.Code, supplement.Sid, supplement.Name);
}
}
public class Supplement
{
public int Code { get; }
public int Sid { get; }
public string Name { get; }
public Supplement(int code, int sid, string name)
{
Code = code;
Sid = sid;
Name = name;
}
}
}
}

View File

@@ -0,0 +1,284 @@
namespace UglyToad.PdfPig.Fonts.Encodings
{
using System.Collections.Generic;
internal class CompactFontFormatExpertEncoding : CompactFontFormatBaseEncoding
{
/// <summary>
/// Table of character codes and their corresponding sid.
/// </summary>
private static readonly Dictionary<int, int> ExpertEncodingTable = new Dictionary<int, int>
{
{0, 0},
{1, 0},
{2, 0},
{3, 0},
{4, 0},
{5, 0},
{6, 0},
{7, 0},
{8, 0},
{9, 0},
{10, 0},
{11, 0},
{12, 0},
{13, 0},
{14, 0},
{15, 0},
{16, 0},
{17, 0},
{18, 0},
{19, 0},
{20, 0},
{21, 0},
{22, 0},
{23, 0},
{24, 0},
{25, 0},
{26, 0},
{27, 0},
{28, 0},
{29, 0},
{30, 0},
{31, 0},
{32, 1},
{33, 229},
{34, 230},
{35, 0},
{36, 231},
{37, 232},
{38, 233},
{39, 234},
{40, 235},
{41, 236},
{42, 237},
{43, 238},
{44, 13},
{45, 14},
{46, 15},
{47, 99},
{48, 239},
{49, 240},
{50, 241},
{51, 242},
{52, 243},
{53, 244},
{54, 245},
{55, 246},
{56, 247},
{57, 248},
{58, 27},
{59, 28},
{60, 249},
{61, 250},
{62, 251},
{63, 252},
{64, 0},
{65, 253},
{66, 254},
{67, 255},
{68, 256},
{69, 257},
{70, 0},
{71, 0},
{72, 0},
{73, 258},
{74, 0},
{75, 0},
{76, 259},
{77, 260},
{78, 261},
{79, 262},
{80, 0},
{81, 0},
{82, 263},
{83, 264},
{84, 265},
{85, 0},
{86, 266},
{87, 109},
{88, 110},
{89, 267},
{90, 268},
{91, 269},
{92, 0},
{93, 270},
{94, 271},
{95, 272},
{96, 273},
{97, 274},
{98, 275},
{99, 276},
{100, 277},
{101, 278},
{102, 279},
{103, 280},
{104, 281},
{105, 282},
{106, 283},
{107, 284},
{108, 285},
{109, 286},
{110, 287},
{111, 288},
{112, 289},
{113, 290},
{114, 291},
{115, 292},
{116, 293},
{117, 294},
{118, 295},
{119, 296},
{120, 297},
{121, 298},
{122, 299},
{123, 300},
{124, 301},
{125, 302},
{126, 303},
{127, 0},
{128, 0},
{129, 0},
{130, 0},
{131, 0},
{132, 0},
{133, 0},
{134, 0},
{135, 0},
{136, 0},
{137, 0},
{138, 0},
{139, 0},
{140, 0},
{141, 0},
{142, 0},
{143, 0},
{144, 0},
{145, 0},
{146, 0},
{147, 0},
{148, 0},
{149, 0},
{150, 0},
{151, 0},
{152, 0},
{153, 0},
{154, 0},
{155, 0},
{156, 0},
{157, 0},
{158, 0},
{159, 0},
{160, 0},
{161, 304},
{162, 305},
{163, 306},
{164, 0},
{165, 0},
{166, 307},
{167, 308},
{168, 309},
{169, 310},
{170, 311},
{171, 0},
{172, 312},
{173, 0},
{174, 0},
{175, 313},
{176, 0},
{177, 0},
{178, 314},
{179, 315},
{180, 0},
{181, 0},
{182, 316},
{183, 317},
{184, 318},
{185, 0},
{186, 0},
{187, 0},
{188, 158},
{189, 155},
{190, 163},
{191, 319},
{192, 320},
{193, 321},
{194, 322},
{195, 323},
{196, 324},
{197, 325},
{198, 0},
{199, 0},
{200, 326},
{201, 150},
{202, 164},
{203, 169},
{204, 327},
{205, 328},
{206, 329},
{207, 330},
{208, 331},
{209, 332},
{210, 333},
{211, 334},
{212, 335},
{213, 336},
{214, 337},
{215, 338},
{216, 339},
{217, 340},
{218, 341},
{219, 342},
{220, 343},
{221, 344},
{222, 345},
{223, 346},
{224, 347},
{225, 348},
{226, 349},
{227, 350},
{228, 351},
{229, 352},
{230, 353},
{231, 354},
{232, 355},
{233, 356},
{234, 357},
{235, 358},
{236, 359},
{237, 360},
{238, 361},
{239, 362},
{240, 363},
{241, 364},
{242, 365},
{243, 366},
{244, 367},
{245, 368},
{246, 369},
{247, 370},
{248, 371},
{249, 372},
{250, 373},
{251, 374},
{252, 375},
{253, 376},
{254, 377},
{255, 378}
};
private CompactFontFormatExpertEncoding()
{
}
public static readonly CompactFontFormatExpertEncoding Instance = new CompactFontFormatExpertEncoding();
static CompactFontFormatExpertEncoding()
{
foreach (var entry in ExpertEncodingTable)
{
Instance.Add(entry.Key, entry.Value);
}
}
}
}

View File

@@ -0,0 +1,18 @@
namespace UglyToad.PdfPig.Fonts.Encodings
{
using System.Collections.Generic;
using Util;
internal class CompactFontFormatFormat0Encoding : CompactFontFormatBuiltInEncoding
{
public CompactFontFormatFormat0Encoding(IReadOnlyList<(int code, int sid, string str)> values) : base(EmptyArray<Supplement>.Instance)
{
Add(0, 0, ".notdef");
foreach (var value in values)
{
Add(value.code, value.sid, value.str);
}
}
}
}

View File

@@ -0,0 +1,21 @@
namespace UglyToad.PdfPig.Fonts.Encodings
{
using System.Collections.Generic;
internal class CompactFontFormatFormat1Encoding : CompactFontFormatBuiltInEncoding
{
public int NumberOfRanges { get; set; }
public CompactFontFormatFormat1Encoding(int numberOfRanges, IReadOnlyList<(int code, int sid, string str)> values, IReadOnlyList<Supplement> supplements) : base(supplements)
{
NumberOfRanges = numberOfRanges;
Add(0, 0, ".notdef");
foreach (var value in values)
{
Add(value.code, value.sid, value.str);
}
}
}
}

View File

@@ -0,0 +1,283 @@
namespace UglyToad.PdfPig.Fonts.Encodings
{
using System.Collections.Generic;
internal class CompactFontFormatStandardEncoding : CompactFontFormatBaseEncoding
{
/// <summary>
/// Table of character codes and their corresponding sid.
/// </summary>
private static readonly Dictionary<int, int> CharacterCodeToSid = new Dictionary<int, int> {
{0, 0},
{1, 0},
{2, 0},
{3, 0},
{4, 0},
{5, 0},
{6, 0},
{7, 0},
{8, 0},
{9, 0},
{10, 0},
{11, 0},
{12, 0},
{13, 0},
{14, 0},
{15, 0},
{16, 0},
{17, 0},
{18, 0},
{19, 0},
{20, 0},
{21, 0},
{22, 0},
{23, 0},
{24, 0},
{25, 0},
{26, 0},
{27, 0},
{28, 0},
{29, 0},
{30, 0},
{31, 0},
{32, 1},
{33, 2},
{34, 3},
{35, 4},
{36, 5},
{37, 6},
{38, 7},
{39, 8},
{40, 9},
{41, 10},
{42, 11},
{43, 12},
{44, 13},
{45, 14},
{46, 15},
{47, 16},
{48, 17},
{49, 18},
{50, 19},
{51, 20},
{52, 21},
{53, 22},
{54, 23},
{55, 24},
{56, 25},
{57, 26},
{58, 27},
{59, 28},
{60, 29},
{61, 30},
{62, 31},
{63, 32},
{64, 33},
{65, 34},
{66, 35},
{67, 36},
{68, 37},
{69, 38},
{70, 39},
{71, 40},
{72, 41},
{73, 42},
{74, 43},
{75, 44},
{76, 45},
{77, 46},
{78, 47},
{79, 48},
{80, 49},
{81, 50},
{82, 51},
{83, 52},
{84, 53},
{85, 54},
{86, 55},
{87, 56},
{88, 57},
{89, 58},
{90, 59},
{91, 60},
{92, 61},
{93, 62},
{94, 63},
{95, 64},
{96, 65},
{97, 66},
{98, 67},
{99, 68},
{100, 69},
{101, 70},
{102, 71},
{103, 72},
{104, 73},
{105, 74},
{106, 75},
{107, 76},
{108, 77},
{109, 78},
{110, 79},
{111, 80},
{112, 81},
{113, 82},
{114, 83},
{115, 84},
{116, 85},
{117, 86},
{118, 87},
{119, 88},
{120, 89},
{121, 90},
{122, 91},
{123, 92},
{124, 93},
{125, 94},
{126, 95},
{127, 0},
{128, 0},
{129, 0},
{130, 0},
{131, 0},
{132, 0},
{133, 0},
{134, 0},
{135, 0},
{136, 0},
{137, 0},
{138, 0},
{139, 0},
{140, 0},
{141, 0},
{142, 0},
{143, 0},
{144, 0},
{145, 0},
{146, 0},
{147, 0},
{148, 0},
{149, 0},
{150, 0},
{151, 0},
{152, 0},
{153, 0},
{154, 0},
{155, 0},
{156, 0},
{157, 0},
{158, 0},
{159, 0},
{160, 0},
{161, 96},
{162, 97},
{163, 98},
{164, 99},
{165, 100},
{166, 101},
{167, 102},
{168, 103},
{169, 104},
{170, 105},
{171, 106},
{172, 107},
{173, 108},
{174, 109},
{175, 110},
{176, 0},
{177, 111},
{178, 112},
{179, 113},
{180, 114},
{181, 0},
{182, 115},
{183, 116},
{184, 117},
{185, 118},
{186, 119},
{187, 120},
{188, 121},
{189, 122},
{190, 0},
{191, 123},
{192, 0},
{193, 124},
{194, 125},
{195, 126},
{196, 127},
{197, 128},
{198, 129},
{199, 130},
{200, 131},
{201, 0},
{202, 132},
{203, 133},
{204, 0},
{205, 134},
{206, 135},
{207, 136},
{208, 137},
{209, 0},
{210, 0},
{211, 0},
{212, 0},
{213, 0},
{214, 0},
{215, 0},
{216, 0},
{217, 0},
{218, 0},
{219, 0},
{220, 0},
{221, 0},
{222, 0},
{223, 0},
{224, 0},
{225, 138},
{226, 0},
{227, 139},
{228, 0},
{229, 0},
{230, 0},
{231, 0},
{232, 140},
{233, 141},
{234, 142},
{235, 143},
{236, 0},
{237, 0},
{238, 0},
{239, 0},
{240, 0},
{241, 144},
{242, 0},
{243, 0},
{244, 0},
{245, 145},
{246, 0},
{247, 0},
{248, 146},
{249, 147},
{250, 148},
{251, 149},
{252, 0},
{253, 0},
{254, 0},
{255, 0}
};
public static readonly CompactFontFormatStandardEncoding Instance = new CompactFontFormatStandardEncoding();
private CompactFontFormatStandardEncoding()
{
}
static CompactFontFormatStandardEncoding()
{
foreach (var entry in CharacterCodeToSid)
{
Instance.Add(entry.Key, entry.Value);
}
}
}
}

View File

@@ -37,7 +37,7 @@
return CodeToName.ContainsKey(code);
}
public string GetName(int code)
public virtual string GetName(int code)
{
if (!CodeToName.TryGetValue(code, out var name))
{

View File

@@ -1,6 +1,8 @@
namespace UglyToad.PdfPig.Fonts.Parser.Handlers
{
using System;
using System.IO;
using System.Linq;
using SystemFonts;
using Cmap;
using Encodings;
@@ -127,6 +129,8 @@
var fontFile = fontFileStream.Decode(filterProvider);
File.WriteAllBytes(@"C:\git\conzantashby.ttf", fontFile.ToArray());
var font = trueTypeFontParser.Parse(new TrueTypeDataBytes(new ByteArrayInputBytes(fontFile)));
return font;

View File

@@ -163,7 +163,7 @@
}
else
{
throw new NotImplementedException("Unclear how to access the character name for CFF fonts when no encoding is present.");
characterName = x.GetCharacterName(characterCode);
}
rect = x.GetCharacterBoundingBox(characterName);
});

View File

@@ -10,6 +10,7 @@
var metricCount = register.HorizontalHeaderTable.NumberOfHeaderMetrics;
data.Seek(header.Offset);
var bytesRead = 0;
// The number of entries in the left side bearing field per entry is number of glyphs - number of metrics
var additionalLeftSideBearingLength = glyphCount - metricCount;
@@ -23,11 +24,18 @@
{
advancedWidths[i] = data.ReadUnsignedShort();
leftSideBearings[i] = data.ReadSignedShort();
bytesRead += 4;
}
for (var i = 0; i < additionalLeftSideBearingLength; i++)
{
if (bytesRead >= header.Length)
{
break;
}
leftSideBearings[metricCount + i] = data.ReadSignedShort();
bytesRead += 2;
}
return new HorizontalMetricsTable(header, advancedWidths, leftSideBearings, metricCount);