Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
87 changes: 49 additions & 38 deletions lib/matplotlib/backends/backend_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def __init__(self, width, height, dpi):
self._filter_renderers = []

self._update_methods()
self.mathtext_parser = MathTextParser('agg')
self.mathtext_parser = MathTextParser('path')

self.bbox = Bbox.from_bounds(0, 0, self.width, self.height)

Expand Down Expand Up @@ -173,46 +173,58 @@ 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 = \
self.mathtext_parser.parse(s, self.dpi, prop,
antialiased=gc.get_antialiased())

xd = descent * sin(radians(angle))
yd = descent * cos(radians(angle))
x = round(x + ox + xd)
y = round(y - oy + yd)
self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
# y is downwards.
parse = self.mathtext_parser.parse(
s, self.dpi, prop, antialiased=gc.get_antialiased())
c = cos(radians(angle))
s = sin(radians(angle))
for font, size, char, dx, dy in parse.glyphs: # dy is upwards.
font.set_size(size, self.dpi)
bitmap = font._render_glyph(
font.get_char_index(char),
# The "y" parameter is upwards (per FreeType).
x + dx * c - dy * s, self.height - y + dx * s + dy * c, angle,
get_hinting_flag())
# draw_text_image's y is downwards & the bitmap bottom side.
self._renderer.draw_text_image(
bitmap["buffer"],
bitmap["left"],
int(self.height) - bitmap["top"] + bitmap["buffer"].shape[0],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking whether we should round here or not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think self.height is already always a integer-valued float, as it's the size of the buffer in pixels (I have a bit of doubt about hiDPI though). In fact, it would probably be nicer if self.height (and likewise self.width) was made an int (in fact, get_width_height, which is a FigureCanvasBase API, unlike self.{width,height}, which are specific to the Agg canvas, returns ints).

0, gc)
if not angle:
for dx, dy, w, h in parse.rects: # dy is upwards & the rect top side.
self._renderer.draw_text_image(
np.full((round(h), round(w)), np.uint8(0xff)),
round(x + dx), round(y - dy - h),
0, gc)
else:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This latter half is seemingly untested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we don't test rotated mathtext fractions? Something like figtext(.5, .5, r"$\frac{3}{4}$", rotation=45) would do.

rgba = gc.get_rgb()
if len(rgba) == 3 or gc.get_forced_alpha():
rgba = rgba[:3] + (gc.get_alpha(),)
gc1 = self.new_gc()
gc1.set_linewidth(0)
for dx, dy, w, h in parse.rects: # dy is upwards & the rect top side.
path = Path._create_closed(
[(dx, dy), (dx + w, dy), (dx + w, dy + h), (dx, dy + h)])
self._renderer.draw_path(
gc1, path,
mpl.transforms.Affine2D()
.rotate_deg(angle).translate(x, self.height - y),
rgba)
gc1.restore()

def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
# docstring inherited
if ismath:
return self.draw_mathtext(gc, x, y, s, prop, angle)
font = self._prepare_font(prop)
# We pass '0' for angle here, since it will be rotated (in raster
# space) in the following call to draw_text_image).
font.set_text(s, 0, flags=get_hinting_flag())
font.draw_glyphs_to_bitmap(
antialiased=gc.get_antialiased())
d = font.get_descent() / 64.0
# The descent needs to be adjusted for the angle.
xo, yo = font.get_bitmap_offset()
xo /= 64.0
yo /= 64.0

rad = radians(angle)
xd = d * sin(rad)
yd = d * cos(rad)
# Rotating the offset vector ensures text rotates around the anchor point.
# Without this, rotated text offsets incorrectly, causing a horizontal shift.
# Applying the 2D rotation matrix.
rotated_xo = xo * cos(rad) - yo * sin(rad)
rotated_yo = xo * sin(rad) + yo * cos(rad)
# Subtract rotated_yo to account for the inverted y-axis in computer graphics,
# compared to the mathematical convention.
x = round(x + rotated_xo + xd)
y = round(y - rotated_yo + yd)

self._renderer.draw_text_image(font, x, y + 1, angle, gc)
font.set_text(s, angle, flags=get_hinting_flag())
for bitmap in font._render_glyphs(x, self.height - y):
self._renderer.draw_text_image(
bitmap["buffer"],
bitmap["left"],
int(self.height) - bitmap["top"] + bitmap["buffer"].shape[0],
0, gc)

def get_text_width_height_descent(self, s, prop, ismath):
# docstring inherited
Expand All @@ -222,9 +234,8 @@ def get_text_width_height_descent(self, s, prop, ismath):
return super().get_text_width_height_descent(s, prop, ismath)

if ismath:
ox, oy, width, height, descent, font_image = \
self.mathtext_parser.parse(s, self.dpi, prop)
return width, height, descent
parse = self.mathtext_parser.parse(s, self.dpi, prop)
return parse.width, parse.height, parse.depth

font = self._prepare_font(prop)
font.set_text(s, 0.0, flags=get_hinting_flag())
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/axvspan_epoch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/barh_tick_label.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/boxplot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/bxp_baseline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/bxp_rangewhis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/canonical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/contour_colorbar.pdf
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/extent_units.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/fill_units.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/grouped_bar.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hexbin_log.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hist_density.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hist_offset.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hist_step_horiz.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hlines_basic.png
Binary file not shown.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/imshow_clip.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/markevery.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/nonfinite_limits.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/pie_ccw_true.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/pie_default.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/pie_frame_grid.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/pie_no_label.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/rc_grid.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/rc_markerfill.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/rc_spines.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/secondary_xy.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/vlines_basic.png
Binary file modified lib/matplotlib/tests/baseline_images/test_backend_pdf/kerning.pdf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Loading