// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System; namespace SixLabors.Fonts.Tables.AdvancedTypographic.Variations { /// /// Implements reading the Font Variations Table `fvar`. /// /// internal class FVarTable : Table { /// /// The table name identifier for the fvar table. /// internal const string TableName = "fvar"; /// /// Initializes a new instance of the class. /// /// The number of variation axes. /// The array of variation axis records. /// The array of named instance records. public FVarTable(ushort axisCount, VariationAxisRecord[] axes, InstanceRecord[] instances) { this.AxisCount = axisCount; this.Axes = axes; this.Instances = instances; } /// /// Gets the number of variation axes defined in this font. /// public ushort AxisCount { get; } /// /// Gets the array of variation axis records defining each axis (e.g. weight, width). /// public VariationAxisRecord[] Axes { get; } /// /// Gets the array of named instance records defined in this font. /// public InstanceRecord[] Instances { get; } /// /// Loads the fvar table from the specified font reader. /// /// The font reader. /// The , or if the table is not present. public static FVarTable? Load(FontReader reader) { if (!reader.TryGetReaderAtTablePosition(TableName, out BigEndianBinaryReader? binaryReader)) { return null; } using (binaryReader) { return Load(binaryReader); } } /// /// Loads the fvar table from the specified binary reader. /// /// The big-endian binary reader positioned at the start of the fvar table. /// The . public static FVarTable Load(BigEndianBinaryReader reader) { // VariationsTable `fvar` // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | Type | Name | Description | // +=================+========================================+================================================================+ // | uint16 | majorVersion | Major version number of the font variations table — set to 1. | // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | uint16 | minorVersion | Minor version number of the font variations table — set to 0. | // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | Offset16 | axesArrayOffset | Offset in bytes from the beginning of the table to the start | // | | | of the VariationAxisRecord array. | // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | uint16 | (reserved) | This field is permanently reserved. Set to 2. | // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | uint16 | axisCount | The number of variation axes in the font | // | | | (the number of records in the axes array). | // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | uint16 | axisSize | The size in bytes of each VariationAxisRecord | // | | | — set to 20 (0x0014) for this version. | // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | uint16 | instanceCount | The number of named instances defined in the font | // | | | (the number of records in the instances array). | // +-----------------+----------------------------------------+----------------------------------------------------------------+ // | uint16 | instanceSize | The size in bytes of each InstanceRecord | // | | | — set to either axisCount * sizeof(Fixed) + 4, | // | | | or to axisCount * sizeof(Fixed) + 6. | // +-----------------+----------------------------------------+----------------------------------------------------------------+ long startOffset = reader.BaseStream.Position; ushort major = reader.ReadUInt16(); ushort minor = reader.ReadUInt16(); ushort axesArrayOffset = reader.ReadOffset16(); ushort reserved = reader.ReadUInt16(); ushort axisCount = reader.ReadUInt16(); ushort axisSize = reader.ReadUInt16(); ushort instanceCount = reader.ReadUInt16(); ushort instanceSize = reader.ReadUInt16(); if (major != 1) { throw new NotSupportedException("Only version 1 of fvar table is supported"); } VariationAxisRecord[] axesArray = new VariationAxisRecord[axisCount]; for (int i = 0; i < axisCount; i++) { axesArray[i] = VariationAxisRecord.Load(reader, axesArrayOffset + (axisSize * i)); } InstanceRecord[] instances = new InstanceRecord[instanceCount]; long instancesOffset = reader.BaseStream.Position - startOffset; for (int i = 0; i < instanceCount; i++) { instances[i] = InstanceRecord.Load(reader, instancesOffset + (i * instanceSize), axisCount); } return new FVarTable(axisCount, axesArray, instances); } } }