[Bug]: Text rotation leads to characters being misplaced within their bounding boxes. Attempted solution provided. · Issue #23021 · matplotlib/matplotlib · GitHub
plt.text(...) is not rotating text correctly. This becomes clear when looking at their bounding boxes, where you can see that a character's position within the bounding box differs depending on the rotation (and sometimes, the text will even exit the box).
These examples were created from the code above, which rotates the text 0/90/180/270 degrees and plots its bonding box. When the character is a ".", it looks like this: https://imgur.com/dBgTRBA
The "." makes the issue obvious, although this issue appears for all characters, e.g., "C": https://imgur.com/a/u3UamAb
Changing the horizontal/vertical alignment does not fix this. I tried every possible combination, and although it moves the text around, it never does so never in the correct way.
Here, we can see that the character is in the same position relative to its bounding box for each possible rotation.
Additional information
I took a stab at trying to fix this. It seems like the issue is related to the Descent and/or Offset/Bearing of the font.
I took a look at backend_agg.py, where the text is being drawn. My solution may is quite crude and violates Chesterton's fence. However, I found that if I comment out some lines in backend_agg.RendererAgg.draw_text(...), this fixes the issue (highlighted here):
defdraw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
# docstring inheritedifismath:
returnself.draw_mathtext(gc, x, y, s, prop, angle)
flags=get_hinting_flag()
font=self._get_agg_font(prop)
iffontisNone:
returnNone# 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=flags)
font.draw_glyphs_to_bitmap(
antialiased=mpl.rcParams['text.antialiased'])
d=font.get_descent() /64.0#The descent needs to be adjusted for the angle. [original comment from the package]# xo, yo = font.get_bitmap_offset() [I deleted these next lines, commented out here]# xo /= 64.0 # yo /= 64.0 # xd = d * sin(radians(angle)) # yd = d * cos(radians(angle))# x = round(x + xo + xd)# y = round(y + yo + yd)self._renderer.draw_text_image(font, x, y+1, angle, gc)
By commenting out those lines, I was able to generate those expected outcome pictures above. I tried this for serif fonts and different vertical/horizontal alignments, and it seems to work as expected. Should I do a PR (or would further tests be needed, if so which)?
I'm having trouble understanding why this code would be here in the first place. Maybe there was some code changed upstream/downstream which already addresses the offset/descent issue, and so the code I pointed out is doing it again, leading to problems?
I think someone before tried to come up with a solution for a related problem (see issue), although their fix was not accepted.
changed the title [-][Bug]: Text rotation issue[/-][+][Bug]: Rotated text leads to characters being misplaced within their bounding boxes. Attempted solution provided.[/+]on May 9, 2022
changed the title [-][Bug]: Rotated text leads to characters being misplaced within their bounding boxes. Attempted solution provided.[/-][+][Bug]: Text rotation leads to characters being misplaced within their bounding boxes. Attempted solution provided.[/+]on May 9, 2022
Activity
QuLogic commented on Jun 30, 2025
This is a duplicate of #13044 and fixed by #29199.