2
2
Figure and Axes text
3
3
"""
4
4
from __future__ import division
5
+ import re
5
6
from matplotlib import verbose
6
7
import matplotlib
7
8
import math
10
11
from font_manager import FontProperties
11
12
from matplotlib import rcParams
12
13
from patches import bbox_artist
13
- from numerix import sin , cos , pi , Matrix , cumsum
14
+ from numerix import sin , cos , pi , cumsum , dot , array
14
15
from transforms import lbwh_to_bbox , bbox_all
15
16
17
+
18
+
16
19
def _process_text_args (override , fontdict = None , ** kwargs ):
17
20
"Return an override dict. See 'text' docstring for info"
18
21
@@ -30,6 +33,8 @@ class Text(Artist):
30
33
Handle storing and drawing of text in window or data coordinates
31
34
32
35
"""
36
+ # special case superscripting to speedup logplots
37
+ _rgxsuper = re .compile ('\$([0-9]+)\^\{(-?[0-9]+)\}\$' )
33
38
34
39
zorder = 3
35
40
def __init__ (self ,
@@ -60,6 +65,7 @@ def __init__(self,
60
65
self ._fontproperties = fontproperties
61
66
self ._bbox = None
62
67
self ._renderer = None
68
+
63
69
def _get_multialignment (self ):
64
70
if self ._multialignment is not None : return self ._multialignment
65
71
else : return self ._horizontalalignment
@@ -145,7 +151,8 @@ def _get_layout(self, renderer):
145
151
offsetLayout = [ (thisx , thisy ) for line , thisx , thisy , w , h in horizLayout ]
146
152
147
153
# now rotate the bbox
148
- cornersRotated = [M * Matrix ([[thisx ],[thisy ],[1 ]]) for thisx , thisy in cornersHoriz ]
154
+
155
+ cornersRotated = [dot (M ,array ([[thisx ],[thisy ],[1 ]])) for thisx , thisy in cornersHoriz ]
149
156
150
157
txs = [float (v [0 ][0 ]) for v in cornersRotated ]
151
158
tys = [float (v [1 ][0 ]) for v in cornersRotated ]
@@ -181,7 +188,7 @@ def _get_layout(self, renderer):
181
188
182
189
183
190
# now rotate the positions around the first x,y position
184
- xys = [M * Matrix ([[thisx ],[thisy ],[1 ]]) for thisx , thisy in offsetLayout ]
191
+ xys = [dot ( M , array ([[thisx ],[thisy ],[1 ]]) ) for thisx , thisy in offsetLayout ]
185
192
186
193
187
194
tx = [float (v [0 ][0 ])+ offsetx for v in xys ]
@@ -223,6 +230,23 @@ def draw(self, renderer):
223
230
if self ._bbox :
224
231
bbox_artist (self , renderer , self ._bbox )
225
232
angle = self .get_rotation ()
233
+
234
+ if angle == 0 :
235
+ m = self ._rgxsuper .match (self ._text )
236
+ if m is not None :
237
+ bbox , info = self ._get_layout_super (self ._renderer , m )
238
+ base , xt , yt = info [0 ]
239
+ renderer .draw_text (gc , xt , yt , base ,
240
+ self ._fontproperties , angle ,
241
+ ismath = False )
242
+
243
+ exponent , xt , yt , fp = info [1 ]
244
+ renderer .draw_text (gc , xt , yt , exponent ,
245
+ fp , angle ,
246
+ ismath = False )
247
+ return
248
+
249
+
226
250
bbox , info = self ._get_layout (renderer )
227
251
228
252
for line , wh , x , y in info :
@@ -318,10 +342,21 @@ def get_verticalalignment(self):
318
342
return self ._verticalalignment
319
343
320
344
def get_window_extent (self , renderer = None ):
345
+ if self ._text == '' :
346
+ tx , ty = self ._transform .xy_tup ( (self ._x , self ._y ) )
347
+ return lbwh_to_bbox (tx ,ty ,0 ,0 )
348
+
321
349
if renderer is not None :
322
350
self ._renderer = renderer
323
351
if self ._renderer is None :
324
352
raise RuntimeError ('Cannot get window extent w/o renderer' )
353
+
354
+ angle = self .get_rotation ()
355
+ if angle == 0 :
356
+ m = self ._rgxsuper .match (self ._text )
357
+ if m is not None :
358
+ bbox , tmp = self ._get_layout_super (self ._renderer , m )
359
+ return bbox
325
360
bbox , info = self ._get_layout (self ._renderer )
326
361
return bbox
327
362
@@ -331,22 +366,22 @@ def get_rotation_matrix(self, x0, y0):
331
366
332
367
theta = pi / 180.0 * self .get_rotation ()
333
368
# translate x0,y0 to origin
334
- Torigin = Matrix ([ [1 , 0 , - x0 ],
369
+ Torigin = array ([ [1 , 0 , - x0 ],
335
370
[0 , 1 , - y0 ],
336
371
[0 , 0 , 1 ]])
337
372
338
373
# rotate by theta
339
- R = Matrix ([ [cos (theta ), - sin (theta ), 0 ],
374
+ R = array ([ [cos (theta ), - sin (theta ), 0 ],
340
375
[sin (theta ), cos (theta ), 0 ],
341
376
[0 , 0 , 1 ]])
342
377
343
378
# translate origin back to x0,y0
344
- Tback = Matrix ([ [1 , 0 , x0 ],
379
+ Tback = array ([ [1 , 0 , x0 ],
345
380
[0 , 1 , y0 ],
346
381
[0 , 0 , 1 ]])
347
382
348
383
349
- return Tback * R * Torigin
384
+ return dot ( dot ( Tback , R ), Torigin )
350
385
351
386
def set_backgroundcolor (self , color ):
352
387
"""
@@ -545,3 +580,53 @@ def set_fontproperties(self, fp):
545
580
546
581
547
582
583
+
584
+ def _get_layout_super (self , renderer , m ):
585
+ """
586
+ a special case optimization if a log super and angle = 0
587
+ Basically, mathtext is slow and we can do simple superscript layout "by hand"
588
+ """
589
+
590
+ key = self .get_prop_tup ()
591
+ if self .cached .has_key (key ): return self .cached [key ]
592
+
593
+ base , exponent = m .group (1 ), m .group (2 )
594
+ size = self ._fontproperties .get_size_in_points ()
595
+ fpexp = self ._fontproperties .copy ()
596
+ fpexp .set_size (0.7 * size )
597
+ wb ,hb = renderer .get_text_width_height (base , self ._fontproperties , False )
598
+ we ,he = renderer .get_text_width_height (exponent , fpexp , False )
599
+
600
+ w = wb + we
601
+
602
+ xb , yb = self ._transform .xy_tup ((self ._x , self ._y ))
603
+ xe = xb + wb
604
+ ye = yb + 0.5 * hb
605
+ h = ye + he - yb
606
+
607
+
608
+
609
+
610
+ if self ._horizontalalignment == 'center' : xo = - w / 2.
611
+ elif self ._horizontalalignment == 'right' : xo = - w
612
+ else : xo = 0
613
+ if self ._verticalalignment == 'center' : yo = - hb / 2.
614
+ elif self ._verticalalignment == 'top' : yo = - hb
615
+ else : yo = 0
616
+
617
+ xb += xo
618
+ yb += yo
619
+ xe += xo
620
+ ye += yo
621
+ bbox = lbwh_to_bbox (xb , yb , w , h )
622
+
623
+ if renderer .flipy ():
624
+ canvasw , canvash = renderer .get_canvas_width_height ()
625
+ yb = canvash - yb
626
+ ye = canvash - ye
627
+
628
+
629
+ val = ( bbox , ((base , xb , yb ), (exponent , xe , ye , fpexp )))
630
+ self .cached [key ] = val
631
+
632
+ return val
0 commit comments