22Figure and Axes text
33"""
44from __future__ import division
5+ import re
56from matplotlib import verbose
67import matplotlib
78import math
1011from font_manager import FontProperties
1112from matplotlib import rcParams
1213from patches import bbox_artist
13- from numerix import sin , cos , pi , Matrix , cumsum
14+ from numerix import sin , cos , pi , cumsum , dot , array
1415from transforms import lbwh_to_bbox , bbox_all
1516
17+
18+
1619def _process_text_args (override , fontdict = None , ** kwargs ):
1720 "Return an override dict. See 'text' docstring for info"
1821
@@ -30,6 +33,8 @@ class Text(Artist):
3033 Handle storing and drawing of text in window or data coordinates
3134
3235 """
36+ # special case superscripting to speedup logplots
37+ _rgxsuper = re .compile ('\$([0-9]+)\^\{(-?[0-9]+)\}\$' )
3338
3439 zorder = 3
3540 def __init__ (self ,
@@ -60,6 +65,7 @@ def __init__(self,
6065 self ._fontproperties = fontproperties
6166 self ._bbox = None
6267 self ._renderer = None
68+
6369 def _get_multialignment (self ):
6470 if self ._multialignment is not None : return self ._multialignment
6571 else : return self ._horizontalalignment
@@ -145,7 +151,8 @@ def _get_layout(self, renderer):
145151 offsetLayout = [ (thisx , thisy ) for line , thisx , thisy , w , h in horizLayout ]
146152
147153 # 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 ]
149156
150157 txs = [float (v [0 ][0 ]) for v in cornersRotated ]
151158 tys = [float (v [1 ][0 ]) for v in cornersRotated ]
@@ -181,7 +188,7 @@ def _get_layout(self, renderer):
181188
182189
183190 # 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 ]
185192
186193
187194 tx = [float (v [0 ][0 ])+ offsetx for v in xys ]
@@ -223,6 +230,23 @@ def draw(self, renderer):
223230 if self ._bbox :
224231 bbox_artist (self , renderer , self ._bbox )
225232 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+
226250 bbox , info = self ._get_layout (renderer )
227251
228252 for line , wh , x , y in info :
@@ -318,10 +342,21 @@ def get_verticalalignment(self):
318342 return self ._verticalalignment
319343
320344 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+
321349 if renderer is not None :
322350 self ._renderer = renderer
323351 if self ._renderer is None :
324352 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
325360 bbox , info = self ._get_layout (self ._renderer )
326361 return bbox
327362
@@ -331,22 +366,22 @@ def get_rotation_matrix(self, x0, y0):
331366
332367 theta = pi / 180.0 * self .get_rotation ()
333368 # translate x0,y0 to origin
334- Torigin = Matrix ([ [1 , 0 , - x0 ],
369+ Torigin = array ([ [1 , 0 , - x0 ],
335370 [0 , 1 , - y0 ],
336371 [0 , 0 , 1 ]])
337372
338373 # rotate by theta
339- R = Matrix ([ [cos (theta ), - sin (theta ), 0 ],
374+ R = array ([ [cos (theta ), - sin (theta ), 0 ],
340375 [sin (theta ), cos (theta ), 0 ],
341376 [0 , 0 , 1 ]])
342377
343378 # translate origin back to x0,y0
344- Tback = Matrix ([ [1 , 0 , x0 ],
379+ Tback = array ([ [1 , 0 , x0 ],
345380 [0 , 1 , y0 ],
346381 [0 , 0 , 1 ]])
347382
348383
349- return Tback * R * Torigin
384+ return dot ( dot ( Tback , R ), Torigin )
350385
351386 def set_backgroundcolor (self , color ):
352387 """
@@ -545,3 +580,53 @@ def set_fontproperties(self, fp):
545580
546581
547582
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