private static Dictionary <uint, uint> LoadSegmentedCoverage(FontSource p) { var dic = new Dictionary <uint, uint>(); // Skip format p.ReadUShort(); // Skip reserved p.ReadUShort(); var length = p.ReadUInt(); var language = p.ReadUInt(); var numGroups = p.ReadUInt(); for (var i = 0; i < numGroups; i++) { var startCharCode = p.ReadUInt(); var endCharCode = p.ReadUInt(); var startGlyphId = p.ReadUInt(); for (var c = startCharCode; c <= endCharCode; c++) { dic[c] = startGlyphId; startGlyphId++; } } return(dic); }
private static uint[] LoadIndexToLocation(FontSource p, uint tableOffset, ushort glyphCount, short indexToLocFormat) { p.Offset = tableOffset; var isLong = indexToLocFormat == 1; var n = glyphCount + 1; var localOffsets = new uint[n]; if (isLong) { for (var i = 0; i < n; i++) { localOffsets[i] = p.ReadUInt(); } } else { for (var i = 0; i < n; i++) { localOffsets[i] = (uint)p.ReadUShort() * 2; } } return(localOffsets); }
private static Dictionary <uint, uint> LoadCharacterToGlyphIndexMappingTable(FontSource p, uint tableOffset) { p.Offset = tableOffset; var version = p.ReadUShort(); var numTables = p.ReadUShort(); var encodingRecords = new EncodingRecord[numTables]; for (var i = 0; i < numTables; i++) { encodingRecords[i] = EncodingRecord.Load(p, tableOffset); } var targetRecordId = -1; for (var i = numTables - 1; i >= 0; i--) { var r = encodingRecords[i]; if (r.PlatformID == 3 && (r.EncodingID == 0 || r.EncodingID == 1 || r.EncodingID == 10) || r.PlatformID == 0 && (r.EncodingID == 0 || r.EncodingID == 1 || r.EncodingID == 2 || r.EncodingID == 3 || r.EncodingID == 4)) { targetRecordId = i; break; } } if (targetRecordId < 0) { throw new FontException("Encoding record not found."); } var targetRecord = encodingRecords[targetRecordId]; if (targetRecord.SubTableFormat == 12) { p.Offset = tableOffset + targetRecord.Offset; return(LoadSegmentedCoverage(p)); } if (targetRecord.SubTableFormat == 4) { p.Offset = tableOffset + targetRecord.Offset; return(LoadSegmentMappingToDeltaValues(p)); } throw new FontException($"Unsupported format: {targetRecord.SubTableFormat}"); }
private static Dictionary <uint, uint> LoadSegmentMappingToDeltaValues(FontSource p) { var dic = new Dictionary <uint, uint>(); var offset = p.Offset; // Skip format p.ReadUShort(); var length = p.ReadUShort(); var language = p.ReadUShort(); var segCount = p.ReadUShort() >> 1; var searchRange = p.ReadUShort(); var entrySelector = p.ReadUShort(); var rangeShift = p.ReadUShort(); var endCodeParser = new FontSource(p.Bytes, offset + 14); var startCodeParser = new FontSource(p.Bytes, (uint)(offset + 16 + segCount * 2)); var idDeltaParser = new FontSource(p.Bytes, (uint)(offset + 16 + segCount * 4)); var idRangeOffsetParser = new FontSource(p.Bytes, (uint)(offset + 16 + segCount * 6)); for (var i = 0; i < segCount - 1; i++) { var endCode = endCodeParser.ReadUShort(); var startCode = startCodeParser.ReadUShort(); var idDelta = idDeltaParser.ReadShort(); var idRangeOffset = idRangeOffsetParser.ReadUShort(); for (var c = startCode; c <= endCode; c++) { uint glyphIndex; if (idRangeOffset != 0) { var glyphIndexOffset = idRangeOffsetParser.Offset - 2; glyphIndexOffset += idRangeOffset; glyphIndexOffset += (uint)(c - startCode) * 2; p.Offset = glyphIndexOffset; glyphIndex = p.ReadUShort(); if (glyphIndex != 0) { glyphIndex = (uint)(glyphIndex + idDelta) & 0xFFFF; } } else { glyphIndex = (uint)(c + idDelta) & 0xFFFF; } dic[c] = glyphIndex; } } return(dic); }
private static void LoadHorizontalMetrics(FontModel font, FontSource p, uint tableOffset, int numberOfHMetrics, int numGlyphs) { ushort advancedWidth = 0; short leftSideBearing = 0; p.Offset = tableOffset; for (var i = 0; i < numGlyphs; i++) { if (i < numberOfHMetrics) { advancedWidth = p.ReadUShort(); leftSideBearing = p.ReadShort(); } font._glyphs[i] = new GlyphInfo(advancedWidth, leftSideBearing); } }
public static GlyphComponent Load(FontSource p) { var gc = new GlyphComponent(); var flags = p.ReadUShort(); gc.GlyphId = p.ReadUShort(); if ((flags & 1) > 0) { if ((flags & 2) > 0) { gc.DX = p.ReadShort(); gc.DY = p.ReadShort(); } else { gc.MatchedPoints = new[] { p.ReadUShort(), p.ReadUShort() }; } } else { if ((flags & 2) > 0) { gc.DX = p.ReadSByte(); gc.DY = p.ReadSByte(); } else { gc.MatchedPoints = new[] { p.ReadUShort(), p.ReadUShort() }; } } if ((flags & 8) > 0) { gc.XScale = gc.YScale = p.ReadF2Dot14(); } else if ((flags & 64) > 0) { gc.XScale = p.ReadF2Dot14(); gc.YScale = p.ReadF2Dot14(); } else if ((flags & 128) > 0) { gc.XScale = p.ReadF2Dot14(); gc.Scale01 = p.ReadF2Dot14(); gc.Scale10 = p.ReadF2Dot14(); gc.YScale = p.ReadF2Dot14(); } gc.MoreComponents = (flags & 32) > 0; return(gc); }
private static void LoadFontHeader(FontSource p, uint tableOffset, out short indexToLocFormat, out ushort unitsPerEm) { p.Offset = tableOffset; p.ReadUShort(); p.ReadUShort(); p.ReadFixed(); p.ReadUInt(); p.ReadUInt(); p.ReadUShort(); unitsPerEm = p.ReadUShort(); p.Offset += 8 * 2; p.ReadShort(); p.ReadShort(); p.ReadShort(); p.ReadShort(); p.ReadUShort(); p.ReadUShort(); p.ReadShort(); indexToLocFormat = p.ReadShort(); p.ReadShort(); }
private static ushort LoadGlyphCount(FontSource p, uint tableOffset) { p.Offset = tableOffset + 4; return(p.ReadUShort()); }
private static ushort LoadNumberOfHMetrics(FontSource p, uint tableOffset) { p.Offset = tableOffset + 34; return(p.ReadUShort()); }
public GlyphPoint[] GetGlyphPoints(FontSource source) { source.Offset = Offset; var endPtsOfContours = new ushort[NumberOfContours]; for (var i = 0; i < NumberOfContours; i++) { endPtsOfContours[i] = source.ReadUShort(); } //instructionLength = data.ReadUShort(); //instructions = new byte[instructionLength]; //for (var i = 0; i < instructionLength; i++) instructions[i] = data.ReadByte(); // Ignore instructions. var instructionLength = source.ReadUShort(); source.Offset += instructionLength; var numberOfCoordinates = endPtsOfContours[endPtsOfContours.Length - 1] + 1; var points = new List <GlyphPoint>(numberOfCoordinates); for (var i = 0; i < numberOfCoordinates; i++) { var flag = source.ReadByte(); var glyphPoint = new GlyphPoint(flag); points.Add(glyphPoint); if (glyphPoint.IsRepeat) { var count = source.ReadByte(); for (var k = 0; k < count; k++) { points.Add(new GlyphPoint(flag)); i++; } } } foreach (var ep in endPtsOfContours) { points[ep].IsEndPoint = true; } short xSum = 0; short ySum = 0; // Read X foreach (var point in points) { var flag = point.Flag; var isShortX = GetFlag(flag, 1); var isSameX = GetFlag(flag, 4); if (isShortX) { if (isSameX) { xSum += source.ReadByte(); } else { xSum += (short)-source.ReadByte(); } } else { if (!isSameX) { xSum += source.ReadShort(); } } point.X = xSum; } // Read Y foreach (var point in points) { var flag = point.Flag; var isShortY = GetFlag(flag, 2); var isSameY = GetFlag(flag, 5); if (isShortY) { if (isSameY) { ySum += source.ReadByte(); } else { ySum += (short)-source.ReadByte(); } } else { if (!isSameY) { ySum += source.ReadShort(); } } point.Y = ySum; } return(points.ToArray()); }