#!/usr/bin/env python3
"""Behavioral and metadata regression tests for Pivot Sans."""

from __future__ import annotations

import json
from copy import deepcopy
from functools import lru_cache
from io import BytesIO
from pathlib import Path

import pytest
import uharfbuzz as hb
from fontTools.ttLib import TTFont

ROOT = Path(__file__).resolve().parent.parent
DIST = ROOT / "dist"
UPSTREAM = ROOT / "upstream"
SPEC = json.loads((ROOT / "pipeline" / "spec.json").read_text())

VARIABLES = [
    (DIST / "PivotSans[wght].ttf", "Regular", "PivotSans"),
    (DIST / "PivotSans[wght].woff2", "Regular", "PivotSans"),
    (DIST / "PivotSans-Italic[wght].ttf", "Italic", "PivotSansItalic"),
    (DIST / "PivotSans-Italic[wght].woff2", "Italic", "PivotSansItalic"),
]
UPSTREAM_VARIABLES = [
    (
        DIST / "PivotSans[wght].ttf",
        UPSTREAM / "InclusiveSans-VariableFont_wght.ttf",
    ),
    (
        DIST / "PivotSans-Italic[wght].ttf",
        UPSTREAM / "InclusiveSans-Italic-VariableFont_wght.ttf",
    ),
]
STATIC_STYLES = [
    ("Light", 300, False, "Pivot Sans Light", "Regular", 668),
    ("Regular", 400, False, "Pivot Sans", "Regular", 660),
    ("Medium", 500, False, "Pivot Sans Medium", "Regular", 666),
    ("SemiBold", 600, False, "Pivot Sans SemiBold", "Regular", 671),
    ("Bold", 700, False, "Pivot Sans", "Bold", 677),
    ("LightItalic", 300, True, "Pivot Sans Light", "Italic", 668),
    ("Italic", 400, True, "Pivot Sans", "Italic", 660),
    ("MediumItalic", 500, True, "Pivot Sans Medium", "Italic", 666),
    ("SemiBoldItalic", 600, True, "Pivot Sans SemiBold", "Italic", 671),
    ("BoldItalic", 700, True, "Pivot Sans", "Bold Italic", 677),
]
PINS = [
    ("Wght450", 450, False, "Weight 450", 663),
    ("Wght550", 550, False, "Weight 550", 669),
    ("Wght450Italic", 450, True, "Weight 450 Italic", 663),
    ("Wght550Italic", 550, True, "Weight 550 Italic", 669),
]

DIGITS = "0123456789"
CURRENCIES = "$£¥₹€"
MONEY_GLYPHS = DIGITS + CURRENCIES
MONEY_SAMPLES = [f"{currency}1,234,567.89" for currency in CURRENCIES]
BASE_NAMES = [
    "zero",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
    "nine",
    "dollar",
    "sterling",
    "yen",
    "uni20B9",
    "Euro",
]
SS02_ENCODED = {
    "l": "l",
    "ĺ": "lacute",
    "ļ": "uni013C",
    "ľ": "lcaron",
    "ŀ": "ldot",
    "ł": "lslash",
    "ḷ": "uni1E37",
    "ḻ": "uni1E3B",
}
SS02_LOCALIZED_SOURCE = "uni013C.loclMAH"
SS02_SOURCES = [*SS02_ENCODED.values(), SS02_LOCALIZED_SOURCE]
SS02_TARGETS = {source: f"{source}.ss02" for source in SS02_SOURCES}
SS02_FOOT = "l.foot.ss02"
SS02_TEXT = "".join(SS02_ENCODED)
MATH = {
    "‰": ("perthousand", ("percent", "degree")),
    "≈": ("approxequal", ("asciitilde", "asciitilde")),
    "≠": ("notequal", ("equal", "slash")),
    "≤": ("lessequal", ("less", "minus")),
    "≥": ("greaterequal", ("greater", "minus")),
}
MATH_TEXT = "".join(MATH)
OVERLAP_COMPOUND = 0x0400
ROUND_XY_TO_GRID = 0x0004
SCALED_COMPONENT_OFFSET = 0x0800
UNSCALED_COMPONENT_OFFSET = 0x1000
FULL_FONT_FILES = [
    *sorted(DIST.glob("*.ttf")),
    *sorted(DIST.glob("*.woff2")),
    *sorted((DIST / "static").glob("*.ttf")),
    *sorted((DIST / "static").glob("*.woff2")),
    *sorted((DIST / "pins").glob("*.ttf")),
    *sorted((DIST / "pins").glob("*.woff2")),
]
SUBSET_FONT_FILES = sorted((DIST / "subsets").glob("*.woff2"))


def component_nonflag_semantics(component):
    return (
        component.glyphName,
        getattr(component, "x", 0),
        getattr(component, "y", 0),
        getattr(component, "scale", None),
        getattr(component, "xscale", None),
        getattr(component, "yscale", None),
        getattr(component, "scale01", None),
        getattr(component, "scale10", None),
        getattr(component, "transform", None),
    )


def native_l_offset(font: TTFont, source: str) -> tuple[int, int]:
    if source == "l":
        return (0, 0)
    glyf = font["glyf"]
    source_glyph = glyf[source]
    if source_glyph.isComposite():
        matches = [
            component
            for component in source_glyph.components
            if component.glyphName == "l"
        ]
        assert len(matches) == 1
        assert getattr(matches[0], "transform", None) is None
        return (round(matches[0].x), round(matches[0].y))

    l_coordinates, l_endpoints, _ = glyf["l"].getCoordinates(glyf)
    assert list(l_endpoints) == [3]
    native_l = [(round(x), round(y)) for x, y in l_coordinates]
    source_coordinates, source_endpoints, _ = source_glyph.getCoordinates(glyf)
    source_points = [(round(x), round(y)) for x, y in source_coordinates]
    matches = []
    start = 0
    for end in source_endpoints:
        contour = source_points[start : end + 1]
        start = end + 1
        if len(contour) != len(native_l):
            continue
        dx = contour[0][0] - native_l[0][0]
        dy = contour[0][1] - native_l[0][1]
        if all(
            (x + dx, y + dy) == point
            for (x, y), point in zip(native_l, contour)
        ):
            matches.append((dx, dy))
    assert len(matches) == 1
    return matches[0]


def resolved_geometry(glyph, glyf):
    coordinates, endpoints, flags = glyph.getCoordinates(glyf)
    return (
        tuple((round(x), round(y)) for x, y in coordinates),
        tuple(endpoints),
        tuple(flags),
    )


def assert_ss02_target_recipe(font: TTFont, source: str, target: str):
    glyf = font["glyf"]
    source_glyph = glyf[source]
    target_glyph = glyf[target]
    assert target_glyph.isComposite()
    body_components = target_glyph.components[:-1]
    foot_component = target_glyph.components[-1]

    if source_glyph.isComposite():
        assert len(body_components) == len(source_glyph.components)
        for index, (actual, native) in enumerate(
            zip(body_components, source_glyph.components)
        ):
            assert component_nonflag_semantics(
                actual
            ) == component_nonflag_semantics(native)
            assert actual.flags == native.flags | (
                OVERLAP_COMPOUND if index == 0 else 0
            )
    else:
        assert len(body_components) == 1
        body = body_components[0]
        assert component_nonflag_semantics(body) == (
            source,
            0,
            0,
            None,
            None,
            None,
            None,
            None,
            None,
        )
        assert body.flags == ROUND_XY_TO_GRID | OVERLAP_COMPOUND

    assert component_nonflag_semantics(foot_component) == (
        SS02_FOOT,
        *native_l_offset(font, source),
        None,
        None,
        None,
        None,
        None,
        None,
    )
    assert foot_component.flags == ROUND_XY_TO_GRID
    assert all(
        not glyf[component.glyphName].isComposite()
        for component in target_glyph.components
    )

    body_glyph = deepcopy(target_glyph)
    body_glyph.components = body_components
    assert resolved_geometry(body_glyph, glyf) == resolved_geometry(
        source_glyph, glyf
    )


@lru_cache(maxsize=None)
def sfnt_bytes(path: Path) -> bytes:
    if path.suffix == ".woff2":
        # HarfBuzz builds are not required to include a WOFF2 decoder. Expand
        # through fontTools so this validates the font rather than .notdef.
        font_file = TTFont(path)
        font_file.flavor = None
        stream = BytesIO()
        font_file.save(stream)
        return stream.getvalue()
    return path.read_bytes()


def shape(
    path: Path,
    text: str,
    weight: int | None = None,
    features=None,
    language: str | None = None,
):
    face = hb.Face(sfnt_bytes(path))
    font = hb.Font(face)
    font.scale = (face.upem, face.upem)
    hb.ot_font_set_funcs(font)
    if weight is not None:
        font.set_variations({"wght": weight})
    buffer = hb.Buffer()
    buffer.add_str(text)
    buffer.guess_segment_properties()
    if language is not None:
        buffer.language = language
    hb.shape(font, buffer, features or {})
    return (
        sum(position.x_advance for position in buffer.glyph_positions),
        [info.codepoint for info in buffer.glyph_infos],
        [
            (
                position.x_advance,
                position.y_advance,
                position.x_offset,
                position.y_offset,
            )
            for position in buffer.glyph_positions
        ],
    )


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_variable_money_grid_at_every_integer_weight(path, _, __):
    for weight in range(300, 701):
        _, _, default_positions = shape(path, MONEY_GLYPHS, weight)
        # The grid is opt-in: the inherited figures and currencies must remain
        # proportional when tnum is absent.
        assert len({position[0] for position in default_positions}) > 1

        _, _, positions = shape(
            path, MONEY_GLYPHS, weight, {"tnum": True}
        )
        advances = [position[0] for position in positions]
        assert len(advances) == 15
        assert len(set(advances)) == 1, (path.name, weight, advances)

        widths = {
            shape(path, sample, weight, {"tnum": True})[0]
            for sample in MONEY_SAMPLES
        }
        assert len(widths) == 1, (path.name, weight, sorted(widths))


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_variable_money_grid_named_weight_slots(path, _, __):
    for weight, expected_slot in (
        (300, 668),
        (400, 660),
        (500, 666),
        (600, 671),
        (700, 677),
    ):
        _, _, positions = shape(
            path, MONEY_GLYPHS, weight, {"tnum": True}
        )
        assert [position[0] for position in positions] == [
            expected_slot
        ] * 15


def test_tnum_substitutes_all_public_money_characters_and_heavy_dollar():
    path = DIST / "PivotSans[wght].ttf"
    font = TTFont(path)
    _, default_ids, _ = shape(path, MONEY_GLYPHS, 400)
    _, tabular_ids, _ = shape(
        path, MONEY_GLYPHS, 400, {"tnum": True}
    )
    assert [font.getGlyphName(glyph_id) for glyph_id in default_ids] == BASE_NAMES
    assert [font.getGlyphName(glyph_id) for glyph_id in tabular_ids] == [
        f"{name}.tf" for name in BASE_NAMES
    ]

    _, heavy_ids, heavy_positions = shape(
        path, MONEY_GLYPHS, 700, {"tnum": True}
    )
    heavy_names = [font.getGlyphName(glyph_id) for glyph_id in heavy_ids]
    assert heavy_names[10] == "dollar.BRACKET.varAlt01.tf"
    assert heavy_names[11:] == [f"{name}.tf" for name in BASE_NAMES[11:]]
    assert [position[0] for position in heavy_positions] == [677] * 15


@pytest.mark.parametrize("fork_path,upstream_path", UPSTREAM_VARIABLES)
def test_variable_default_shaping_unchanged(fork_path, upstream_path):
    samples = [
        "Hamburgefontsiv 0123456789",
        "$1,111 £2,222 ¥3,333 ₹4,444 €5,555",
        "acct_Il1l-class lĺļľŀłḷḻ",
        "ÀÁÂÃÄÅ ĀĂĄ ÇĆĈĊČ",
        "TAVATAR office affine",
        "Tiếng Việt rõ ràng",
    ]
    for weight in (300, 350, 400, 450, 500, 550, 600, 650, 700):
        for sample in samples:
            assert shape(fork_path, sample, weight) == shape(
                upstream_path, sample, weight
            )


def test_upright_and_italic_slot_parity():
    upright = DIST / "PivotSans[wght].ttf"
    italic = DIST / "PivotSans-Italic[wght].ttf"
    for weight in range(300, 701):
        assert shape(
            upright, MONEY_GLYPHS, weight, {"tnum": True}
        )[2] == shape(
            italic, MONEY_GLYPHS, weight, {"tnum": True}
        )[2]


@pytest.mark.parametrize("path,_,__", VARIABLES[::2])
def test_ss01_survives(path, _, __):
    assert shape(path, "a", 400)[1] != shape(
        path, "a", 400, {"ss01": True}
    )[1]


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_variable_ss02_is_default_off_and_metric_pure_at_every_integer_weight(
    path, _, __
):
    font = TTFont(path)
    expected_sources = list(SS02_ENCODED.values())
    expected_targets = [SS02_TARGETS[source] for source in expected_sources]

    for weight in range(300, 701):
        default = shape(path, SS02_TEXT, weight)
        explicitly_disabled = shape(
            path, SS02_TEXT, weight, {"ss02": False}
        )
        enabled = shape(path, SS02_TEXT, weight, {"ss02": True})

        assert explicitly_disabled == default
        assert [
            font.getGlyphName(glyph_id) for glyph_id in default[1]
        ] == expected_sources
        assert [
            font.getGlyphName(glyph_id) for glyph_id in enabled[1]
        ] == expected_targets
        assert enabled[0] == default[0]
        assert enabled[2] == default[2]


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_variable_ss02_covers_mah_localized_l_at_every_integer_weight(
    path, _, __
):
    font = TTFont(path)
    for weight in range(300, 701):
        default = shape(path, "ļ", weight, language="mah")
        explicitly_disabled = shape(
            path,
            "ļ",
            weight,
            {"ss02": False},
            language="mah",
        )
        enabled = shape(
            path,
            "ļ",
            weight,
            {"ss02": True},
            language="mah",
        )

        assert explicitly_disabled == default
        assert font.getGlyphName(default[1][0]) == SS02_LOCALIZED_SOURCE
        assert (
            font.getGlyphName(enabled[1][0])
            == SS02_TARGETS[SS02_LOCALIZED_SOURCE]
        )
        assert enabled[0] == default[0]
        assert enabled[2] == default[2]


@pytest.mark.parametrize("path", FULL_FONT_FILES)
def test_ss02_glyph_construction_metrics_and_encoding(path):
    font = TTFont(path)
    glyf = font["glyf"]
    cmap_names = set(font.getBestCmap().values())

    foot = glyf[SS02_FOOT]
    assert not foot.isComposite()
    assert foot.numberOfContours == 1
    assert len(foot.coordinates) == 4
    assert font["hmtx"][SS02_FOOT][0] == font["hmtx"]["l"][0]
    assert SS02_FOOT not in cmap_names

    for source, target in SS02_TARGETS.items():
        assert_ss02_target_recipe(font, source, target)
        assert font["hmtx"][target][0] == font["hmtx"][source][0]
        assert target not in cmap_names


@pytest.mark.parametrize(
    "path", [*FULL_FONT_FILES, *SUBSET_FONT_FILES]
)
def test_ss02_targets_never_contain_nested_components(path):
    font = TTFont(path)
    glyf = font["glyf"]
    order = set(font.getGlyphOrder())
    for target in SS02_TARGETS.values():
        if target not in order:
            continue
        assert all(
            not glyf[component.glyphName].isComposite()
            for component in glyf[target].components
        ), (path.name, target)


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_ss02_preserves_source_kerning_and_combining_mark_positioning(
    path, _, __
):
    font = TTFont(path)
    samples = {
        "BlVa": "l.ss02",
        "yła": "lslash.ss02",
        "l\u0302": "l.ss02",
    }
    for weight in (300, 400, 500, 600, 700):
        for sample, alternate in samples.items():
            default = shape(path, sample, weight)
            enabled = shape(path, sample, weight, {"ss02": True})
            assert enabled[0] == default[0]
            assert enabled[2] == default[2]
            assert alternate in {
                font.getGlyphName(glyph_id) for glyph_id in enabled[1]
            }


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_ss01_ss02_and_tnum_interoperate_without_cross_substitution(
    path, _, __
):
    font = TTFont(path)
    for weight in (300, 400, 500, 600, 700):
        _, glyph_ids, positions = shape(
            path,
            "al" + MONEY_GLYPHS,
            weight,
            {"ss01": True, "ss02": True, "tnum": True},
        )
        names = [font.getGlyphName(glyph_id) for glyph_id in glyph_ids]
        assert names[:2] == ["a.ss01", "l.ss02"]
        assert names[2:12] == [f"{name}.tf" for name in BASE_NAMES[:10]]
        expected_dollar = (
            "dollar.BRACKET.varAlt01.tf"
            if weight >= 600
            else "dollar.tf"
        )
        assert names[12:] == [
            expected_dollar,
            *[f"{name}.tf" for name in BASE_NAMES[11:]],
        ]
        assert len({position[0] for position in positions[2:]}) == 1


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_composite_math_symbols_are_encoded_and_shape(path, _, __):
    font = TTFont(path)
    cmap = font.getBestCmap()
    expected_names = [MATH[character][0] for character in MATH_TEXT]
    assert [cmap[ord(character)] for character in MATH_TEXT] == expected_names

    for character, (glyph_name, component_names) in MATH.items():
        glyph = font["glyf"][glyph_name]
        assert glyph.isComposite()
        assert tuple(c.glyphName for c in glyph.components) == component_names

    for weight in (300, 400, 500, 600, 700):
        _, glyph_ids, positions = shape(path, MATH_TEXT, weight)
        assert [font.getGlyphName(glyph_id) for glyph_id in glyph_ids] == (
            expected_names
        )
        assert all(position[0] > 0 for position in positions)


@pytest.mark.parametrize("path", FULL_FONT_FILES)
def test_math_composite_flags_are_explicit_and_portable(path):
    glyf = TTFont(path)["glyf"]
    notequal = glyf["notequal"].components
    perthousand = glyf["perthousand"].components

    assert notequal[0].flags & OVERLAP_COMPOUND
    assert notequal[1].flags & UNSCALED_COMPONENT_OFFSET
    assert perthousand[1].flags & UNSCALED_COMPONENT_OFFSET
    assert not notequal[1].flags & SCALED_COMPONENT_OFFSET
    assert not perthousand[1].flags & SCALED_COMPONENT_OFFSET


@pytest.mark.parametrize("path,_,__", VARIABLES)
def test_relation_composites_share_equal_advance(path, _, __):
    for weight in range(300, 701):
        equal_advance = shape(path, "=", weight)[2][0][0]
        _, _, positions = shape(path, "≠≤≥≈", weight)
        assert [position[0] for position in positions] == [
            equal_advance
        ] * 4
        assert shape(path, "‰", weight)[2][0][0] > shape(
            path, "%", weight
        )[2][0][0]


@pytest.mark.parametrize("path,subfamily,prefix", VARIABLES[::2])
def test_variable_names_license_authorship_and_axes(path, subfamily, prefix):
    font = TTFont(path)
    name = font["name"]
    assert name.getDebugName(1) == "Pivot Sans"
    assert name.getDebugName(2) == subfamily
    assert name.getDebugName(5) == "Version 1.200"
    assert name.getDebugName(6) == f"PivotSans-{subfamily}"
    assert name.getDebugName(8) == "Beacon Bay Technologies, Inc."
    assert "Olivia King (original Inclusive Sans design)" in name.getDebugName(9)
    assert "Beacon Bay Technologies, Inc. (Pivot Sans fork)" in name.getDebugName(9)
    assert name.getDebugName(11) == "https://pivotsans.com"
    assert name.getDebugName(12) == "https://www.oliviaking.com"
    assert name.getDebugName(25) == prefix
    assert "Inclusive Sans Project Authors" in name.getDebugName(0)
    assert "Beacon Bay Technologies, Inc." in name.getDebugName(0)
    assert "SIL Open Font License" in name.getDebugName(13)
    assert font["OS/2"].usWinAscent == 1159
    assert font["OS/2"].usWinDescent >= 399
    assert len(font["fvar"].axes) == 1
    axis = font["fvar"].axes[0]
    assert (axis.axisTag, axis.minValue, axis.defaultValue, axis.maxValue) == (
        "wght",
        300,
        400,
        700,
    )


def test_italic_and_upright_instance_postscript_prefixes_are_unique():
    upright = TTFont(DIST / "PivotSans[wght].ttf")["name"].getDebugName(25)
    italic = TTFont(DIST / "PivotSans-Italic[wght].ttf")["name"].getDebugName(25)
    assert upright == "PivotSans"
    assert italic == "PivotSansItalic"
    assert upright != italic


@pytest.mark.parametrize(
    "suffix,weight,is_italic,legacy_family,legacy_subfamily,slot", STATIC_STYLES
)
def test_static_ttf_behavior_and_style_linking(
    suffix, weight, is_italic, legacy_family, legacy_subfamily, slot
):
    path = DIST / "static" / f"PivotSans-{suffix}.ttf"
    assert path.is_file()
    font = TTFont(path)
    name = font["name"]

    assert name.getDebugName(1) == legacy_family
    assert name.getDebugName(2) == legacy_subfamily
    assert name.getDebugName(5) == "Version 1.200"
    assert name.getDebugName(6) == f"PivotSans-{suffix}"
    assert name.getDebugName(8) == "Beacon Bay Technologies, Inc."
    assert name.getDebugName(11) == "https://pivotsans.com"
    assert font["OS/2"].usWeightClass == weight
    assert font["OS/2"].usWinAscent == 1159
    assert bool(font["OS/2"].fsSelection & 0x01) is is_italic
    assert bool(font["head"].macStyle & 0x02) is is_italic
    assert not {"fvar", "gvar", "HVAR"} & set(font.keys())

    _, glyph_ids, positions = shape(path, MONEY_GLYPHS, features={"tnum": True})
    assert [position[0] for position in positions] == [slot] * 15
    if weight >= 600:
        assert font.getGlyphName(glyph_ids[10]) == (
            "dollar.BRACKET.varAlt01.tf"
        )
    assert len(
        {
            shape(path, sample, features={"tnum": True})[0]
            for sample in MONEY_SAMPLES
        }
    ) == 1
    assert [font.getGlyphName(glyph_id) for glyph_id in shape(path, MATH_TEXT)[1]] == [
        MATH[character][0] for character in MATH_TEXT
    ]


@pytest.mark.parametrize("suffix,_,__,___,____,slot", STATIC_STYLES)
def test_static_woff2_loads_and_shapes(suffix, _, __, ___, ____, slot):
    path = DIST / "static" / f"PivotSans-{suffix}.woff2"
    font = TTFont(path)
    assert font["name"].getDebugName(1).startswith("Pivot Sans")
    _, _, positions = shape(path, MONEY_GLYPHS, features={"tnum": True})
    assert [position[0] for position in positions] == [slot] * 15


@pytest.mark.parametrize(
    "suffix,weight,is_italic,preferred_subfamily,slot", PINS
)
def test_custom_static_pin_names_behavior_and_variable_equivalence(
    suffix, weight, is_italic, preferred_subfamily, slot
):
    path = DIST / "pins" / f"PivotSans-{suffix}.ttf"
    variable = DIST / (
        "PivotSans-Italic[wght].ttf" if is_italic else "PivotSans[wght].ttf"
    )
    font = TTFont(path)
    name = font["name"]

    assert name.getDebugName(1) == f"Pivot Sans {weight}"
    assert name.getDebugName(2) == ("Italic" if is_italic else "Regular")
    assert name.getDebugName(4) == f"Pivot Sans {weight}" + (
        " Italic" if is_italic else ""
    )
    assert name.getDebugName(6) == f"PivotSans-{suffix}"
    assert name.getDebugName(16) == "Pivot Sans"
    assert name.getDebugName(17) == preferred_subfamily
    assert name.getDebugName(5) == "Version 1.200"
    assert name.getDebugName(8) == "Beacon Bay Technologies, Inc."
    assert name.getDebugName(11) == "https://pivotsans.com"
    assert font["OS/2"].usWeightClass == weight
    assert bool(font["OS/2"].fsSelection & 0x01) is is_italic
    assert bool(font["OS/2"].fsSelection & 0x40) is (not is_italic)
    assert bool(font["head"].macStyle & 0x02) is is_italic
    assert not {"fvar", "gvar", "HVAR", "avar"} & set(font.keys())
    assert len(font.getGlyphOrder()) == 577
    assert not any(
        "BRACKET.varAlt01" in glyph_name
        for glyph_name in font.getGlyphOrder()
    )
    stat = font["STAT"].table
    weight_axis_index = next(
        index
        for index, axis in enumerate(stat.DesignAxisRecord.Axis)
        if axis.AxisTag == "wght"
    )
    weight_values = [
        axis_value
        for axis_value in stat.AxisValueArray.AxisValue
        if getattr(axis_value, "AxisIndex", None) == weight_axis_index
    ]
    assert len(weight_values) == 1
    assert weight_values[0].Format == 1
    assert weight_values[0].Value == weight
    assert name.getDebugName(weight_values[0].ValueNameID) == f"Weight {weight}"

    _, _, positions = shape(path, MONEY_GLYPHS, features={"tnum": True})
    assert [position[0] for position in positions] == [slot] * 15
    for sample, features in (
        ("Hamburgefontsiv AVATAR office", {}),
        (MONEY_GLYPHS, {"tnum": True}),
        (MATH_TEXT, {}),
        ("a", {"ss01": True}),
        (SS02_TEXT, {"ss02": True}),
    ):
        pin_result = shape(path, sample, features=features)
        variable_result = shape(variable, sample, weight, features)
        assert pin_result[0] == variable_result[0]
        assert pin_result[2] == variable_result[2]
        variable_font = TTFont(variable)
        assert [
            font.getGlyphName(glyph_id) for glyph_id in pin_result[1]
        ] == [
            variable_font.getGlyphName(glyph_id)
            for glyph_id in variable_result[1]
        ]


def test_fork_features_are_attached_to_every_gsub_language_system():
    for path, _, _ in VARIABLES[::2]:
        gsub = TTFont(path)["GSUB"].table
        records = gsub.FeatureList.FeatureRecord
        feature_indices = {}
        for feature_tag in ("ss02", "tnum"):
            indices = [
                index
                for index, record in enumerate(records)
                if record.FeatureTag == feature_tag
            ]
            assert len(indices) == 1
            feature_indices[feature_tag] = indices[0]
        assert {record.ScriptTag for record in gsub.ScriptList.ScriptRecord} == {
            "DFLT",
            "latn",
        }
        for script_record in gsub.ScriptList.ScriptRecord:
            language_systems = [script_record.Script.DefaultLangSys]
            language_systems.extend(
                record.LangSys
                for record in script_record.Script.LangSysRecord
            )
            for language_system in language_systems:
                if language_system is not None:
                    for feature_index in feature_indices.values():
                        assert feature_index in language_system.FeatureIndex


def test_held_and_withdrawn_scope_remains_absent():
    expected_pins = {
        "PivotSans-Wght450.ttf",
        "PivotSans-Wght450.woff2",
        "PivotSans-Wght450Italic.ttf",
        "PivotSans-Wght450Italic.woff2",
        "PivotSans-Wght550.ttf",
        "PivotSans-Wght550.woff2",
        "PivotSans-Wght550Italic.ttf",
        "PivotSans-Wght550Italic.woff2",
    }
    assert {
        path.name for path in (DIST / "pins").iterdir() if path.is_file()
    } == expected_pins

    for path, _, _ in VARIABLES[::2]:
        font = TTFont(path)
        assert [axis.axisTag for axis in font["fvar"].axes] == ["wght"]
        assert [
            instance.coordinates
            for instance in font["fvar"].instances
        ] == [
            {"wght": 300.0},
            {"wght": 400.0},
            {"wght": 500.0},
            {"wght": 600.0},
            {"wght": 700.0},
        ]
        assert 0x00B5 not in font.getBestCmap()
        for punctuation in ".,:;":
            assert shape(path, punctuation, 400, {"tnum": True}) == shape(
                path, punctuation, 400
            )


@pytest.mark.parametrize("ttf_path", sorted(DIST.rglob("*.ttf")))
def test_woff2_decompresses_to_same_tables(ttf_path):
    woff2_path = ttf_path.with_suffix(".woff2")
    ttf = TTFont(ttf_path)
    woff2 = TTFont(woff2_path)
    assert set(ttf.keys()) == set(woff2.keys())
    for tag in ttf.keys():
        if tag in {"GlyphOrder", "head"}:
            continue
        assert ttf.getTableData(tag) == woff2.getTableData(tag), (
            ttf_path.name,
            tag,
        )
    for field, value in vars(ttf["head"]).items():
        if field.startswith("_") or field == "checkSumAdjustment":
            continue
        if field == "flags":
            # WOFF2 reconstruction sets bit 11 as required by the WOFF2 spec.
            assert getattr(woff2["head"], field) & ~0x0800 == value
            continue
        assert getattr(woff2["head"], field) == value


def main() -> int:
    return pytest.main([str(Path(__file__).resolve()), "-q"])


if __name__ == "__main__":
    raise SystemExit(main())
