From 50ec1c6bb14f3b79928040dcee42b226b5597f9d Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 27 Aug 2020 20:59:13 -0400 Subject: [PATCH] Support horizontalalignment in TextArea/AnchoredText. Fixes #18363. --- lib/matplotlib/offsetbox.py | 46 ++++++++++-------- .../test_offsetbox/anchoredtext_align.png | Bin 0 -> 6729 bytes lib/matplotlib/tests/test_offsetbox.py | 19 +++++++- 3 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_offsetbox/anchoredtext_align.png diff --git a/lib/matplotlib/offsetbox.py b/lib/matplotlib/offsetbox.py index b721a5a20134..a788d34040bb 100644 --- a/lib/matplotlib/offsetbox.py +++ b/lib/matplotlib/offsetbox.py @@ -769,10 +769,11 @@ def draw(self, renderer): class TextArea(OffsetBox): """ - The TextArea is contains a single Text instance. The text is - placed at (0, 0) with baseline+left alignment. The width and height - of the TextArea instance is the width and height of the its child - text. + The TextArea is a container artist for a single Text instance. + + The text is placed at (0, 0) with baseline+left alignment, by default. The + width and height of the TextArea instance is the width and height of its + child text. """ def __init__(self, s, textprops=None, @@ -876,37 +877,43 @@ def get_offset(self): def get_window_extent(self, renderer): """Return the bounding box in display space.""" w, h, xd, yd = self.get_extent(renderer) - ox, oy = self.get_offset() # w, h, xd, yd) + ox, oy = self.get_offset() return mtransforms.Bbox.from_bounds(ox - xd, oy - yd, w, h) def get_extent(self, renderer): _, h_, d_ = renderer.get_text_width_height_descent( "lp", self._text._fontproperties, ismath=False) - bbox, info, d = self._text._get_layout(renderer) + bbox, info, yd = self._text._get_layout(renderer) w, h = bbox.width, bbox.height self._baseline_transform.clear() if len(info) > 1 and self._multilinebaseline: - d_new = 0.5 * h - 0.5 * (h_ - d_) - self._baseline_transform.translate(0, d - d_new) - d = d_new + yd_new = 0.5 * h - 0.5 * (h_ - d_) + self._baseline_transform.translate(0, yd - yd_new) + yd = yd_new else: # single line - h_d = max(h_ - d_, h - d) + h_d = max(h_ - d_, h - yd) if self.get_minimumdescent(): - ## to have a minimum descent, #i.e., "l" and "p" have same - ## descents. - d = max(d, d_) - #else: - # d = d + # To have a minimum descent, i.e., "l" and "p" have same + # descents. + yd = max(yd, d_) - h = h_d + d + h = h_d + yd - return w, h, 0., d + ha = self._text.get_horizontalalignment() + if ha == 'left': + xd = 0 + elif ha == 'center': + xd = w / 2 + elif ha == 'right': + xd = w + + return w, h, xd, yd def draw(self, renderer): # docstring inherited @@ -1288,11 +1295,10 @@ def __init__(self, s, loc, pad=0.4, borderpad=0.5, prop=None, **kwargs): if prop is None: prop = {} - badkwargs = {'ha', 'horizontalalignment', 'va', 'verticalalignment'} + badkwargs = {'va', 'verticalalignment'} if badkwargs & set(prop): raise ValueError( - "Mixing horizontalalignment or verticalalignment with " - "AnchoredText is not supported.") + 'Mixing verticalalignment with AnchoredText is not supported.') self.txt = TextArea(s, textprops=prop, minimumdescent=False) fp = self.txt._text.get_fontproperties() diff --git a/lib/matplotlib/tests/baseline_images/test_offsetbox/anchoredtext_align.png b/lib/matplotlib/tests/baseline_images/test_offsetbox/anchoredtext_align.png new file mode 100644 index 0000000000000000000000000000000000000000..42a80e17b068a1476f2f5f9a0942b53f18649ab0 GIT binary patch literal 6729 zcmeHMXIxX~8b65DTBS%uhRh4C1B4JkHbe@6sug4?hzJTuK$d|pWP7m?8KKo8C`uGm zKxD}XJ17KHmdFSah9qnV5FrT!lHB*y_I~JR@0WY;hx|@{=j6QOd7l4xpWHlcZ6)^2 zzHcB15KBOf^Kn-W zy&M$m6BwYasjZ3Byc!sc)7M98dR`9IQpX^X9-f|hURrvGmA!GetHFi{g#W)^)C>&5 zAQoLaF<|f=SARMe3_;?T;EzZ?D$fUkWV4T3m^p;sXO8%%IIur7jYoWd(c|)RZ9^lY!i>7wTKC?kr;rz$;=H}R^T*#panWZa(e)dPb;$7Lk2C%1(=}Qm zgJS;v{#cqnsXsy%YBDPgWe&+4@%*VM!*&lG>Ppv^NAz3_M5EC>X5Kw21CPA}0*XHm zR^X81qSEC_lM|I<^et2Ootd9} zTp6|gse0i>yE~&bRj_5oY>I4}DIC%gvR`h-9uZlSl{3XfVjw@xmS0#!pRKH)c!)pw%U++6&1Q*V=0YEBegvU8`W~Nfx?4W}^m)Qdo(dHCdX2?kWO@*82Gz(*yIeK1u=xGN z6B)e#mlQ=4!^LU_A)GrB=FyrWTNW@<>+S2COdt?4b$skxu1%&R{f8=MW@hjhVzh3R zKTWDRQM{zFdaao$rf6L4MONzjbNh{7Hz^(gQ|t3)ay=$q|JHBTFkf7kQ&xt|4yWIo z8L11iu#gY#Kw`TLrdu>f!`~G;mJm9#^xEL>fIlQ8SVe)+>MEvdez}O~*^^~hM(Z3W zt|55WkNyVR=98i4kEC70|H0!hOk&m1TY(Ug$5?uh9GKZP>G)uKudO?NOC{d?jPoMe(`bJR4j{$QeYM3{qt@oRL~R z`!tKgGXXk;jOMLonnp+X4OJYnOjA?{p6a+cUqTjm&_qq|dhEW^j&wrZ7g;cCP7q5* zCreRy?D^c>T-B$ivZPj~yVK5B$ce9n}7_4nZPtBOz2u*8?L4$ZfJJL0^Sn!Wj%- zC~KoLCFs-fYYZi!Q@fk^T=t(kGX82f-dcbBhEw&`@c^or?2+%gP{Pe{ zKAY+>-Sxm$Gow)HmcgZ0H^O01jMRqojE*XrC+xbZnr8fh*8tMNnz(JlnJ9r0b^g5x z!*`%UWRUJHih;h~-gr>DKwuIbzq1bb+Ppb&Q&$YB-fDXU7WG<9X%WHtlZXJ$v^5tUp7G{`BSmW1+m; zbcQzh5h=%v3mpy{i|)5EN&5rxF1Q{v(yJp=pOK>NKG#>!)6*jnD_9|VjMiUcy;U!9Ak}#H za^n$6j+7_KZ> z5(*HlX-Z0{&2e!?5or``!k<<}`TdYR{pNw}{1_%cB>h=oangb8a20ska!fbjRF>`; z(gwg0vzLFYTkEf=rfbKUcy6w-upP)Yiy9ZgPR(j%6_tH*avt*oMc7tZOv_A9E`wmS zhzC*81A&kL_mcrqVLCc~dp{-J(Nz|>PMEF2IUg_{v?_mO)Y`HPU~dbHkgWLa;-h)& zj!dMgV$|}>YT!jZ-aRzy0d@rr_2F|bzK`H8Dg@TEER8ppo69`k+^U|s=L_VGlBzc< zV-&i8-&i7}R8$mWH(Awl&kE^Pw1DI?kG57&wclxDx>69a>+RT;PQBO#3|JLd@O_D7 zDUD~v+-CMz#C#E}NmRV08)QsI*Ut%_0tq94-S3#|MvlQw-Nm$m!185GB5)~yMgpqG z6T%m3rs-6&AOwfQwE)ic0BPuF666g&K^&>=S?hYjb9bZ5-ALbX&I5&(kU&R9ZnOoQ zuMfvcNKojMA6%mCNG{0m~SH_e3O#O8>}=}M-irc%Jx?SNJ2 zcwj`rtnxn( zQ{~xW7gMMFy9H=_gn~=36VNu5#^nG?G`kj1bl)?7qQjEF(tP zA@0@=Uag?9`8+m_8KMZr7-4c;8zRtvA1tDl4R2kj3#D92RH&j+qgFpP4wharU!Cop z_TV;O&bS~o4U{3kjrQ){Zm>nb1S3qMIsY#P^z8&h)|Y2PoHJW}B%x~AA{SUMp*Mo- zbtRY7)EGRqAu0k%Oanlt0L*%H-8X>CUO;tMc&wM@LZ z&GnH3Ng#|jC${CFlj(9}YnE&tC0ROl0g)!GByC)5BPd`6>(gz3TB@l_4ZOL++*qLi z2{bkH$mJ9FLx+5jeuJeA0U11ZL1*k)udxNHDh7&tS9+=0y(b3^lOW6$IS1*mms($$ zZhL;N9A1G0>m_YcDPrak9v{xEq|#^eh{cWCez27Yp6-&-x_B%kOa1I~{F%bDXe%qL z5IN$+jXl=*@-9R5fO=MIKCs07{d>u46ofm-M1LN{p@2{_U~xt9XKh#jQ>`OmV+t^! z@yRl=B``h0Sv53OW1Hkk+PHnEQFaV$kc=1uJZs2Hr z_-c<8BS9_z57bFpvu5JfU`;S4q)txP51-*0aR?p@#AjnO@||`EdA zxjDO-b<7o57NIDFg*0@HDCDJV|Oyz#%11O--q&Bmv{e#1;uRe*6fYrK>wi zxvjr-Oltnt=s7S5s!1ZE+a%Laf^aqm2D6n?^lAVt6BQf7BCD4BQj6(%D85h6(2(=$ z(ipjV^HY1WPw&&cWBkQ16f34~v35S`y6AQ(3ESbQl}^wapkxI$o&&(G0o{dz1jD&} z`f{^40{GsuAgmA90A-$m2g=mOSck{~(`JqIeEq9CFtljfsAZLjL-tQ4i;9ZS7LsIM ze+j2nX>H-Iut8f$j8$qF>lAE{2;y)nlmr=i*Co;Bwwv9F-}Y#vpZLMq**T}7!Q@_6 zR#+WVNw{VOS6o>*iw=uJUO-`Cp}K1S9#hnKvBqT3@ms;1XaQSTXHQm&#-2O`*WdsQt{1{wZhVqzd!xh|SYtHj7n zR@)MnTkJ+Qg|+?m{!>7oLHt`^{jyVhM)*Kp$NTiIeLCJ`GSU3@x-f3NyKN!1X@P4j z@;b(7p|sh3{M9ck+L%DM7W8xa@@-kbR-AG3-bKVr5ubMmrsE+`a`gC4w?QU(=K9Ya zsB?Gu-P@PogL|uNQ}^Jf$#&m{8-2sV%1J?q1~=BfM(Eql7rxp05##x>>3YA7PF~f$ zd-vSI_exhwwJCB;rZ5{Lm`_|EGg1-_hD@3M6ToyBJQP+X#(RKYA#pSBoDr%DD{e|1 zvHqDtUMXpvi`3e(94Dg;>92-wa`x|r;&5N0*#n5Gs^Ofq>OayX+MK7@c1+ff%;sI){a{X|7Y#p9Swj^tH6a5@HJTj{zD zY7${dYJJJB%$KOu|ANl*-{1yVRz(G*py|FRcRO8 zG&6il_dy?z)dS-LI#PD?m-{Tte=~@!n*~i{lHZ5#;4}46-+{*p4P8|#(V_FieHMDgPU8s6byBM#>!hMUh^!WjcH=C*o@@Xev-{lZ4~KwIZZ2R@G)C{M)x#S(F@w@