public static FeatureList CreateFrom(BinaryReader reader, long beginAt) { //https://www.microsoft.com/typography/otspec/chapter2.htm //FeatureList table //Type Name Description //USHORT FeatureCount Number of FeatureRecords in this table //struct FeatureRecord[FeatureCount] Array of FeatureRecords-zero-based (first feature has FeatureIndex = 0)-listed alphabetically by FeatureTag //FeatureRecord //Type Name Description //Tag FeatureTag 4-byte feature identification tag //Offset Feature Offset to Feature table-from beginning of FeatureList reader.BaseStream.Seek(beginAt, SeekOrigin.Begin); // FeatureList featureList = new FeatureList(); ushort featureCount = reader.ReadUInt16(); FeatureRecord[] featureRecords = new FeatureRecord[featureCount]; for (int i = 0; i < featureCount; ++i) { //read script record featureRecords[i] = new FeatureRecord( reader.ReadUInt32(), //feature tag reader.ReadInt16()); //offset } //read each feature table FeatureTable[] featureTables = featureList.featureTables = new FeatureTable[featureCount]; for (int i = 0; i < featureCount; ++i) { FeatureRecord frecord = featureRecords[i]; (featureTables[i] = FeatureTable.CreateFrom(reader, beginAt + frecord.offset)).FeatureTag = frecord.featureTag; } return featureList; }
protected override void ReadContentFrom(BinaryReader reader) { gposTableStartAt = reader.BaseStream.Position; //------------------------------------------- // GPOS Header //The GPOS 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 Header table definition. //GPOS Header, Version 1.0 //Value Type Description //USHORT MajorVersion Major version of the GPOS table, = 1 //USHORT MinorVersion Minor version of the GPOS table, = 0 //Offset ScriptList Offset to ScriptList table, from beginning of GPOS table //Offset FeatureList Offset to FeatureList table, from beginning of GPOS table //Offset LookupList Offset to LookupList table, from beginning of GPOS table //GPOS Header, Version 1.1 //Value Type Description //USHORT MajorVersion Major version of the GPOS table, = 1 //USHORT MinorVersion Minor version of the GPOS table, = 1 //Offset ScriptList Offset to ScriptList table, from beginning of GPOS table //Offset FeatureList Offset to FeatureList table, from beginning of GPOS table //Offset LookupList Offset to LookupList table, from beginning of GPOS table //ULONG FeatureVariations Offset to FeatureVariations table, from beginning of GPOS table (may be NULL) this.MajorVersion = reader.ReadUInt16(); this.MinorVersion = reader.ReadUInt16(); ushort scriptListOffset = reader.ReadUInt16();//from beginning of GSUB table ushort featureListOffset = reader.ReadUInt16();//from beginning of GSUB table ushort lookupListOffset = reader.ReadUInt16();//from beginning of GSUB table uint featureVariations = (MinorVersion == 1) ? reader.ReadUInt32() : 0;//from beginning of GSUB table //----------------------- //1. scriptlist scriptList = ScriptList.CreateFrom(reader, gposTableStartAt + scriptListOffset); //----------------------- //2. feature list featureList = FeatureList.CreateFrom(reader, gposTableStartAt + featureListOffset); //----------------------- //3. lookup list ReadLookupListTable(reader, gposTableStartAt + lookupListOffset); //----------------------- //4. feature variations if (featureVariations > 0) { reader.BaseStream.Seek(this.Header.Offset + featureVariations, SeekOrigin.Begin); ReadFeaureVariations(reader); } }