@@ -37,23 +37,22 @@ def _get_textbox(text, renderer):
3737 # called within the _get_textbox. So, it would be better to move this
3838 # function as a method with some refactoring of _get_layout method.
3939
40- projected_xs = []
41- projected_ys = []
40+ projected_xys = []
4241
4342 theta = np .deg2rad (text .get_rotation ())
4443 tr = Affine2D ().rotate (- theta )
4544
46- _ , parts , d = text ._get_layout (renderer )
45+ _ , parts = text ._get_layout (renderer )
4746
48- for t , wh , x , y in parts :
49- w , h = wh
50-
51- xt1 , yt1 = tr . transform (( x , y ))
52- yt1 -= d
53- xt2 , yt2 = xt1 + w , yt1 + h
54-
55- projected_xs . extend ([ xt1 , xt2 ])
56- projected_ys . extend ([ yt1 , yt2 ] )
47+ for t , ( w , a , d ), xy in parts :
48+ xt , yt = tr . transform ( xy )
49+ projected_xys . extend ([
50+ ( xt , yt + a ),
51+ ( xt , yt - d ),
52+ ( xt + w , yt + a ),
53+ ( xt + w , yt - d ),
54+ ])
55+ projected_xs , projected_ys = zip ( * projected_xys )
5756
5857 xt_box , yt_box = min (projected_xs ), min (projected_ys )
5958 w_box , h_box = max (projected_xs ) - xt_box , max (projected_ys ) - yt_box
@@ -434,15 +433,18 @@ def update_from(self, other):
434433
435434 def _get_layout (self , renderer ):
436435 """
437- Return the extent (bbox) of the text together with
438- multiple-alignment information. Note that it returns an extent
439- of a rotated text when necessary.
436+ Return
437+
438+ - the (rotated) text bbox, and
439+ - a list of ``(line, (width, ascent, descent), xy)`` tuples for each line.
440440 """
441441 thisx , thisy = 0.0 , 0.0
442442 lines = self ._get_wrapped_text ().split ("\n " ) # Ensures lines is not empty.
443443
444- ws = []
445- hs = []
444+ # Reminder: The ascent (a) goes from the baseline to the top and the
445+ # descent (d) from the baseline to the bottom; both are (typically)
446+ # nonnegative. The height h is the sum, h = a + d.
447+ wads = [] # (width, ascents, descents)
446448 xs = []
447449 ys = []
448450
@@ -451,7 +453,8 @@ def _get_layout(self, renderer):
451453 renderer , "lp" , self ._fontproperties ,
452454 ismath = "TeX" if self .get_usetex () else False ,
453455 dpi = self .get_figure (root = True ).dpi )
454- min_dy = (lp_h - lp_d ) * self ._linespacing
456+ lp_a = lp_h - lp_d
457+ min_dy = lp_a * self ._linespacing
455458
456459 for i , line in enumerate (lines ):
457460 clean_line , ismath = self ._preprocess_math (line )
@@ -462,25 +465,21 @@ def _get_layout(self, renderer):
462465 else :
463466 w = h = d = 0
464467
465- # For multiline text, increase the line spacing when the text
466- # net-height (excluding baseline) is larger than that of a "l"
467- # (e.g., use of superscripts), which seems what TeX does .
468- h = max (h , lp_h )
468+ a = h - d
469+ # To ensure good linespacing, pretend that the ascent (resp.
470+ # descent) of all lines is at least as large as "l" (resp. "p") .
471+ a = max (a , lp_a )
469472 d = max (d , lp_d )
470473
471- ws .append (w )
472- hs .append (h )
473-
474474 # Metrics of the last line that are needed later:
475- baseline = ( h - d ) - thisy
475+ baseline = a - thisy
476476
477- if i == 0 :
478- # position at baseline
479- thisy = - (h - d )
480- else :
481- # put baseline a good distance from bottom of previous line
482- thisy -= max (min_dy , (h - d ) * self ._linespacing )
477+ if i == 0 : # position at baseline
478+ thisy = - a
479+ else : # put baseline a good distance from bottom of previous line
480+ thisy -= max (min_dy , a * self ._linespacing )
483481
482+ wads .append ((w , a , d ))
484483 xs .append (thisx ) # == 0.
485484 ys .append (thisy )
486485
@@ -490,6 +489,7 @@ def _get_layout(self, renderer):
490489 descent = d
491490
492491 # Bounding box definition:
492+ ws = [w for w , a , d in wads ]
493493 width = max (ws )
494494 xmin = 0
495495 xmax = width
@@ -587,7 +587,7 @@ def _get_layout(self, renderer):
587587 # now rotate the positions around the first (x, y) position
588588 xys = M .transform (offset_layout ) - (offsetx , offsety )
589589
590- return bbox , list (zip (lines , zip ( ws , hs ), * xys . T )), descent
590+ return bbox , list (zip (lines , wads , xys ))
591591
592592 def set_bbox (self , rectprops ):
593593 """
@@ -840,7 +840,7 @@ def draw(self, renderer):
840840 renderer .open_group ('text' , self .get_gid ())
841841
842842 with self ._cm_set (text = self ._get_wrapped_text ()):
843- bbox , info , descent = self ._get_layout (renderer )
843+ bbox , info = self ._get_layout (renderer )
844844 trans = self .get_transform ()
845845
846846 # don't use self.get_position here, which refers to text
@@ -876,7 +876,7 @@ def draw(self, renderer):
876876
877877 angle = self .get_rotation ()
878878
879- for line , wh , x , y in info :
879+ for line , wad , ( x , y ) in info :
880880
881881 mtext = self if len (info ) == 1 else None
882882 x = x + posx
@@ -1064,7 +1064,7 @@ def get_window_extent(self, renderer=None, dpi=None):
10641064 "want to call 'figure.draw_without_rendering()' first." )
10651065
10661066 with cbook ._setattr_cm (fig , dpi = dpi ):
1067- bbox , info , descent = self ._get_layout (self ._renderer )
1067+ bbox , _ = self ._get_layout (self ._renderer )
10681068 x , y = self .get_unitless_position ()
10691069 x , y = self .get_transform ().transform ((x , y ))
10701070 bbox = bbox .translated (x , y )
0 commit comments