# Source code for fontTools.ttLib.tables._a_v_a_r

    from fontTools.misc import sstruct
    from fontTools.misc.fixedTools import (
        fixedToFloat as fi2fl,
        floatToFixed as fl2fi,
        floatToFixedToStr as fl2str,
        strToFixedToFloat as str2fl,
    )
    from fontTools.misc.textTools import bytesjoin
    from fontTools.ttLib import TTLibError
    from . import DefaultTable
    import struct
    import logging

    log = logging.getLogger(__name__)

    # Apple's documentation of 'avar':
    # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6avar.html

    AVAR_HEADER_FORMAT = """
        > # big endian
        majorVersion:  H
        minorVersion:  H
        reserved:      H
        axisCount:     H
    """
    assert sstruct.calcsize(AVAR_HEADER_FORMAT) == 8, sstruct.calcsize(AVAR_HEADER_FORMAT)

    class table__a_v_a_r(DefaultTable.DefaultTable):
        """Axis Variations Table

        This class represents the ``avar`` table of a variable font. The object has one
        substantive attribute, ``segments``, which maps axis tags to a segments dictionary::

            >>> font["avar"].segments   # doctest: +SKIP
            {'wght': {-1.0: -1.0,
              0.0: 0.0,
              0.125: 0.11444091796875,
              0.25: 0.23492431640625,
              0.5: 0.35540771484375,
              0.625: 0.5,
              0.75: 0.6566162109375,
              0.875: 0.81927490234375,
              1.0: 1.0},
             'ital': {-1.0: -1.0, 0.0: 0.0, 1.0: 1.0}}

        Notice that the segments dictionary is made up of normalized values. A valid
        ``avar`` segment mapping must contain the entries ``-1.0: -1.0, 0.0: 0.0, 1.0: 1.0``.
        fontTools does not enforce this, so it is your responsibility to ensure that
        mappings are valid.
        """

        dependencies = ["fvar"]

        def __init__(self, tag=None):
            DefaultTable.DefaultTable.__init__(self, tag)
            self.segments = {}

        def compile(self, ttFont):
            axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
            header = {
                "majorVersion": 1,
                "minorVersion": 0,
                "reserved": 0,
                "axisCount": len(axisTags)
            }
            result = [sstruct.pack(AVAR_HEADER_FORMAT, header)]
            for axis in axisTags:
                mappings = sorted(self.segments[axis].items())
                result.append(struct.pack(">H", len(mappings)))
                for key, value in mappings:
                    fixedKey = fl2fi(key, 14)
                    fixedValue = fl2fi(value, 14)
                    result.append(struct.pack(">hh", fixedKey, fixedValue))
            return bytesjoin(result)

        def decompile(self, data, ttFont):
            axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
            header = {}
            headerSize = sstruct.calcsize(AVAR_HEADER_FORMAT)
            header = sstruct.unpack(AVAR_HEADER_FORMAT, data[0:headerSize])
            majorVersion = header["majorVersion"]
            if majorVersion != 1:
                raise TTLibError("unsupported 'avar' version %d" % majorVersion)
            pos = headerSize
            for axis in axisTags:
                segments = self.segments[axis] = {}
                numPairs = struct.unpack(">H", data[pos:pos+2])[0]
                pos = pos + 2
                for _ in range(numPairs):
                    fromValue, toValue = struct.unpack(">hh", data[pos:pos+4])
                    segments[fi2fl(fromValue, 14)] = fi2fl(toValue, 14)
                    pos = pos + 4

        def toXML(self, writer, ttFont):
            axisTags = [axis.axisTag for axis in ttFont["fvar"].axes]
            for axis in axisTags:
                writer.begintag("segment", axis=axis)
                writer.newline()
                for key, value in sorted(self.segments[axis].items()):
                    key = fl2str(key, 14)
                    value = fl2str(value, 14)
                    writer.simpletag("mapping", **{"from": key, "to": value})
                    writer.newline()
                writer.endtag("segment")
                writer.newline()

        def fromXML(self, name, attrs, content, ttFont):
            if name == "segment":
                axis = attrs["axis"]
                segment = self.segments[axis] = {}
                for element in content:
                    if isinstance(element, tuple):
                        elementName, elementAttrs, _ = element
                        if elementName == "mapping":
                            fromValue = str2fl(elementAttrs["from"], 14)
                            toValue = str2fl(elementAttrs["to"], 14)
                            if fromValue in segment:
                                log.warning("duplicate entry for %s in axis '%s'",
                                            fromValue, axis)
                            segment[fromValue] = toValue