8000 Merge pull request #18002 from anntzer/unmathtext · matplotlib/matplotlib@a0b9fe3 · GitHub
[go: up one dir, main page]

Skip to content
< 65FF script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/sessions-eed3aa0554dd.js" defer="defer">

Commit a0b9fe3

Browse files
authored
Merge pull request #18002 from anntzer/unmathtext
Deprecate various vector-backend-specific mathtext helpers.
2 parents 164e650 + 4b2a3a9 commit a0b9fe3

File tree

9 files changed

+127
-68
lines changed

9 files changed

+127
-68
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Deprecation of various mathtext helpers
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
The ``MathtextBackendPdf``, ``MathtextBackendPs``, ``MathtextBackendSvg``,
4+
and ``MathtextBackendCairo`` classes from the :mod:`.mathtext` module, as
5+
well as the corresponding ``.mathtext_parser`` attributes on ``RendererPdf``,
6+
``RendererPS``, ``RendererSVG``, and ``RendererCairo``, are deprecated. The
7+
``MathtextBackendPath`` class can be used to obtain a list of glyphs and
8+
rectangles in a mathtext expression, and renderer-specific logic should be
9+
directly implemented in the renderer.
10+
11+
``StandardPsFonts.pswriter`` is unused and deprecated.

lib/matplotlib/afm.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,10 @@ def get_fontname(self):
469469
"""Return the font name, e.g., 'Times-Roman'."""
470470
return self._header[b'FontName']
471471

472+
@property
473+
def postscript_name(self): # For consistency with FT2Font.
474+
return self.get_fontname()
475+
472476
def get_fullname(self):
473477
"""Return the font full name, e.g., 'Times-Roman'."""
474478
name = self._header.get(b'FullName')

lib/matplotlib/backends/_backend_pdf_ps.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def track(self, font, s):
4545
fname = font.fname
4646
self.used.setdefault(fname, set()).update(map(ord, s))
4747

48+
# Not public, can be removed when pdf/ps merge_used_characters is removed.
4849
def merge(self, other):
4950
"""Update self with a font path to character codepoints."""
5051
for fname, charset in other.items():
@@ -87,7 +88,12 @@ def get_text_width_height_descent(self, s, prop, ismath):
8788
s, fontsize, renderer=self)
8889
return w, h, d
8990
elif ismath:
90-
parse = self.mathtext_parser.parse(s, 72, prop)
91+
# Circular import.
92+
from matplotlib.backends.backend_ps import RendererPS
93+
parse = self._text2path.mathtext_parser.parse(
94+
s, 72, prop,
95+
_force_standard_ps_fonts=(isinstance(self, RendererPS)
96+
and mpl.rcParams["ps.useafm"]))
9197
return parse.width, parse.height, parse.depth
9298
elif mpl.rcParams[self._use_afm_rc_name]:
9399
font = self._get_font_afm(prop)

lib/matplotlib/backends/backend_cairo.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,13 @@ def __init__(self, dpi):
131131
self.gc = GraphicsContextCairo(renderer=self)
132132
self.text_ctx = cairo.Context(
133133
cairo.ImageSurface(cairo.FORMAT_ARGB32, 1, 1))
134-
self.mathtext_parser = MathTextParser('Cairo')
135134
RendererBase.__init__(self)
136135

136+
@cbook.deprecated("3.4")
137+
@property
138+
def mathtext_parser(self):
139+
return MathTextParser('Cairo')
140+
137141
def set_ctx_from_surface(self, surface):
138142
self.gc.ctx = cairo.Context(surface)
139143
# Although it may appear natural to automatically call
@@ -254,26 +258,25 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
254258

255259
def _draw_mathtext(self, gc, x, y, s, prop, angle):
256260
ctx = gc.ctx
257-
width, height, descent, glyphs, rects = self.mathtext_parser.parse(
258-
s, self.dpi, prop)
261+
width, height, descent, glyphs, rects = \
262+
self._text2path.mathtext_parser.parse(s, self.dpi, prop)
259263

260264
ctx.save()
261265
ctx.translate(x, y)
262266
if angle:
263267
ctx.rotate(np.deg2rad(-angle))
264268

265-
for font, fontsize, s, ox, oy in glyphs:
269+
for font, fontsize, idx, ox, oy in glyphs:
266270
ctx.new_path()
267-
ctx.move_to(ox, oy)
268-
271+
ctx.move_to(ox, -oy)
269272
ctx.select_font_face(
270273
*_cairo_font_args_from_font_prop(ttfFontProperty(font)))
271274
ctx.set_font_size(fontsize * self.dpi / 72)
272-
ctx.show_text(s)
275+
ctx.show_text(chr(idx))
273276

274277
for ox, oy, w, h in rects:
275278
ctx.new_path()
276-
ctx.rectangle(ox, oy, w, h)
279+
ctx.rectangle(ox, -oy, w, -h)
277280
ctx.set_source_rgb(0, 0, 0)
278281
ctx.fill_preserve()
279282

@@ -290,8 +293,9 @@ def get_text_width_height_descent(self, s, prop, ismath):
290293
return super().get_text_width_height_descent(s, prop, ismath)
291294

292295
if ismath:
293-
dims = self.mathtext_parser.parse(s, self.dpi, prop)
294-
return dims[0:3] # return width, height, descent
296+
width, height, descent, *_ = \
297+
self._text2path.mathtext_parser.parse(s, self.dpi, prop)
298+
return width, height, descent
295299

296300
ctx = self.text_ctx
297301
# problem - scale remembers last setting and font can become

lib/matplotlib/backends/backend_pdf.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,9 +1796,13 @@ def __init__(self, file, image_dpi, height, width):
17961796
super().__init__(width, height)
17971797
self.file = file
17981798
self.gc = self.new_gc()
1799-
self.mathtext_parser = MathTextParser("Pdf")
18001799
self.image_dpi = image_dpi
18011800

1801+
@cbook.deprecated("3.4")
1802+
@property
1803+
def mathtext_parser(self):
1804+
return MathTextParser("Pdf")
1805+
18021806
def finalize(self):
18031807
self.file.output(*self.gc.finalize())
18041808

@@ -2044,9 +2048,8 @@ def _setup_textpos(self, x, y, angle, oldx=0, oldy=0, oldangle=0):
20442048

20452049
def draw_mathtext(self, gc, x, y, s, prop, angle):
20462050
# TODO: fix positioning and encoding
2047-
width, height, descent, glyphs, rects, used_characters = \
2048-
self.mathtext_parser.parse(s, 72, prop)
2049-
self.file._character_tracker.merge(used_characters)
2051+
width, height, descent, glyphs, rects = \
2052+
self._text2path.mathtext_parser.parse(s, 72, prop)
20502053

20512054
# When using Type 3 fonts, we can't use character codes higher
20522055
# than 255, so we use the "Do" command to render those
@@ -2064,7 +2067,9 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
20642067
self.file.output(Op.begin_text)
20652068
prev_font = None, None
20662069
oldx, oldy = 0, 0
2067-
for ox, oy, fontname, fontsize, num, symbol_name in glyphs:
2070+
for font, fontsize, num, ox, oy in glyphs:
2071+
self.file._character_tracker.track(font, chr(num))
2072+
fontname = font.fname
20682073
if is_opentype_cff_font(fontname):
20692074
fonttype = 42
20702075
else:
@@ -2084,7 +2089,8 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
20842089
# If using Type 3 fonts, render all of the multi-byte characters
20852090
# as XObjects using the 'Do' command.
20862091
if global_fonttype == 3:
2087-
for ox, oy, fontname, fontsize, num, symbol_name in glyphs:
2092+
for font, fontsize, num, ox, oy in glyphs:
2093+
fontname = font.fname
20882094
if is_opentype_cff_font(fontname):
20892095
fonttype = 42
20902096
else:
@@ -2096,6 +2102,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
20962102
0.001 * fontsize, 0,
20972103
0, 0.001 * fontsize,
20982104
ox, oy, Op.concat_matrix)
2105+
symbol_name = font.get_glyph_name(font.get_char_index(num))
20992106
name = self.file._get_xobject_symbol_name(
21002107
fontname, symbol_name)
21012108
self.file.output(Name(name), Op.use_xobject)

lib/matplotlib/backends/backend_ps.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import matplotlib as mpl
2121
from matplotlib import cbook, _path
2222
from matplotlib import _text_layout
23+
from matplotlib.afm import AFM
2324
from matplotlib.backend_bases import (
2425
_Backend, _check_savefig_extra_args, FigureCanvasBase, FigureManagerBase,
2526
GraphicsContextBase, RendererBase)
@@ -167,7 +168,11 @@ def __init__(self, width, height, pswriter, imagedpi=72):
167168
self._path_collection_id = 0
168169

169170
self._character_tracker = _backend_pdf_ps.CharacterTracker()
170-
self.mathtext_parser = MathTextParser("PS")
171+
172+
@cbook.deprecated("3.3")
173+
@property
174+
def mathtext_parser(self):
175+
return MathTextParser("PS")
171176

172177
@cbook.deprecated("3.3")
173178
@property
@@ -599,18 +604,33 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
599604
if debugPS:
600605
self._pswriter.write("% mathtext\n")
601606

602-
width, height, descent, pswriter, used_characters = \
603-
self.mathtext_parser.parse(s, 72, prop)
604-
self._character_tracker.merge(used_characters)
607+
width, height, descent, glyphs, rects = \
608+
self._text2path.mathtext_parser.parse(
609+
s, 72, prop,
610+
_force_standard_ps_fonts=mpl.rcParams["ps.useafm"])
605611
self.set_color(*gc.get_rgb())
606-
thetext = pswriter.getvalue()
607-
self._pswriter.write(f"""\
608-
gsave
609-
{x:f} {y:f} translate
610-
{angle:f} rotate
611-
{thetext}
612-
grestore
613-
""")
612+
self._pswriter.write(
613+
f"gsave\n"
614+
f"{x:f} {y:f} translate\n"
615+
f"{angle:f} rotate\n")
616+
lastfont = None
617+
for font, fontsize, num, ox, oy in glyphs:
618+
self._character_tracker.track(font, chr(num))
619+
if (font.postscript_name, fontsize) != lastfont:
620+
lastfont = font.postscript_name, fontsize
621+
self._pswriter.write(
622+
f"/{font.postscript_name} findfont\n"
623+
f"{fontsize} scalefont\n"
624+
f"setfont\n")
625+
symbol_name = (
626+
font.get_name_char(chr(num)) if isinstance(font, AFM) else
627+
font.get_glyph_name(font.get_char_index(num)))
628+
self._pswriter.write(
629+
f"{ox:f} {oy:f} moveto\n"
630+
f"/{symbol_name} glyphshow\n")
631+
for ox, oy, w, h in rects:
632+
self._pswriter.write(f"{ox} {oy} {w} {h} rectfill\n")
633+
self._pswriter.write("grestore\n")
614634

615635
def draw_gouraud_triangle(self, gc, points, colors, trans):
616636
self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)),

lib/matplotlib/backends/backend_svg.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ def __init__(self, width, height, svgwriter, basename=None, image_dpi=72,
294294
self._has_gouraud = False
295295
self._n_gradients = 0
296296
self._fonts = OrderedDict()
297-
self.mathtext_parser = MathTextParser('SVG')
298297

299298
RendererBase.__init__(self)
300299
self._glyph_map = dict()
@@ -312,6 +311,11 @@ def __init__(self, width, height, svgwriter, basename=None, image_dpi=72,
312311
self._write_metadata(metadata)
313312
self._write_default_style()
314313

314+
@cbook.deprecated("3.4")
315+
@property
316+
def mathtext_parser(self):
317+
return MathTextParser('SVG')
318+
315319
def finalize(self):
316320
self._write_clips()
317321
self._write_hatches()
@@ -1173,26 +1177,23 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
11731177
else:
11741178
writer.comment(s)
11751179

1176-
width, height, descent, svg_elements, used_characters = \
1177-
self.mathtext_parser.parse(s, 72, prop)
1178-
svg_glyphs = svg_elements.svg_glyphs
1179-
svg_rects = svg_elements.svg_rects
1180-
1181-
attrib = {}
1182-
attrib['style'] = generate_css(style)
1183-
attrib['transform'] = generate_transform([
1184-
('translate', (x, y)),
1185-
('rotate', (-angle,))])
1180+
width, height, descent, glyphs, rects = \
1181+
self._text2path.mathtext_parser.parse(s, 72, prop)
11861182

11871183
# Apply attributes to 'g', not 'text', because we likely have some
11881184
# rectangles as well with the same style and transformation.
1189-
writer.start('g', attrib=attrib)
1185+
writer.start('g',
1186+
style=generate_css(style),
1187+
transform=generate_transform([
1188+
('translate', (x, y)),
1189+
('rotate', (-angle,))]),
1190+
)
11901191

11911192
writer.start('text')
11921193

11931194
# Sort the characters by font, and output one tspan for each.
11941195
spans = OrderedDict()
1195-
for font, fontsize, thetext, new_x, new_y, metrics in svg_glyphs:
1196+
for font, fontsize, thetext, new_x, new_y in glyphs:
11961197
style = generate_css({
11971198
'font-size': short_float_fmt(fontsize) + 'px',
11981199
'font-family': font.family_name,
@@ -1223,15 +1224,14 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
12231224

12241225
writer.end('text')
12251226

1226-
if len(svg_rects):
1227-
for x, y, width, height in svg_rects:
1228-
writer.element(
1229-
'rect',
1230-
x=short_float_fmt(x),
1231-
y=short_float_fmt(-y + height),
1232-
width=short_float_fmt(width),
1233-
height=short_float_fmt(height)
1234-
)
1227+
for x, y, width, height in rects:
1228+
writer.element(
1229+
'rect',
1230+
x=short_float_fmt(x),
1231+
y=short_float_fmt(-y-1),
1232+
width=short_float_fmt(width),
1233+
height=short_float_fmt(height)
1234+
)
12351235

12361236
writer.end('g')
12371237

0 commit comments

Comments
 (0)
0