Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Description
Bug summary
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).
Code for reproduction
importmatplotlib.pyplotaspltdefplot_rotation_period(y,rotation,r):c0=plt.gca().annotate('.',xy=(0.5,y),xytext=(0.5,y),rotation=rotation,fontsize=80,rotation_mode='anchor',fontfamily='monospace',va='bottom',ha='center',transform_rotates_text=False)bb0=c0.get_window_extent(renderer=r).transformed(plt.gca().transData.inverted())rect0=plt.Rectangle((bb0.x0,bb0.y0),bb0.width,bb0.height,facecolor="C1",alpha=0.3,zorder=2)plt.gca().add_patch(rect0)if__name__=='__main__':fig=plt.gcf()r=fig.canvas.get_renderer()fig.set_size_inches(15,15)plt.xlim(0,1)plt.ylim(0,1)plot_rotation_period(0.8,0,r)print('1')plot_rotation_period(0.6,90,r)print('2')plot_rotation_period(0.4,180,r)print('3')plot_rotation_period(0.2,270,r)plt.plot([0.5,0.5], [0,1],linestyle='--')plt.show()# plt.savefig('example_C.png') # this issue becomes a bit clearer if you do plt.savefig()
Actual outcome
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.
Expected outcome
Correct outcome for "C":https://imgur.com/2XT7wdA
Correct outcome for ".":https://imgur.com/Zx22cV1
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 theDescent and/orOffset/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 violatesChesterton'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.
Operating system
Windows 10
Matplotlib Version
3.4.3
Matplotlib Backend
Qt5Agg
Python version
3.8.12
Jupyter version
No response
Installation
conda