/// <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); } }
private void WriteFontTable(FontTable table) { // Start position required to generate checksum and length long startPosition = stream.SetRestorePoint(); // FontTable subclass is responsible for writing itself table.Write(this); // Align table on 4-byte boundary int padding = stream.Pad(); // Restore will reset stream position back to startPosition long endPosition = stream.Restore(); // The table length not including the padding table.Entry.Length = (uint)(endPosition - startPosition - padding); table.Entry.Offset = (uint)startPosition; table.Entry.CheckSum = CalculateCheckSum(table.Entry.Length); }
/// <summary> /// Reads a string from the storage area beginning at <i>offset</i> /// consisting of <i>length</i> bytes. The returned string will be /// converted using the Unicode encoding. /// </summary> /// <param name="stream">Big-endian font stream.</param> /// <param name="stringOffset"> /// The offset in bytes from the beginning of the string storage area. /// </param> /// <param name="length">The length of the string in bytes.</param> /// <returns></returns> private string ReadString(FontFileStream stream, int stringOffset, int length) { // Set a restore point stream.SetRestorePoint(); // Navigate to beginning of string stream.Position = Entry.Offset + storageOffset + stringOffset; // Read string data byte[] buffer = new byte[length]; stream.Read(buffer, 0, length); stream.Restore(); // Convert to a little-endian Unicode string return(Encoding.BigEndianUnicode.GetString(buffer)); }
/// <summary> /// Reads a string from the storage area beginning at <i>offset</i> /// consisting of <i>length</i> bytes. The returned string will be /// converted using the Unicode encoding. /// </summary> /// <param name="stream">Big-endian font stream.</param> /// <param name="stringOffset"> /// The offset in bytes from the beginning of the string storage area. /// </param> /// <param name="length">The length of the string in bytes.</param> /// <returns></returns> private string ReadString(FontFileStream stream, int stringOffset, int length) { // Set a restore point stream.SetRestorePoint(); // Navigate to beginning of string stream.Position = Entry.Offset + storageOffset + stringOffset; // Read string data byte[] buffer = new byte[length]; stream.Read(buffer, 0, length); stream.Restore(); // Convert to a little-endian Unicode string return Encoding.BigEndianUnicode.GetString(buffer); }