Skip to content

Commit 35c4647

Browse files
anntzerQuLogic
authored andcommitted
Draw mathtext symbols from their baselines.
1 parent fddbfe2 commit 35c4647

File tree

1,466 files changed

+53577
-69635
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,466 files changed

+53577
-69635
lines changed

lib/matplotlib/_mathtext.py

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import enum
1010
import functools
1111
import logging
12+
import math
1213
import os
1314
import re
1415
import types
@@ -127,50 +128,59 @@ def __init__(self, box: Box):
127128
def to_vector(self) -> VectorParse:
128129
w, h, d = map(
129130
np.ceil, [self.box.width, self.box.height, self.box.depth])
130-
gs = [(info.font, info.fontsize, info.num, ox, h - oy + info.offset)
131+
gs = [(info.font, info.fontsize, info.num, ox, -oy + info.offset)
131132
for ox, oy, info in self.glyphs]
132-
rs = [(x1, h - y2, x2 - x1, y2 - y1)
133+
rs = [(x1, -y2, x2 - x1, y2 - y1)
133134
for x1, y1, x2, y2 in self.rects]
134135
return VectorParse(w, h + d, d, gs, rs)
135136

136137
def to_raster(self, *, antialiased: bool) -> RasterParse:
137138
# Metrics y's and mathtext y's are oriented in opposite directions,
138139
# hence the switch between ymin and ymax.
139140
xmin = min([*[ox + info.metrics.xmin for ox, oy, info in self.glyphs],
140-
*[x1 for x1, y1, x2, y2 in self.rects], 0]) - 1
141-
ymin = min([*[oy - info.metrics.ymax for ox, oy, info in self.glyphs],
142-
*[y1 for x1, y1, x2, y2 in self.rects], 0]) - 1
141+
*[x1 for x1, y1, x2, y2 in self.rects], 0])
142+
ymin = min([*[oy - max(info.metrics.ymax, info.metrics.iceberg)
143+
for ox, oy, info in self.glyphs],
144+
*[y1 for x1, y1, x2, y2 in self.rects], 0])
143145
xmax = max([*[ox + info.metrics.xmax for ox, oy, info in self.glyphs],
144-
*[x2 for x1, y1, x2, y2 in self.rects], 0]) + 1
146+
*[x2 for x1, y1, x2, y2 in self.rects], 0])
145147
ymax = max([*[oy - info.metrics.ymin for ox, oy, info in self.glyphs],
146-
*[y2 for x1, y1, x2, y2 in self.rects], 0]) + 1
148+
*[y2 for x1, y1, x2, y2 in self.rects], 0])
149+
# Rasterizing can leak into the neighboring pixel, hence the +/-1; it
150+
# will be cropped at the end.
151+
xmin = math.floor(xmin - 1)
152+
ymin = math.floor(ymin - 1)
153+
xmax = math.ceil(xmax + 1)
154+
ymax = math.ceil(ymax + 1)
147155
w = xmax - xmin
148-
h = ymax - ymin - self.box.depth
149-
d = ymax - ymin - self.box.height
150-
image = FT2Image(int(np.ceil(w)), int(np.ceil(h + max(d, 0))))
156+
h = max(-ymin, 0)
157+
d = max(ymax, 0)
158+
image = FT2Image(w, h + d)
151159

152-
# Ideally, we could just use self.glyphs and self.rects here, shifting
153-
# their coordinates by (-xmin, -ymin), but this yields slightly
154-
# different results due to floating point slop; shipping twice is the
155-
# old approach and keeps baseline images backcompat.
156-
shifted = ship(self.box, (-xmin, -ymin))
157-
158-
for ox, oy, info in shifted.glyphs:
160+
for ox, oy, info in self.glyphs:
161+
ox -= xmin
162+
oy -= (-h + info.offset)
159163
info.font.draw_glyph_to_bitmap(
160-
image,
161-
int(ox),
162-
int(oy - np.ceil(info.metrics.iceberg)),
163-
info.glyph,
164-
antialiased=antialiased)
165-
for x1, y1, x2, y2 in shifted.rects:
164+
image, ox, oy, info.glyph, antialiased=antialiased)
165+
for x1, y1, x2, y2 in self.rects:
166+
x1 -= xmin
167+
x2 -= xmin
168+
y1 -= -h
169+
y2 -= -h
166170
height = max(int(y2 - y1) - 1, 0)
167171
if height == 0:
168172
center = (y2 + y1) / 2
169173
y = int(center - (height + 1) / 2)
170174
else:
171175
y = int(y1)
172-
image.draw_rect_filled(int(x1), y, int(np.ceil(x2)), y + height)
173-
return RasterParse(0, 0, w, h + d, d, image)
176+
image.draw_rect_filled(int(x1), y, math.ceil(x2), y + height)
177+
178+
image = np.asarray(image)
179+
while h and (image[0] == 0).all():
180+
image = image[1:]
181+
while d and (image[-1] == 0).all():
182+
image = image[:-1]
183+
return RasterParse(xmin, 0, w, h + d, d, image)
174184

175185

176186
class FontMetrics(NamedTuple):
@@ -1602,7 +1612,7 @@ def ship(box: Box, xy: tuple[float, float] = (0, 0)) -> Output:
16021612
cur_v = 0.
16031613
cur_h = 0.
16041614
off_h = ox
1605-
off_v = oy + box.height
1615+
off_v = oy
16061616
output = Output(box)
16071617

16081618
def clamp(value: float) -> float:

lib/matplotlib/backends/backend_agg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
180180
yd = descent * cos(radians(angle))
181181
x = round(x + ox + xd)
182182
y = round(y - oy + yd)
183-
self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
183+
self._renderer.draw_text_image(font_image, x, y, angle, gc)
184184

185185
def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
186186
# docstring inherited
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Binary file not shown.

0 commit comments

Comments
 (0)