// 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());
}
}