/// <summary> /// Read the header table from the data stream. /// </summary> public static HeaderTable Load(TrueTypeDataBytes data, TrueTypeHeaderTable table) { data.Seek(table.Offset); var version = data.Read32Fixed(); var fontRevision = data.Read32Fixed(); var checkSumAdjustment = data.ReadUnsignedInt(); var magicNumber = data.ReadUnsignedInt(); if (magicNumber != 0x5F0F3CF5) { throw new InvalidOperationException("The magic number for this TrueType font was incorrect. Value was: " + magicNumber); } var flags = data.ReadUnsignedShort(); var unitsPerEm = data.ReadUnsignedShort(); if (unitsPerEm < 16 || unitsPerEm > 16384) { throw new InvalidOperationException($"The units per em for this TrueType font was incorrect, value should be between 16 and 16384 but found {unitsPerEm} istead."); } DateTime created; try { created = data.ReadInternationalDate(); } catch (InvalidFontFormatException) { created = DateTime.MinValue; } DateTime modified; try { modified = data.ReadInternationalDate(); } catch (InvalidFontFormatException) { modified = DateTime.MinValue; } var xMin = data.ReadSignedShort(); var yMin = data.ReadSignedShort(); var xMax = data.ReadSignedShort(); var yMax = data.ReadSignedShort(); var macStyle = data.ReadUnsignedShort(); var lowestRecPpem = data.ReadUnsignedShort(); var fontDirectionHint = data.ReadSignedShort(); var indexToLocFormat = (IndexToLocationTable.EntryFormat)data.ReadSignedShort(); var glyphDataFormat = data.ReadSignedShort(); return(new HeaderTable(table, version, fontRevision, checkSumAdjustment, magicNumber, flags, unitsPerEm, created, modified, xMin, yMin, xMax, yMax, macStyle, lowestRecPpem, fontDirectionHint, indexToLocFormat, glyphDataFormat)); }
private static TrueTypeHeaderTable?ReadTable(TrueTypeDataBytes data) { var tag = data.ReadTag(); var checksum = data.ReadUnsignedInt(); var offset = data.ReadUnsignedInt(); var length = data.ReadUnsignedInt(); // skip tables with zero length (except glyf) if (length == 0 && !string.Equals(tag, TrueTypeHeaderTable.Glyf)) { return(null); } return(new TrueTypeHeaderTable(tag, checksum, offset, length)); }
public static PostScriptTable Load(TrueTypeDataBytes data, TrueTypeHeaderTable table, BasicMaximumProfileTable maximumProfileTable) { data.Seek(table.Offset); var formatType = data.Read32Fixed(); var italicAngle = data.Read32Fixed(); var underlinePosition = data.ReadSignedShort(); var underlineThickness = data.ReadSignedShort(); var isFixedPitch = data.ReadUnsignedInt(); var minMemType42 = data.ReadUnsignedInt(); var maxMemType42 = data.ReadUnsignedInt(); var mimMemType1 = data.ReadUnsignedInt(); var maxMemType1 = data.ReadUnsignedInt(); var glyphNames = GetGlyphNamesByFormat(data, maximumProfileTable, formatType); return(new PostScriptTable(table, (decimal)formatType, (decimal)italicAngle, underlinePosition, underlineThickness, isFixedPitch, minMemType42, maxMemType42, mimMemType1, maxMemType1, glyphNames)); }
public void ReadUnsignedInt() { var input = new ByteArrayInputBytes(new byte[] { 220, 43, 250, 6 }); var data = new TrueTypeDataBytes(input); var result = data.ReadUnsignedInt(); Assert.Equal(3693869574L, result); }
public CMapTable Parse(TrueTypeHeaderTable header, TrueTypeDataBytes data, TableRegister.Builder register) { data.Seek(header.Offset); var tableVersionNumber = data.ReadUnsignedShort(); var numberOfEncodingTables = data.ReadUnsignedShort(); var subTableHeaders = new SubTableHeaderEntry[numberOfEncodingTables]; for (int i = 0; i < numberOfEncodingTables; i++) { var platformId = (TrueTypeCMapPlatform)data.ReadUnsignedShort(); var encodingId = data.ReadUnsignedShort(); var offset = data.ReadUnsignedInt(); subTableHeaders[i] = new SubTableHeaderEntry(platformId, encodingId, offset); } var tables = new List <ICMapSubTable>(numberOfEncodingTables); var numberofGlyphs = register.MaximumProfileTable.NumberOfGlyphs; for (var i = 0; i < subTableHeaders.Length; i++) { var subTableHeader = subTableHeaders[i]; data.Seek(header.Offset + subTableHeader.Offset); var format = data.ReadUnsignedShort(); /* * There are 9 currently available formats: * 0: Character code and glyph indices are restricted to a single byte. Rare. * 2: Suitable for CJK characters. Contain mixed 8/16 byte encoding. * 4: 2 byte encoding format. Used when character codes fall into (gappy) contiguous ranges. * 6: 'Trimmed table mapping', used when character codes fall into a single contiguous range. This is dense mapping. * 8: 16/32 bit coverage. Uses mixed length character codes. * 10: Similar to format 6, trimmed table/array for 32 bits. * 12: Segmented coverage, similar to format 4 but for 32 bit/4 byte. * 13: Many to one mappings. Used by Apple for the LastResort font. * 14: Unicode variation sequences. * * Many of the formats are obsolete or not really used. Modern fonts will tend to use formats 4, 6 and 12. * For PDF we will support 0, 2 and 4 since these are in the original TrueType spec. */ switch (format) { case 0: { // Simple 1 to 1 mapping of character codes to glyph codes. var item = ByteEncodingCMapTable.Load(data, subTableHeader.PlatformId, subTableHeader.EncodingId); tables.Add(item); break; } case 2: { // Useful for CJK characters. Use mixed 8/16 bit encoding. var item = HighByteMappingCMapTable.Load(data, numberofGlyphs, subTableHeader.PlatformId, subTableHeader.EncodingId); tables.Add(item); break; } case 4: { // Microsoft's standard mapping table. var item = Format4CMapTable.Load(data, subTableHeader.PlatformId, subTableHeader.EncodingId); tables.Add(item); break; } case 6: { var item = TrimmedTableMappingCMapTable.Load(data, subTableHeader.PlatformId, subTableHeader.EncodingId); tables.Add(item); break; } } } return(new CMapTable(tableVersionNumber, header, tables)); }
public Os2Table Parse(TrueTypeHeaderTable header, TrueTypeDataBytes data, TableRegister.Builder register) { data.Seek(header.Offset); var version = data.ReadUnsignedShort(); var xAvgCharWidth = data.ReadSignedShort(); var weightClass = data.ReadUnsignedShort(); var widthClass = data.ReadUnsignedShort(); var typeFlags = data.ReadUnsignedShort(); var ySubscriptXSize = data.ReadSignedShort(); var ySubscriptYSize = data.ReadSignedShort(); var ySubscriptXOffset = data.ReadSignedShort(); var ySubscriptYOffset = data.ReadSignedShort(); var ySuperscriptXSize = data.ReadSignedShort(); var ySuperscriptYSize = data.ReadSignedShort(); var ySuperscriptXOffset = data.ReadSignedShort(); var ySuperscriptYOffset = data.ReadSignedShort(); var yStrikeoutSize = data.ReadSignedShort(); var yStrikeoutPosition = data.ReadSignedShort(); var familyClass = data.ReadSignedShort(); var panose = data.ReadByteArray(10); var ulCharRange1 = data.ReadUnsignedInt(); var ulCharRange2 = data.ReadUnsignedInt(); var ulCharRange3 = data.ReadUnsignedInt(); var ulCharRange4 = data.ReadUnsignedInt(); var vendorIdBytes = data.ReadByteArray(4); var selectionFlags = data.ReadUnsignedShort(); var firstCharacterIndex = data.ReadUnsignedShort(); var lastCharacterIndex = data.ReadUnsignedShort(); var unicodeCharRange = new[] { ulCharRange1, ulCharRange2, ulCharRange3, ulCharRange4 }; var vendorId = Encoding.ASCII.GetString(vendorIdBytes); /* * Documentation for OS/2 version 0 in Apple’s TrueType Reference Manual stops at the usLastCharIndex field * and does not include the last five fields of the table as it was defined by Microsoft. * Some legacy TrueType fonts may have been built with a shortened version 0 OS/2 table. * Applications should check the table length for a version 0 OS/2 table before reading these fields. */ if (version == 0 && header.Length == 68) { return(new Os2Table(header, version, xAvgCharWidth, weightClass, widthClass, typeFlags, ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, ySuperscriptXOffset, ySuperscriptYOffset, yStrikeoutSize, yStrikeoutPosition, familyClass, panose, unicodeCharRange, vendorId, selectionFlags, firstCharacterIndex, lastCharacterIndex)); } short sTypoAscender; short sTypoDescender; short sTypoLineGap; ushort usWinAscent; ushort usWinDescent; try { sTypoAscender = data.ReadSignedShort(); sTypoDescender = data.ReadSignedShort(); sTypoLineGap = data.ReadSignedShort(); usWinAscent = data.ReadUnsignedShort(); usWinDescent = data.ReadUnsignedShort(); } catch { // Font may be invalid. Try falling back to shorter version... return(new Os2Table(header, version, xAvgCharWidth, weightClass, widthClass, typeFlags, ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, ySuperscriptXOffset, ySuperscriptYOffset, yStrikeoutSize, yStrikeoutPosition, familyClass, panose, unicodeCharRange, vendorId, selectionFlags, firstCharacterIndex, lastCharacterIndex)); } if (version == 0) { return(new Os2RevisedVersion0Table(header, version, xAvgCharWidth, weightClass, widthClass, typeFlags, ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, ySuperscriptXOffset, ySuperscriptYOffset, yStrikeoutSize, yStrikeoutPosition, familyClass, panose, unicodeCharRange, vendorId, selectionFlags, firstCharacterIndex, lastCharacterIndex, sTypoAscender, sTypoDescender, sTypoLineGap, usWinAscent, usWinDescent)); } var ulCodePageRange1 = data.ReadUnsignedInt(); var ulCodePageRange2 = data.ReadUnsignedInt(); if (version == 1) { return(new Os2Version1Table(header, version, xAvgCharWidth, weightClass, widthClass, typeFlags, ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, ySuperscriptXOffset, ySuperscriptYOffset, yStrikeoutSize, yStrikeoutPosition, familyClass, panose, unicodeCharRange, vendorId, selectionFlags, firstCharacterIndex, lastCharacterIndex, sTypoAscender, sTypoDescender, sTypoLineGap, usWinAscent, usWinDescent, ulCodePageRange1, ulCodePageRange2)); } var sxHeight = data.ReadSignedShort(); var sCapHeight = data.ReadSignedShort(); var usDefaultChar = data.ReadUnsignedShort(); var usBreakChar = data.ReadUnsignedShort(); var usMaxContext = data.ReadUnsignedShort(); if (version < 5) { return(new Os2Version2To4OpenTypeTable(header, version, xAvgCharWidth, weightClass, widthClass, typeFlags, ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, ySuperscriptXOffset, ySuperscriptYOffset, yStrikeoutSize, yStrikeoutPosition, familyClass, panose, unicodeCharRange, vendorId, selectionFlags, firstCharacterIndex, lastCharacterIndex, sTypoAscender, sTypoDescender, sTypoLineGap, usWinAscent, usWinDescent, ulCodePageRange1, ulCodePageRange2, sxHeight, sCapHeight, usDefaultChar, usBreakChar, usMaxContext)); } var usLowerOpticalPointSize = data.ReadUnsignedShort(); var usUpperOpticalPointSize = data.ReadUnsignedShort(); return(new Os2Version5OpenTypeTable(header, version, xAvgCharWidth, weightClass, widthClass, typeFlags, ySubscriptXSize, ySubscriptYSize, ySubscriptXOffset, ySubscriptYOffset, ySuperscriptXSize, ySuperscriptYSize, ySuperscriptXOffset, ySuperscriptYOffset, yStrikeoutSize, yStrikeoutPosition, familyClass, panose, unicodeCharRange, vendorId, selectionFlags, firstCharacterIndex, lastCharacterIndex, sTypoAscender, sTypoDescender, sTypoLineGap, usWinAscent, usWinDescent, ulCodePageRange1, ulCodePageRange2, sxHeight, sCapHeight, usDefaultChar, usBreakChar, usMaxContext, usLowerOpticalPointSize, usUpperOpticalPointSize)); }