public override bool TryUpdatePosition(
                FontMetrics fontMetrics,
                GPosTable table,
                GlyphPositioningCollection collection,
                Tag feature,
                ushort index,
                int count)
            {
                // Implements Chained Contexts Substitution, Format 1:
                // https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#61-chained-contexts-substitution-format-1-simple-glyph-contexts
                ushort glyphId = collection[index][0];

                if (glyphId == 0)
                {
                    return(false);
                }

                // Search for the current glyph in the Coverage table.
                int offset = this.coverageTable.CoverageIndexOf(glyphId);

                if (offset <= -1)
                {
                    return(false);
                }

                if (this.seqRuleSetTables is null || this.seqRuleSetTables.Length is 0)
                {
                    return(false);
                }

                ChainedSequenceRuleSetTable seqRuleSet = this.seqRuleSetTables[offset];

                if (seqRuleSet is null)
                {
                    return(false);
                }

                // Apply ruleset for the given glyph id.
                ChainedSequenceRuleTable[] rules    = seqRuleSet.SequenceRuleTables;
                SkippingGlyphIterator      iterator = new(fontMetrics, collection, index, this.LookupFlags);

                for (int lookupIndex = 0; lookupIndex < rules.Length; lookupIndex++)
                {
                    ChainedSequenceRuleTable rule = rules[lookupIndex];
                    if (!AdvancedTypographicUtils.ApplyChainedSequenceRule(iterator, rule))
                    {
                        continue;
                    }

                    bool hasChanged = false;
                    for (int j = 0; j < rule.SequenceLookupRecords.Length; j++)
                    {
                        SequenceLookupRecord sequenceLookupRecord = rule.SequenceLookupRecords[j];
                        LookupTable          lookup = table.LookupList.LookupTables[sequenceLookupRecord.LookupListIndex];
                        ushort sequenceIndex        = sequenceLookupRecord.SequenceIndex;
                        if (lookup.TryUpdatePosition(fontMetrics, table, collection, feature, (ushort)(index + sequenceIndex), 1))
                        {
                            hasChanged = true;
                        }
                    }

                    return(hasChanged);
                }

                return(false);
            }
            public override bool TryUpdatePosition(
                FontMetrics fontMetrics,
                GPosTable table,
                GlyphPositioningCollection collection,
                Tag feature,
                ushort index,
                int count)
            {
                // Implements Chained Contexts Substitution for Format 2:
                // https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#62-chained-contexts-substitution-format-2-class-based-glyph-contexts
                ushort glyphId = collection[index][0];

                if (glyphId == 0)
                {
                    return(false);
                }

                // Search for the current glyph in the Coverage table.
                int offset = this.coverageTable.CoverageIndexOf(glyphId);

                if (offset <= -1)
                {
                    return(false);
                }

                // Search in the class definition table to find the class value assigned to the currently glyph.
                int classId = this.inputClassDefinitionTable.ClassIndexOf(glyphId);

                ChainedClassSequenceRuleTable[]? rules = classId >= 0 && classId < this.sequenceRuleSetTables.Length ? this.sequenceRuleSetTables[classId].SubRules : null;
                if (rules is null)
                {
                    return(false);
                }

                // Apply ruleset for the given glyph class id.
                SkippingGlyphIterator iterator = new(fontMetrics, collection, index, this.LookupFlags);

                for (int lookupIndex = 0; lookupIndex < rules.Length; lookupIndex++)
                {
                    ChainedClassSequenceRuleTable rule = rules[lookupIndex];
                    if (!AdvancedTypographicUtils.ApplyChainedClassSequenceRule(iterator, rule, this.inputClassDefinitionTable, this.backtrackClassDefinitionTable, this.lookaheadClassDefinitionTable))
                    {
                        continue;
                    }

                    // It's a match. Perform position update and return true if anything changed.
                    bool hasChanged = false;
                    for (int j = 0; j < rule.SequenceLookupRecords.Length; j++)
                    {
                        SequenceLookupRecord sequenceLookupRecord = rule.SequenceLookupRecords[j];
                        LookupTable          lookup = table.LookupList.LookupTables[sequenceLookupRecord.LookupListIndex];
                        ushort sequenceIndex        = sequenceLookupRecord.SequenceIndex;
                        if (lookup.TryUpdatePosition(fontMetrics, table, collection, feature, (ushort)(index + sequenceIndex), 1))
                        {
                            hasChanged = true;
                        }
                    }

                    return(hasChanged);
                }

                return(false);
            }