mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 19:54:52 +08:00
test letter positions with truetype standard14 mutant. fix truetype table overflow. read compact font format encodings
This commit is contained in:
BIN
src/UglyToad.PdfPig.Tests/Integration/Documents/byz.jpg
Normal file
BIN
src/UglyToad.PdfPig.Tests/Integration/Documents/byz.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
BIN
src/UglyToad.PdfPig.Tests/Integration/Documents/byz.pdf
Normal file
BIN
src/UglyToad.PdfPig.Tests/Integration/Documents/byz.pdf
Normal file
Binary file not shown.
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetStringIdByGlyphId(int glyphId)
|
||||
public int GetStringIdByGlyphId(int glyphId)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetStringIdByGlyphId(int glyphId)
|
||||
public int GetStringIdByGlyphId(int glyphId)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetStringIdByGlyphId(int glyphId)
|
||||
public int GetStringIdByGlyphId(int glyphId)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
|
||||
string GetNameByStringId(int stringId);
|
||||
|
||||
string GetStringIdByGlyphId(int glyphId);
|
||||
int GetStringIdByGlyphId(int glyphId);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user