23
23
"cairo backend requires that pycairo>=1.11.0 or cairocffi"
24
24
"is installed" ) from err
25
25
26
- from .. import cbook
26
+ from .. import cbook , font_manager
27
27
from matplotlib .backend_bases import (
28
28
_Backend , FigureCanvasBase , FigureManagerBase , GraphicsContextBase ,
29
29
RendererBase )
@@ -70,33 +70,60 @@ def _append_path(ctx, path, transform, clip=None):
70
70
ctx .curve_to (* points )
71
71
72
72
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
+
73
93
class 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
+ }
100
127
101
128
def __init__ (self , dpi ):
102
129
self .dpi = dpi
@@ -215,17 +242,12 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
215
242
ctx = gc .ctx
216
243
ctx .new_path ()
217
244
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
223
245
246
+ ctx .select_font_face (* _cairo_font_args_from_font_prop (prop ))
224
247
ctx .save ()
248
+ ctx .set_font_size (prop .get_size_in_points () * self .dpi / 72 )
225
249
if angle :
226
250
ctx .rotate (np .deg2rad (- angle ))
227
- ctx .set_font_size (size )
228
-
229
251
ctx .show_text (s )
230
252
ctx .restore ()
231
253
@@ -243,13 +265,9 @@ def _draw_mathtext(self, gc, x, y, s, prop, angle):
243
265
ctx .new_path ()
244
266
ctx .move_to (ox , oy )
245
267
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 )
253
271
ctx .show_text (s )
254
272
255
273
for ox , oy , w , h in rects :
@@ -273,19 +291,14 @@ def get_text_width_height_descent(self, s, prop, ismath):
273
291
return width , height , descent
274
292
275
293
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
-
285
294
# problem - scale remembers last setting and font can become
286
295
# enormous causing program to crash
287
296
# 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 )
289
302
290
303
y_bearing , w , h = ctx .text_extents (s )[1 :4 ]
291
304
ctx .restore ()
0 commit comments