// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.Fonts.Tables.General.Kern {
///
/// Represents the coverage field of a kerning subtable, describing the format
/// and properties of the kerning data.
///
///
internal readonly struct KerningCoverage
{
///
/// Initializes a new instance of the struct.
///
/// Whether the table contains horizontal kerning data.
/// Whether the table contains minimum values instead of kerning values.
/// Whether kerning is perpendicular to the flow of text.
/// Whether the kerning value should replace the currently accumulated value.
/// The subtable format number.
private KerningCoverage(bool horizontal, bool hasMinimum, bool crossStream, bool overrideAccumulator, byte format)
{
this.Horizontal = horizontal;
this.HasMinimum = hasMinimum;
this.CrossStream = crossStream;
this.OverrideAccumulator = overrideAccumulator;
this.Format = format;
}
///
/// Gets a value indicating whether the table contains horizontal kerning data.
/// If , the table contains vertical kerning data.
///
public bool Horizontal { get; }
///
/// Gets a value indicating whether the table contains minimum values.
/// If , the table contains kerning values.
///
public bool HasMinimum { get; }
///
/// Gets a value indicating whether kerning is perpendicular to the flow of text.
///
public bool CrossStream { get; }
///
/// Gets a value indicating whether the value in this table should replace
/// the value currently being accumulated.
///
public bool OverrideAccumulator { get; }
///
/// Gets the format of the subtable. Only formats 0 and 2 have been defined.
///
public byte Format { get; }
///
/// Reads a from the specified binary reader.
///
/// The binary reader positioned at the coverage field.
/// The parsed .
public static KerningCoverage Read(BigEndianBinaryReader reader)
{
// The coverage field is divided into the following sub-fields, with sizes given in bits:
// Sub-field | Bits #'s | Size | Description
// -------------|----------|------|-----------------------------------------------
// horizontal | 0 | 1 | 1 if table has horizontal data, 0 if vertical.
// minimum | 1 | 1 | If this bit is set to 1, the table has minimum values.If set to 0, the table has kerning values.
// cross-stream | 2 | 1 | If set to 1, kerning is perpendicular to the flow of the text.
// If the text is normally written horizontally, kerning will be done in the up and down directions.If kerning values are positive, the text will be kerned upwards; if they are negative, the text will be kerned downwards.
// If the text is normally written vertically, kerning will be done in the left and right directions.If kerning values are positive, the text will be kerned to the right; if they are negative, the text will be kerned to the left.
// The value 0x8000 in the kerning data resets the cross-stream kerning back to 0.
// override | 3 | 1 | If this bit is set to 1 the value in this table should replace the value currently being accumulated.
// reserved1 | 4 -7 | 4 | Reserved.This should be set to zero.
// format | 8 -15 | 8 | Format of the subtable. Only formats 0 and 2 have been defined.Formats 1 and 3 through 255 are reserved for future use.
ushort coverage = reader.ReadUInt16();
bool horizontal = (coverage & 0x1) == 1;
bool hasMinimum = ((coverage >> 1) & 0x1) == 1;
bool crossStream = ((coverage >> 2) & 0x1) == 1;
bool overrideAccumulator = ((coverage >> 3) & 0x1) == 1;
byte format = (byte)((coverage >> 7) & 0xff);
return new KerningCoverage(horizontal, hasMinimum, crossStream, overrideAccumulator, format);
}
}
}