Repository: matplotlib/matplotlib
File: lib/matplotlib/backends/backend_agg.py (Python)

Code before:

    def draw_mathtext(self, gc, x, y, s, prop, angle):
        """Draw mathtext using :mod:`matplotlib.mathtext`."""
        # y is downwards.
        parse = self.mathtext_parser.parse(
            s, self.dpi, prop, antialiased=gc.get_antialiased())
        cos = math.cos(math.radians(angle))
        sin = math.sin(math.radians(angle))
        for font, size, _char, glyph_index, dx, dy in parse.glyphs:  # dy is upwards.
            font.set_size(size, self.dpi)
            hf = font._hinting_factor
            font._set_transform(
                [[round(0x10000 * cos / hf), round(0x10000 * -sin)],
                 [round(0x10000 * sin / hf), round(0x10000 * cos)]],
                [round(0x40 * (x + dx * cos - dy * sin)),
                 # FreeType's y is upwards.
                 round(0x40 * (self.height - y + dx * sin + dy * cos))]
            )
            bitmap = font._render_glyph(
                glyph_index, get_hinting_flag(),
                RenderMode.NORMAL if gc.get_antialiased() else RenderMode.MONO)
            # 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],
                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:
            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

Review comment (bug):
`MONO` is a 1-bit image; `FT2Font::draw_glyph(s)_to_bitmap` understand that, but I don't think `draw_text_image` does, hence the broken results without antialiasing.

Code after:

    def draw_mathtext(self, gc, x, y, s, prop, angle):
        """Draw mathtext using :mod:`matplotlib.mathtext`."""
        # y is downwards.
        parse = self.mathtext_parser.parse(
            s, self.dpi, prop, antialiased=gc.get_antialiased())
        cos = math.cos(math.radians(angle))
        sin = math.sin(math.radians(angle))
        for font, size, _char, glyph_index, dx, dy in parse.glyphs:  # dy is upwards.
            font.set_size(size, self.dpi)
            hf = font._hinting_factor
            font._set_transform(
                [[round(0x10000 * cos / hf), round(0x10000 * -sin)],
                 [round(0x10000 * sin / hf), round(0x10000 * cos)]],
                [round(0x40 * (x + dx * cos - dy * sin)),
                 # FreeType's y is upwards.
                 round(0x40 * (self.height - y + dx * sin + dy * cos))]
            )
            bitmap = font._render_glyph(
                glyph_index, get_hinting_flag(),
                RenderMode.NORMAL if gc.get_antialiased() else RenderMode.MONO)
            buffer = np.asarray(bitmap.buffer)
            if not gc.get_antialiased():
                buffer *= 0xff
            # draw_text_image's y is downwards & the bitmap bottom side.
            self._renderer.draw_text_image(
                buffer,
                bitmap.left, int(self.height) - bitmap.top + buffer.shape[0],
                0, gc)
        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)
        gc1.set_snap(gc.get_snap())
        for dx, dy, w, h in parse.rects:  # dy is upwards & the rect top side.
            if gc1.get_snap() in [None, True]:
                # Prevent thin bars from disappearing by growing symmetrically.
                if w < 1:
                    dx -= (1 - w) / 2
                    w = 1
                if h < 1:
                    dy -= (1 - h) / 2
                    h = 1
            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)