// Parses the format 12 cmap table // Refer to https://www.microsoft.com/typography/otspec/cmap.htm to learn about how this format is organized private void ParseFormat12(byte[] source, ref uint offset, List <GlyphModel> allChars) { CmapFormat12Header header = ParseCmapFormat12Header(source, ref offset); for (int i = 0; i < header.nGroups; i++) { uint startCharCode = ReadDataAndIncreaseIndex <uint>(source, ref offset, sizeof(uint)); uint endCharCode = ReadDataAndIncreaseIndex <uint>(source, ref offset, sizeof(uint)); uint startGlyphID = ReadDataAndIncreaseIndex <uint>(source, ref offset, sizeof(uint)); for (uint j = startCharCode; j <= endCharCode; j++) { GlyphModel newChar = new GlyphModel(); newChar.CodePoint = j; newChar.GlyphID = (ushort)startGlyphID; startGlyphID++; byte[] byteJ = BitConverter.GetBytes(j); newChar.Definition = Encoding.UTF32.GetString(byteJ); if (!allChars.Contains(newChar)) { allChars.Add(newChar); } } } }
// Parses the format 0 cmap table // Refer to https://www.microsoft.com/typography/otspec/cmap.htm to learn about how this format is organized private void ParseFormat0(byte[] source, ref uint offset, List <GlyphModel> allChars) { ushort formatID = ReadDataAndIncreaseIndex <ushort>(source, ref offset, sizeof(ushort)); Debug.Assert(formatID == 0); ushort length = ReadDataAndIncreaseIndex <ushort>(source, ref offset, sizeof(ushort)); ushort language = ReadDataAndIncreaseIndex <ushort>(source, ref offset, sizeof(ushort)); byte[] idArray = ReadByteArrayAndIncreaseIndex(256, source, ref offset, sizeof(byte) * 256); for (uint i = 0; i < idArray.Length; i++) { if (idArray[i] != 0) { GlyphModel newChar = new GlyphModel(); newChar.CodePoint = i; newChar.GlyphID = idArray[i]; byte[] byteI = BitConverter.GetBytes(i); newChar.Definition = Encoding.UTF32.GetString(byteI); if (!allChars.Contains(newChar)) { allChars.Add(newChar); } } } }
// Parses the format 4 cmap table // Refer to https://www.microsoft.com/typography/otspec/cmap.htm to learn about how this format is organized private void ParseFormat4(byte[] source, ref uint offset, List <GlyphModel> allChars) { CmapFormat4Header header = ParseCmapFormat4Header(source, ref offset); int segCount = (int)header.segCountX2 / 2; ushort[] endCountArray = ReadUshortArrayAndIncreaseIndex(segCount, source, ref offset, sizeof(ushort)); ushort reservedPad = ReadDataAndIncreaseIndex <ushort>(source, ref offset, sizeof(ushort)); ushort[] startCountArray = ReadUshortArrayAndIncreaseIndex(segCount, source, ref offset, sizeof(ushort)); short[] idDeltaArray = ReadShortArrayAndIncreaseIndex(segCount, source, ref offset, sizeof(short)); uint idRangeTableOffset = offset; ushort[] idRangeTable = ReadUshortArrayAndIncreaseIndex(segCount, source, ref offset, sizeof(ushort)); for (byte i = 0; i < startCountArray.Length - 1; i++) { if (idRangeTable[i] == 0) { for (uint j = startCountArray[i]; j <= endCountArray[i]; j++) { GlyphModel newChar = new GlyphModel(); newChar.CodePoint = j; newChar.GlyphID = (ushort)(j + idDeltaArray[i]); byte[] byteJ = BitConverter.GetBytes(j); newChar.Definition = Encoding.UTF32.GetString(byteJ); if (!allChars.Contains(newChar)) { allChars.Add(newChar); } } } else { uint glyphIdOffset = idRangeTableOffset + idRangeTable[i] + (uint)(i * 2); for (uint j = startCountArray[i]; j <= endCountArray[i]; j++) { ushort gID = ReadDataAndIncreaseIndex <ushort>(source, ref glyphIdOffset, sizeof(ushort)); GlyphModel newChar = new GlyphModel(); newChar.CodePoint = j; newChar.GlyphID = gID; byte[] byteJ = BitConverter.GetBytes(j); newChar.Definition = Encoding.UTF32.GetString(byteJ); if (!allChars.Contains(newChar)) { allChars.Add(newChar); } } } } }
// Parses the format 6 cmap table // Refer to https://www.microsoft.com/typography/otspec/cmap.htm to learn about how this format is organized private void ParseFormat6(byte[] source, ref uint offset, List <GlyphModel> allChars) { CmapFormat6Header header = ParseCmapFormat6Header(source, ref offset); for (uint i = 0; i < header.entryCount; i++) { ushort gID = ReadDataAndIncreaseIndex <ushort>(source, ref offset, sizeof(ushort)); if (gID != 0) { GlyphModel newChar = new GlyphModel(); newChar.CodePoint = i; newChar.GlyphID = gID; byte[] byteI = BitConverter.GetBytes(i); newChar.Definition = Encoding.UTF32.GetString(byteI); if (!allChars.Contains(newChar)) { allChars.Add(newChar); } } } }