From 0ae20c51f3eff13c16105188e7fdb439ccabb3c2 Mon Sep 17 00:00:00 2001 From: Eliot Jones Date: Sat, 31 Mar 2018 12:43:06 +0100 Subject: [PATCH] implement glyph index getter for the 3 implemented truetype cmap sub tables --- .../CMapSubTables/ByteEncodingCMapTable.cs | 19 +++++++++++++---- .../Tables/CMapSubTables/Format4CMapTable.cs | 21 ++++++++++++++++++- .../CMapSubTables/HighByteMappingCMapTable.cs | 16 +++++++++++--- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/ByteEncodingCMapTable.cs b/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/ByteEncodingCMapTable.cs index 3f3d5054..1f6360e5 100644 --- a/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/ByteEncodingCMapTable.cs +++ b/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/ByteEncodingCMapTable.cs @@ -6,29 +6,40 @@ /// internal class ByteEncodingCMapTable : ICMapSubTable { + private const int GlyphMappingLength = 256; + private readonly byte[] glyphMapping; + public int PlatformId { get; } public int EncodingId { get; } - private ByteEncodingCMapTable(int platformId, int encodingId) + private ByteEncodingCMapTable(int platformId, int encodingId, byte[] glyphMapping) { + this.glyphMapping = glyphMapping; PlatformId = platformId; EncodingId = encodingId; } public static ByteEncodingCMapTable Load(TrueTypeDataBytes data, int platformId, int encodingId) { + // ReSharper disable UnusedVariable var length = data.ReadUnsignedShort(); var version = data.ReadUnsignedShort(); + // ReSharper restore UnusedVariable - var glyphMapping = data.ReadByteArray(256); + var glyphMapping = data.ReadByteArray(GlyphMappingLength); - return new ByteEncodingCMapTable(platformId, encodingId); + return new ByteEncodingCMapTable(platformId, encodingId, glyphMapping); } public int CharacterCodeToGlyphIndex(int characterCode) { - throw new System.NotImplementedException(); + if (characterCode < GlyphMappingLength || characterCode >= GlyphMappingLength) + { + return 0; + } + + return glyphMapping[characterCode]; } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/Format4CMapTable.cs b/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/Format4CMapTable.cs index 6e14e5e3..604a6df8 100644 --- a/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/Format4CMapTable.cs +++ b/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/Format4CMapTable.cs @@ -34,7 +34,26 @@ namespace UglyToad.PdfPig.Fonts.TrueType.Tables.CMapSubTables public int CharacterCodeToGlyphIndex(int characterCode) { - throw new NotImplementedException(); + for (var i = 0; i < Segments.Count; i++) + { + var segment = Segments[i]; + + if (segment.EndCode < characterCode || segment.StartCode > characterCode) + { + continue; + } + + if (segment.IdRangeOffset == 0) + { + return (characterCode + segment.IdDelta) % ushort.MaxValue; + } + + var offset = segment.IdRangeOffset / 2 + (characterCode - segment.StartCode); + + return GlyphIds[offset - Segments.Count + i]; + } + + return 0; } public static Format4CMapTable Load(TrueTypeDataBytes data, int platformId, int encodingId) diff --git a/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/HighByteMappingCMapTable.cs b/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/HighByteMappingCMapTable.cs index 605393bd..a0388a2a 100644 --- a/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/HighByteMappingCMapTable.cs +++ b/src/UglyToad.PdfPig/Fonts/TrueType/Tables/CMapSubTables/HighByteMappingCMapTable.cs @@ -10,25 +10,35 @@ /// internal class HighByteMappingCMapTable : ICMapSubTable { + private readonly IReadOnlyDictionary characterCodesToGlyphIndices; + public int PlatformId { get; } public int EncodingId { get; } - public HighByteMappingCMapTable(int platformId, int encodingId) + private HighByteMappingCMapTable(int platformId, int encodingId, IReadOnlyDictionary characterCodesToGlyphIndices) { + this.characterCodesToGlyphIndices = characterCodesToGlyphIndices ?? throw new ArgumentNullException(nameof(characterCodesToGlyphIndices)); PlatformId = platformId; EncodingId = encodingId; } public int CharacterCodeToGlyphIndex(int characterCode) { - throw new NotImplementedException(); + if (!characterCodesToGlyphIndices.TryGetValue(characterCode, out var index)) + { + return 0; + } + + return index; } public static HighByteMappingCMapTable Load(TrueTypeDataBytes data, int numberOfGlyphs, int platformId, int encodingId) { + // ReSharper disable UnusedVariable var length = data.ReadUnsignedShort(); var version = data.ReadUnsignedShort(); + // ReSharper restore UnusedVariable var subHeaderKeys = new int[256]; var maximumSubHeaderIndex = 0; @@ -83,7 +93,7 @@ } } - return new HighByteMappingCMapTable(platformId, encodingId); + return new HighByteMappingCMapTable(platformId, encodingId, characterCodeToGlyphId); } public struct SubHeader