/// <summary> /// Reads the Offset and Directory tables. If the FontFileStream represents /// a TrueType collection, this method will look for the aforementioned /// tables belonging to <i>fontName</i>. /// </summary> /// <remarks> /// This method can handle a TrueType collection. /// </remarks> protected void ReadTableHeaders() { // Check for possible TrueType collection string tag = Encoding.ASCII.GetString(stream.ReadTag()); if (tag == TableNames.Ttcf) { // Skip Version field - will be either 1.0 or 2.0 stream.Skip(PrimitiveSizes.ULong); // Number of fonts in TrueType collection int numFonts = (int)stream.ReadULong(); bool foundFont = false; for (int i = 0; i < numFonts && !foundFont; i++) { // Offset from beginning of file to a font's subtable uint directoryOffset = stream.ReadULong(); // Set a restore point since the code below will alter the stream position stream.SetRestorePoint(); stream.Position = directoryOffset; header = new TrueTypeHeader(); header.Read(stream); // To ascertain whether this font is the one we're looking for, // we must read the 'name' table. if (!header.Contains(TableNames.Name)) { throw new Exception("Unable to parse TrueType collection - missing 'head' table."); } // If font name is not supplied, select the first font in the colleciton; // otherwise must have an exact match NameTable nameTable = (NameTable)GetTable(TableNames.Name); if (fontName == String.Empty || nameTable.FullName == fontName) { foundFont = true; } // Stream will now point to the next directory offset stream.Restore(); } // We were unable to locate font in collection if (!foundFont) { throw new Exception("Unable to locate font '" + fontName + "' in TrueType collection"); } } else { stream.Position = 0; // Read Offset and Directory tables header = new TrueTypeHeader(); header.Read(stream); } }
/// <summary> /// Reads the contents of the "post" table from the supplied stream /// at the current position. /// </summary> /// <param name="reader"></param> protected internal override void Read(FontFileReader reader) { FontFileStream stream = reader.Stream; version = stream.ReadFixed(); // The italic angle is stored in the stupid fixed field format. italicAngle = (float)stream.ReadFixed() / 65536.0f; underlinePosition = stream.ReadFWord(); underlineThickness = stream.ReadFWord(); fixedPitch = stream.ReadULong(); minMemType42 = stream.ReadULong(); maxMemType42 = stream.ReadULong(); minMemType1 = stream.ReadULong(); maxMemType1 = stream.ReadULong(); }
protected internal void Read(FontFileStream stream) { // Skip sfnt version (0x00010000 for version 1.0). stream.Skip(PrimitiveSizes.Fixed); // Number of tables int numTables = stream.ReadUShort(); // Skip searchRange, entrySelector and rangeShift entries (3 x ushort) stream.Skip(PrimitiveSizes.UShort*3); directoryEntries = new Hashtable(numTables); for (int i = 0; i < numTables; i++) { DirectoryEntry entry = new DirectoryEntry( stream.ReadTag(), // 4-byte identifier. stream.ReadULong(), // CheckSum for this table. stream.ReadULong(), // Offset from beginning of TrueType font file. stream.ReadULong() // Length of this table. ); directoryEntries.Add(entry.TableName, entry); } }
/// <summary> /// Reads the contents of the "head" table from the current position /// in the supplied stream. /// </summary> /// <param name="reader"></param> protected internal override void Read(FontFileReader reader) { FontFileStream stream = reader.Stream; versionNo = stream.ReadFixed(); fontRevision = stream.ReadFixed(); checkSumAdjustment = stream.ReadULong(); magicNumber = stream.ReadULong(); flags = stream.ReadUShort(); unitsPermEm = stream.ReadUShort(); // Some fonts have dodgy date offsets that cause AddSeconds to throw an exception createDate = GetDate(stream.ReadLongDateTime()); updateDate = GetDate(stream.ReadLongDateTime()); xMin = stream.ReadShort(); yMin = stream.ReadShort(); xMax = stream.ReadShort(); yMax = stream.ReadShort(); macStyle = stream.ReadUShort(); lowestRecPPEM = stream.ReadUShort(); fontDirectionHint = stream.ReadShort(); indexToLocFormat = stream.ReadShort(); glyphDataFormat = stream.ReadShort(); }
protected internal void Read(FontFileStream stream) { // Skip sfnt version (0x00010000 for version 1.0). stream.Skip(PrimitiveSizes.Fixed); // Number of tables int numTables = stream.ReadUShort(); // Skip searchRange, entrySelector and rangeShift entries (3 x ushort) stream.Skip(PrimitiveSizes.UShort * 3); directoryEntries = new Hashtable(numTables); for (int i = 0; i < numTables; i++) { DirectoryEntry entry = new DirectoryEntry( stream.ReadTag(), // 4-byte identifier. stream.ReadULong(), // CheckSum for this table. stream.ReadULong(), // Offset from beginning of TrueType font file. stream.ReadULong() // Length of this table. ); directoryEntries.Add(entry.TableName, entry); } }
/// <summary> /// Calculates the checksum of a <see cref="FontTable"/>. /// </summary> /// <remarks> /// The supplied <i>stream</i> must be positioned at the beginning of /// the table. /// </remarks> /// <param name="length"></param> /// <returns></returns> private uint CalculateCheckSum(long length) { long numBytes = length + (length % 4); uint checkSum = 0; for (long i = 0; i < numBytes; i += PrimitiveSizes.ULong) { checkSum += stream.ReadULong(); if (checkSum > 0xFFFFFFFF) { checkSum = checkSum - 0xFFFFFFFF; } } return(checkSum); }
/// <summary> /// Reads the contents of the "os/2" table from the supplied stream /// at the current position. /// </summary> /// <param name="reader"></param> protected internal override void Read(FontFileReader reader) { FontFileStream stream = reader.Stream; version = stream.ReadUShort(); avgCharWidth = stream.ReadShort(); usWeightClass = stream.ReadUShort(); usWidthClass = stream.ReadUShort(); // According to the OpenType spec, bit 0 must be zero. fsType = (ushort)(stream.ReadUShort() & ~1); subscriptXSize = stream.ReadShort(); subscriptYSize = stream.ReadShort(); subscriptXOffset = stream.ReadShort(); subscriptYOffset = stream.ReadShort(); superscriptXSize = stream.ReadShort(); superscriptYSize = stream.ReadShort(); superscriptXOffset = stream.ReadShort(); superscriptYOffset = stream.ReadShort(); strikeoutSize = stream.ReadShort(); strikeoutPosition = stream.ReadShort(); short familyClass = stream.ReadShort(); classID = (byte)(familyClass >> 8); subclassID = (byte)(familyClass & 255); stream.Read(panose, 0, panose.Length); unicodeRange1 = stream.ReadULong(); unicodeRange2 = stream.ReadULong(); unicodeRange3 = stream.ReadULong(); unicodeRange4 = stream.ReadULong(); vendorID[0] = stream.ReadChar(); vendorID[1] = stream.ReadChar(); vendorID[2] = stream.ReadChar(); vendorID[3] = stream.ReadChar(); fsSelection = stream.ReadUShort(); usFirstCharIndex = stream.ReadUShort(); usLastCharIndex = stream.ReadUShort(); typoAscender = stream.ReadShort(); typoDescender = stream.ReadShort(); typoLineGap = stream.ReadShort(); usWinAscent = stream.ReadUShort(); usWinDescent = stream.ReadUShort(); codePageRange1 = stream.ReadULong(); codePageRange2 = stream.ReadULong(); sxHeight = stream.ReadShort(); sCapHeight = stream.ReadShort(); usDefaultChar = stream.ReadUShort(); usBreakChar = stream.ReadUShort(); usMaxContext = stream.ReadUShort(); }
/// <summary> /// Reads the contents of the "loca" table from the supplied stream /// at the current position. /// </summary> /// <param name="reader"></param> protected internal override void Read(FontFileReader reader) { FontFileStream stream = reader.Stream; // Glyph offsets can be stored in either short of long format bool isShortFormat = reader.GetHeaderTable().IsShortFormat; // Number of glyphs including extra entry int glyphCount = reader.GetMaximumProfileTable().GlyphCount + 1; offsets = new ArrayList(glyphCount); for (int i = 0; i < glyphCount; i++) { offsets.Insert(i, (isShortFormat) ? (uint)(stream.ReadUShort() << 1) : stream.ReadULong()); } }