From 1de8ffb275c4efd65f43f3932eba6aa70657f464 Mon Sep 17 00:00:00 2001 From: Ratnabali Dutta Date: Tue, 11 Apr 2023 11:50:18 +0530 Subject: [PATCH] Add boldsymbol functionality in mathtext --- doc/users/next_whats_new/boldsym_mathtext.rst | 14 +++++++ lib/matplotlib/_mathtext.py | 36 ++++++++++++++++++ .../test_mathtext/mathtext1_dejavusans_05.png | Bin 0 -> 4749 bytes lib/matplotlib/tests/test_mathtext.py | 8 +++- 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 doc/users/next_whats_new/boldsym_mathtext.rst create mode 100644 lib/matplotlib/tests/baseline_images/test_mathtext/mathtext1_dejavusans_05.png diff --git a/doc/users/next_whats_new/boldsym_mathtext.rst b/doc/users/next_whats_new/boldsym_mathtext.rst new file mode 100644 index 000000000000..d58532d5661e --- /dev/null +++ b/doc/users/next_whats_new/boldsym_mathtext.rst @@ -0,0 +1,14 @@ +Boldsymbol mathtext command ``\boldsymbol`` +------------------------------------------- + +Supports using the ``\boldsymbol{}`` command in mathtext: + +To change symbols to bold enclose the text in a font command as +shown: + +.. code-block:: + + r'$\boldsymbol{a+2+\alpha}$' + +.. math:: + \boldsymbol{a+2+\alpha} diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index a166f3bc21a7..b1942d0c98e4 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -11,6 +11,7 @@ import re import types import unicodedata +import string import numpy as np from pyparsing import ( @@ -1811,6 +1812,11 @@ class _MathStyle(enum.Enum): _right_delims = set(r") ] \} > \rfloor \rangle \rceil".split()) _delims = _left_delims | _right_delims | _ambi_delims + _small_greek = set([unicodedata.name(chr(i)).split()[-1].lower() for i in + range(ord('\N{GREEK SMALL LETTER ALPHA}'), + ord('\N{GREEK SMALL LETTER OMEGA}') + 1)]) + _latin_alphabets = set(string.ascii_letters) + def __init__(self): p = types.SimpleNamespace() @@ -1933,6 +1939,9 @@ def csnames(group, names): p.operatorname = cmd(r"\operatorname", "{" + ZeroOrMore(p.simple)("name") + "}") + p.boldsymbol = cmd( + r"\boldsymbol", "{" + ZeroOrMore(p.simple)("value") + "}") + p.placeable <<= ( p.accent # Must be before symbol as all accents are symbols | p.symbol # Must be second to catch all named symbols and single @@ -1949,6 +1958,7 @@ def csnames(group, names): | p.sqrt | p.overline | p.text + | p.boldsymbol ) p.auto_delim <<= ( @@ -2597,3 +2607,29 @@ def auto_delim(self, s, loc, toks): # if "mid" in toks ... can be removed when requiring pyparsing 3. toks["mid"].asList() if "mid" in toks else [], toks["right"]) + + def boldsymbol(self, s, loc, toks): + self.push_state() + state = self.get_state() + hlist = [] + name = toks["value"] + for c in name: + if isinstance(c, Hlist): + k = c.children[1] + if isinstance(k, Char): + k.font = "bf" + k._update_metrics() + hlist.append(c) + elif isinstance(c, Char): + c.font = "bf" + if (c.c in self._latin_alphabets or + c.c[1:] in self._small_greek): + c.font = "bfit" + c._update_metrics() + c._update_metrics() + hlist.append(c) + else: + hlist.append(c) + self.pop_state() + + return Hlist(hlist) diff --git a/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext1_dejavusans_05.png b/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext1_dejavusans_05.png new file mode 100644 index 0000000000000000000000000000000000000000..f7ac08149bcdd5ba3dff1bb953704d89f07fb94d GIT binary patch literal 4749 zcmd6rWmr^Q*T)YaAW{NKgD?sxjdUY$lQM*KcQbU$P{sfPfZ-H=QaV zJ@in5@Ai7H>;3wEe4Y<8bFOpdoU`{@|MmZ^y<>FXs^m8qZ$J=4uCAu62SNDc;8^oI z5%@lQ@%bD0G4lJz*zbv_qhFwnj{~G->F4fZ%NF3^$cfPlyU-Olgn<0Q}oT~7h8An{T& z@r58to4+5tV)-H$2%?%-SAL`)^kHWqSjS-X5Aog!At8URHR3vTgJ-JdWP=T@6h%6w zWYszDol8T(lXOW}YsV*c4>UGclBF1a6{ngdr{?EJHn@F{LOr97V;ea3*UXLqZ12!Uhh)i8;xYm6h{J-w=WG zW6#wIsHmtmI`Sh?D3qVgm;$)gB*C_#<}D$&iK0Kwp4a%FAGt8gBbz%?b@Nm{ z!ZW2NTJKz(?Do{UO z@3TX6C3XR0{)6=Ux&d$u_Q+i3kSHBw(0W~5on-)Tt#1XgX=;$z~ z{1#2U|Tl>>IT!F#!XAq5PsKb}ckf4j+lt3Tdj`qRg*?(TP? z^J!^mKQ}f?Ot|jeU1lG$kIBu2^$iZ*rb@blJbeVISz2bHP!&7b(t+?7WDGD-x5-LAQ|XVkXJ{B07+hQ4aB2UH7hhD+)ul2wHy3pL zMlW-*T?0kXaKXRVPFX&w;(S8_#_Q$h_besFsNlly1Zx3t{Gr%wz2GMzXS_!IGP$z6 zp+VwtmW&C_E*6^ra`yOx1l3)YS2{*V^@xRzw-285?>NnVc2U#TuJjAXPQ~8l8L4*A zEHkaWK^sR1y-rJuDS1-V(bGd56BDyqfpMGSmpPgD1yket<|rJI9G>UDHEA=JuWry< zsoW%kEqi{2c_=K*!Og7!QoLF-Ecb?xlvXV$sNo(b=WO?^<>l9|u3qp+`@Uq3YM)h& zM!yZc#<2YS{ND59Er-$Ef2!^KsAuXtGFDbridO@%^GRA6V(MyYC?HwXjQe{^`QJLn zwT^>~7!OVkj=s%_QjUA~lqV}J%xwPDK`0C+^tn*oUGhAYcIXzSNlY!!-NhEZKwA6s!KV>~MY|At76EYO2Db8icVie&EqA6oKR@3! zIH(1oGBPqm+$JB3c`laWE-j5JEpHnc8R4;c%+2WBIrzy7awf<6mUK}!4K+2jf}YSe z_0ILtyyMJX;_WRHDh~2c$pip{+fp z^B#DL+fbOdw|8R|Fr=yZp#~#3JVE0{!0sYnYisLmPI7RXPC!5aGptZ)*>WucxP+#L zMyw-CTsKVfJ+E#R@UZvM#FU0XuiD$&xseyR9am{A7K^U{Dp2n%28Jej%(z~4pP&DI z$nj?1_x5Oq$ug5_=TR7gsO#JFT)%(-L!*hAnVEEfbzm`lui2II4N48sg98Ja-D_)W znkoDi#yIx(_H=}RYo=UXUbrPEF^amX>FOq-Q1%WE z>RXfL1{c6g?5}>GrQew?E-t>2c%}|#1a2m>Cc)0$&dB}?o%BqWTpf`2g#N|I1eOqTiXeShS#)Y?KHuM)i9O-C3(MlYxU z^^Sa0;^5;e|7Q2}e51%f9%Lw>C+zzdyoI&6Vs3BTHCb9%)XIu|Lt~@MY^7CO!t}Ip z>SNCQ!om(9pC@)Ym;evJ6K0Ru&yRpZ1LPznB}IPzEMng1Ls)KF+cDqh>;1Ef1X5^2 zUIKLDQBqPu3LzmK{AKmgz1HBuSFz>juZ$()z#Hrr+YS-WwDGwv}2CGwY7D@yUW`pv8@LO z2O_%zXz^mRdVb)EI{NzglR}K~u8pOorJRenu#HBfF$oFD>Gx>Laa`N)15Hfo$cWAd zDSwTYKp!7PXXpF)`1m5;y1KfjSj_H7gSQ>8Mbqc8RwYG6{rGNxL?Q2=%G)zF#010? z*B}tnZ<*3YHE`g-QUTkjme7-*y-9ab2?<{l<*!hur$Nu2J$oxj0|W4T@ZbRyf!mo| z26v~5d$Lln$`s>jJ(pVFVFh&kt;ZA+pU=2|1r>FZfgvV8|K7^4UmdQsxt~7WgscVW zM{*v4=)ihOXgG6#;XxX$`5B^ag|P>JL$Nl*^7LY-9)bYZ+^0W1;vj?m^77RyGG!GN zd}wp3GI6HHsdN?OMK3&s_K~B#z4h|fc(g1x_l?ofQAp#)w#LlWUY2|~Yv&8{8fk1) z6g~zg>@@UcX{qfejbS8uy%e+!=_lfzi^||1q8@kJF;Mx|Dg%>c|xO zj=lvh1`|U!Sy>YRZVjjF`|LXa&ha2^+2dP_$O{jMBfCm(x9yLdjI6Ba79k6n-%hm5ZXIg3bzBJT%W4ElNGXAa^obeSW3_(M->aAzdlh) zHb5Si?XkV0jJt>!}vcXOJ-CFt(%Mqd_XBe@S7(#1T`SBQ}uJe5S&a+9m& zMEP9D!E}1LrwxS*VkN;h4MtNi80nCs^~gNcM0_YxN%}2ImT7G`+bFvf^hExz zfb()Afg#>zRmzqN`xLlqIk^7V1e@9NZ-FLVLsOIO*}*EHf6rn|sF44rzWeOwl8&95 z25~)M;m@u@e+_3>Vh7>bau#5~D3tqLomOokv!q^k;QGj;+MceiVjOUeiNz*=H!7-` z=HQw__($HQ@INiF4AKE*uJxwnXaruwZ`_1mEUoNM6L#u<>fq#L6f_?c z<;JM2oWLrJ&LaN);|F_+fR*6@=pZI8kf1{2&1BQdXEU#bG+ZlMzSF@$< zsig#H$L)N4aFG0Ok@nJ*_snEP*VnJHC^bL7&lW;4j`MW_augld1;xY{H_Bo|J%hZ_mm!#(lb!+ z&B2HI3sHc=N=ry2GCl0%@Gu&v;IHIBsz6Wl6O<06tnHozi=@xB{r&yT02T1+kP~b< zLWqo2h8}ba1Uh*f&^!ZTxi*M@9B7&qT#XH!C{A}-W` z#^oxcz+Lw?in7rmH=^4iD=RCAWKM@rc zKExYpmYquyol7U4lX}yy!h=E&E)SWmw>h03ZEVK&Ig4l{vdVUKb}DU-m*mZ!Y|q?< z!GI{!OI%OexWnd3-bNFV>*d`BWj0o2r#d)cn?kWCA%Ozy97h{y z){1&An(ugedsq2wj;r&Pn$=evZBA%P1!8%JhKBGJ6qS^CWDzp$cgcad@g8bm{8VCh z%A&@MHr5poh>Fk7ql&fCQc|uzX$36H&ie)iN{=>?K>ysx-q-B!zNX00wc{kI9b_}d za5L1a4?J*9y|iR?drJqI73VeR78GJk*0z|glo1;@PX2? z(ov2C@cDVwJ7LcfSfugqH%4KC_F=8(n>_xvumAp|7QJII1zK)Fz!(5q<8ng)ban{| zdXPjk+wkZp73gg`PxqG%%z(XO7hB?h_TZ>T4rWEs5%yaJ}+D?yFg1>vzyU$R6{P=OR4=`-;n$E*H$HnI0VyiZ} z*tj@<+0|+oSlvaTp!<@QOHU8UL96rwkO(YV{ACW;hQo`IDAu=+G~_=jC%&F=?Jm$v z(b3U~2-uk|5wMd*%r`_H9r=lPE;e_V;Xi-=Tn!Fa0nJ5obMrR$93L%da&j^o%z3V^ zyrMNOHr8vk|2Bw{i2L--tgI}DE6TL1(yOzzJNLM_I-Nywf%z5dE{{%{W(+!-w;@@; zLP(IF%z3^+sJW%3)cpci_OCz#H%VH*P)r|NA2;fAAV#tGyu_Yl{S%Kal!AaODa`>!|+$Jy;31 literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/test_mathtext.py b/lib/matplotlib/tests/test_mathtext.py index 8084ffcd9179..41619c18cf91 100644 --- a/lib/matplotlib/tests/test_mathtext.py +++ b/lib/matplotlib/tests/test_mathtext.py @@ -134,7 +134,7 @@ r'$\sum x\quad\sum^nx\quad\sum_nx\quad\sum_n^nx\quad\prod x\quad\prod^nx\quad\prod_nx\quad\prod_n^nx$', # GitHub issue 18085 r'$1.$ $2.$ $19680801.$ $a.$ $b.$ $mpl.$', r'$\text{text}_{\text{sub}}^{\text{sup}} + \text{\$foo\$} + \frac{\text{num}}{\mathbf{\text{den}}}\text{with space, curly brackets \{\}, and dash -}$', - + r'$\boldsymbol{abcde} \boldsymbol{+} \boldsymbol{\Gamma + \Omega} \boldsymbol{01234} \boldsymbol{\alpha * \beta}$', ] digits = "0123456789" @@ -538,3 +538,9 @@ def test_mathtext_operators(): fig.text(0.5, (x + 0.5)/len(test_str), r'${%s}$' % i) fig.draw_without_rendering() + + +@check_figures_equal(extensions=["png"]) +def test_boldsymbol(fig_test, fig_ref): + fig_test.text(0.1, 0.2, r"$\boldsymbol{\mathrm{abc0123\alpha}}$") + fig_ref.text(0.1, 0.2, r"$\mathrm{abc0123\alpha}$")