mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-12 10:19:07 +00:00
219 lines
13 KiB
C#
219 lines
13 KiB
C#
//Apache2, 2016-present, WinterDev, Sam Hocevar <sam@hocevar.net>
|
|
|
|
using System.IO;
|
|
|
|
namespace Typography.OpenFont.Tables
|
|
{
|
|
//from https://docs.microsoft.com/en-us/typography/opentype/spec/otff#otttables
|
|
//Data Types
|
|
|
|
// The following data types are used in the OpenType font file.All OpenType fonts use Motorola-style byte ordering (Big Endian):
|
|
// Data Type Description
|
|
// uint8 8-bit unsigned integer.
|
|
// int8 8-bit signed integer.
|
|
// uint16 16-bit unsigned integer.
|
|
// int16 16-bit signed integer.
|
|
// uint24 24-bit unsigned integer.
|
|
// uint32 32-bit unsigned integer.
|
|
// int32 32-bit signed integer.
|
|
// Fixed 32-bit signed fixed-point number(16.16)
|
|
// FWORD int16 that describes a quantity in font design units.
|
|
// UFWORD uint16 that describes a quantity in font design units.
|
|
// F2DOT14 16 - bit signed fixed number with the low 14 bits of fraction(2.14).
|
|
// LONGDATETIME Date represented in number of seconds since 12:00 midnight, January 1, 1904.The value is represented as a signed 64 - bit integer.
|
|
// Tag Array of four uint8s(length = 32 bits) used to identify a script, language system, feature, or baseline
|
|
// Offset16 Short offset to a table, same as uint16, NULL offset = 0x0000
|
|
// Offset32 Long offset to a table, same as uint32, NULL offset = 0x00000000
|
|
|
|
// https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
|
|
// https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
|
|
|
|
public abstract class GlyphShapingTableEntry : TableEntry
|
|
{
|
|
|
|
public ushort MajorVersion { get; private set; }
|
|
public ushort MinorVersion { get; private set; }
|
|
|
|
public ScriptList ScriptList { get; private set; }
|
|
public FeatureList FeatureList { get; private set; }
|
|
|
|
/// <summary>
|
|
/// read script_list, feature_list, and skip look up table
|
|
/// </summary>
|
|
internal bool OnlyScriptList { get; set; } //
|
|
|
|
protected override void ReadContentFrom(BinaryReader reader)
|
|
{
|
|
//-------------------------------------------
|
|
// GPOS/GSUB Header
|
|
// The GPOS/GSUB table begins with a header that contains a version number for the table. Two versions are defined.
|
|
// Version 1.0 contains offsets to three tables: ScriptList, FeatureList, and LookupList.
|
|
// Version 1.1 also includes an offset to a FeatureVariations table.
|
|
// For descriptions of these tables, see the chapter, OpenType Layout Common Table Formats .
|
|
// Example 1 at the end of this chapter shows a GPOS/GSUB Header table definition.
|
|
//
|
|
// GPOS/GSUB Header, Version 1.0
|
|
// Value Type Description
|
|
// uint16 MajorVersion Major version of the GPOS/GSUB table, = 1
|
|
// uint16 MinorVersion Minor version of the GPOS/GSUB table, = 0
|
|
// Offset16 ScriptList Offset to ScriptList table, from beginning of GPOS/GSUB table
|
|
// Offset16 FeatureList Offset to FeatureList table, from beginning of GPOS/GSUB table
|
|
// Offset16 LookupList Offset to LookupList table, from beginning of GPOS/GSUB table
|
|
//
|
|
// GPOS/GSUB Header, Version 1.1
|
|
// Value Type Description
|
|
// uint16 MajorVersion Major version of the GPOS/GSUB table, = 1
|
|
// uint16 MinorVersion Minor version of the GPOS/GSUB table, = 1
|
|
// Offset16 ScriptList Offset to ScriptList table, from beginning of GPOS/GSUB table
|
|
// Offset16 FeatureList Offset to FeatureList table, from beginning of GPOS/GSUB table
|
|
// Offset16 LookupList Offset to LookupList table, from beginning of GPOS/GSUB table
|
|
// Offset32 FeatureVariations Offset to FeatureVariations table, from beginning of GPOS/GSUB table (may be NULL)
|
|
|
|
long tableStartAt = reader.BaseStream.Position;
|
|
|
|
MajorVersion = reader.ReadUInt16();
|
|
MinorVersion = reader.ReadUInt16();
|
|
|
|
ushort scriptListOffset = reader.ReadUInt16(); // from beginning of table
|
|
ushort featureListOffset = reader.ReadUInt16(); // from beginning of table
|
|
ushort lookupListOffset = reader.ReadUInt16(); // from beginning of table
|
|
uint featureVariations = (MinorVersion == 1) ? reader.ReadUInt32() : 0; // from beginning of table
|
|
|
|
//-----------------------
|
|
//1. scriptlist
|
|
ScriptList = ScriptList.CreateFrom(reader, tableStartAt + scriptListOffset);
|
|
|
|
if (OnlyScriptList) return; //for preview script-list and feature list only
|
|
|
|
//-----------------------
|
|
//2. feature list
|
|
|
|
FeatureList = FeatureList.CreateFrom(reader, tableStartAt + featureListOffset);
|
|
|
|
//3. lookup list
|
|
ReadLookupListTable(reader, tableStartAt + lookupListOffset);
|
|
|
|
//-----------------------
|
|
//4. feature variations
|
|
if (featureVariations > 0)
|
|
{
|
|
ReadFeatureVariations(reader, tableStartAt + featureVariations);
|
|
}
|
|
}
|
|
|
|
void ReadLookupListTable(BinaryReader reader, long lookupListBeginAt)
|
|
{
|
|
//https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2
|
|
// -----------------------
|
|
// LookupList table
|
|
// -----------------------
|
|
// Type Name Description
|
|
// uint16 LookupCount Number of lookups in this table
|
|
// Offset16 Lookup[LookupCount] Array of offsets to Lookup tables-from beginning of LookupList -zero based (first lookup is Lookup index = 0)
|
|
// -----------------------
|
|
//
|
|
// Lookup Table
|
|
// A Lookup table (Lookup) defines the specific conditions, type,
|
|
// and results of a substitution or positioning action that is used to implement a feature.
|
|
// For example, a substitution operation requires a list of target glyph indices to be replaced,
|
|
// a list of replacement glyph indices, and a description of the type of substitution action.
|
|
// Each Lookup table may contain only one type of information (LookupType),
|
|
// determined by whether the lookup is part of a GSUB or GPOS table. GSUB supports eight LookupTypes,
|
|
// and GPOS supports nine LookupTypes (for details about LookupTypes, see the GSUB and GPOS chapters of the document).
|
|
//
|
|
// Each LookupType is defined with one or more subtables,
|
|
// and each subtable definition provides a different representation format.
|
|
// The format is determined by the content of the information required for an operation and by required storage efficiency.
|
|
// When glyph information is best presented in more than one format,
|
|
// a single lookup may contain more than one subtable, as long as all the subtables are the same LookupType.
|
|
// For example, within a given lookup, a glyph index array format may best represent one set of target glyphs,
|
|
// whereas a glyph index range format may be better for another set of target glyphs.
|
|
//
|
|
// During text processing, a client applies a lookup to each glyph in the string before moving to the next lookup.
|
|
// A lookup is finished for a glyph after the client makes the substitution/positioning operation.
|
|
// To move to the “next” glyph, the client will typically skip all the glyphs that participated in the lookup operation: glyphs
|
|
// that were substituted/positioned as well as any other glyphs that formed a context for the operation.
|
|
// However, in the case of pair positioning operations (i.e., kerning),
|
|
// the “next” glyph in a sequence may be the second glyph of the positioned pair (see pair positioning lookup for details).
|
|
//
|
|
// A Lookup table contains a LookupType, specified as an integer, that defines the type of information stored in the lookup.
|
|
// The LookupFlag specifies lookup qualifiers that assist a text-processing client in substituting or positioning glyphs.
|
|
// The SubTableCount specifies the total number of SubTables.
|
|
// The SubTable array specifies offsets, measured from the beginning of the Lookup table, to each SubTable enumerated in the SubTable array.
|
|
//
|
|
// Lookup table
|
|
// --------------------------------
|
|
// Type Name Description
|
|
// unit16 LookupType Different enumerations for GSUB and GPOS
|
|
// unit16 LookupFlag Lookup qualifiers
|
|
// unit16 SubTableCount Number of SubTables for this lookup
|
|
// Offset16 SubTable[SubTableCount] Array of offsets to SubTables-from beginning of Lookup table
|
|
// uint16 MarkFilteringSet Index (base 0) into GDEF mark glyph sets structure.
|
|
// *** This field is only present if bit UseMarkFilteringSet of lookup flags is set.
|
|
// --------------------------------
|
|
|
|
|
|
// --------------------------------
|
|
//The LookupFlag uses two bytes of data:
|
|
|
|
//Each of the first four bits can be set in order to specify additional instructions for applying a lookup to a glyph string.The LookUpFlag bit enumeration table provides details about the use of these bits.
|
|
//The fifth bit indicates the presence of a MarkFilteringSet field in the Lookup table.
|
|
//The next three bits are reserved for future use.
|
|
|
|
//The high byte is set to specify the type of mark attachment.
|
|
|
|
|
|
//LookupFlag bit enumeration
|
|
//Type Name Description
|
|
//0x0001 rightToLeft This bit relates only to the correct processing of the cursive attachment lookup type(GPOS lookup type 3).When this bit is set, the last glyph in a given sequence to which the cursive attachment lookup is applied, will be positioned on the baseline.
|
|
// Note: Setting of this bit is not intended to be used by operating systems or applications to determine text direction.
|
|
//0x0002 ignoreBaseGlyphs If set, skips over base glyphs
|
|
//0x0004 ignoreLigatures If set, skips over ligatures
|
|
//0x0008 ignoreMarks If set, skips over all combining marks
|
|
//0x0010 useMarkFilteringSet If set, indicates that the lookup table structure is followed by a MarkFilteringSet field.
|
|
// The layout engine skips over all mark glyphs not in the mark filtering set indicated.
|
|
//0x00E0 reserved For future use(Set to zero)
|
|
//0xFF00 markAttachmentType If not zero, skips over all marks of attachment type different from specified.
|
|
// --------------------------------
|
|
|
|
|
|
reader.BaseStream.Seek(lookupListBeginAt, SeekOrigin.Begin);
|
|
ushort lookupCount = reader.ReadUInt16();
|
|
ushort[] lookupTableOffsets = Utils.ReadUInt16Array(reader, lookupCount);
|
|
|
|
//----------------------------------------------
|
|
//load each sub table
|
|
|
|
foreach (ushort lookupTableOffset in lookupTableOffsets)
|
|
{
|
|
long lookupTablePos = lookupListBeginAt + lookupTableOffset;
|
|
reader.BaseStream.Seek(lookupTablePos, SeekOrigin.Begin);
|
|
|
|
ushort lookupType = reader.ReadUInt16(); //Each Lookup table may contain only one type of information (LookupType)
|
|
ushort lookupFlags = reader.ReadUInt16();
|
|
ushort subTableCount = reader.ReadUInt16();
|
|
|
|
//Each LookupType is defined with one or more subtables, and each subtable definition provides a different representation format
|
|
ushort[] subTableOffsets = Utils.ReadUInt16Array(reader, subTableCount);
|
|
|
|
ushort markFilteringSet =
|
|
((lookupFlags & 0x0010) == 0x0010) ? reader.ReadUInt16() : (ushort)0;
|
|
|
|
ReadLookupTable(reader,
|
|
lookupTablePos,
|
|
lookupType,
|
|
lookupFlags,
|
|
subTableOffsets, //Array of offsets to SubTables-from beginning of Lookup table
|
|
markFilteringSet);
|
|
}
|
|
}
|
|
|
|
protected abstract void ReadLookupTable(BinaryReader reader, long lookupTablePos,
|
|
ushort lookupType, ushort lookupFlags,
|
|
ushort[] subTableOffsets, ushort markFilteringSet);
|
|
protected abstract void ReadFeatureVariations(BinaryReader reader, long featureVariationsBeginAt);
|
|
|
|
|
|
}
|
|
}
|