"""
This type stub file was generated by pyright.
"""

import abc
import enum
import functools
import typing as T
from typing import NamedTuple
from pyparsing import Literal, ParseResults, ParserElement, __version__ as pyparsing_version
from .font_manager import FontProperties
from .ft2font import FT2Font, FT2Image, Glyph
from packaging.version import parse as parse_version

"""
Implementation details for :mod:`.mathtext`.
"""
if parse_version(pyparsing_version).major < 3:
    ...
else:
    ...
if T.TYPE_CHECKING:
    ...
_log = ...
def get_unicode_index(symbol: str) -> int:
    r"""
    Return the integer index (from the Unicode table) of *symbol*.

    Parameters
    ----------
    symbol : str
        A single (Unicode) character, a TeX command (e.g. r'\pi') or a Type1
        symbol name (e.g. 'phi').
    """
    ...

class VectorParse(NamedTuple):
    """
    The namedtuple type returned by ``MathTextParser("path").parse(...)``.

    Attributes
    ----------
    width, height, depth : float
        The global metrics.
    glyphs : list
        The glyphs including their positions.
    rect : list
        The list of rectangles.
    """
    width: float
    height: float
    depth: float
    glyphs: list[tuple[FT2Font, float, int, float, float]]
    rects: list[tuple[float, float, float, float]]
    ...


class RasterParse(NamedTuple):
    """
    The namedtuple type returned by ``MathTextParser("agg").parse(...)``.

    Attributes
    ----------
    ox, oy : float
        The offsets are always zero.
    width, height, depth : float
        The global metrics.
    image : FT2Image
        A raster image.
    """
    ox: float
    oy: float
    width: float
    height: float
    depth: float
    image: FT2Image
    ...


class Output:
    r"""
    Result of `ship`\ping a box: lists of positioned glyphs and rectangles.

    This class is not exposed to end users, but converted to a `VectorParse` or
    a `RasterParse` by `.MathTextParser.parse`.
    """
    def __init__(self, box: Box) -> None:
        ...
    
    def to_vector(self) -> VectorParse:
        ...
    
    def to_raster(self, *, antialiased: bool) -> RasterParse:
        ...
    


class FontMetrics(NamedTuple):
    """
    Metrics of a font.

    Attributes
    ----------
    advance : float
        The advance distance (in points) of the glyph.
    height : float
        The height of the glyph in points.
    width : float
        The width of the glyph in points.
    xmin, xmax, ymin, ymax : float
        The ink rectangle of the glyph.
    iceberg : float
        The distance from the baseline to the top of the glyph. (This corresponds to
        TeX's definition of "height".)
    slanted : bool
        Whether the glyph should be considered as "slanted" (currently used for kerning
        sub/superscripts).
    """
    advance: float
    height: float
    width: float
    xmin: float
    xmax: float
    ymin: float
    ymax: float
    iceberg: float
    slanted: bool
    ...


class FontInfo(NamedTuple):
    font: FT2Font
    fontsize: float
    postscript_name: str
    metrics: FontMetrics
    num: int
    glyph: Glyph
    offset: float
    ...


class Fonts(abc.ABC):
    """
    An abstract base class for a system of fonts to use for mathtext.

    The class must be able to take symbol keys and font file names and
    return the character metrics.  It also delegates to a backend class
    to do the actual drawing.
    """
    def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int) -> None:
        """
        Parameters
        ----------
        default_font_prop : `~.font_manager.FontProperties`
            The default non-math font, or the base font for Unicode (generic)
            font rendering.
        load_glyph_flags : int
            Flags passed to the glyph loader (e.g. ``FT_Load_Glyph`` and
            ``FT_Load_Char`` for FreeType-based fonts).
        """
        ...
    
    def get_kern(self, font1: str, fontclass1: str, sym1: str, fontsize1: float, font2: str, fontclass2: str, sym2: str, fontsize2: float, dpi: float) -> float:
        """
        Get the kerning distance for font between *sym1* and *sym2*.

        See `~.Fonts.get_metrics` for a detailed description of the parameters.
        """
        ...
    
    def get_metrics(self, font: str, font_class: str, sym: str, fontsize: float, dpi: float) -> FontMetrics:
        r"""
        Parameters
        ----------
        font : str
            One of the TeX font names: "tt", "it", "rm", "cal", "sf", "bf",
            "default", "regular", "bb", "frak", "scr".  "default" and "regular"
            are synonyms and use the non-math font.
        font_class : str
            One of the TeX font names (as for *font*), but **not** "bb",
            "frak", or "scr".  This is used to combine two font classes.  The
            only supported combination currently is ``get_metrics("frak", "bf",
            ...)``.
        sym : str
            A symbol in raw TeX form, e.g., "1", "x", or "\sigma".
        fontsize : float
            Font size in points.
        dpi : float
            Rendering dots-per-inch.

        Returns
        -------
        FontMetrics
        """
        ...
    
    def render_glyph(self, output: Output, ox: float, oy: float, font: str, font_class: str, sym: str, fontsize: float, dpi: float) -> None:
        """
        At position (*ox*, *oy*), draw the glyph specified by the remaining
        parameters (see `get_metrics` for their detailed description).
        """
        ...
    
    def render_rect_filled(self, output: Output, x1: float, y1: float, x2: float, y2: float) -> None:
        """
        Draw a filled rectangle from (*x1*, *y1*) to (*x2*, *y2*).
        """
        ...
    
    def get_xheight(self, font: str, fontsize: float, dpi: float) -> float:
        """
        Get the xheight for the given *font* and *fontsize*.
        """
        ...
    
    def get_underline_thickness(self, font: str, fontsize: float, dpi: float) -> float:
        """
        Get the line thickness that matches the given font.  Used as a
        base unit for drawing lines such as in a fraction or radical.
        """
        ...
    
    def get_sized_alternatives_for_symbol(self, fontname: str, sym: str) -> list[tuple[str, str]]:
        """
        Override if your font provides multiple sizes of the same
        symbol.  Should return a list of symbols matching *sym* in
        various sizes.  The expression renderer will select the most
        appropriate size for a given situation from this list.
        """
        ...
    


class TruetypeFonts(Fonts, metaclass=abc.ABCMeta):
    """
    A generic base class for all font setups that use Truetype fonts
    (through FT2Font).
    """
    def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int) -> None:
        ...
    
    def get_xheight(self, fontname: str, fontsize: float, dpi: float) -> float:
        ...
    
    def get_underline_thickness(self, font: str, fontsize: float, dpi: float) -> float:
        ...
    
    def get_kern(self, font1: str, fontclass1: str, sym1: str, fontsize1: float, font2: str, fontclass2: str, sym2: str, fontsize2: float, dpi: float) -> float:
        ...
    


class BakomaFonts(TruetypeFonts):
    """
    Use the Bakoma TrueType fonts for rendering.

    Symbols are strewn about a number of font files, each of which has
    its own proprietary 8-bit encoding.
    """
    _fontmap = ...
    def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int) -> None:
        ...
    
    _slanted_symbols = ...
    _size_alternatives = ...
    def get_sized_alternatives_for_symbol(self, fontname: str, sym: str) -> list[tuple[str, str]]:
        ...
    


class UnicodeFonts(TruetypeFonts):
    """
    An abstract base class for handling Unicode fonts.

    While some reasonably complete Unicode fonts (such as DejaVu) may
    work in some situations, the only Unicode font I'm aware of with a
    complete set of math symbols is STIX.

    This class will "fallback" on the Bakoma fonts when a required
    symbol cannot be found in the font.
    """
    _cmr10_substitutions = ...
    def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int) -> None:
        ...
    
    _slanted_symbols = ...
    def get_sized_alternatives_for_symbol(self, fontname: str, sym: str) -> list[tuple[str, str]]:
        ...
    


class DejaVuFonts(UnicodeFonts, metaclass=abc.ABCMeta):
    _fontmap: dict[str | int, str] = ...
    def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int) -> None:
        ...
    


class DejaVuSerifFonts(DejaVuFonts):
    """
    A font handling class for the DejaVu Serif fonts

    If a glyph is not found it will fallback to Stix Serif
    """
    _fontmap = ...


class DejaVuSansFonts(DejaVuFonts):
    """
    A font handling class for the DejaVu Sans fonts

    If a glyph is not found it will fallback to Stix Sans
    """
    _fontmap = ...


class StixFonts(UnicodeFonts):
    """
    A font handling class for the STIX fonts.

    In addition to what UnicodeFonts provides, this class:

    - supports "virtual fonts" which are complete alpha numeric
      character sets with different font styles at special Unicode
      code points, such as "Blackboard".

    - handles sized alternative characters for the STIXSizeX fonts.
    """
    _fontmap: dict[str | int, str] = ...
    _fallback_font = ...
    _sans = ...
    def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int) -> None:
        ...
    
    @functools.cache
    def get_sized_alternatives_for_symbol(self, fontname: str, sym: str) -> list[tuple[str, str]] | list[tuple[int, str]]:
        ...
    


class StixSansFonts(StixFonts):
    """
    A font handling class for the STIX fonts (that uses sans-serif
    characters by default).
    """
    _sans = ...


SHRINK_FACTOR = ...
NUM_SIZE_LEVELS = ...
class FontConstantsBase:
    """
    A set of constants that controls how certain things, such as sub-
    and superscripts are laid out.  These are all metrics that can't
    be reliably retrieved from the font metrics in the font itself.
    """
    script_space: T.ClassVar[float] = ...
    subdrop: T.ClassVar[float] = ...
    sup1: T.ClassVar[float] = ...
    sub1: T.ClassVar[float] = ...
    sub2: T.ClassVar[float] = ...
    delta: T.ClassVar[float] = ...
    delta_slanted: T.ClassVar[float] = ...
    delta_integral: T.ClassVar[float] = ...


class ComputerModernFontConstants(FontConstantsBase):
    script_space = ...
    subdrop = ...
    sup1 = ...
    sub1 = ...
    sub2 = ...
    delta = ...
    delta_slanted = ...
    delta_integral = ...


class STIXFontConstants(FontConstantsBase):
    script_space = ...
    sup1 = ...
    sub2 = ...
    delta = ...
    delta_slanted = ...
    delta_integral = ...


class STIXSansFontConstants(FontConstantsBase):
    script_space = ...
    sup1 = ...
    delta_slanted = ...
    delta_integral = ...


class DejaVuSerifFontConstants(FontConstantsBase):
    ...


class DejaVuSansFontConstants(FontConstantsBase):
    ...


_font_constant_mapping = ...
class Node:
    """A node in the TeX box model."""
    def __init__(self) -> None:
        ...
    
    def __repr__(self) -> str:
        ...
    
    def get_kerning(self, next: Node | None) -> float:
        ...
    
    def shrink(self) -> None:
        """
        Shrinks one level smaller.  There are only three levels of
        sizes, after which things will no longer get smaller.
        """
        ...
    
    def render(self, output: Output, x: float, y: float) -> None:
        """Render this node."""
        ...
    


class Box(Node):
    """A node with a physical location."""
    def __init__(self, width: float, height: float, depth: float) -> None:
        ...
    
    def shrink(self) -> None:
        ...
    
    def render(self, output: Output, x1: float, y1: float, x2: float, y2: float) -> None:
        ...
    


class Vbox(Box):
    """A box with only height (zero width)."""
    def __init__(self, height: float, depth: float) -> None:
        ...
    


class Hbox(Box):
    """A box with only width (zero height and depth)."""
    def __init__(self, width: float) -> None:
        ...
    


class Char(Node):
    """
    A single character.

    Unlike TeX, the font information and metrics are stored with each `Char`
    to make it easier to lookup the font metrics when needed.  Note that TeX
    boxes have a width, height, and depth, unlike Type1 and TrueType which use
    a full bounding box and an advance in the x-direction.  The metrics must
    be converted to the TeX model, and the advance (if different from width)
    must be converted into a `Kern` node when the `Char` is added to its parent
    `Hlist`.
    """
    def __init__(self, c: str, state: ParserState) -> None:
        ...
    
    def __repr__(self) -> str:
        ...
    
    def is_slanted(self) -> bool:
        ...
    
    def get_kerning(self, next: Node | None) -> float:
        """
        Return the amount of kerning between this and the given character.

        This method is called when characters are strung together into `Hlist`
        to create `Kern` nodes.
        """
        ...
    
    def render(self, output: Output, x: float, y: float) -> None:
        ...
    
    def shrink(self) -> None:
        ...
    


class Accent(Char):
    """
    The font metrics need to be dealt with differently for accents,
    since they are already offset correctly from the baseline in
    TrueType fonts.
    """
    def shrink(self) -> None:
        ...
    
    def render(self, output: Output, x: float, y: float) -> None:
        ...
    


class List(Box):
    """A list of nodes (either horizontal or vertical)."""
    def __init__(self, elements: T.Sequence[Node]) -> None:
        ...
    
    def __repr__(self) -> str:
        ...
    
    def shrink(self) -> None:
        ...
    


class Hlist(List):
    """A horizontal list of boxes."""
    def __init__(self, elements: T.Sequence[Node], w: float = ..., m: T.Literal['additional', 'exactly'] = ..., do_kern: bool = ...) -> None:
        ...
    
    def kern(self) -> None:
        """
        Insert `Kern` nodes between `Char` nodes to set kerning.

        The `Char` nodes themselves determine the amount of kerning they need
        (in `~Char.get_kerning`), and this function just creates the correct
        linked list.
        """
        ...
    
    def hpack(self, w: float = ..., m: T.Literal['additional', 'exactly'] = ...) -> None:
        r"""
        Compute the dimensions of the resulting boxes, and adjust the glue if
        one of those dimensions is pre-specified.  The computed sizes normally
        enclose all of the material inside the new box; but some items may
        stick out if negative glue is used, if the box is overfull, or if a
        ``\vbox`` includes other boxes that have been shifted left.

        Parameters
        ----------
        w : float, default: 0
            A width.
        m : {'exactly', 'additional'}, default: 'additional'
            Whether to produce a box whose width is 'exactly' *w*; or a box
            with the natural width of the contents, plus *w* ('additional').

        Notes
        -----
        The defaults produce a box with the natural width of the contents.
        """
        ...
    


class Vlist(List):
    """A vertical list of boxes."""
    def __init__(self, elements: T.Sequence[Node], h: float = ..., m: T.Literal['additional', 'exactly'] = ...) -> None:
        ...
    
    def vpack(self, h: float = ..., m: T.Literal['additional', 'exactly'] = ..., l: float = ...) -> None:
        """
        Compute the dimensions of the resulting boxes, and to adjust the glue
        if one of those dimensions is pre-specified.

        Parameters
        ----------
        h : float, default: 0
            A height.
        m : {'exactly', 'additional'}, default: 'additional'
            Whether to produce a box whose height is 'exactly' *h*; or a box
            with the natural height of the contents, plus *h* ('additional').
        l : float, default: np.inf
            The maximum height.

        Notes
        -----
        The defaults produce a box with the natural height of the contents.
        """
        ...
    


class Rule(Box):
    """
    A solid black rectangle.

    It has *width*, *depth*, and *height* fields just as in an `Hlist`.
    However, if any of these dimensions is inf, the actual value will be
    determined by running the rule up to the boundary of the innermost
    enclosing box.  This is called a "running dimension".  The width is never
    running in an `Hlist`; the height and depth are never running in a `Vlist`.
    """
    def __init__(self, width: float, height: float, depth: float, state: ParserState) -> None:
        ...
    
    def render(self, output: Output, x: float, y: float, w: float, h: float) -> None:
        ...
    


class Hrule(Rule):
    """Convenience class to create a horizontal rule."""
    def __init__(self, state: ParserState, thickness: float | None = ...) -> None:
        ...
    


class Vrule(Rule):
    """Convenience class to create a vertical rule."""
    def __init__(self, state: ParserState) -> None:
        ...
    


class _GlueSpec(NamedTuple):
    width: float
    stretch: float
    stretch_order: int
    shrink: float
    shrink_order: int
    ...


class Glue(Node):
    """
    Most of the information in this object is stored in the underlying
    ``_GlueSpec`` class, which is shared between multiple glue objects.
    (This is a memory optimization which probably doesn't matter anymore, but
    it's easier to stick to what TeX does.)
    """
    def __init__(self, glue_type: _GlueSpec | T.Literal["fil", "fill", "filll", "neg_fil", "neg_fill", "neg_filll", "empty", "ss"]) -> None:
        ...
    
    def shrink(self) -> None:
        ...
    


class HCentered(Hlist):
    """
    A convenience class to create an `Hlist` whose contents are
    centered within its enclosing box.
    """
    def __init__(self, elements: list[Node]) -> None:
        ...
    


class VCentered(Vlist):
    """
    A convenience class to create a `Vlist` whose contents are
    centered within its enclosing box.
    """
    def __init__(self, elements: list[Node]) -> None:
        ...
    


class Kern(Node):
    """
    A `Kern` node has a width field to specify a (normally
    negative) amount of spacing. This spacing correction appears in
    horizontal lists between letters like A and V when the font
    designer said that it looks better to move them closer together or
    further apart. A kern node can also appear in a vertical list,
    when its *width* denotes additional spacing in the vertical
    direction.
    """
    height = ...
    depth = ...
    def __init__(self, width: float) -> None:
        ...
    
    def __repr__(self) -> str:
        ...
    
    def shrink(self) -> None:
        ...
    


class AutoHeightChar(Hlist):
    """
    A character as close to the given height and depth as possible.

    When using a font with multiple height versions of some characters (such as
    the BaKoMa fonts), the correct glyph will be selected, otherwise this will
    always just return a scaled version of the glyph.
    """
    def __init__(self, c: str, height: float, depth: float, state: ParserState, always: bool = ..., factor: float | None = ...) -> None:
        ...
    


class AutoWidthChar(Hlist):
    """
    A character as close to the given width as possible.

    When using a font with multiple width versions of some characters (such as
    the BaKoMa fonts), the correct glyph will be selected, otherwise this will
    always just return a scaled version of the glyph.
    """
    def __init__(self, c: str, width: float, state: ParserState, always: bool = ..., char_class: type[Char] = ...) -> None:
        ...
    


def ship(box: Box, xy: tuple[float, float] = ...) -> Output:
    """
    Ship out *box* at offset *xy*, converting it to an `Output`.

    Since boxes can be inside of boxes inside of boxes, the main work of `ship`
    is done by two mutually recursive routines, `hlist_out` and `vlist_out`,
    which traverse the `Hlist` nodes and `Vlist` nodes inside of horizontal
    and vertical boxes.  The global variables used in TeX to store state as it
    processes have become local variables here.
    """
    ...

def Error(msg: str) -> ParserElement:
    """Helper class to raise parser errors."""
    ...

class ParserState:
    """
    Parser state.

    States are pushed and popped from a stack as necessary, and the "current"
    state is always at the top of the stack.

    Upon entering and leaving a group { } or math/non-math, the stack is pushed
    and popped accordingly.
    """
    def __init__(self, fontset: Fonts, font: str, font_class: str, fontsize: float, dpi: float) -> None:
        ...
    
    def copy(self) -> ParserState:
        ...
    
    @property
    def font(self) -> str:
        ...
    
    @font.setter
    def font(self, name: str) -> None:
        ...
    
    def get_current_underline_thickness(self) -> float:
        """Return the underline thickness for this state."""
        ...
    


def cmd(expr: str, args: ParserElement) -> ParserElement:
    r"""
    Helper to define TeX commands.

    ``cmd("\cmd", args)`` is equivalent to
    ``"\cmd" - (args | Error("Expected \cmd{arg}{...}"))`` where the names in
    the error message are taken from element names in *args*.  If *expr*
    already includes arguments (e.g. "\cmd{arg}{...}"), then they are stripped
    when constructing the parse element, but kept (and *expr* is used as is) in
    the error message.
    """
    ...

class Parser:
    """
    A pyparsing-based parser for strings containing math expressions.

    Raw text may also appear outside of pairs of ``$``.

    The grammar is based directly on that in TeX, though it cuts a few corners.
    """
    class _MathStyle(enum.Enum):
        DISPLAYSTYLE = ...
        TEXTSTYLE = ...
        SCRIPTSTYLE = ...
        SCRIPTSCRIPTSTYLE = ...
    
    
    _binary_operators = ...
    _relation_symbols = ...
    _arrow_symbols = ...
    _spaced_symbols = ...
    _punctuation_symbols = ...
    _overunder_symbols = ...
    _overunder_functions = ...
    _dropsub_symbols = ...
    _fontnames = ...
    _function_names = ...
    _ambi_delims = ...
    _left_delims = ...
    _right_delims = ...
    _delims = ...
    _small_greek = ...
    _latin_alphabets = ...
    def __init__(self) -> None:
        ...
    
    def parse(self, s: str, fonts_object: Fonts, fontsize: float, dpi: float) -> Hlist:
        """
        Parse expression *s* using the given *fonts_object* for
        output, at the given *fontsize* and *dpi*.

        Returns the parse tree of `Node` instances.
        """
        ...
    
    def get_state(self) -> ParserState:
        """Get the current `State` of the parser."""
        ...
    
    def pop_state(self) -> None:
        """Pop a `State` off of the stack."""
        ...
    
    def push_state(self) -> None:
        """Push a new `State` onto the stack, copying the current state."""
        ...
    
    def main(self, toks: ParseResults) -> list[Hlist]:
        ...
    
    def math_string(self, toks: ParseResults) -> ParseResults:
        ...
    
    def math(self, toks: ParseResults) -> T.Any:
        ...
    
    def non_math(self, toks: ParseResults) -> T.Any:
        ...
    
    float_literal = ...
    def text(self, toks: ParseResults) -> T.Any:
        ...
    
    _space_widths = ...
    def space(self, toks: ParseResults) -> T.Any:
        ...
    
    def customspace(self, toks: ParseResults) -> T.Any:
        ...
    
    def symbol(self, s: str, loc: int, toks: ParseResults | dict[str, str]) -> T.Any:
        ...
    
    def unknown_symbol(self, s: str, loc: int, toks: ParseResults) -> T.Any:
        ...
    
    _accent_map = ...
    _wide_accents = ...
    def accent(self, toks: ParseResults) -> T.Any:
        ...
    
    def function(self, s: str, loc: int, toks: ParseResults) -> T.Any:
        ...
    
    def operatorname(self, s: str, loc: int, toks: ParseResults) -> T.Any:
        ...
    
    def start_group(self, toks: ParseResults) -> T.Any:
        ...
    
    def group(self, toks: ParseResults) -> T.Any:
        ...
    
    def required_group(self, toks: ParseResults) -> T.Any:
        ...
    
    optional_group = ...
    def end_group(self) -> T.Any:
        ...
    
    def unclosed_group(self, s: str, loc: int, toks: ParseResults) -> T.Any:
        ...
    
    def font(self, toks: ParseResults) -> T.Any:
        ...
    
    def is_overunder(self, nucleus: Node) -> bool:
        ...
    
    def is_dropsub(self, nucleus: Node) -> bool:
        ...
    
    def is_slanted(self, nucleus: Node) -> bool:
        ...
    
    def subsuper(self, s: str, loc: int, toks: ParseResults) -> T.Any:
        ...
    
    def style_literal(self, toks: ParseResults) -> T.Any:
        ...
    
    def genfrac(self, toks: ParseResults) -> T.Any:
        ...
    
    def frac(self, toks: ParseResults) -> T.Any:
        ...
    
    def dfrac(self, toks: ParseResults) -> T.Any:
        ...
    
    def binom(self, toks: ParseResults) -> T.Any:
        ...
    
    underset = ...
    def sqrt(self, toks: ParseResults) -> T.Any:
        ...
    
    def overline(self, toks: ParseResults) -> T.Any:
        ...
    
    def auto_delim(self, toks: ParseResults) -> T.Any:
        ...
    
    def boldsymbol(self, toks: ParseResults) -> T.Any:
        ...
    
    def substack(self, toks: ParseResults) -> T.Any:
        ...
    


