public static Woff2Header ReadHeader(Woff2VersionReader version, BigEndianReader reader) { uint flavour = reader.ReadUInt32(); uint length = reader.ReadUInt32(); ushort numTables = reader.ReadUInt16(); var reserved = reader.ReadUInt16(); var totalFontSize = reader.ReadUInt32(); var compressedSize = reader.ReadUInt32(); var major = reader.ReadUInt16(); var minor = reader.ReadUInt16(); Woff2Header header = new Woff2Header(version, numTables); header.Flavour = flavour; header.Length = length; header.TotalFontSize = totalFontSize; header.TotalCompressedSize = compressedSize; header.WoffInnerVersion = new Version(major, minor); header.MetaDataOffset = reader.ReadUInt32(); header.MetaDataLength = reader.ReadUInt32(); header.MetaDataOriginalLength = reader.ReadUInt32(); header.PrivateDataOffset = reader.ReadUInt32(); header.PrivateDataLength = reader.ReadUInt32(); return(header); }
private Woff2CacheData ReadCachableDataAfterVersion(BigEndianReader reader, string source) { Woff2CacheData cache = null; Woff2Header header = Woff2Header.ReadHeader(this, reader); Woff2TableEntryList list = new Woff2TableEntryList(); uint startAt = (uint)reader.Position; uint offset = 0; bool hasOs2 = false; bool hasFHead = false; bool hasName = false; for (var i = 0; i < header.NumberOfTables; i++) { Woff2TableEntry entry = new Woff2TableEntry(offset); entry.Read(reader); if (entry.Tag == TrueTypeTableNames.WindowsMetrics) { hasOs2 = true; } else if (entry.Tag == TrueTypeTableNames.FontHeader) { hasFHead = true; } else if (entry.Tag == TrueTypeTableNames.NamingTable) { hasName = true; } // If the table data has been transformed, // then that will be the offset of the next table if (entry.HasTransformation) { offset += entry.TransformedLength; } else { offset += entry.Length; } list.Add(entry); } if (!(hasOs2 || hasName)) { return(null);// new Utility.UnknownTypefaceInfo(source, "Not all the required tables (head with OS/2 or name) were found in the font file"); } if (!hasFHead) { return(null);// new Utility.UnknownTypefaceInfo(source, "Not all the required tables (head with OS/2 or name) were found in the font file"); } //After the table entries, the entire table data is compressed using the Brotli alogorythm offset = (uint)reader.Position; var compressedData = reader.Read((int)header.TotalCompressedSize); var decompressedData = Woff2Brotli.DecompressData(compressedData); using (var uncompressed = new MemoryStream(decompressedData)) { #if RANGE_CHECK if (uncompressed.Length + offset != header.TotalFontSize) { throw new ArgumentOutOfRangeException("The header uncompressed size is not the same"); } #endif using (var newReader = new BigEndianReader(uncompressed)) { var info = ReadInfoFromTables(list, newReader, source, hasOs2); if (null != info && info.FontCount > 0) { cache = new Woff2CacheData() { Entries = list, Header = header, Info = info, Source = source, UncompressedData = decompressedData }; } } } return(cache); }