// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.IO; namespace SixLabors.Fonts.Tables.Woff { /// /// Represents a table directory entry in a WOFF1 font file. /// Each entry describes a single font table within the WOFF container, /// including its compressed and original lengths. /// See: . /// internal sealed class WoffTableHeader : TableHeader { /// /// Initializes a new instance of the class. /// /// The 4-byte sfnt table identifier. /// The offset to the data from the beginning of the WOFF file. /// The length of the compressed table data, excluding padding. /// The length of the uncompressed table data, excluding padding. /// The checksum of the uncompressed table data. public WoffTableHeader(string tag, uint offset, uint compressedLength, uint origLength, uint checkSum) : base(tag, checkSum, offset, origLength) => this.CompressedLength = compressedLength; /// /// Gets the length of the compressed table data, excluding padding. /// public uint CompressedLength { get; } /// /// Creates a for the table data, decompressing with zlib if necessary. /// /// The stream containing the WOFF font data. /// A positioned at the start of the uncompressed table data. public override BigEndianBinaryReader CreateReader(Stream stream) { // Stream is not compressed. if (this.Length == this.CompressedLength) { return base.CreateReader(stream); } // Read all data from the compressed stream. stream.Seek(this.Offset, SeekOrigin.Begin); using var compressedStream = new IO.ZlibInflateStream(stream); byte[] uncompressedBytes = new byte[this.Length]; int totalBytesRead = 0; int bytesLeftToRead = uncompressedBytes.Length; while (totalBytesRead < this.Length) { int bytesRead = compressedStream.Read(uncompressedBytes, totalBytesRead, bytesLeftToRead); if (bytesRead <= 0) { throw new InvalidFontFileException($"Could not read compressed data! Expected bytes: {this.Length}, bytes read: {totalBytesRead}"); } totalBytesRead += bytesRead; bytesLeftToRead -= bytesRead; } var memoryStream = new MemoryStream(uncompressedBytes); return new BigEndianBinaryReader(memoryStream, false); } // WOFF TableDirectoryEntry // UInt32 | tag | 4-byte sfnt table identifier. // UInt32 | offset | Offset to the data, from beginning of WOFF file. // UInt32 | compLength | Length of the compressed data, excluding padding. // UInt32 | origLength | Length of the uncompressed table, excluding padding. // UInt32 | origChecksum | Checksum of the uncompressed table. /// /// Reads a from the given reader. /// /// The big-endian binary reader. /// The parsed . public static new WoffTableHeader Read(BigEndianBinaryReader reader) => new WoffTableHeader( reader.ReadTag(), reader.ReadUInt32(), reader.ReadUInt32(), reader.ReadUInt32(), reader.ReadUInt32()); } }