@@ -46,12 +46,23 @@ class RendererAgg(RendererBase):
46
46
context instance that controls the colors/styles
47
47
"""
48
48
debug = 1
49
- _fontd = maxdict (50 )
49
+
50
+ # we want to cache the fonts at the class level so that when
51
+ # multiple figures are created we can reuse them. This helps with
52
+ # a bug on windows where the creation of too many figures leads to
53
+ # too many open file handles. However, storing them at the class
54
+ # level is not thread safe. The solution here is to cache the
55
+ # fonts at class level, but for a given renderer to slurp them
56
+ # down into the instance cache "_fontd_instance" from the
57
+ # "_fontd_class" in a call to pre_draw_hook (managed by the
58
+ # FigureCanvas) and to restore them to the fontd_class in the
59
+ # post_draw_hook.
60
+ _fontd_class = maxdict (50 )
50
61
def __init__ (self , width , height , dpi ):
51
62
if __debug__ : verbose .report ('RendererAgg.__init__' , 'debug-annoying' )
52
63
RendererBase .__init__ (self )
53
64
self .texd = maxdict (50 ) # a cache of tex image rasters
54
-
65
+ self . _fontd_instance = maxdict ( 50 )
55
66
56
67
57
68
self .dpi = dpi
@@ -71,6 +82,16 @@ def __init__(self, width, height, dpi):
71
82
if __debug__ : verbose .report ('RendererAgg.__init__ done' ,
72
83
'debug-annoying' )
73
84
85
+ def pre_draw_hook (self ):
86
+ 'called by FigureCanvas right before draw; slurp in the class level cache'
87
+ self ._fontd_instance = RendererAgg ._fontd_class
88
+ RendererAgg ._fontd_class = {}
89
+
90
+ def post_draw_hook (self ):
91
+ 'called by FigureCanvas right after draw; restore the class level cache'
92
+ RendererAgg ._fontd_class = self ._fontd_instance
93
+ self ._fontd_instance = {}
94
+
74
95
def _get_hinting_flag (self ):
75
96
if rcParams ['text.hinting' ]:
76
97
return LOAD_FORCE_AUTOHINT
@@ -217,16 +238,16 @@ def _get_agg_font(self, prop):
217
238
'debug-annoying' )
218
239
219
240
key = hash (prop )
220
- font = RendererAgg . _fontd .get (key )
241
+ font = self . _fontd_instance .get (key )
221
242
222
243
if font is None :
223
244
fname = findfont (prop )
224
- font = RendererAgg . _fontd .get (fname )
245
+ font = self . _fontd_instance .get (fname )
225
246
if font is None :
226
247
font = FT2Font (str (fname ))
227
- RendererAgg . _fontd [fname ] = font
248
+ self . _fontd_instance [fname ] = font
228
249
229
- RendererAgg . _fontd [key ] = font
250
+ self . _fontd_instance [key ] = font
230
251
231
252
font .clear ()
232
253
size = prop .get_size_in_points ()
@@ -361,6 +382,7 @@ def post_processing(image, dpi):
361
382
image )
362
383
363
384
385
+
364
386
def new_figure_manager (num , * args , ** kwargs ):
365
387
"""
366
388
Create a new figure manager instance
@@ -401,7 +423,9 @@ def draw(self):
401
423
if __debug__ : verbose .report ('FigureCanvasAgg.draw' , 'debug-annoying' )
402
424
403
425
self .renderer = self .get_renderer ()
426
+ self .renderer .pre_draw_hook ()
404
427
self .figure .draw (self .renderer )
428
+ self .renderer .post_draw_hook ()
405
429
406
430
def get_renderer (self ):
407
431
l , b , w , h = self .figure .bbox .bounds
0 commit comments