from fontTools.misc import sstruct
from fontTools.misc.textTools import Tag, tostr, binary2num, safeEval
from fontTools.feaLib.error import FeatureLibError
from fontTools.feaLib.lookupDebugInfo import (
    LookupDebugInfo,
    LOOKUP_DEBUG_INFO_KEY,
    LOOKUP_DEBUG_ENV_VAR,
)
from fontTools.feaLib.parser import Parser
from fontTools.feaLib.ast import FeatureFile
from fontTools.feaLib.variableScalar import VariableScalar
from fontTools.otlLib import builder as otl
from fontTools.otlLib.maxContextCalc import maxCtxFont
from fontTools.ttLib import newTable, getTableModule
from fontTools.ttLib.tables import otBase, otTables
from fontTools.otlLib.builder import (
    AlternateSubstBuilder,
    ChainContextPosBuilder,
    ChainContextSubstBuilder,
    LigatureSubstBuilder,
    MultipleSubstBuilder,
    CursivePosBuilder,
    MarkBasePosBuilder,
    MarkLigPosBuilder,
    MarkMarkPosBuilder,
    ReverseChainSingleSubstBuilder,
    SingleSubstBuilder,
    ClassPairPosSubtableBuilder,
    PairPosBuilder,
    SinglePosBuilder,
    ChainContextualRule,
)
from fontTools.otlLib.error import OpenTypeLibError
from fontTools.varLib.varStore import OnlineVarStoreBuilder
from fontTools.varLib.builder import buildVarDevTable
from fontTools.varLib.featureVars import addFeatureVariationsRaw
from fontTools.varLib.models import normalizeValue, piecewiseLinearMap
from collections import defaultdict
import copy
import itertools
from io import StringIO
import logging
import warnings
import os


log = logging.getLogger(__name__)


def addOpenTypeFeatures(font, featurefile, tables=None, debug=False):
    """Add features from a file to a font. Note that this replaces any features
    currently present.

    Args:
        font (feaLib.ttLib.TTFont): The font object.
        featurefile: Either a path or file object (in which case we
            parse it into an AST), or a pre-parsed AST instance.
        tables: If passed, restrict the set of affected tables to those in the
            list.
        debug: Whether to add source debugging information to the font in the
            ``Debg`` table

    """
    builder = Builder(font, featurefile)
    builder.build(tables=tables, debug=debug)


def addOpenTypeFeaturesFromString(
    font, features, filename=None, tables=None, debug=False
):
    """Add features from a string to a font. Note that this replaces any
    features currently present.

    Args:
        font (feaLib.ttLib.TTFont): The font object.
        features: A string containing feature code.
        filename: The directory containing ``filename`` is used as the root of
            relative ``include()`` paths; if ``None`` is provided, the current
            directory is assumed.
        tables: If passed, restrict the set of affected tables to those in the
            list.
        debug: Whether to add source debugging information to the font in the
            ``Debg`` table

    """

    featurefile = StringIO(tostr(features))
    if filename:
        featurefile.name = filename
    addOpenTypeFeatures(font, featurefile, tables=tables, debug=debug)


class Builder(object):
    supportedTables = frozenset(
        Tag(tag)
        for tag in [
            "BASE",
            "GDEF",
            "GPOS",
            "GSUB",
            "OS/2",
            "head",
            "hhea",
            "name",
            "vhea",
            "STAT",
        ]
    )

    def __init__(self, font, featurefile):
        self.font = font
        # 'featurefile' can be either a path or file object (in which case we
        # parse it into an AST), or a pre-parsed AST instance
        if isinstance(featurefile, FeatureFile):
            self.parseTree, self.file = featurefile, None
        else:
            self.parseTree, self.file = None, featurefile
        self.glyphMap = font.getReverseGlyphMap()
        self.varstorebuilder = None
        if "fvar" in font:
            self.axes = font["fvar"].axes
            self.varstorebuilder = OnlineVarStoreBuilder(
                [ax.axisTag for ax in self.axes]
            )
        self.default_language_systems_ = set()
        self.script_ = None
        self.lookupflag_ = 0
        self.lookupflag_markFilterSet_ = None
        self.language_systems = set()
        self.seen_non_DFLT_script_ = False
        self.named_lookups_ = {}
        self.cur_lookup_ = None
        self.cur_lookup_name_ = None
        self.cur_feature_name_ = None
        self.lookups_ = []
        self.lookup_locations = {"GSUB": {}, "GPOS": {}}
        self.features_ = {}  # ('latn', 'DEU ', 'smcp') --> [LookupBuilder*]
        self.required_features_ = {}  # ('latn', 'DEU ') --> 'scmp'
        self.feature_variations_ = {}
        # for feature 'aalt'
        self.aalt_features_ = []  # [(location, featureName)*], for 'aalt'
        self.aalt_location_ = None
        self.aalt_alternates_ = {}
        # for 'featureNames'
        self.featureNames_ = set()
        self.featureNames_ids_ = {}
        # for 'cvParameters'
        self.cv_parameters_ = set()
        self.cv_parameters_ids_ = {}
        self.cv_num_named_params_ = {}
        self.cv_characters_ = defaultdict(list)
        # for feature 'size'
        self.size_parameters_ = None
        # for table 'head'
        self.fontRevision_ = None  # 2.71
        # for table 'name'
        self.names_ = []
        # for table 'BASE'
        self.base_horiz_axis_ = None
        self.base_vert_axis_ = None
        # for table 'GDEF'
        self.attachPoints_ = {}  # "a" --> {3, 7}
        self.ligCaretCoords_ = {}  # "f_f_i" --> {300, 600}
        self.ligCaretPoints_ = {}  # "f_f_i" --> {3, 7}
        self.glyphClassDefs_ = {}  # "fi" --> (2, (file, line, column))
        self.markAttach_ = {}  # "acute" --> (4, (file, line, column))
        self.markAttachClassID_ = {}  # frozenset({"acute", "grave"}) --> 4
        self.markFilterSets_ = {}  # frozenset({"acute", "grave"}) --> 4
        # for table 'OS/2'
        self.os2_ = {}
        # for table 'hhea'
        self.hhea_ = {}
        # for table 'vhea'
        self.vhea_ = {}
        # for table 'STAT'
        self.stat_ = {}
        # for conditionsets
        self.conditionsets_ = {}
        # We will often use exactly the same locations (i.e. the font's masters)
        # for a large number of variable scalars. Instead of creating a model
        # for each, let's share the models.
        self.model_cache = {}

    def build(self, tables=None, debug=False):
        if self.parseTree is None:
            self.parseTree = Parser(self.file, self.glyphMap).parse()
        self.parseTree.build(self)
        # by default, build all the supported tables
        if tables is None:
            tables = self.supportedTables
        else:
            tables = frozenset(tables)
            unsupported = tables - self.supportedTables
            if unsupported:
                unsupported_string = ", ".join(sorted(unsupported))
                raise NotImplementedError(
                    "The following tables were requested but are unsupported: "
                    f"{unsupported_string}."
                )
        if "GSUB" in tables:
            self.build_feature_aalt_()
        if "head" in tables:
            self.build_head()
        if "hhea" in tables:
            self.build_hhea()
        if "vhea" in tables:
            self.build_vhea()
        if "name" in tables:
            self.build_name()
        if "OS/2" in tables:
            self.build_OS_2()
        if "STAT" in tables:
            self.build_STAT()
        for tag in ("GPOS", "GSUB"):
            if tag not in tables:
                continue
            table = self.makeTable(tag)
            if self.feature_variations_:
                self.makeFeatureVariations(table, tag)
            if (
                table.ScriptList.ScriptCount > 0
                or table.FeatureList.FeatureCount > 0
                or table.LookupList.LookupCount > 0
            ):
                fontTable = self.font[tag] = newTable(tag)
                fontTable.table = table
            elif tag in self.font:
                del self.font[tag]
        if any(tag in self.font for tag in ("GPOS", "GSUB")) and "OS/2" in self.font:
            self.font["OS/2"].usMaxContext = maxCtxFont(self.font)
        if "GDEF" in tables:
            gdef = self.buildGDEF()
            if gdef:
                self.font["GDEF"] = gdef
            elif "GDEF" in self.font:
                del self.font["GDEF"]
        if "BASE" in tables:
            base = self.buildBASE()
            if base:
                self.font["BASE"] = base
            elif "BASE" in self.font:
                del self.font["BASE"]
        if debug or os.environ.get(LOOKUP_DEBUG_ENV_VAR):
            self.buildDebg()

    def get_chained_lookup_(self, location, builder_class):
        result = builder_class(self.font, location)
        result.lookupflag = self.lookupflag_
        result.markFilterSet = self.lookupflag_markFilterSet_
        self.lookups_.append(result)
        return result

    def add_lookup_to_feature_(self, lookup, feature_name):
        for script, lang in self.language_systems:
            key = (script, lang, feature_name)
            self.features_.setdefault(key, []).append(lookup)

    def get_lookup_(self, location, builder_class):
        if (
            self.cur_lookup_
            and type(self.cur_lookup_) == builder_class
            and self.cur_lookup_.lookupflag == self.lookupflag_
            and self.cur_lookup_.markFilterSet == self.lookupflag_markFilterSet_
        ):
            return self.cur_lookup_
        if self.cur_lookup_name_ and self.cur_lookup_:
            raise FeatureLibError(
                "Within a named lookup block, all rules must be of "
                "the same lookup type and flag",
                location,
            )
        self.cur_lookup_ = builder_class(self.font, location)
        self.cur_lookup_.lookupflag = self.lookupflag_
        self.cur_lookup_.markFilterSet = self.lookupflag_markFilterSet_
        self.lookups_.append(self.cur_lookup_)
        if self.cur_lookup_name_:
            # We are starting a lookup rule inside a named lookup block.
            self.named_lookups_[self.cur_lookup_name_] = self.cur_lookup_
        if self.cur_feature_name_:
            # We are starting a lookup rule inside a feature. This includes
            # lookup rules inside named lookups inside features.
            self.add_lookup_to_feature_(self.cur_lookup_, self.cur_feature_name_)
        return self.cur_lookup_

    def build_feature_aalt_(self):
        if not self.aalt_features_ and not self.aalt_alternates_:
            return
        # > alternate glyphs will be sorted in the order that the source features
        # > are named in the aalt definition, not the order of the feature definitions
        # > in the file. Alternates defined explicitly ... will precede all others.
        # https://github.com/fonttools/fonttools/issues/836
        alternates = {g: list(a) for g, a in self.aalt_alternates_.items()}
        for location, name in self.aalt_features_ + [(None, "aalt")]:
            feature = [
                (script, lang, feature, lookups)
                for (script, lang, feature), lookups in self.features_.items()
                if feature == name
            ]
            # "aalt" does not have to specify its own lookups, but it might.
            if not feature and name != "aalt":
                warnings.warn("%s: Feature %s has not been defined" % (location, name))
                continue
            for script, lang, feature, lookups in feature:
                for lookuplist in lookups:
                    if not isinstance(lookuplist, list):
                        lookuplist = [lookuplist]
                    for lookup in lookuplist:
                        for glyph, alts in lookup.getAlternateGlyphs().items():
                            alts_for_glyph = alternates.setdefault(glyph, [])
                            alts_for_glyph.extend(
                                g for g in alts if g not in alts_for_glyph
                            )
        single = {
            glyph: repl[0] for glyph, repl in alternates.items() if len(repl) == 1
        }
        multi = {glyph: repl for glyph, repl in alternates.items() if len(repl) > 1}
        if not single and not multi:
            return
        self.features_ = {
            (script, lang, feature): lookups
            for (script, lang, feature), lookups in self.features_.items()
            if feature != "aalt"
        }
        old_lookups = self.lookups_
        self.lookups_ = []
        self.start_feature(self.aalt_location_, "aalt")
        if single:
            single_lookup = self.get_lookup_(location, SingleSubstBuilder)
            single_lookup.mapping = single
        if multi:
            multi_lookup = self.get_lookup_(location, AlternateSubstBuilder)
            multi_lookup.alternates = multi
        self.end_feature()
        self.lookups_.extend(old_lookups)

    def build_head(self):
        if not self.fontRevision_:
            return
        table = self.font.get("head")
        if not table:  # this only happens for unit tests
            table = self.font["head"] = newTable("head")
            table.decompile(b"\0" * 54, self.font)
            table.tableVersion = 1.0
            table.created = table.modified = 3406620153  # 2011-12-13 11:22:33
        table.fontRevision = self.fontRevision_

    def build_hhea(self):
        if not self.hhea_:
            return
        table = self.font.get("hhea")
        if not table:  # this only happens for unit tests
            table = self.font["hhea"] = newTable("hhea")
            table.decompile(b"\0" * 36, self.font)
            table.tableVersion = 0x00010000
        if "caretoffset" in self.hhea_:
            table.caretOffset = self.hhea_["caretoffset"]
        if "ascender" in self.hhea_:
            table.ascent = self.hhea_["ascender"]
        if "descender" in self.hhea_:
            table.descent = self.hhea_["descender"]
        if "linegap" in self.hhea_:
            table.lineGap = self.hhea_["linegap"]

    def build_vhea(self):
        if not self.vhea_:
            return
        table = self.font.get("vhea")
        if not table:  # this only happens for unit tests
            table = self.font["vhea"] = newTable("vhea")
            table.decompile(b"\0" * 36, self.font)
            table.tableVersion = 0x00011000
        if "verttypoascender" in self.vhea_:
            table.ascent = self.vhea_["verttypoascender"]
        if "verttypodescender" in self.vhea_:
            table.descent = self.vhea_["verttypodescender"]
        if "verttypolinegap" in self.vhea_:
            table.lineGap = self.vhea_["verttypolinegap"]

    def get_user_name_id(self, table):
        # Try to find first unused font-specific name id
        nameIDs = [name.nameID for name in table.names]
        for user_name_id in range(256, 32767):
            if user_name_id not in nameIDs:
                return user_name_id

    def buildFeatureParams(self, tag):
        params = None
        if tag == "size":
            params = otTables.FeatureParamsSize()
            (
                params.DesignSize,
                params.SubfamilyID,
                params.RangeStart,
                params.RangeEnd,
            ) = self.size_parameters_
            if tag in self.featureNames_ids_:
                params.SubfamilyNameID = self.featureNames_ids_[tag]
            else:
                params.SubfamilyNameID = 0
        elif tag in self.featureNames_:
            if not self.featureNames_ids_:
                # name table wasn't selected among the tables to build; skip
                pass
            else:
                assert tag in self.featureNames_ids_
                params = otTables.FeatureParamsStylisticSet()
                params.Version = 0
                params.UINameID = self.featureNames_ids_[tag]
        elif tag in self.cv_parameters_:
            params = otTables.FeatureParamsCharacterVariants()
            params.Format = 0
            params.FeatUILabelNameID = self.cv_parameters_ids_.get(
                (tag, "FeatUILabelNameID"), 0
            )
            params.FeatUITooltipTextNameID = self.cv_parameters_ids_.get(
                (tag, "FeatUITooltipTextNameID"), 0
            )
            params.SampleTextNameID = self.cv_parameters_ids_.get(
                (tag, "SampleTextNameID"), 0
            )
            params.NumNamedParameters = self.cv_num_named_params_.get(tag, 0)
            params.FirstParamUILabelNameID = self.cv_parameters_ids_.get(
                (tag, "ParamUILabelNameID_0"), 0
            )
            params.CharCount = len(self.cv_characters_[tag])
            params.Character = self.cv_characters_[tag]
        return params

    def build_name(self):
        if not self.names_:
            return
        table = self.font.get("name")
        if not table:  # this only happens for unit tests
            table = self.font["name"] = newTable("name")
            table.names = []
        for name in self.names_:
            nameID, platformID, platEncID, langID, string = name
            # For featureNames block, nameID is 'feature tag'
            # For cvParameters blocks, nameID is ('feature tag', 'block name')
            if not isinstance(nameID, int):
                tag = nameID
                if tag in self.featureNames_:
                    if tag not in self.featureNames_ids_:
                        self.featureNames_ids_[tag] = self.get_user_name_id(table)
                        assert self.featureNames_ids_[tag] is not None
                    nameID = self.featureNames_ids_[tag]
                elif tag[0] in self.cv_parameters_:
                    if tag not in self.cv_parameters_ids_:
                        self.cv_parameters_ids_[tag] = self.get_user_name_id(table)
                        assert self.cv_parameters_ids_[tag] is not None
                    nameID = self.cv_parameters_ids_[tag]
            table.setName(string, nameID, platformID, platEncID, langID)
        table.names.sort()

    def build_OS_2(self):
        if not self.os2_:
            return
        table = self.font.get("OS/2")
        if not table:  # this only happens for unit tests
            table = self.font["OS/2"] = newTable("OS/2")
            data = b"\0" * sstruct.calcsize(getTableModule("OS/2").OS2_format_0)
            table.decompile(data, self.font)
        version = 0
        if "fstype" in self.os2_:
            table.fsType = self.os2_["fstype"]
        if "panose" in self.os2_:
            panose = getTableModule("OS/2").Panose()
            (
                panose.bFamilyType,
                panose.bSerifStyle,
                panose.bWeight,
                panose.bProportion,
                panose.bContrast,
                panose.bStrokeVariation,
                panose.bArmStyle,
                panose.bLetterForm,
                panose.bMidline,
                panose.bXHeight,
            ) = self.os2_["panose"]
            table.panose = panose
        if "typoascender" in self.os2_:
            table.sTypoAscender = self.os2_["typoascender"]
        if "typodescender" in self.os2_:
            table.sTypoDescender = self.os2_["typodescender"]
        if "typolinegap" in self.os2_:
            table.sTypoLineGap = self.os2_["typolinegap"]
        if "winascent" in self.os2_:
            table.usWinAscent = self.os2_["winascent"]
        if "windescent" in self.os2_:
            table.usWinDescent = self.os2_["windescent"]
        if "vendor" in self.os2_:
            table.achVendID = safeEval("'''" + self.os2_["vendor"] + "'''")
        if "weightclass" in self.os2_:
            table.usWeightClass = self.os2_["weightclass"]
        if "widthclass" in self.os2_:
            table.usWidthClass = self.os2_["widthclass"]
        if "unicoderange" in self.os2_:
            table.setUnicodeRanges(self.os2_["unicoderange"])
        if "codepagerange" in self.os2_:
            pages = self.build_codepages_(self.os2_["codepagerange"])
            table.ulCodePageRange1, table.ulCodePageRange2 = pages
            version = 1
        if "xheight" in self.os2_:
            table.sxHeight = self.os2_["xheight"]
            version = 2
        if "capheight" in self.os2_:
            table.sCapHeight = self.os2_["capheight"]
            version = 2
        if "loweropsize" in self.os2_:
            table.usLowerOpticalPointSize = self.os2_["loweropsize"]
            version = 5
        if "upperopsize" in self.os2_:
            table.usUpperOpticalPointSize = self.os2_["upperopsize"]
            version = 5

        def checkattr(table, attrs):
            for attr in attrs:
                if not hasattr(table, attr):
                    setattr(table, attr, 0)

        table.version = max(version, table.version)
        # this only happens for unit tests
        if version >= 1:
            checkattr(table, ("ulCodePageRange1", "ulCodePageRange2"))
        if version >= 2:
            checkattr(
                table,
                (
                    "sxHeight",
                    "sCapHeight",
                    "usDefaultChar",
                    "usBreakChar",
                    "usMaxContext",
                ),
            )
        if version >= 5:
            checkattr(table, ("usLowerOpticalPointSize", "usUpperOpticalPointSize"))

    def setElidedFallbackName(self, value, location):
        # ElidedFallbackName is a convenience method for setting
        # ElidedFallbackNameID so only one can be allowed
        for token in ("ElidedFallbackName", "ElidedFallbackNameID"):
            if token in self.stat_:
                raise FeatureLibError(
                    f"{token} is already set.",
                    location,
                )
        if isinstance(value, int):
            self.stat_["ElidedFallbackNameID"] = value
        elif isinstance(value, list):
            self.stat_["ElidedFallbackName"] = value
        else:
            raise AssertionError(value)

    def addDesignAxis(self, designAxis, location):
        if "DesignAxes" not in self.stat_:
            self.stat_["DesignAxes"] = []
        if designAxis.tag in (r.tag for r in self.stat_["DesignAxes"]):
            raise FeatureLibError(
                f'DesignAxis already defined for tag "{designAxis.tag}".',
                location,
            )
        if designAxis.axisOrder in (r.axisOrder for r in self.stat_["DesignAxes"]):
            raise FeatureLibError(
                f"DesignAxis already defined for axis number {designAxis.axisOrder}.",
                location,
            )
        self.stat_["DesignAxes"].append(designAxis)

    def addAxisValueRecord(self, axisValueRecord, location):
        if "AxisValueRecords" not in self.stat_:
            self.stat_["AxisValueRecords"] = []
        # Check for duplicate AxisValueRecords
        for record_ in self.stat_["AxisValueRecords"]:
            if (
                {n.asFea() for n in record_.names}
                == {n.asFea() for n in axisValueRecord.names}
                and {n.asFea() for n in record_.locations}
                == {n.asFea() for n in axisValueRecord.locations}
                and record_.flags == axisValueRecord.flags
            ):
                raise FeatureLibError(
                    "An AxisValueRecord with these values is already defined.",
                    location,
                )
        self.stat_["AxisValueRecords"].append(axisValueRecord)

    def build_STAT(self):
        if not self.stat_:
            return

        axes = self.stat_.get("DesignAxes")
        if not axes:
            raise FeatureLibError("DesignAxes not defined", None)
        axisValueRecords = self.stat_.get("AxisValueRecords")
        axisValues = {}
        format4_locations = []
        for tag in axes:
            axisValues[tag.tag] = []
        if axisValueRecords is not None:
            for avr in axisValueRecords:
                valuesDict = {}
                if avr.flags > 0:
                    valuesDict["flags"] = avr.flags
                if len(avr.locations) == 1:
                    location = avr.locations[0]
                    values = location.values
                    if len(values) == 1:  # format1
                        valuesDict.update({"value": values[0], "name": avr.names})
                    if len(values) == 2:  # format3
                        valuesDict.update(
                            {
                                "value": values[0],
                                "linkedValue": values[1],
                                "name": avr.names,
                            }
                        )
                    if len(values) == 3:  # format2
                        nominal, minVal, maxVal = values
                        valuesDict.update(
                            {
                                "nominalValue": nominal,
                                "rangeMinValue": minVal,
                                "rangeMaxValue": maxVal,
                                "name": avr.names,
                            }
                        )
                    axisValues[location.tag].append(valuesDict)
                else:
                    valuesDict.update(
                        {
                            "location": {i.tag: i.values[0] for i in avr.locations},
                            "name": avr.names,
                        }
                    )
                    format4_locations.append(valuesDict)

        designAxes = [
            {
                "ordering": a.axisOrder,
                "tag": a.tag,
                "name": a.names,
                "values": axisValues[a.tag],
            }
            for a in axes
        ]

        nameTable = self.font.get("name")
        if not nameTable:  # this only happens for unit tests
            nameTable = self.font["name"] = newTable("name")
            nameTable.names = []

        if "ElidedFallbackNameID" in self.stat_:
            nameID = self.stat_["ElidedFallbackNameID"]
            name = nameTable.getDebugName(nameID)
            if not name:
                raise FeatureLibError(
                    f"ElidedFallbackNameID {nameID} points "
                    "to a nameID that does not exist in the "
                    '"name" table',
                    None,
                )
        elif "ElidedFallbackName" in self.stat_:
            nameID = self.stat_["ElidedFallbackName"]

        otl.buildStatTable(
            self.font,
            designAxes,
            locations=format4_locations,
            elidedFallbackName=nameID,
        )

    def build_codepages_(self, pages):
        pages2bits = {
            1252: 0,
            1250: 1,
            1251: 2,
            1253: 3,
            1254: 4,
            1255: 5,
            1256: 6,
            1257: 7,
            1258: 8,
            874: 16,
            932: 17,
            936: 18,
            949: 19,
            950: 20,
            1361: 21,
            869: 48,
            866: 49,
            865: 50,
            864: 51,
            863: 52,
            862: 53,
            861: 54,
            860: 55,
            857: 56,
            855: 57,
            852: 58,
            775: 59,
            737: 60,
            708: 61,
            850: 62,
            437: 63,
        }
        bits = [pages2bits[p] for p in pages if p in pages2bits]
        pages = []
        for i in range(2):
            pages.append("")
            for j in range(i * 32, (i + 1) * 32):
                if j in bits:
                    pages[i] += "1"
                else:
                    pages[i] += "0"
        return [binary2num(p[::-1]) for p in pages]

    def buildBASE(self):
        if not self.base_horiz_axis_ and not self.base_vert_axis_:
            return None
        base = otTables.BASE()
        base.Version = 0x00010000
        base.HorizAxis = self.buildBASEAxis(self.base_horiz_axis_)
        base.VertAxis = self.buildBASEAxis(self.base_vert_axis_)

        result = newTable("BASE")
        result.table = base
        return result

    def buildBASEAxis(self, axis):
        if not axis:
            return
        bases, scripts = axis
        axis = otTables.Axis()
        axis.BaseTagList = otTables.BaseTagList()
        axis.BaseTagList.BaselineTag = bases
        axis.BaseTagList.BaseTagCount = len(bases)
        axis.BaseScriptList = otTables.BaseScriptList()
        axis.BaseScriptList.BaseScriptRecord = []
        axis.BaseScriptList.BaseScriptCount = len(scripts)
        for script in sorted(scripts):
            record = otTables.BaseScriptRecord()
            record.BaseScriptTag = script[0]
            record.BaseScript = otTables.BaseScript()
            record.BaseScript.BaseLangSysCount = 0
            record.BaseScript.BaseValues = otTables.BaseValues()
            record.BaseScript.BaseValues.DefaultIndex = bases.index(script[1])
            record.BaseScript.BaseValues.BaseCoord = []
            record.BaseScript.BaseValues.BaseCoordCount = len(script[2])
            for c in script[2]:
                coord = otTables.BaseCoord()
                coord.Format = 1
                coord.Coordinate = c
                record.BaseScript.BaseValues.BaseCoord.append(coord)
            axis.BaseScriptList.BaseScriptRecord.append(record)
        return axis

    def buildGDEF(self):
        gdef = otTables.GDEF()
        gdef.GlyphClassDef = self.buildGDEFGlyphClassDef_()
        gdef.AttachList = otl.buildAttachList(self.attachPoints_, self.glyphMap)
        gdef.LigCaretList = otl.buildLigCaretList(
            self.ligCaretCoords_, self.ligCaretPoints_, self.glyphMap
        )
        gdef.MarkAttachClassDef = self.buildGDEFMarkAttachClassDef_()
        gdef.MarkGlyphSetsDef = self.buildGDEFMarkGlyphSetsDef_()
        gdef.Version = 0x00010002 if gdef.MarkGlyphSetsDef else 0x00010000
        if self.varstorebuilder:
            store = self.varstorebuilder.finish()
            if store:
                gdef.Version = 0x00010003
                gdef.VarStore = store
                varidx_map = store.optimize()

                gdef.remap_device_varidxes(varidx_map)
                if "GPOS" in self.font:
                    self.font["GPOS"].table.remap_device_varidxes(varidx_map)
            self.model_cache.clear()
        if any(
            (
                gdef.GlyphClassDef,
                gdef.AttachList,
                gdef.LigCaretList,
                gdef.MarkAttachClassDef,
                gdef.MarkGlyphSetsDef,
            )
        ) or hasattr(gdef, "VarStore"):
            result = newTable("GDEF")
            result.table = gdef
            return result
        else:
            return None

    def buildGDEFGlyphClassDef_(self):
        if self.glyphClassDefs_:
            classes = {g: c for (g, (c, _)) in self.glyphClassDefs_.items()}
        else:
            classes = {}
            for lookup in self.lookups_:
                classes.update(lookup.inferGlyphClasses())
            for markClass in self.parseTree.markClasses.values():
                for markClassDef in markClass.definitions:
                    for glyph in markClassDef.glyphSet():
                        classes[glyph] = 3
        if classes:
            result = otTables.GlyphClassDef()
            result.classDefs = classes
            return result
        else:
            return None

    def buildGDEFMarkAttachClassDef_(self):
        classDefs = {g: c for g, (c, _) in self.markAttach_.items()}
        if not classDefs:
            return None
        result = otTables.MarkAttachClassDef()
        result.classDefs = classDefs
        return result

    def buildGDEFMarkGlyphSetsDef_(self):
        sets = []
        for glyphs, id_ in sorted(
            self.markFilterSets_.items(), key=lambda item: item[1]
        ):
            sets.append(glyphs)
        return otl.buildMarkGlyphSetsDef(sets, self.glyphMap)

    def buildDebg(self):
        if "Debg" not in self.font:
            self.font["Debg"] = newTable("Debg")
            self.font["Debg"].data = {}
        self.font["Debg"].data[LOOKUP_DEBUG_INFO_KEY] = self.lookup_locations

    def buildLookups_(self, tag):
        assert tag in ("GPOS", "GSUB"), tag
        for lookup in self.lookups_:
            lookup.lookup_index = None
        lookups = []
        for lookup in self.lookups_:
            if lookup.table != tag:
                continue
            lookup.lookup_index = len(lookups)
            self.lookup_locations[tag][str(lookup.lookup_index)] = LookupDebugInfo(
                location=str(lookup.location),
                name=self.get_lookup_name_(lookup),
                feature=None,
            )
            lookups.append(lookup)
        otLookups = []
        for l in lookups:
            try:
                otLookups.append(l.build())
            except OpenTypeLibError as e:
                raise FeatureLibError(str(e), e.location) from e
            except Exception as e:
                location = self.lookup_locations[tag][str(l.lookup_index)].location
                raise FeatureLibError(str(e), location) from e
        return otLookups

    def makeTable(self, tag):
        table = getattr(otTables, tag, None)()
        table.Version = 0x00010000
        table.ScriptList = otTables.ScriptList()
        table.ScriptList.ScriptRecord = []
        table.FeatureList = otTables.FeatureList()
        table.FeatureList.FeatureRecord = []
        table.LookupList = otTables.LookupList()
        table.LookupList.Lookup = self.buildLookups_(tag)

        # Build a table for mapping (tag, lookup_indices) to feature_index.
        # For example, ('liga', (2,3,7)) --> 23.
        feature_indices = {}
        required_feature_indices = {}  # ('latn', 'DEU') --> 23
        scripts = {}  # 'latn' --> {'DEU': [23, 24]} for feature #23,24
        # Sort the feature table by feature tag:
        # https://github.com/fonttools/fonttools/issues/568
        sortFeatureTag = lambda f: (f[0][2], f[0][1], f[0][0], f[1])
        for key, lookups in sorted(self.features_.items(), key=sortFeatureTag):
            script, lang, feature_tag = key
            # l.lookup_index will be None when a lookup is not needed
            # for the table under construction. For example, substitution
            # rules will have no lookup_index while building GPOS tables.
            lookup_indices = tuple(
                [l.lookup_index for l in lookups if l.lookup_index is not None]
            )

            size_feature = tag == "GPOS" and feature_tag == "size"
            force_feature = self.any_feature_variations(feature_tag, tag)
            if len(lookup_indices) == 0 and not size_feature and not force_feature:
                continue

            for ix in lookup_indices:
                try:
                    self.lookup_locations[tag][str(ix)] = self.lookup_locations[tag][
                        str(ix)
                    ]._replace(feature=key)
                except KeyError:
                    warnings.warn(
                        "feaLib.Builder subclass needs upgrading to "
                        "stash debug information. See fonttools#2065."
                    )

            feature_key = (feature_tag, lookup_indices)
            feature_index = feature_indices.get(feature_key)
            if feature_index is None:
                feature_index = len(table.FeatureList.FeatureRecord)
                frec = otTables.FeatureRecord()
                frec.FeatureTag = feature_tag
                frec.Feature = otTables.Feature()
                frec.Feature.FeatureParams = self.buildFeatureParams(feature_tag)
                frec.Feature.LookupListIndex = list(lookup_indices)
                frec.Feature.LookupCount = len(lookup_indices)
                table.FeatureList.FeatureRecord.append(frec)
                feature_indices[feature_key] = feature_index
            scripts.setdefault(script, {}).setdefault(lang, []).append(feature_index)
            if self.required_features_.get((script, lang)) == feature_tag:
                required_feature_indices[(script, lang)] = feature_index

        # Build ScriptList.
        for script, lang_features in sorted(scripts.items()):
            srec = otTables.ScriptRecord()
            srec.ScriptTag = script
            srec.Script = otTables.Script()
            srec.Script.DefaultLangSys = None
            srec.Script.LangSysRecord = []
            for lang, feature_indices in sorted(lang_features.items()):
                langrec = otTables.LangSysRecord()
                langrec.LangSys = otTables.LangSys()
                langrec.LangSys.LookupOrder = None

                req_feature_index = required_feature_indices.get((script, lang))
                if req_feature_index is None:
                    langrec.LangSys.ReqFeatureIndex = 0xFFFF
                else:
                    langrec.LangSys.ReqFeatureIndex = req_feature_index

                langrec.LangSys.FeatureIndex = [
                    i for i in feature_indices if i != req_feature_index
                ]
                langrec.LangSys.FeatureCount = len(langrec.LangSys.FeatureIndex)

                if lang == "dflt":
                    srec.Script.DefaultLangSys = langrec.LangSys
                else:
                    langrec.LangSysTag = lang
                    srec.Script.LangSysRecord.append(langrec)
            srec.Script.LangSysCount = len(srec.Script.LangSysRecord)
            table.ScriptList.ScriptRecord.append(srec)

        table.ScriptList.ScriptCount = len(table.ScriptList.ScriptRecord)
        table.FeatureList.FeatureCount = len(table.FeatureList.FeatureRecord)
        table.LookupList.LookupCount = len(table.LookupList.Lookup)
        return table

    def makeFeatureVariations(self, table, table_tag):
        feature_vars = {}
        has_any_variations = False
        # Sort out which lookups to build, gather their indices
        for (_, _, feature_tag), variations in self.feature_variations_.items():
            feature_vars[feature_tag] = []
            for conditionset, builders in variations.items():
                raw_conditionset = self.conditionsets_[conditionset]
                indices = []
                for b in builders:
                    if b.table != table_tag:
                        continue
                    assert b.lookup_index is not None
                    indices.append(b.lookup_index)
                    has_any_variations = True
                feature_vars[feature_tag].append((raw_conditionset, indices))

        if has_any_variations:
            for feature_tag, conditions_and_lookups in feature_vars.items():
                addFeatureVariationsRaw(
                    self.font, table, conditions_and_lookups, feature_tag
                )

    def any_feature_variations(self, feature_tag, table_tag):
        for (_, _, feature), variations in self.feature_variations_.items():
            if feature != feature_tag:
                continue
            for conditionset, builders in variations.items():
                if any(b.table == table_tag for b in builders):
                    return True
        return False

    def get_lookup_name_(self, lookup):
        rev = {v: k for k, v in self.named_lookups_.items()}
        if lookup in rev:
            return rev[lookup]
        return None

    def add_language_system(self, location, script, language):
        # OpenType Feature File Specification, section 4.b.i
        if script == "DFLT" and language == "dflt" and self.default_language_systems_:
            raise FeatureLibError(
                'If "languagesystem DFLT dflt" is present, it must be '
                "the first of the languagesystem statements",
                location,
            )
        if script == "DFLT":
            if self.seen_non_DFLT_script_:
                raise FeatureLibError(
                    'languagesystems using the "DFLT" script tag must '
                    "precede all other languagesystems",
                    location,
                )
        else:
            self.seen_non_DFLT_script_ = True
        if (script, language) in self.default_language_systems_:
            raise FeatureLibError(
                '"languagesystem %s %s" has already been specified'
                % (script.strip(), language.strip()),
                location,
            )
        self.default_language_systems_.add((script, language))

    def get_default_language_systems_(self):
        # OpenType Feature File specification, 4.b.i. languagesystem:
        # If no "languagesystem" statement is present, then the
        # implementation must behave exactly as though the following
        # statement were present at the beginning of the feature file:
        # languagesystem DFLT dflt;
        if self.default_language_systems_:
            return frozenset(self.default_language_systems_)
        else:
            return frozenset({("DFLT", "dflt")})

    def start_feature(self, location, name):
        self.language_systems = self.get_default_language_systems_()
        self.script_ = "DFLT"
        self.cur_lookup_ = None
        self.cur_feature_name_ = name
        self.lookupflag_ = 0
        self.lookupflag_markFilterSet_ = None
        if name == "aalt":
            self.aalt_location_ = location

    def end_feature(self):
        assert self.cur_feature_name_ is not None
        self.cur_feature_name_ = None
        self.language_systems = None
        self.cur_lookup_ = None
        self.lookupflag_ = 0
        self.lookupflag_markFilterSet_ = None

    def start_lookup_block(self, location, name):
        if name in self.named_lookups_:
            raise FeatureLibError(
                'Lookup "%s" has already been defined' % name, location
            )
        if self.cur_feature_name_ == "aalt":
            raise FeatureLibError(
                "Lookup blocks cannot be placed inside 'aalt' features; "
                "move it out, and then refer to it with a lookup statement",
                location,
            )
        self.cur_lookup_name_ = name
        self.named_lookups_[name] = None
        self.cur_lookup_ = None
        if self.cur_feature_name_ is None:
            self.lookupflag_ = 0
            self.lookupflag_markFilterSet_ = None

    def end_lookup_block(self):
        assert self.cur_lookup_name_ is not None
        self.cur_lookup_name_ = None
        self.cur_lookup_ = None
        if self.cur_feature_name_ is None:
            self.lookupflag_ = 0
            self.lookupflag_markFilterSet_ = None

    def add_lookup_call(self, lookup_name):
        assert lookup_name in self.named_lookups_, lookup_name
        self.cur_lookup_ = None
        lookup = self.named_lookups_[lookup_name]
        if lookup is not None:  # skip empty named lookup
            self.add_lookup_to_feature_(lookup, self.cur_feature_name_)

    def set_font_revision(self, location, revision):
        self.fontRevision_ = revision

    def set_language(self, location, language, include_default, required):
        assert len(language) == 4
        if self.cur_feature_name_ in ("aalt", "size"):
            raise FeatureLibError(
                "Language statements are not allowed "
                'within "feature %s"' % self.cur_feature_name_,
                location,
            )
        if self.cur_feature_name_ is None:
            raise FeatureLibError(
                "Language statements are not allowed "
                "within standalone lookup blocks",
                location,
            )
        self.cur_lookup_ = None

        key = (self.script_, language, self.cur_feature_name_)
        lookups = self.features_.get((key[0], "dflt", key[2]))
        if (language == "dflt" or include_default) and lookups:
            self.features_[key] = lookups[:]
        else:
            self.features_[key] = []
        self.language_systems = frozenset([(self.script_, language)])

        if required:
            key = (self.script_, language)
            if key in self.required_features_:
                raise FeatureLibError(
                    "Language %s (script %s) has already "
                    "specified feature %s as its required feature"
                    % (
                        language.strip(),
                        self.script_.strip(),
                        self.required_features_[key].strip(),
                    ),
                    location,
                )
            self.required_features_[key] = self.cur_feature_name_

    def getMarkAttachClass_(self, location, glyphs):
        glyphs = frozenset(glyphs)
        id_ = self.markAttachClassID_.get(glyphs)
        if id_ is not None:
            return id_
        id_ = len(self.markAttachClassID_) + 1
        self.markAttachClassID_[glyphs] = id_
        for glyph in glyphs:
            if glyph in self.markAttach_:
                _, loc = self.markAttach_[glyph]
                raise FeatureLibError(
                    "Glyph %s already has been assigned "
                    "a MarkAttachmentType at %s" % (glyph, loc),
                    location,
                )
            self.markAttach_[glyph] = (id_, location)
        return id_

    def getMarkFilterSet_(self, location, glyphs):
        glyphs = frozenset(glyphs)
        id_ = self.markFilterSets_.get(glyphs)
        if id_ is not None:
            return id_
        id_ = len(self.markFilterSets_)
        self.markFilterSets_[glyphs] = id_
        return id_

    def set_lookup_flag(self, location, value, markAttach, markFilter):
        value = value & 0xFF
        if markAttach:
            markAttachClass = self.getMarkAttachClass_(location, markAttach)
            value = value | (markAttachClass << 8)
        if markFilter:
            markFilterSet = self.getMarkFilterSet_(location, markFilter)
            value = value | 0x10
            self.lookupflag_markFilterSet_ = markFilterSet
        else:
            self.lookupflag_markFilterSet_ = None
        self.lookupflag_ = value

    def set_script(self, location, script):
        if self.cur_feature_name_ in ("aalt", "size"):
            raise FeatureLibError(
                "Script statements are not allowed "
                'within "feature %s"' % self.cur_feature_name_,
                location,
            )
        if self.cur_feature_name_ is None:
            raise FeatureLibError(
                "Script statements are not allowed " "within standalone lookup blocks",
                location,
            )
        if self.language_systems == {(script, "dflt")}:
            # Nothing to do.
            return
        self.cur_lookup_ = None
        self.script_ = script
        self.lookupflag_ = 0
        self.lookupflag_markFilterSet_ = None
        self.set_language(location, "dflt", include_default=True, required=False)

    def find_lookup_builders_(self, lookups):
        """Helper for building chain contextual substitutions

        Given a list of lookup names, finds the LookupBuilder for each name.
        If an input name is None, it gets mapped to a None LookupBuilder.
        """
        lookup_builders = []
        for lookuplist in lookups:
            if lookuplist is not None:
                lookup_builders.append(
                    [self.named_lookups_.get(l.name) for l in lookuplist]
                )
            else:
                lookup_builders.append(None)
        return lookup_builders

    def add_attach_points(self, location, glyphs, contourPoints):
        for glyph in glyphs:
            self.attachPoints_.setdefault(glyph, set()).update(contourPoints)

    def add_feature_reference(self, location, featureName):
        if self.cur_feature_name_ != "aalt":
            raise FeatureLibError(
                'Feature references are only allowed inside "feature aalt"', location
            )
        self.aalt_features_.append((location, featureName))

    def add_featureName(self, tag):
        self.featureNames_.add(tag)

    def add_cv_parameter(self, tag):
        self.cv_parameters_.add(tag)

    def add_to_cv_num_named_params(self, tag):
        """Adds new items to ``self.cv_num_named_params_``
        or increments the count of existing items."""
        if tag in self.cv_num_named_params_:
            self.cv_num_named_params_[tag] += 1
        else:
            self.cv_num_named_params_[tag] = 1

    def add_cv_character(self, character, tag):
        self.cv_characters_[tag].append(character)

    def set_base_axis(self, bases, scripts, vertical):
        if vertical:
            self.base_vert_axis_ = (bases, scripts)
        else:
            self.base_horiz_axis_ = (bases, scripts)

    def set_size_parameters(
        self, location, DesignSize, SubfamilyID, RangeStart, RangeEnd
    ):
        if self.cur_feature_name_ != "size":
            raise FeatureLibError(
                "Parameters statements are not allowed "
                'within "feature %s"' % self.cur_feature_name_,
                location,
            )
        self.size_parameters_ = [DesignSize, SubfamilyID, RangeStart, RangeEnd]
        for script, lang in self.language_systems:
            key = (script, lang, self.cur_feature_name_)
            self.features_.setdefault(key, [])

    # GSUB rules

    # GSUB 1
    def add_single_subst(self, location, prefix, suffix, mapping, forceChain):
        if self.cur_feature_name_ == "aalt":
            for from_glyph, to_glyph in mapping.items():
                alts = self.aalt_alternates_.setdefault(from_glyph, [])
                if to_glyph not in alts:
                    alts.append(to_glyph)
            return
        if prefix or suffix or forceChain:
            self.add_single_subst_chained_(location, prefix, suffix, mapping)
            return
        lookup = self.get_lookup_(location, SingleSubstBuilder)
        for from_glyph, to_glyph in mapping.items():
            if from_glyph in lookup.mapping:
                if to_glyph == lookup.mapping[from_glyph]:
                    log.info(
                        "Removing duplicate single substitution from glyph"
                        ' "%s" to "%s" at %s',
                        from_glyph,
                        to_glyph,
                        location,
                    )
                else:
                    raise FeatureLibError(
                        'Already defined rule for replacing glyph "%s" by "%s"'
                        % (from_glyph, lookup.mapping[from_glyph]),
                        location,
                    )
            lookup.mapping[from_glyph] = to_glyph

    # GSUB 2
    def add_multiple_subst(
        self, location, prefix, glyph, suffix, replacements, forceChain=False
    ):
        if prefix or suffix or forceChain:
            chain = self.get_lookup_(location, ChainContextSubstBuilder)
            sub = self.get_chained_lookup_(location, MultipleSubstBuilder)
            sub.mapping[glyph] = replacements
            chain.rules.append(ChainContextualRule(prefix, [{glyph}], suffix, [sub]))
            return
        lookup = self.get_lookup_(location, MultipleSubstBuilder)
        if glyph in lookup.mapping:
            if replacements == lookup.mapping[glyph]:
                log.info(
                    "Removing duplicate multiple substitution from glyph"
                    ' "%s" to %s%s',
                    glyph,
                    replacements,
                    f" at {location}" if location else "",
                )
            else:
                raise FeatureLibError(
                    'Already defined substitution for glyph "%s"' % glyph, location
                )
        lookup.mapping[glyph] = replacements

    # GSUB 3
    def add_alternate_subst(self, location, prefix, glyph, suffix, replacement):
        if self.cur_feature_name_ == "aalt":
            alts = self.aalt_alternates_.setdefault(glyph, [])
            alts.extend(g for g in replacement if g not in alts)
            return
        if prefix or suffix:
            chain = self.get_lookup_(location, ChainContextSubstBuilder)
            lookup = self.get_chained_lookup_(location, AlternateSubstBuilder)
            chain.rules.append(ChainContextualRule(prefix, [{glyph}], suffix, [lookup]))
        else:
            lookup = self.get_lookup_(location, AlternateSubstBuilder)
        if glyph in lookup.alternates:
            raise FeatureLibError(
                'Already defined alternates for glyph "%s"' % glyph, location
            )
        # We allow empty replacement glyphs here.
        lookup.alternates[glyph] = replacement

    # GSUB 4
    def add_ligature_subst(
        self, location, prefix, glyphs, suffix, replacement, forceChain
    ):
        if prefix or suffix or forceChain:
            chain = self.get_lookup_(location, ChainContextSubstBuilder)
            lookup = self.get_chained_lookup_(location, LigatureSubstBuilder)
            chain.rules.append(ChainContextualRule(prefix, glyphs, suffix, [lookup]))
        else:
            lookup = self.get_lookup_(location, LigatureSubstBuilder)

        if not all(glyphs):
            raise FeatureLibError("Empty glyph class in substitution", location)

        # OpenType feature file syntax, section 5.d, "Ligature substitution":
        # "Since the OpenType specification does not allow ligature
        # substitutions to be specified on target sequences that contain
        # glyph classes, the implementation software will enumerate
        # all specific glyph sequences if glyph classes are detected"
        for g in itertools.product(*glyphs):
            lookup.ligatures[g] = replacement

    # GSUB 5/6
    def add_chain_context_subst(self, location, prefix, glyphs, suffix, lookups):
        if not all(glyphs) or not all(prefix) or not all(suffix):
            raise FeatureLibError(
                "Empty glyph class in contextual substitution", location
            )
        lookup = self.get_lookup_(location, ChainContextSubstBuilder)
        lookup.rules.append(
            ChainContextualRule(
                prefix, glyphs, suffix, self.find_lookup_builders_(lookups)
            )
        )

    def add_single_subst_chained_(self, location, prefix, suffix, mapping):
        if not mapping or not all(prefix) or not all(suffix):
            raise FeatureLibError(
                "Empty glyph class in contextual substitution", location
            )
        # https://github.com/fonttools/fonttools/issues/512
        # https://github.com/fonttools/fonttools/issues/2150
        chain = self.get_lookup_(location, ChainContextSubstBuilder)
        sub = chain.find_chainable_single_subst(mapping)
        if sub is None:
            sub = self.get_chained_lookup_(location, SingleSubstBuilder)
        sub.mapping.update(mapping)
        chain.rules.append(
            ChainContextualRule(prefix, [list(mapping.keys())], suffix, [sub])
        )

    # GSUB 8
    def add_reverse_chain_single_subst(self, location, old_prefix, old_suffix, mapping):
        if not mapping:
            raise FeatureLibError("Empty glyph class in substitution", location)
        lookup = self.get_lookup_(location, ReverseChainSingleSubstBuilder)
        lookup.rules.append((old_prefix, old_suffix, mapping))

    # GPOS rules

    # GPOS 1
    def add_single_pos(self, location, prefix, suffix, pos, forceChain):
        if prefix or suffix or forceChain:
            self.add_single_pos_chained_(location, prefix, suffix, pos)
        else:
            lookup = self.get_lookup_(location, SinglePosBuilder)
            for glyphs, value in pos:
                if not glyphs:
                    raise FeatureLibError(
                        "Empty glyph class in positioning rule", location
                    )
                otValueRecord = self.makeOpenTypeValueRecord(
                    location, value, pairPosContext=False
                )
                for glyph in glyphs:
                    try:
                        lookup.add_pos(location, glyph, otValueRecord)
                    except OpenTypeLibError as e:
                        raise FeatureLibError(str(e), e.location) from e

    # GPOS 2
    def add_class_pair_pos(self, location, glyphclass1, value1, glyphclass2, value2):
        if not glyphclass1 or not glyphclass2:
            raise FeatureLibError("Empty glyph class in positioning rule", location)
        lookup = self.get_lookup_(location, PairPosBuilder)
        v1 = self.makeOpenTypeValueRecord(location, value1, pairPosContext=True)
        v2 = self.makeOpenTypeValueRecord(location, value2, pairPosContext=True)
        lookup.addClassPair(location, glyphclass1, v1, glyphclass2, v2)

    def add_specific_pair_pos(self, location, glyph1, value1, glyph2, value2):
        if not glyph1 or not glyph2:
            raise FeatureLibError("Empty glyph class in positioning rule", location)
        lookup = self.get_lookup_(location, PairPosBuilder)
        v1 = self.makeOpenTypeValueRecord(location, value1, pairPosContext=True)
        v2 = self.makeOpenTypeValueRecord(location, value2, pairPosContext=True)
        lookup.addGlyphPair(location, glyph1, v1, glyph2, v2)

    # GPOS 3
    def add_cursive_pos(self, location, glyphclass, entryAnchor, exitAnchor):
        if not glyphclass:
            raise FeatureLibError("Empty glyph class in positioning rule", location)
        lookup = self.get_lookup_(location, CursivePosBuilder)
        lookup.add_attachment(
            location,
            glyphclass,
            self.makeOpenTypeAnchor(location, entryAnchor),
            self.makeOpenTypeAnchor(location, exitAnchor),
        )

    # GPOS 4
    def add_mark_base_pos(self, location, bases, marks):
        builder = self.get_lookup_(location, MarkBasePosBuilder)
        self.add_marks_(location, builder, marks)
        if not bases:
            raise FeatureLibError("Empty glyph class in positioning rule", location)
        for baseAnchor, markClass in marks:
            otBaseAnchor = self.makeOpenTypeAnchor(location, baseAnchor)
            for base in bases:
                builder.bases.setdefault(base, {})[markClass.name] = otBaseAnchor

    # GPOS 5
    def add_mark_lig_pos(self, location, ligatures, components):
        builder = self.get_lookup_(location, MarkLigPosBuilder)
        componentAnchors = []
        if not ligatures:
            raise FeatureLibError("Empty glyph class in positioning rule", location)
        for marks in components:
            anchors = {}
            self.add_marks_(location, builder, marks)
            for ligAnchor, markClass in marks:
                anchors[markClass.name] = self.makeOpenTypeAnchor(location, ligAnchor)
            componentAnchors.append(anchors)
        for glyph in ligatures:
            builder.ligatures[glyph] = componentAnchors

    # GPOS 6
    def add_mark_mark_pos(self, location, baseMarks, marks):
        builder = self.get_lookup_(location, MarkMarkPosBuilder)
        self.add_marks_(location, builder, marks)
        if not baseMarks:
            raise FeatureLibError("Empty glyph class in positioning rule", location)
        for baseAnchor, markClass in marks:
            otBaseAnchor = self.makeOpenTypeAnchor(location, baseAnchor)
            for baseMark in baseMarks:
                builder.baseMarks.setdefault(baseMark, {})[
                    markClass.name
                ] = otBaseAnchor

    # GPOS 7/8
    def add_chain_context_pos(self, location, prefix, glyphs, suffix, lookups):
        if not all(glyphs) or not all(prefix) or not all(suffix):
            raise FeatureLibError(
                "Empty glyph class in contextual positioning rule", location
            )
        lookup = self.get_lookup_(location, ChainContextPosBuilder)
        lookup.rules.append(
            ChainContextualRule(
                prefix, glyphs, suffix, self.find_lookup_builders_(lookups)
            )
        )

    def add_single_pos_chained_(self, location, prefix, suffix, pos):
        if not pos or not all(prefix) or not all(suffix):
            raise FeatureLibError(
                "Empty glyph class in contextual positioning rule", location
            )
        # https://github.com/fonttools/fonttools/issues/514
        chain = self.get_lookup_(location, ChainContextPosBuilder)
        targets = []
        for _, _, _, lookups in chain.rules:
            targets.extend(lookups)
        subs = []
        for glyphs, value in pos:
            if value is None:
                subs.append(None)
                continue
            otValue = self.makeOpenTypeValueRecord(
                location, value, pairPosContext=False
            )
            sub = chain.find_chainable_single_pos(targets, glyphs, otValue)
            if sub is None:
                sub = self.get_chained_lookup_(location, SinglePosBuilder)
                targets.append(sub)
            for glyph in glyphs:
                sub.add_pos(location, glyph, otValue)
            subs.append(sub)
        assert len(pos) == len(subs), (pos, subs)
        chain.rules.append(
            ChainContextualRule(prefix, [g for g, v in pos], suffix, subs)
        )

    def add_marks_(self, location, lookupBuilder, marks):
        """Helper for add_mark_{base,liga,mark}_pos."""
        for _, markClass in marks:
            for markClassDef in markClass.definitions:
                for mark in markClassDef.glyphs.glyphSet():
                    if mark not in lookupBuilder.marks:
                        otMarkAnchor = self.makeOpenTypeAnchor(
                            location, copy.deepcopy(markClassDef.anchor)
                        )
                        lookupBuilder.marks[mark] = (markClass.name, otMarkAnchor)
                    else:
                        existingMarkClass = lookupBuilder.marks[mark][0]
                        if markClass.name != existingMarkClass:
                            raise FeatureLibError(
                                "Glyph %s cannot be in both @%s and @%s"
                                % (mark, existingMarkClass, markClass.name),
                                location,
                            )

    def add_subtable_break(self, location):
        self.cur_lookup_.add_subtable_break(location)

    def setGlyphClass_(self, location, glyph, glyphClass):
        oldClass, oldLocation = self.glyphClassDefs_.get(glyph, (None, None))
        if oldClass and oldClass != glyphClass:
            raise FeatureLibError(
                "Glyph %s was assigned to a different class at %s"
                % (glyph, oldLocation),
                location,
            )
        self.glyphClassDefs_[glyph] = (glyphClass, location)

    def add_glyphClassDef(
        self, location, baseGlyphs, ligatureGlyphs, markGlyphs, componentGlyphs
    ):
        for glyph in baseGlyphs:
            self.setGlyphClass_(location, glyph, 1)
        for glyph in ligatureGlyphs:
            self.setGlyphClass_(location, glyph, 2)
        for glyph in markGlyphs:
            self.setGlyphClass_(location, glyph, 3)
        for glyph in componentGlyphs:
            self.setGlyphClass_(location, glyph, 4)

    def add_ligatureCaretByIndex_(self, location, glyphs, carets):
        for glyph in glyphs:
            if glyph not in self.ligCaretPoints_:
                self.ligCaretPoints_[glyph] = carets

    def makeLigCaret(self, location, caret):
        if not isinstance(caret, VariableScalar):
            return caret
        default, device = self.makeVariablePos(location, caret)
        if device is not None:
            return (default, device)
        return default

    def add_ligatureCaretByPos_(self, location, glyphs, carets):
        carets = [self.makeLigCaret(location, caret) for caret in carets]
        for glyph in glyphs:
            if glyph not in self.ligCaretCoords_:
                self.ligCaretCoords_[glyph] = carets

    def add_name_record(self, location, nameID, platformID, platEncID, langID, string):
        self.names_.append([nameID, platformID, platEncID, langID, string])

    def add_os2_field(self, key, value):
        self.os2_[key] = value

    def add_hhea_field(self, key, value):
        self.hhea_[key] = value

    def add_vhea_field(self, key, value):
        self.vhea_[key] = value

    def add_conditionset(self, location, key, value):
        if "fvar" not in self.font:
            raise FeatureLibError(
                "Cannot add feature variations to a font without an 'fvar' table",
                location,
            )

        # Normalize
        axisMap = {
            axis.axisTag: (axis.minValue, axis.defaultValue, axis.maxValue)
            for axis in self.axes
        }

        value = {
            tag: (
                normalizeValue(bottom, axisMap[tag]),
                normalizeValue(top, axisMap[tag]),
            )
            for tag, (bottom, top) in value.items()
        }

        # NOTE: This might result in rounding errors (off-by-ones) compared to
        # rules in Designspace files, since we're working with what's in the
        # `avar` table rather than the original values.
        if "avar" in self.font:
            mapping = self.font["avar"].segments
            value = {
                axis: tuple(
                    piecewiseLinearMap(v, mapping[axis]) if axis in mapping else v
                    for v in condition_range
                )
                for axis, condition_range in value.items()
            }

        self.conditionsets_[key] = value

    def makeVariablePos(self, location, varscalar):
        if not self.varstorebuilder:
            raise FeatureLibError(
                "Can't define a variable scalar in a non-variable font", location
            )

        varscalar.axes = self.axes
        if not varscalar.does_vary:
            return varscalar.default, None

        default, index = varscalar.add_to_variation_store(
            self.varstorebuilder, self.model_cache, self.font.get("avar")
        )

        device = None
        if index is not None and index != 0xFFFFFFFF:
            device = buildVarDevTable(index)

        return default, device

    def makeOpenTypeAnchor(self, location, anchor):
        """ast.Anchor --> otTables.Anchor"""
        if anchor is None:
            return None
        variable = False
        deviceX, deviceY = None, None
        if anchor.xDeviceTable is not None:
            deviceX = otl.buildDevice(dict(anchor.xDeviceTable))
        if anchor.yDeviceTable is not None:
            deviceY = otl.buildDevice(dict(anchor.yDeviceTable))
        for dim in ("x", "y"):
            varscalar = getattr(anchor, dim)
            if not isinstance(varscalar, VariableScalar):
                continue
            if getattr(anchor, dim + "DeviceTable") is not None:
                raise FeatureLibError(
                    "Can't define a device coordinate and variable scalar", location
                )
            default, device = self.makeVariablePos(location, varscalar)
            setattr(anchor, dim, default)
            if device is not None:
                if dim == "x":
                    deviceX = device
                else:
                    deviceY = device
                variable = True

        otlanchor = otl.buildAnchor(
            anchor.x, anchor.y, anchor.contourpoint, deviceX, deviceY
        )
        if variable:
            otlanchor.Format = 3
        return otlanchor

    _VALUEREC_ATTRS = {
        name[0].lower() + name[1:]: (name, isDevice)
        for _, name, isDevice, _ in otBase.valueRecordFormat
        if not name.startswith("Reserved")
    }

    def makeOpenTypeValueRecord(self, location, v, pairPosContext):
        """ast.ValueRecord --> otBase.ValueRecord"""
        if not v:
            return None

        vr = {}
        for astName, (otName, isDevice) in self._VALUEREC_ATTRS.items():
            val = getattr(v, astName, None)
            if not val:
                continue
            if isDevice:
                vr[otName] = otl.buildDevice(dict(val))
            elif isinstance(val, VariableScalar):
                otDeviceName = otName[0:4] + "Device"
                feaDeviceName = otDeviceName[0].lower() + otDeviceName[1:]
                if getattr(v, feaDeviceName):
                    raise FeatureLibError(
                        "Can't define a device coordinate and variable scalar", location
                    )
                vr[otName], device = self.makeVariablePos(location, val)
                if device is not None:
                    vr[otDeviceName] = device
            else:
                vr[otName] = val

        if pairPosContext and not vr:
            vr = {"YAdvance": 0} if v.vertical else {"XAdvance": 0}
        valRec = otl.buildValue(vr)
        return valRec
