From 2ad10dedbe79e342abeea7a2f12e167f333e32a1 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 26 Oct 2021 14:31:47 +0200 Subject: [PATCH 1/7] Remove _mathtext.Node.grow. It has never been used, and the implementation was in fact buggy (if one calls `shrink` many times beyond num_size_levels, `.size` would continue to decrease while `.width` would not; if one then calls `grow`, `.size` and `.width` would then both increase, but get out of sync with one another). I can't find a reference to grow() in the TeXbook or "TeX the program" either(?) --- lib/matplotlib/_mathtext.py | 44 +------------------------------------ 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 06d97bc57171..62943e38c56a 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -923,10 +923,8 @@ def get_underline_thickness(self, font, fontsize, dpi): # Note that (as TeX) y increases downward, unlike many other parts of # matplotlib. -# How much text shrinks when going to the next-smallest level. GROW_FACTOR -# must be the inverse of SHRINK_FACTOR. +# How much text shrinks when going to the next-smallest level. SHRINK_FACTOR = 0.7 -GROW_FACTOR = 1 / SHRINK_FACTOR # The number of different sizes of chars to use, beyond which they will not # get any smaller NUM_SIZE_LEVELS = 6 @@ -1059,13 +1057,6 @@ def shrink(self): """ self.size += 1 - def grow(self): - """ - Grows one level larger. There is no limit to how big - something can get. - """ - self.size -= 1 - def render(self, x, y): pass @@ -1086,12 +1077,6 @@ def shrink(self): self.height *= SHRINK_FACTOR self.depth *= SHRINK_FACTOR - def grow(self): - super().grow() - self.width *= GROW_FACTOR - self.height *= GROW_FACTOR - self.depth *= GROW_FACTOR - def render(self, x1, y1, x2, y2): pass @@ -1185,13 +1170,6 @@ def shrink(self): self.height *= SHRINK_FACTOR self.depth *= SHRINK_FACTOR - def grow(self): - super().grow() - self.fontsize *= GROW_FACTOR - self.width *= GROW_FACTOR - self.height *= GROW_FACTOR - self.depth *= GROW_FACTOR - class Accent(Char): """ @@ -1210,10 +1188,6 @@ def shrink(self): super().shrink() self._update_metrics() - def grow(self): - super().grow() - self._update_metrics() - def render(self, x, y): """ Render the character to the canvas. @@ -1276,13 +1250,6 @@ def shrink(self): self.shift_amount *= SHRINK_FACTOR self.glue_set *= SHRINK_FACTOR - def grow(self): - for child in self.children: - child.grow() - super().grow() - self.shift_amount *= GROW_FACTOR - self.glue_set *= GROW_FACTOR - class Hlist(List): """A horizontal list of boxes.""" @@ -1551,11 +1518,6 @@ def shrink(self): g = self.glue_spec self.glue_spec = g._replace(width=g.width * SHRINK_FACTOR) - def grow(self): - super().grow() - g = self.glue_spec - self.glue_spec = g._replace(width=g.width * GROW_FACTOR) - class HCentered(Hlist): """ @@ -1603,10 +1565,6 @@ def shrink(self): if self.size < NUM_SIZE_LEVELS: self.width *= SHRINK_FACTOR - def grow(self): - super().grow() - self.width *= GROW_FACTOR - class SubSuperCluster(Hlist): """ From 4df33d20739a86e624adc19f4098ed8e882e4105 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 2 Sep 2021 22:34:23 +0200 Subject: [PATCH 2/7] Stop computing glyph_name in mathtext font handling. None of the MathtextBackends actually accesses the .glyph_name attribute anymore, and they are the only public API that can interact with the glyph infos returned by the Fonts classes (and there is no public API to register new MathtextBackends). --- lib/matplotlib/_mathtext.py | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 62943e38c56a..81645a2824b0 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -245,8 +245,8 @@ def _get_info(self, fontname, font_class, sym, fontsize, dpi, math=True): if bunch is not None: return bunch - font, num, glyph_name, fontsize, slanted = \ - self._get_glyph(fontname, font_class, sym, fontsize, math) + font, num, fontsize, slanted = self._get_glyph( + fontname, font_class, sym, fontsize, math) font.set_size(fontsize, dpi) glyph = font.load_char( @@ -273,8 +273,6 @@ def _get_info(self, fontname, font_class, sym, fontsize, dpi, math=True): fontsize = fontsize, postscript_name = font.postscript_name, metrics = metrics, - glyph_name = glyph_name, - symbol_name = glyph_name, # Backcompat alias. num = num, glyph = glyph, offset = offset @@ -340,7 +338,6 @@ def __init__(self, *args, **kwargs): _slanted_symbols = set(r"\int \oint".split()) def _get_glyph(self, fontname, font_class, sym, fontsize, math=True): - glyph_name = None font = None if fontname in self.fontmap and sym in latex_to_bakoma: basename, num = latex_to_bakoma[sym] @@ -351,18 +348,12 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True): font = self._get_font(fontname) if font is not None: num = ord(sym) - - if font is not None: - gid = font.get_char_index(num) - if gid != 0: - glyph_name = font.get_glyph_name(gid) - - if glyph_name is None: + if font is not None and font.get_char_index(num) != 0: + return font, num, fontsize, slanted + else: return self._stix_fallback._get_glyph( fontname, font_class, sym, fontsize, math) - return font, num, glyph_name, fontsize, slanted - # The Bakoma fonts contain many pre-sized alternatives for the # delimiters. The AutoSizedChar class will use these alternatives # and select the best (closest sized) glyph. @@ -532,14 +523,11 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True): _log.warning("Font {!r} does not have a glyph for {!a} " "[U+{:x}], substituting with a dummy " "symbol.".format(new_fontname, sym, uniindex)) - fontname = 'rm' - font = self._get_font(fontname) + font = self._get_font('rm') uniindex = 0xA4 # currency char, for lack of anything better - glyphindex = font.get_char_index(uniindex) slanted = False - glyph_name = font.get_glyph_name(glyphindex) - return font, uniindex, glyph_name, fontsize, slanted + return font, uniindex, fontsize, slanted def get_sized_alternatives_for_symbol(self, fontname, sym): if self.cm_fallback: From a89289238aeeb689bba7afd67990cb3c31f601c2 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 2 Sep 2021 23:12:33 +0200 Subject: [PATCH 3/7] Remove used_characters tracking in mathtext. Backends that need to track what characters have been used (pdf/ps, for subsetting purposes) already have their own logic to do so, so don't do it in mathtext as well. Changes in Fonts are only touching private API. Changes in the call signature of MathtextBackendAgg/MathtextBackendPath look like they are touching public API, but it is in fact impossible for an external user to construct a valid `box` parameter (this requires classes defined in `_mathtext`), so `get_results` is effectively private API from a caller PoV. It is also impossible to register new MathtextBackends without touching private API. Thus, the only difference is in the tuple returned by MathtextBackendAgg, which now has one fewer element. Because the return value is a tuple which is unpacked at the call site, it is not possible to emit a proper deprecation warning (one would need to know whether the result is being unpacked to 6 or 7 values). Callers can work around this by e.g. unpacking the last item into `*_`. Note that because this is only for MathtextBackendAgg (i.e., a raster backend), it is unlikely that callers actually care about the used_characters info at all. --- doc/api/next_api_changes/behavior/22204-AL.rst | 7 +++++++ lib/matplotlib/_mathtext.py | 2 -- lib/matplotlib/backends/backend_agg.py | 4 ++-- lib/matplotlib/mathtext.py | 7 +++---- 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 doc/api/next_api_changes/behavior/22204-AL.rst diff --git a/doc/api/next_api_changes/behavior/22204-AL.rst b/doc/api/next_api_changes/behavior/22204-AL.rst new file mode 100644 index 000000000000..151ac6618bf6 --- /dev/null +++ b/doc/api/next_api_changes/behavior/22204-AL.rst @@ -0,0 +1,7 @@ +``MathtextBackendAgg.get_results`` no longer returns ``used_characters`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The last item (``used_characters``) in the tuple returned by +``MathtextBackendAgg.get_results`` has been removed. In order to unpack this +tuple in a backward and forward-compatible way, use e.g. +``ox, oy, width, height, descent, image, *_ = parse(...)``, +which will ignore ``used_characters`` if it was present. diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 81645a2824b0..eb44098e3a1a 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -89,7 +89,6 @@ def __init__(self, default_font_prop, mathtext_backend): """ self.default_font_prop = default_font_prop self.mathtext_backend = mathtext_backend - self.used_characters = {} def get_kern(self, font1, fontclass1, sym1, fontsize1, font2, fontclass2, sym2, fontsize2, dpi): @@ -157,7 +156,6 @@ def render_glyph(self, ox, oy, font, font_class, sym, fontsize, dpi): parameters (see `get_metrics` for their detailed description). """ info = self._get_info(font, font_class, sym, fontsize, dpi) - self.used_characters.setdefault(info.font.fname, set()).add(info.num) self.mathtext_backend.render_glyph(ox, oy, info) def render_rect_filled(self, x1, y1, x2, y2): diff --git a/lib/matplotlib/backends/backend_agg.py b/lib/matplotlib/backends/backend_agg.py index f7bffe382a2c..38089d5e0db9 100644 --- a/lib/matplotlib/backends/backend_agg.py +++ b/lib/matplotlib/backends/backend_agg.py @@ -211,7 +211,7 @@ def draw_path(self, gc, path, transform, rgbFace=None): def draw_mathtext(self, gc, x, y, s, prop, angle): """Draw mathtext using :mod:`matplotlib.mathtext`.""" - ox, oy, width, height, descent, font_image, used_characters = \ + ox, oy, width, height, descent, font_image = \ self.mathtext_parser.parse(s, self.dpi, prop) xd = descent * sin(radians(angle)) @@ -254,7 +254,7 @@ def get_text_width_height_descent(self, s, prop, ismath): return w, h, d if ismath: - ox, oy, width, height, descent, fonts, used_characters = \ + ox, oy, width, height, descent, font_image = \ self.mathtext_parser.parse(s, self.dpi, prop) return width, height, descent diff --git a/lib/matplotlib/mathtext.py b/lib/matplotlib/mathtext.py index f9bc3f4faac4..1668479f0063 100644 --- a/lib/matplotlib/mathtext.py +++ b/lib/matplotlib/mathtext.py @@ -134,7 +134,7 @@ def render_rect_filled(self, x1, y1, x2, y2): y = int(y1) self.image.draw_rect_filled(int(x1), y, np.ceil(x2), y + height) - def get_results(self, box, used_characters): + def get_results(self, box): self.mode = 'bbox' orig_height = box.height orig_depth = box.depth @@ -152,8 +152,7 @@ def get_results(self, box, used_characters): self.width, self.height + self.depth, self.depth, - self.image, - used_characters) + self.image) self.image = None return result @@ -182,7 +181,7 @@ def render_glyph(self, ox, oy, info): def render_rect_filled(self, x1, y1, x2, y2): self.rects.append((x1, self.height - y2, x2 - x1, y2 - y1)) - def get_results(self, box, used_characters): + def get_results(self, box): _mathtext.ship(0, 0, box) return self._Result(self.width, self.height + self.depth, From 2ecbb56c8e6dd8b150d72297f124eb53cce76100 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 2 Sep 2021 23:29:36 +0200 Subject: [PATCH 4/7] Remove Fonts.{set_canvas_size,width,height,descent,get_results}. We can just inline the calls directly to the backend itself at the sole use site (in _parse_cached). The width, height, and depth attributes on Fonts are never used either. --- lib/matplotlib/_mathtext.py | 18 ------------------ lib/matplotlib/mathtext.py | 4 ++-- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index eb44098e3a1a..825d72136dce 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -140,15 +140,6 @@ def get_metrics(self, font, font_class, sym, fontsize, dpi, math=True): info = self._get_info(font, font_class, sym, fontsize, dpi, math) return info.metrics - def set_canvas_size(self, w, h, d): - """ - Set the size of the buffer used to render the math expression. - Only really necessary for the bitmap backends. - """ - self.width, self.height, self.depth = np.ceil([w, h, d]) - self.mathtext_backend.set_canvas_size( - self.width, self.height, self.depth) - @_api.rename_parameter("3.4", "facename", "font") def render_glyph(self, ox, oy, font, font_class, sym, fontsize, dpi): """ @@ -185,15 +176,6 @@ def get_used_characters(self): """ return self.used_characters - def get_results(self, box): - """ - Get the data needed by the backend to render the math - expression. The return value is backend-specific. - """ - result = self.mathtext_backend.get_results( - box, self.get_used_characters()) - return result - def get_sized_alternatives_for_symbol(self, fontname, sym): """ Override if your font provides multiple sizes of the same diff --git a/lib/matplotlib/mathtext.py b/lib/matplotlib/mathtext.py index 1668479f0063..cdadcdbc9e6d 100644 --- a/lib/matplotlib/mathtext.py +++ b/lib/matplotlib/mathtext.py @@ -256,8 +256,8 @@ def _parse_cached(self, s, dpi, prop): self.__class__._parser = _mathtext.Parser() box = self._parser.parse(s, font_output, fontsize, dpi) - font_output.set_canvas_size(box.width, box.height, box.depth) - return font_output.get_results(box) + backend.set_canvas_size(*np.ceil([box.width, box.height, box.depth])) + return backend.get_results(box) def math_to_image(s, filename_or_obj, prop=None, dpi=None, format=None, From c00ae8e9c8ff600f56d994cf4133d438d46ff7bc Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 12 Jan 2022 00:13:25 +0100 Subject: [PATCH 5/7] Expire rename_parameter in _mathtext. --- lib/matplotlib/_mathtext.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 825d72136dce..e4351e3047e5 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -17,7 +17,7 @@ ParseResults, QuotedString, Regex, StringEnd, Suppress, White, ZeroOrMore) import matplotlib as mpl -from . import _api, cbook +from . import cbook from ._mathtext_data import ( latex_to_bakoma, latex_to_standard, stix_glyph_fixes, stix_virtual_fonts, tex2uni) @@ -140,7 +140,6 @@ def get_metrics(self, font, font_class, sym, fontsize, dpi, math=True): info = self._get_info(font, font_class, sym, fontsize, dpi, math) return info.metrics - @_api.rename_parameter("3.4", "facename", "font") def render_glyph(self, ox, oy, font, font_class, sym, fontsize, dpi): """ At position (*ox*, *oy*), draw the glyph specified by the remaining From afe8d9e0a2fce4452addd467486e09a4b0f966ed Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 12 Jan 2022 11:46:52 +0100 Subject: [PATCH 6/7] Lift Parser.State to toplevel as standalone class. It doesn't need to be a nested class. --- lib/matplotlib/_mathtext.py | 81 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index e4351e3047e5..0b3297b3acd2 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -2,6 +2,7 @@ Implementation details for :mod:`.mathtext`. """ +import copy from collections import namedtuple import enum import functools @@ -1783,6 +1784,43 @@ def raise_error(s, loc, toks): return empty +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, font_output, font, font_class, fontsize, dpi): + self.font_output = font_output + self._font = font + self.font_class = font_class + self.fontsize = fontsize + self.dpi = dpi + + def copy(self): + return copy.copy(self) + + @property + def font(self): + return self._font + + @font.setter + def font(self, name): + if name in ('rm', 'it', 'bf'): + self.font_class = name + self._font = name + + def get_current_underline_thickness(self): + """Return the underline thickness for this state.""" + return self.font_output.get_underline_thickness( + self.font, self.fontsize, self.dpi) + + class Parser: """ A pyparsing-based parser for strings containing math expressions. @@ -2128,7 +2166,7 @@ def parse(self, s, fonts_object, fontsize, dpi): Returns the parse tree of `Node` instances. """ self._state_stack = [ - self.State(fonts_object, 'default', 'rm', fontsize, dpi)] + ParserState(fonts_object, 'default', 'rm', fontsize, dpi)] self._em_width_cache = {} try: result = self._expression.parseString(s) @@ -2142,47 +2180,6 @@ def parse(self, s, fonts_object, fontsize, dpi): self._expression.resetCache() return result[0] - # The state of the parser is maintained in a stack. Upon - # entering and leaving a group { } or math/non-math, the stack - # is pushed and popped accordingly. The current state always - # exists in the top element of the stack. - class State: - """ - Stores the state of the parser. - - States are pushed and popped from a stack as necessary, and - the "current" state is always at the top of the stack. - """ - def __init__(self, font_output, font, font_class, fontsize, dpi): - self.font_output = font_output - self._font = font - self.font_class = font_class - self.fontsize = fontsize - self.dpi = dpi - - def copy(self): - return Parser.State( - self.font_output, - self.font, - self.font_class, - self.fontsize, - self.dpi) - - @property - def font(self): - return self._font - - @font.setter - def font(self, name): - if name in ('rm', 'it', 'bf'): - self.font_class = name - self._font = name - - def get_current_underline_thickness(self): - """Return the underline thickness for this state.""" - return self.font_output.get_underline_thickness( - self.font, self.fontsize, self.dpi) - def get_state(self): """Get the current `State` of the parser.""" return self._state_stack[-1] From 519d1ebf5ddcfb6ddb6ce6af418d5ce96d07ee24 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 12 Jan 2022 19:23:52 +0100 Subject: [PATCH 7/7] Remove now unused StandardPsFonts, latex_to_{standard,cmex}, use_cmex. --- lib/matplotlib/_mathtext.py | 164 +----------------------------- lib/matplotlib/_mathtext_data.py | 167 ------------------------------- 2 files changed, 1 insertion(+), 330 deletions(-) diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 0b3297b3acd2..f0980c990302 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -20,9 +20,7 @@ import matplotlib as mpl from . import cbook from ._mathtext_data import ( - latex_to_bakoma, latex_to_standard, stix_glyph_fixes, stix_virtual_fonts, - tex2uni) -from ._afm import AFM + latex_to_bakoma, stix_glyph_fixes, stix_virtual_fonts, tex2uni) from .font_manager import FontProperties, findfont, get_font from .ft2font import KERNING_DEFAULT @@ -405,7 +403,6 @@ class UnicodeFonts(TruetypeFonts): This class will "fallback" on the Bakoma fonts when a required symbol can not be found in the font. """ - use_cmex = True # Unused; delete once mathtext becomes private. def __init__(self, *args, **kwargs): # This must come first so the backend's owner is set correctly @@ -517,7 +514,6 @@ def get_sized_alternatives_for_symbol(self, fontname, sym): class DejaVuFonts(UnicodeFonts): - use_cmex = False # Unused; delete once mathtext becomes private. def __init__(self, *args, **kwargs): # This must come first so the backend's owner is set correctly @@ -620,7 +616,6 @@ class StixFonts(UnicodeFonts): 4: 'STIXSizeFourSym', 5: 'STIXSizeFiveSym', } - use_cmex = False # Unused; delete once mathtext becomes private. cm_fallback = False _sans = False @@ -710,163 +705,6 @@ class StixSansFonts(StixFonts): _sans = True -class StandardPsFonts(Fonts): - """ - Use the standard postscript fonts for rendering to backend_ps - - Unlike the other font classes, BakomaFont and UnicodeFont, this - one requires the Ps backend. - """ - basepath = str(cbook._get_data_path('fonts/afm')) - - fontmap = { - 'cal': 'pzcmi8a', # Zapf Chancery - 'rm': 'pncr8a', # New Century Schoolbook - 'tt': 'pcrr8a', # Courier - 'it': 'pncri8a', # New Century Schoolbook Italic - 'sf': 'phvr8a', # Helvetica - 'bf': 'pncb8a', # New Century Schoolbook Bold - None: 'psyr', # Symbol - } - - def __init__(self, default_font_prop, mathtext_backend=None): - if mathtext_backend is None: - # Circular import, can be dropped after public access to - # StandardPsFonts is removed and mathtext_backend made a required - # parameter. - from . import mathtext - mathtext_backend = mathtext.MathtextBackendPath() - super().__init__(default_font_prop, mathtext_backend) - self.glyphd = {} - self.fonts = {} - - filename = findfont(default_font_prop, fontext='afm', - directory=self.basepath) - if filename is None: - filename = findfont('Helvetica', fontext='afm', - directory=self.basepath) - with open(filename, 'rb') as fd: - default_font = AFM(fd) - default_font.fname = filename - - self.fonts['default'] = default_font - self.fonts['regular'] = default_font - - def _get_font(self, font): - if font in self.fontmap: - basename = self.fontmap[font] - else: - basename = font - - cached_font = self.fonts.get(basename) - if cached_font is None: - fname = os.path.join(self.basepath, basename + ".afm") - with open(fname, 'rb') as fd: - cached_font = AFM(fd) - cached_font.fname = fname - self.fonts[basename] = cached_font - self.fonts[cached_font.get_fontname()] = cached_font - return cached_font - - def _get_info(self, fontname, font_class, sym, fontsize, dpi, math=True): - """Load the cmfont, metrics and glyph with caching.""" - key = fontname, sym, fontsize, dpi - tup = self.glyphd.get(key) - - if tup is not None: - return tup - - # Only characters in the "Letter" class should really be italicized. - # This class includes greek letters, so we're ok - if (fontname == 'it' and - (len(sym) > 1 - or not unicodedata.category(sym).startswith("L"))): - fontname = 'rm' - - found_symbol = False - - if sym in latex_to_standard: - fontname, num = latex_to_standard[sym] - glyph = chr(num) - found_symbol = True - elif len(sym) == 1: - glyph = sym - num = ord(glyph) - found_symbol = True - else: - _log.warning( - "No TeX to built-in Postscript mapping for {!r}".format(sym)) - - slanted = (fontname == 'it') - font = self._get_font(fontname) - - if found_symbol: - try: - glyph_name = font.get_name_char(glyph) - except KeyError: - _log.warning( - "No glyph in standard Postscript font {!r} for {!r}" - .format(font.get_fontname(), sym)) - found_symbol = False - - if not found_symbol: - glyph = '?' - num = ord(glyph) - glyph_name = font.get_name_char(glyph) - - offset = 0 - - scale = 0.001 * fontsize - - xmin, ymin, xmax, ymax = [val * scale - for val in font.get_bbox_char(glyph)] - metrics = types.SimpleNamespace( - advance = font.get_width_char(glyph) * scale, - width = font.get_width_char(glyph) * scale, - height = font.get_height_char(glyph) * scale, - xmin = xmin, - xmax = xmax, - ymin = ymin+offset, - ymax = ymax+offset, - # iceberg is the equivalent of TeX's "height" - iceberg = ymax + offset, - slanted = slanted - ) - - self.glyphd[key] = types.SimpleNamespace( - font = font, - fontsize = fontsize, - postscript_name = font.get_fontname(), - metrics = metrics, - glyph_name = glyph_name, - symbol_name = glyph_name, # Backcompat alias. - num = num, - glyph = glyph, - offset = offset - ) - - return self.glyphd[key] - - def get_kern(self, font1, fontclass1, sym1, fontsize1, - font2, fontclass2, sym2, fontsize2, dpi): - if font1 == font2 and fontsize1 == fontsize2: - info1 = self._get_info(font1, fontclass1, sym1, fontsize1, dpi) - info2 = self._get_info(font2, fontclass2, sym2, fontsize2, dpi) - font = info1.font - return (font.get_kern_dist(info1.glyph, info2.glyph) - * 0.001 * fontsize1) - return super().get_kern(font1, fontclass1, sym1, fontsize1, - font2, fontclass2, sym2, fontsize2, dpi) - - def get_xheight(self, font, fontsize, dpi): - font = self._get_font(font) - return font.get_xheight() * 0.001 * fontsize - - def get_underline_thickness(self, font, fontsize, dpi): - font = self._get_font(font) - return font.get_underline_thickness() * 0.001 * fontsize - - ############################################################################## # TeX-LIKE BOX MODEL diff --git a/lib/matplotlib/_mathtext_data.py b/lib/matplotlib/_mathtext_data.py index 9429cbf92d55..a60634731b6b 100644 --- a/lib/matplotlib/_mathtext_data.py +++ b/lib/matplotlib/_mathtext_data.py @@ -236,173 +236,6 @@ '\\_' : ('cmtt10', 0x5f) } -latex_to_cmex = { # Unused; delete once mathtext becomes private. - r'\__sqrt__' : 112, - r'\bigcap' : 92, - r'\bigcup' : 91, - r'\bigodot' : 75, - r'\bigoplus' : 77, - r'\bigotimes' : 79, - r'\biguplus' : 93, - r'\bigvee' : 95, - r'\bigwedge' : 94, - r'\coprod' : 97, - r'\int' : 90, - r'\leftangle' : 173, - r'\leftbrace' : 169, - r'\oint' : 73, - r'\prod' : 89, - r'\rightangle' : 174, - r'\rightbrace' : 170, - r'\sum' : 88, - r'\widehat' : 98, - r'\widetilde' : 101, -} - -latex_to_standard = { - r'\cong' : ('psyr', 64), - r'\Delta' : ('psyr', 68), - r'\Phi' : ('psyr', 70), - r'\Gamma' : ('psyr', 89), - r'\alpha' : ('psyr', 97), - r'\beta' : ('psyr', 98), - r'\chi' : ('psyr', 99), - r'\delta' : ('psyr', 100), - r'\varepsilon' : ('psyr', 101), - r'\phi' : ('psyr', 102), - r'\gamma' : ('psyr', 103), - r'\eta' : ('psyr', 104), - r'\iota' : ('psyr', 105), - r'\varphi' : ('psyr', 106), - r'\kappa' : ('psyr', 108), - r'\nu' : ('psyr', 110), - r'\pi' : ('psyr', 112), - r'\theta' : ('psyr', 113), - r'\rho' : ('psyr', 114), - r'\sigma' : ('psyr', 115), - r'\tau' : ('psyr', 116), - r'\upsilon' : ('psyr', 117), - r'\varpi' : ('psyr', 118), - r'\omega' : ('psyr', 119), - r'\xi' : ('psyr', 120), - r'\psi' : ('psyr', 121), - r'\zeta' : ('psyr', 122), - r'\sim' : ('psyr', 126), - r'\leq' : ('psyr', 163), - r'\infty' : ('psyr', 165), - r'\clubsuit' : ('psyr', 167), - r'\diamondsuit' : ('psyr', 168), - r'\heartsuit' : ('psyr', 169), - r'\spadesuit' : ('psyr', 170), - r'\leftrightarrow' : ('psyr', 171), - r'\leftarrow' : ('psyr', 172), - r'\uparrow' : ('psyr', 173), - r'\rightarrow' : ('psyr', 174), - r'\downarrow' : ('psyr', 175), - r'\pm' : ('psyr', 176), - r'\geq' : ('psyr', 179), - r'\times' : ('psyr', 180), - r'\propto' : ('psyr', 181), - r'\partial' : ('psyr', 182), - r'\bullet' : ('psyr', 183), - r'\div' : ('psyr', 184), - r'\neq' : ('psyr', 185), - r'\equiv' : ('psyr', 186), - r'\approx' : ('psyr', 187), - r'\ldots' : ('psyr', 188), - r'\aleph' : ('psyr', 192), - r'\Im' : ('psyr', 193), - r'\Re' : ('psyr', 194), - r'\wp' : ('psyr', 195), - r'\otimes' : ('psyr', 196), - r'\oplus' : ('psyr', 197), - r'\oslash' : ('psyr', 198), - r'\cap' : ('psyr', 199), - r'\cup' : ('psyr', 200), - r'\supset' : ('psyr', 201), - r'\supseteq' : ('psyr', 202), - r'\subset' : ('psyr', 204), - r'\subseteq' : ('psyr', 205), - r'\in' : ('psyr', 206), - r'\notin' : ('psyr', 207), - r'\angle' : ('psyr', 208), - r'\nabla' : ('psyr', 209), - r'\textregistered' : ('psyr', 210), - r'\copyright' : ('psyr', 211), - r'\texttrademark' : ('psyr', 212), - r'\Pi' : ('psyr', 213), - r'\prod' : ('psyr', 213), - r'\surd' : ('psyr', 214), - r'\__sqrt__' : ('psyr', 214), - r'\cdot' : ('psyr', 215), - r'\urcorner' : ('psyr', 216), - r'\vee' : ('psyr', 217), - r'\wedge' : ('psyr', 218), - r'\Leftrightarrow' : ('psyr', 219), - r'\Leftarrow' : ('psyr', 220), - r'\Uparrow' : ('psyr', 221), - r'\Rightarrow' : ('psyr', 222), - r'\Downarrow' : ('psyr', 223), - r'\Diamond' : ('psyr', 224), - r'\Sigma' : ('psyr', 229), - r'\sum' : ('psyr', 229), - r'\forall' : ('psyr', 34), - r'\exists' : ('psyr', 36), - r'\lceil' : ('psyr', 233), - r'\lbrace' : ('psyr', 123), - r'\Psi' : ('psyr', 89), - r'\bot' : ('psyr', 0o136), - r'\Omega' : ('psyr', 0o127), - r'\leftbracket' : ('psyr', 0o133), - r'\rightbracket' : ('psyr', 0o135), - r'\leftbrace' : ('psyr', 123), - r'\leftparen' : ('psyr', 0o50), - r'\prime' : ('psyr', 0o242), - r'\sharp' : ('psyr', 0o43), - r'\slash' : ('psyr', 0o57), - r'\Lambda' : ('psyr', 0o114), - r'\neg' : ('psyr', 0o330), - r'\Upsilon' : ('psyr', 0o241), - r'\rightbrace' : ('psyr', 0o175), - r'\rfloor' : ('psyr', 0o373), - r'\lambda' : ('psyr', 0o154), - r'\to' : ('psyr', 0o256), - r'\Xi' : ('psyr', 0o130), - r'\emptyset' : ('psyr', 0o306), - r'\lfloor' : ('psyr', 0o353), - r'\rightparen' : ('psyr', 0o51), - r'\rceil' : ('psyr', 0o371), - r'\ni' : ('psyr', 0o47), - r'\epsilon' : ('psyr', 0o145), - r'\Theta' : ('psyr', 0o121), - r'\langle' : ('psyr', 0o341), - r'\leftangle' : ('psyr', 0o341), - r'\rangle' : ('psyr', 0o361), - r'\rightangle' : ('psyr', 0o361), - r'\rbrace' : ('psyr', 0o175), - r'\circ' : ('psyr', 0o260), - r'\diamond' : ('psyr', 0o340), - r'\mu' : ('psyr', 0o155), - r'\mid' : ('psyr', 0o352), - r'\imath' : ('pncri8a', 105), - r'\%' : ('pncr8a', 37), - r'\$' : ('pncr8a', 36), - r'\{' : ('pncr8a', 123), - r'\}' : ('pncr8a', 125), - r'\backslash' : ('pncr8a', 92), - r'\ast' : ('pncr8a', 42), - r'\#' : ('pncr8a', 35), - - r'\circumflexaccent' : ('pncri8a', 124), # for \hat - r'\combiningbreve' : ('pncri8a', 81), # for \breve - r'\combininggraveaccent' : ('pncri8a', 114), # for \grave - r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute - r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot - r'\combiningtilde' : ('pncri8a', 75), # for \tilde - r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec - r'\combiningdotabove' : ('pncri8a', 26), # for \dot -} - # Automatically generated. type12uni = {