math-acc.mklx /size: 15 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=math-acc,
3%D        version=2013.07.31,
4%D          title=\CONTEXT\ Math Macros,
5%D       subtitle=Accents,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Math Macros / Accents}
15
16% There are probably errors ... too distracted by amazing (piano) music videos running
17% on top of scite ... so: experimental code.
18
19\unprotect
20
21%D This module permits overloading of accents so that we can do fancy things. The
22%D implementation is similar to stackers. By default accenst are defined in a simple
23%D way. Contrary to extensibles accents cannot grow indefinitely. Alas the
24%D implementation of accents is different too, in the sense that they are
25%D prepositioned i.e. are already raised. (In my opinion for no real reason as they
26%D need to adapt anyway).
27%D
28%D In \MKIV\ we used virtual characters in the "FE* range but in \LMTX\ we do it a bit
29%D different as we have a more powerful virtual subsystem. For details on the older
30%D but neat approach see the lua and mkiv files.
31%D
32%D Older implementations are kept in the \MKII\ and \MKIV\ modules for educational
33%D purposes.
34
35%D Only very few fonts provide flat accents but we emulate them for those that don't
36%D have them. We also need to fix the related font parameter for a few fonts like
37%D Lucida and Garamond.
38
39% \startbuffer
40% \im{
41%     \dostepwiserecurse{`A}{`Z}{1}{
42%         \blackrule[height=\the\Umathflattenedaccentbaseheight\textstyle,depth=0pt,width=0.05ts]
43%         \hat{\char#1}
44%     }
45% }
46% \stopbuffer
47%
48% \start % TEXpage[offset=1ts]
49%     \showglyphs
50%     \switchtobodyfont[modern]     \getbuffer\par
51%     \switchtobodyfont[erewhon]    \getbuffer\par
52%     \switchtobodyfont[concrete]   \getbuffer\par
53%     \switchtobodyfont[libertinus] \getbuffer\par
54%     \switchtobodyfont[stixtwo]    \getbuffer\par
55%     \switchtobodyfont[kpfonts]    \getbuffer\par
56%     \switchtobodyfont[minion]     \getbuffer\par
57%     \switchtobodyfont[schola]     \getbuffer\par
58%     \switchtobodyfont[lucida]     \getbuffer\par
59%     \switchtobodyfont[xcharter]   \getbuffer\par
60%     \switchtobodyfont[libertinus] \getbuffer\par
61%     \switchtobodyfont[termes]     \getbuffer\par
62% \stop %TEXpage
63
64% scale:
65%
66%   no   : only use base
67%   yes  : use base, variants and extensible, stretch and shrink when set
68%   keep : use base, variants and extensible, stretch and shrink when set, but keep base
69%
70% alignsymbol:
71%
72%   center when accent is wider than base
73%
74% stretch|shrink:
75%
76%   scale accent to fit (base and variants depending on 'scale' value)
77
78\installcorenamespace{mathaccents}
79
80\installcommandhandler \??mathaccents {mathaccent} \??mathaccents
81
82\aliased\let\setupmathaccents\setupmathaccent
83
84\setupmathaccents
85  [\c!top=,
86   \c!bottom=,
87   \c!mathstyle=,
88   \c!color=,
89   \c!symbolcolor=\mathaccentparameter\c!color,
90   \c!textcolor=\mathaccentparameter\c!color,
91   \c!scale=\v!no,
92   \c!alignsymbol=\v!yes,
93  %\c!stretch=\v!no,
94  %\c!shrink=\v!no,
95   \c!define=\v!yes, % not used
96   \c!snap=\mathematicsparameter\c!snap]
97
98\definemathaccent
99  [\v!both]
100
101\definemathaccent
102  [\v!top]
103  [\v!both]
104
105\definemathaccent
106  [\v!bottom]
107  [\v!both]
108
109\setupmathaccents
110  [\v!top]
111  [i=\v!auto]
112
113\setupmathaccents
114  [\v!both]
115  [i=\v!auto]
116
117\setupmathaccents
118  [\v!bottom]
119  [i=]
120
121% \permanent\tolerant\protected\def\definemathtopaccent[#1]#*[#2]#*[#3]% class name top
122%   {\ifparameter#3\or
123%      \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_common                      {#1}{#2}\plusone{\number#3}\zerocount}%
124%    \else
125%      \frozen\protected\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusone{\number#2}\zerocount}%
126%    \fi}
127
128% \permanent\tolerant\protected\def\definemathbottomaccent[#1]#*[#2]#*[#3]% class name bottom
129%   {\ifparameter#3\or
130%      \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plustwo\zerocount{\number#3}}%
131%    \else
132%      \frozen\protected\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plustwo\zerocount{\number#2}}%
133%    \fi}
134
135% \permanent\tolerant\protected\def\definemathdoubleaccent[#1]#*[#2]#*[#3]#*[#4]% class name top bottom
136%   {\ifparameter#4\or
137%      \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plusthree{\number#3}{\number#4}}%
138%    \else
139%      \frozen\protected\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusthree{\number#2}{\number#3}}%
140%    \fi}
141
142% \installlocalcurrenthandler \??mathaccents {mathaccent}
143
144\permanent\tolerant\protected\def\definemathtopaccent[#1]#*[#2]#*[#3]% class name top
145  {\ifparameter#3\or
146     \definemathaccent[#2][#1]%
147     \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plusone{\number#3}\zerocount}%
148   \else
149     \definemathaccent[#1]%
150     \frozen\protected\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusone{\number#2}\zerocount}%
151   \fi}
152
153\permanent\tolerant\protected\def\definemathbottomaccent[#1]#*[#2]#*[#3]% class name bottom
154  {\ifparameter#3\or
155     \definemathaccent[#2][#1]%
156     \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plustwo\zerocount{\number#3}}%
157   \else
158     \definemathaccent[#1]%
159     \frozen\protected\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plustwo\zerocount{\number#2}}%
160   \fi}
161
162\permanent\tolerant\protected\def\definemathdoubleaccent[#1]#*[#2]#*[#3]#*[#4]% class name top bottom
163  {\ifparameter#4\or
164     \definemathaccent[#2][#1]%
165     \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_common                       {#1}{#2}\plusthree{\number#3}{\number#4}}%
166   \else
167     \definemathaccent[#1]%
168     \frozen\protected\instance\edefcsname#1\endcsname{\math_accent_common\noexpand\currentmathaccent{#1}\plusthree{\number#2}{\number#3}}%
169   \fi}
170
171%D \starttyping
172%D \im { \showboxes \showglyphs
173%D     \hat{\tilde{\dot{x}}}
174%D }
175%D \im { \showboxes \showglyphs
176%D     \hat[align=middle]{\tilde[align=middle]{\dot{x}}}
177%D }
178%D \stoptyping
179
180\tolerant\protected\def\math_accent_common#class#name#kind#top#bottom#*[#settings]#:#content%
181  {\beginmathgroup
182 % \setlocalmathaccentcurrent{#class}% \edef\currentmathaccent{#class}%
183   \cdef\currentmathaccent{#name}% \edef\currentmathaccent{#class}%
184   \setupcurrentmathaccent[#settings]%
185   \edef\p_scale{\mathaccentparameter\c!scale}%
186   \ifx\p_scale\v!keep
187     \lettonothing\m_fixed
188   \orelse\ifx\p_scale\v!yes
189     \lettonothing\m_fixed
190   \else
191     \let\m_fixed\s!fixed
192   \fi
193   \ifcstok{\mathaccentparameter\c!plugin}\v!mp
194     \edef\p_mp{\mathaccentparameter\c!mp}%
195     \ifempty\p_mp\else
196       \clf_set_extensible_data
197           mp     {\p_mp}
198           left   \scratchcounterthree
199           right  \scratchcounterthree
200           middle \scratchcounterthree
201        \relax
202     \fi
203   \else
204     \lettonothing\p_mp
205   \fi
206   \math_tags_mfunctionlab\plustwo{#name}{\ifcase#kind\or\v!top\or\v!bottom\else\v!both\fi}%
207   \Umathaccent
208     \usedsymbolcolorparameterattributes{\mathaccentparameter\c!symbolcolor}%
209 % nooverflow % there is never na overflow anyway but we do accept the key
210   \ifcstok{\mathaccentparameter\c!align}\v!middle
211     \s!center\relaxedspace
212   \fi
213   \ifcstok{\mathaccentparameter\c!stretch}\v!yes
214     \s!stretch\relaxedspace
215   \fi
216   \ifcstok{\mathaccentparameter\c!shrink}\v!yes
217     \s!shrink\relaxedspace
218   \fi
219   \ifcstok{\mathaccentparameter\c!snap}\v!yes
220     \s!single\relaxedspace
221   \fi
222   \ifempty\p_mp\else
223     \s!usecallback\relaxedspace
224   \fi
225   \ifx\p_scale\v!keep
226     \s!keepbase\relaxedspace
227   \fi
228   \ifcstok{\mathaccentparameter\c!alignsymbol}\v!yes
229     \s!nooverflow\relaxedspace
230   \fi
231   \ifcstok{\mathaccentparameter\c!offset}\v!auto
232     \s!base\relaxedspace
233   \fi
234   \ifcase#kind\or
235     \s!top\relaxedspace
236     \m_fixed
237     \fam\zerocount#top
238% \fam\mathaccentcode#top % class is signal
239   \or
240     \s!bottom\relaxedspace
241     \m_fixed
242     \fam\zerocount#bottom
243% \fam\mathaccentcode#bottom % class is signal
244   \or
245     \s!both\relaxedspace
246     \m_fixed
247     \fam\zerocount#bottom
248     \fam\zerocount#top
249%      \fam\mathaccentcode#bottom % class is signal
250%      \fam\mathaccentcode#top % class is signal
251   \fi
252   {\usemathaccentcolorparameter\c!textcolor
253    \startusemathstyleparameter\mathaccentparameter\c!mathstyle
254    \ifcstok{\mathaccentparameter{i}}\v!auto\mathdotless\fi
255    #content%
256    \stopusemathstyleparameter}%
257   \endmathgroup}
258
259%D Relative new:
260
261% \newconditional\c_math_accent_auto_dotless \c_math_accent_auto_dotless\conditionaltrue % cf opentype math
262
263% \aliased\let\normalgrave\grave
264% \aliased\let\normalddot \ddot
265% \aliased\let\normalbar  \bar
266% \aliased\let\normalacute\acute
267% \aliased\let\normalhat  \hat     \aliased\let\normalwidehat  \widehat
268% \aliased\let\normalcheck\check
269% \aliased\let\normalbreve\breve
270% \aliased\let\normaldot  \dot
271% \aliased\let\normalring \ring
272% \aliased\let\normaltilde\tilde
273% \aliased\let\normaldddot\dddot
274
275\pushoverloadmode
276
277% These retain the given unicode values ... but can stretch when configured
278% to do so: \setupmathaccent[\v!top][\c!scale=\v!yes]
279
280% Extended/modified below
281%
282% \definemathtopaccent[\v!top][grave]["0060] % these are old school
283% \definemathtopaccent[\v!top][ddot] ["00A8]
284% \definemathtopaccent[\v!top][bar]  ["00AF]
285% \definemathtopaccent[\v!top][acute]["00B4]
286% \definemathtopaccent[\v!top][hat]  ["02C6]
287% \definemathtopaccent[\v!top][check]["02C7]
288% \definemathtopaccent[\v!top][breve]["02D8]
289% \definemathtopaccent[\v!top][dot]  ["02D9]
290% \definemathtopaccent[\v!top][ring] ["02DA]
291% \definemathtopaccent[\v!top][tilde]["02DC]
292% \definemathtopaccent[\v!top][dddot]["20DB]
293
294\definemathtopaccent[\v!top][grave]   ["0300]
295\definemathtopaccent[\v!top][acute]   ["0301]
296\definemathtopaccent[\v!top][hat]     ["0302]
297\definemathtopaccent[\v!top][tilde]   ["0303]
298\definemathtopaccent[\v!top][bar]     ["0305]
299%definemathtopaccent[\v!top][overbar] ["0305]% We expect overbar to stretch, so later
300\definemathtopaccent[\v!top][breve]   ["0306]
301\definemathtopaccent[\v!top][dot]     ["0307]
302\definemathtopaccent[\v!top][ddot]    ["0308]
303\definemathtopaccent[\v!top][overhook]["0309]
304\definemathtopaccent[\v!top][ring]    ["030A]
305\definemathtopaccent[\v!top][check]   ["030C]
306
307% Here starts the weird unicode ones
308
309%definemathtopaccent[\v!top][candra]               ["0310]
310%definemathtopaccent[\v!top][overturnedcomma]      ["0312]
311%definemathtopaccent[\v!top][overcommatopright]    ["0315]
312%definemathtopaccent[\v!top][leftangleabove]       ["031A]
313\definemathtopaccent[\v!top][overleftharpoon]      ["20D0]
314\definemathtopaccent[\v!top][overrightharpoon]     ["20D1]
315%definemathtopaccent[\v!top][verticaloverlayaccent]["20D2]
316%definemathtopaccent[\v!top][vec]                  ["20D7]% We expect vec to stretch, so later
317\definemathtopaccent[\v!top][dddot]                ["20DB]
318\definemathtopaccent[\v!top][ddddot]               ["20DC]
319%definemathtopaccent[\v!top][annuityaccent]        ["20E7]
320%definemathtopaccent[\v!top][overbracketaccent]    ["20E9]
321%definemathtopaccent[\v!top][asterixaccent]        ["20F0]
322
323% Weird ones (why no single and double underdots in unicode?)
324
325%definemathbottomaccent[\v!bottom][underdot]  ["0323]%Conflicting
326%definemathbottomaccent[\v!bottom][underddot] ["0324]
327%definemathbottomaccent[\v!bottom][underdddot]["20E8]
328
329\definemathaccent
330  [\v!top:\v!stretch]
331  [\v!top]
332  [\c!scale=\v!keep,\c!stretch=\v!yes,\c!shrink=\v!yes]
333
334\definemathaccent
335  [\v!bottom:\v!stretch]
336  [\v!bottom]
337  [\c!scale=\v!keep,\c!stretch=\v!yes,\c!shrink=\v!yes]
338
339\definemathaccent
340  [\v!both:\v!stretch]
341  [\v!both]
342  [\c!scale=\v!keep,\c!stretch=\v!yes,\c!shrink=\v!yes]
343
344\definemathaccent
345  [\v!top:\v!dot]
346  [\v!top:\v!stretch]
347  [i=]
348
349%D We have a problem. We can use stackers but then we need to adapt the dimensions
350%D which is font dependent. So, for now we keep them as accents.
351
352\definemathtopaccent[\v!top:\v!stretch][widegrave]["0300] % these are generic modern
353\definemathtopaccent[\v!top:\v!stretch][wideacute]["0301]
354\definemathtopaccent[\v!top:\v!stretch][widehat]  ["0302]
355\definemathtopaccent[\v!top:\v!stretch][widetilde]["0303]
356\definemathtopaccent[\v!top:\v!stretch][widebar]  ["0305]% (not 304, the caret)
357\definemathtopaccent[\v!top:\v!stretch][widebreve]["0306]
358\definemathtopaccent[\v!top:\v!stretch][widedot]  ["0307]
359\definemathtopaccent[\v!top:\v!stretch][wideddot] ["0308]
360\definemathtopaccent[\v!top:\v!stretch][widering] ["030A]
361\definemathtopaccent[\v!top:\v!stretch][widecheck]["030C]
362\definemathtopaccent[\v!top:\v!stretch][widedddot]["20DB]
363
364\definemathtopaccent[\v!top:\v!stretch][vec]["20D7] % clumsy notation for vectors
365
366\definemathtopaccent[\v!top:\v!stretch][wideoverleftharpoon]   ["20D0]
367\definemathtopaccent[\v!top:\v!stretch][wideoverrightharpoon]  ["20D1]
368\definemathtopaccent[\v!top:\v!stretch][wideoverleftarrow]     ["20D6]
369\definemathtopaccent[\v!top:\v!stretch][wideoverrightarrow]    ["20D7]
370\definemathtopaccent[\v!top:\v!stretch][wideoverleftrightarrow]["20E1]
371
372\definemathbottomaccent[\v!bottom:\v!stretch][wideundertilde]         ["0330]
373\definemathbottomaccent[\v!bottom:\v!stretch][wideunderbar]           ["0332]
374\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftrightarrow]["034D] % weird code
375\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightharpoon]  ["20EC]
376\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftharpoon]   ["20ED]
377\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftarrow]     ["20EE]
378\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightarrow]    ["20EF]
379
380% For complex conjugate: i below keeps the dot
381%
382% \im { \widebar  {\cos\theta + \ii \sin\theta} = \cos\theta - \ii\sin\theta }\par
383% \im { \conjugate{\cos\theta + \ii \sin\theta} = \cos\theta - \ii\sin\theta }
384
385\definemathtopaccent[\v!top:\v!dot][conjugate]["0305]
386\definemathtopaccent[\v!top:\v!dot][closure]  ["0305]
387\definemathtopaccent[\v!top:\v!dot][conjugate]["0305]
388
389\aliased\let\mathring\ring % for a while
390
391% \permanent\protected\def\not#1{\Umathaccent class \mathordinarycode exact overlay 0 0 "338 {#1}}
392% \permanent\protected\def\not#1{\Umathaccent class \mathrelationcode exact overlay 0 0 "338 {#1}}
393% \permanent\protected\def\not#1{\Umathaccent class \mathbinarycode   exact overlay 0 0 "338 {#1}}
394%
395% \definemathcommand[slashD][ordinary]{\Umathaccent class \mathordinarycode exact  overlay 0 0 "338 {D}}
396% \definemathcommand[slashD][ordinary]{\Umathaccent class \mathordinarycode center overlay 0 0 "338 {D}}
397
398\permanent\tolerant\protected\def\slashed[#1]#:#2%
399  {\Umathaccent
400     \usedcolorparameterattributes{\mathaccentparameter\c!symbolcolor}%
401     \s!class  \mathcodechecked{#1}%
402     \s!center \relaxedspace
403     \s!overlay\relaxedspace
404     \zerocount \zerocount \forwardslashasciicode
405   {\usemathaccentcolorparameter\c!textcolor
406    #2}} % exact when =
407
408% \definemathcommand[slashD]{\slashed[ordinary]{D}}
409% \definemathcommand[slashD]{\slashed{D}}
410
411\popoverloadmode
412
413\protect \endinput
414