2323 "cairo backend requires that pycairo>=1.11.0 or cairocffi"
2424 "is installed" ) from err
2525
26- from .. import cbook
26+ from .. import cbook , font_manager
2727from matplotlib .backend_bases import (
2828 _Backend , FigureCanvasBase , FigureManagerBase , GraphicsContextBase ,
2929 RendererBase )
@@ -70,33 +70,60 @@ def _append_path(ctx, path, transform, clip=None):
7070 ctx .curve_to (* points )
7171
7272
73+ def _cairo_font_args_from_font_prop (prop ):
74+ """
75+ Convert a `.FontProperties` or a `.FontEntry` to arguments that can be
76+ passed to `.Context.select_font_face`.
77+ """
78+ def attr (field ):
79+ try :
80+ return getattr (prop , f"get_{ field } " )()
81+ except AttributeError :
82+ return getattr (prop , field )
83+
84+ name = attr ("name" )
85+ slant = getattr (cairo , f"FONT_SLANT_{ attr ('style' ).upper ()} " )
86+ weight = attr ("weight" )
87+ weight = (cairo .FONT_WEIGHT_NORMAL
88+ if font_manager .weight_dict .get (weight , weight ) < 550
89+ else cairo .FONT_WEIGHT_BOLD )
90+ return name , slant , weight
91+
92+
7393class RendererCairo (RendererBase ):
74- fontweights = {
75- 100 : cairo .FONT_WEIGHT_NORMAL ,
76- 200 : cairo .FONT_WEIGHT_NORMAL ,
77- 300 : cairo .FONT_WEIGHT_NORMAL ,
78- 400 : cairo .FONT_WEIGHT_NORMAL ,
79- 500 : cairo .FONT_WEIGHT_NORMAL ,
80- 600 : cairo .FONT_WEIGHT_BOLD ,
81- 700 : cairo .FONT_WEIGHT_BOLD ,
82- 800 : cairo .FONT_WEIGHT_BOLD ,
83- 900 : cairo .FONT_WEIGHT_BOLD ,
84- 'ultralight' : cairo .FONT_WEIGHT_NORMAL ,
85- 'light' : cairo .FONT_WEIGHT_NORMAL ,
86- 'normal' : cairo .FONT_WEIGHT_NORMAL ,
87- 'medium' : cairo .FONT_WEIGHT_NORMAL ,
88- 'regular' : cairo .FONT_WEIGHT_NORMAL ,
89- 'semibold' : cairo .FONT_WEIGHT_BOLD ,
90- 'bold' : cairo .FONT_WEIGHT_BOLD ,
91- 'heavy' : cairo .FONT_WEIGHT_BOLD ,
92- 'ultrabold' : cairo .FONT_WEIGHT_BOLD ,
93- 'black' : cairo .FONT_WEIGHT_BOLD ,
94- }
95- fontangles = {
96- 'italic' : cairo .FONT_SLANT_ITALIC ,
97- 'normal' : cairo .FONT_SLANT_NORMAL ,
98- 'oblique' : cairo .FONT_SLANT_OBLIQUE ,
99- }
94+ @cbook .deprecated ("3.3" )
95+ @property
96+ def fontweights (self ):
97+ return {
98+ 100 : cairo .FONT_WEIGHT_NORMAL ,
99+ 200 : cairo .FONT_WEIGHT_NORMAL ,
100+ 300 : cairo .FONT_WEIGHT_NORMAL ,
101+ 400 : cairo .FONT_WEIGHT_NORMAL ,
102+ 500 : cairo .FONT_WEIGHT_NORMAL ,
103+ 600 : cairo .FONT_WEIGHT_BOLD ,
104+ 700 : cairo .FONT_WEIGHT_BOLD ,
105+ 800 : cairo .FONT_WEIGHT_BOLD ,
106+ 900 : cairo .FONT_WEIGHT_BOLD ,
107+ 'ultralight' : cairo .FONT_WEIGHT_NORMAL ,
108+ 'light' : cairo .FONT_WEIGHT_NORMAL ,
109+ 'normal' : cairo .FONT_WEIGHT_NORMAL ,
110+ 'medium' : cairo .FONT_WEIGHT_NORMAL ,
111+ 'regular' : cairo .FONT_WEIGHT_NORMAL ,
112+ 'semibold' : cairo .FONT_WEIGHT_BOLD ,
113+ 'bold' : cairo .FONT_WEIGHT_BOLD ,
114+ 'heavy' : cairo .FONT_WEIGHT_BOLD ,
115+ 'ultrabold' : cairo .FONT_WEIGHT_BOLD ,
116+ 'black' : cairo .FONT_WEIGHT_BOLD ,
117+ }
118+
119+ @cbook .deprecated ("3.3" )
120+ @property
121+ def fontangles (self ):
122+ return {
123+ 'italic' : cairo .FONT_SLANT_ITALIC ,
124+ 'normal' : cairo .FONT_SLANT_NORMAL ,
125+ 'oblique' : cairo .FONT_SLANT_OBLIQUE ,
126+ }
100127
101128 def __init__ (self , dpi ):
102129 self .dpi = dpi
@@ -215,17 +242,12 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
215242 ctx = gc .ctx
216243 ctx .new_path ()
217244 ctx .move_to (x , y )
218- ctx .select_font_face (prop .get_name (),
219- self .fontangles [prop .get_style ()],
220- self .fontweights [prop .get_weight ()])
221-
222- size = prop .get_size_in_points () * self .dpi / 72.0
223245
246+ ctx .select_font_face (* _cairo_font_args_from_font_prop (prop ))
224247 ctx .save ()
248+ ctx .set_font_size (prop .get_size_in_points () * self .dpi / 72 )
225249 if angle :
226250 ctx .rotate (np .deg2rad (- angle ))
227- ctx .set_font_size (size )
228-
229251 ctx .show_text (s )
230252 ctx .restore ()
231253
@@ -243,13 +265,9 @@ def _draw_mathtext(self, gc, x, y, s, prop, angle):
243265 ctx .new_path ()
244266 ctx .move_to (ox , oy )
245267
246- fontProp = ttfFontProperty (font )
247- ctx .select_font_face (fontProp .name ,
248- self .fontangles [fontProp .style ],
249- self .fontweights [fontProp .weight ])
250-
251- size = fontsize * self .dpi / 72.0
252- ctx .set_font_size (size )
268+ ctx .select_font_face (
269+ * _cairo_font_args_from_font_prop (ttfFontProperty (font )))
270+ ctx .set_font_size (fontsize * self .dpi / 72 )
253271 ctx .show_text (s )
254272
255273 for ox , oy , w , h in rects :
@@ -273,19 +291,14 @@ def get_text_width_height_descent(self, s, prop, ismath):
273291 return width , height , descent
274292
275293 ctx = self .text_ctx
276- ctx .save ()
277- ctx .select_font_face (prop .get_name (),
278- self .fontangles [prop .get_style ()],
279- self .fontweights [prop .get_weight ()])
280-
281- # Cairo (says it) uses 1/96 inch user space units, ref: cairo_gstate.c
282- # but if /96.0 is used the font is too small
283- size = prop .get_size_in_points () * self .dpi / 72
284-
285294 # problem - scale remembers last setting and font can become
286295 # enormous causing program to crash
287296 # save/restore prevents the problem
288- ctx .set_font_size (size )
297+ ctx .save ()
298+ ctx .select_font_face (* _cairo_font_args_from_font_prop (prop ))
299+ # Cairo (says it) uses 1/96 inch user space units, ref: cairo_gstate.c
300+ # but if /96.0 is used the font is too small
301+ ctx .set_font_size (prop .get_size_in_points () * self .dpi / 72 )
289302
290303 y_bearing , w , h = ctx .text_extents (s )[1 :4 ]
291304 ctx .restore ()
0 commit comments