summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/ontarget/ontarget-math.tex
blob: c7e5551d55ed09ab82f4441ec5ff9d8c9cfe5234 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
% language=us runpath=texruns:manuals/ontarget

% \profilemacro\scaledfontdimen

% \usebodyfont[modern]
% \usebodyfont[cambria]
% \usebodyfont[termes]
% \usebodyfont[pagella]
% \usebodyfont[bonum]

\startcomponent ontarget-math

\environment ontarget-style

\startchapter[title={A different approach to math spacing}]

\startsubject[title=Introduction]

The \TEX\ engine is famous for its rendering of math and even after decades there
is no real contender. And so there also is no real pressure to see if we can do
better. However, when Mikael Sundqvist ran into a Swedish math rendering
specification and we started discussing a possible support for that in \CONTEXT,
it quickly became clear that the way \TEX\ does spacing is a bit less flexible
than one wishes for. We already have much of what is needed in place but it also
has to work well with how \TEX\ sees things:

\startitemize[packed,n]
\startitem
    Math is made from a sequence of atoms: a quantity with a nucleus, superscript
    subscript. \footnote {I suddenly realize why in the engine noads have a
    nucleus field: they are atoms \unknown\ but what does that make super and
    subscripts.} Atoms are spaced by \type {\thinmuskip}, \type {\medmuskip} and
    \type {\thickmuskip} or nothing, and that is sort of hard coded.
\stopitem
\startitem
    Atoms are organized by class and there are seven (or eight, depending on how
    you look at it) of them visible: binary symbols, relations, etc. The
    invisible ones, composites like fractions and fenced material (we call them
    molecules) are at some point mapped onto the core set. Molecules like fences
    have a different class left and right of the fenced material.
\stopitem
\startitem
    In addition the engine itself has all kind of spacing related parameters and
    these kick in automatically and sometimes have side effects. The same is
    true for penalties.
\stopitem
\stopitemize

The normal approach to spacing other than imposed by the engine is to use
correction space, like \type {\,} and I think that quite some \TEX\ users think
that this is how it is supposed to be. The standard way to enter math relates to
scientific publishing and there the standards are often chiseled in stone so why
should users tweak anyway. However, in \CONTEXT\ we tend to start from the users
and not the publishers end so there we can decide to follow different routes.
Users can always work around something they don't like but we focus on reliable
input giving predictable output. Also, when reading on, it is good to realize
that it is all about the user experience here: it should look nice (which then of
course makes one become aware of issues elsewhere) and we don't care much about
specific demands of publishers in the scientific field: the fact that they often
re|-|key content doesn't go well with users paying attention themselves, let
alone the fact that nowadays they can demand word processor formats.

The three mentioned steps are fine for the average case but sometimes make no
sense. It was definitely the best approach given time and resources but when
\LUATEX\ went \OPENTYPE\ a lot of parameters were added and at that time we
therefore added spacing by class pair. That not only decoupled the relation
between the three (configurable) muskip parameters but also made it possible to
use plenty of them. Now it must be said that for consistency having these three
skips works great but given the tweaking expected from users consistency is
not always what comes out.

This situation is very well comparable to the proclaimed qualities of the
typesetting of text by \TEX. Yes, it can do a great job, and often does, but users
can mess up quite well. I remember that when we did tests with \HZ\ the outcomes
were pretty unimpressive. When you give an audience a set of sample renderings,
where each sample is slightly different and each user gets a randomized subset,
the sudden lack of being able to compare (and agree) with another \TEX ie makes
for interesting conclusions. They look for the opposites of what is claimed to be
perfect. So, two lines with hyphens rate low, even if not doing it would look
worse. The same for a few short words in the last line of a paragraph. Excessive
spacing is also seen as bad. So, when asked why some paragraphs looked okay
noticing (excessive and troublesome) expansion was not seen as a problem; instead
it were hyphens that got the attraction.

The same is probably true for math: the input with lots of correction spaces or
commands where characters would do can be horrible but it's just the way it is
supposed to be. The therefore expected output can only be perfect, right,
independent of how one actually messed up spacing. But personally I think that it
is often spacing messed up by users that make a \TEX\ document recognizable. It
compares to word processor results that one can sometimes identify by multiple
consecutive spaces in the typeset text instead of using a glue model like \TEX.
Reaching perfection is not always trivial, but fortunately we can also find
plenty of nice looking documents done with \TEX.

The \TEX book has an excellent and intriguing chapter on the fine points of math
and it definitely shows why Don Knuth wrote \TEX\ as a tool for his books. He
pays a lot of attention to detail and that is also why it all works out so well.
If you need to render from unseen sources (as happens in an \XML\ workflow)
coming from several authors and have time nor money to check everything, you're
off worse. And I'm not even talking of input where invisible \UNICODE\ spacing
characters are injected. It is the \TEX\ book(s) that draw me to this program and
believe it or not, in the first project I was involved in that demanded typeset
(quantum mechanics) math the \IBM\ typewriter with changing bulbs ruled the
scenery. In fact, our involvement was quickly cut off when we dared to show a
chapter done in \TEX\ that looked better.

Apart from an occasional tweak, in \CONTEXT\ we never really used this opened up
math atom pair spacing mechanism available in \LUATEX\ extensively. So, when I
was pondering how to proceed it stroke me that it would make sense to generalize
this mechanism. It was already possible (via a mode parameter) to bypass the
second step mentioned above, but we definitely needed more than the visible
classes that the engine had. In \CONTEXT\ we already had more classes but those
were meant for assigning characters and commands to specific math constructs
(think of fences, fractions and radicals) so in the end they were not really
classes. Considering this option was made easier by the fact that Mikael would do
the testing and help configuring the defaults, which all will result in a new
math user manual.

There are extensions introduced in \LUATEX\ and later \LUAMETATEX\ that are not
discussed here. In this expose we concentrate on the features that were explored,
extended and introduced while we worked on updating math support in \LMTX.

\stopsubject

\startsubject[title=An example]

Before we go into details, let's give an example of unnoticed spacing effects. We
use three simple formulas all using fractions:

\startbuffer[one]
\ruledhbox{$\frac{x^2}{a+1}$}
\stopbuffer

\startbuffer[two]
\ruledhbox{$x + \frac{x^2}{a+1} = 10$}
\stopbuffer

\startbuffer[three]
\ruledhbox{$\frac{1}{2}\frac{1}{2}x$}
\stopbuffer

\typebuffer[one]

and:

\typebuffer[two]

as well as:

\typebuffer[three]

\startbuffer[all]
\dontleavehmode
\scale[scale=4000]{\getbuffer[one]}
\scale[scale=4000]{\getbuffer[two]}
\scale[scale=4000]{\getbuffer[three]}
\stopbuffer

\startlinecorrection
\nulldelimiterspace=1.2pt\getbuffer[all]
\stoplinecorrection

If you look closely you see that the fraction has a little space at the left and
right. Where does that come from? Because we normally don't put a tight frame
around a fraction, we are not really aware of it. The spacing between what are
called ordinary, operator, binary, relation and other classes of atoms is
explained in the \TEX book (or \quotation {\TEX\ by Topic} if you want a summary)
and basically we have a class by class matrix that is built into \TEX. The
engine looks at successive items and spacing depends on their (perceived) class.
Because the number of classes is limited, and because the spacing pairs are hard
coded, the engine cheats a little. Depending on what came before or comes next
the class of an atom is adapted to suit the spacing matrix. One can say that a
\quotation {reading mathematician} is built in. And most of the decisions are
okay. If needed one can always wrap something in e.g.\ \type {\mathrel} but of
course that also can interfere with grouping. All this is true for \TEX, \PDFTEX,
\XETEX\ and \LUATEX, but a bit different in \LUAMETATEX\ as we will see.

The little spacing on both edges of the fraction is a side effect of the way they
are build internally: fractions are actually a generalized form of \quotation
{stuff put on top of other stuff} and they can have left and|/|or right
delimiters: this is driven by primitives that have names like \type {\atop} and
\type {\atopwithdelims}. The way the components are placed is (especially in the
case of \OPENTYPE) driven by lots of parameters and I will leave that out of the
discussion.

When there are no delimiters, a so called \type {\nulldelimiterspace} will be
injected. That parameter is set to 1.2 points and I have to admit that in
\CONTEXT\ I never considered letting that one adapt to the body font size, which
means that, as we default to a 12 point body font, the value there should have
been 1.44 points: mea culpa. When we set this parameter to zero point, we get
this:

\startlinecorrection
\nulldelimiterspace=0pt\getbuffer[all]
\stoplinecorrection

As intermezzo and moment of contemplation I show some examples of fractions mixed
into text. When we have the delimiter space set we get this:

\start \nulldelimiterspace=1.2pt \dorecurse{100}{test $\frac{1}{#1}$ } \stop

While with zero it looks like this, quite a different outcome:

\start \nulldelimiterspace=0pt   \dorecurse{100}{test $\frac{1}{#1}$ } \stop

A little tracing shows it more clearly:

\start \showboxes \nulldelimiterspace=1.2pt \dorecurse{100}{test $\frac{1}{#1}$ } \stop

You can zoom in and see where it interferes with margin alignment.

\start \showboxes \nulldelimiterspace=0pt   \dorecurse{100}{test $\frac{1}{#1}$ } \stop

So, if you ever meet a user who claims perfection and superiority of typesetting,
check out her|/|his work which might have inline fractions done the spacy way. It
might make other visually typesetting claims less trustworthy. And yes, one can
wonder if margin kerning could help here but as this content is wrapped in boxes it
is unlikely to work out well (and not worth the effort).

In order to get a better picture of the spacing, two more renderings are shown.
This time we show the bounding boxes of the characters too (you might need to zoom
in to see it):

\startlinecorrection
\showglyphs\nulldelimiterspace=1.2pt\getbuffer[all]
\stoplinecorrection

Again we also show the zero case

\startlinecorrection
\showglyphs\nulldelimiterspace=0pt\getbuffer[all]
\stoplinecorrection

This makes clear why there actually is this extra space around a fraction:
regular operators have side bearings and thereby have some added space. And when
we put a fraction in front of a symbol we need that little extra space. Of course
a proper class pair spacing value could do the job but there is no fraction
class. The engine cheats by changing the class depending on what follows or came
before and this is why on the average it looks okay. However, these examples
demonstrate that there are some assumptions with regard to for instance fonts
and this is one of the reasons why the more or less official expected \OPENTYPE\
behavior as dictated by the Cambria font doesn't always work out well for fonts
that evolved from the ones used in the \TEX\ community. Also imagine how this
interferes with the fact that traditional \TEX\ fonts and the machinery do magic
with cheating about width combined with italic correction (all plausible and
quite clever but somewhat tricky with respect to \OPENTYPE).

Because here we discuss the way \LUAMETATEX\ and \CONTEXT\ deal with this, the
next examples show a probably unexpected outcome. Again first the non|-|zero
case:

\startlinecorrection
\showglyphs\showmakeup[mathglue]\nulldelimiterspace=1.2pt\getbuffer[all]
\stoplinecorrection

And here the zero case:

\startlinecorrection
\showglyphs\showmakeup[mathglue]\nulldelimiterspace=0pt\getbuffer[all]
\stoplinecorrection

I will not go into details about the way fractions are supported in the engine
because some extensions are already around for quite a while. The main
observation here is that in \LUAMETATEX\ we have alternative primitives that
assume forward scanning, as if the numerator and denominator are arguments. The
engine also supports skewed (vulgar) fractions natively where numerator and
denominator are raised and lowered relative to the (often) slash. Many aspects
of the rendering can be tuned in the so called font goodie files, which is also
the place where we define the additional font parameters.

\stopsubject

\startsubject[title=Atom spacing]

If you are familiar with traditional \TEX\ you know that there is some build in
\type {ordbin} spacing. But there is no such pair for a fraction and a relation,
simply because there is no fraction class. However, in \LUAMETATEX\ there is one,
and we'd better set it up if we zero the margins of a fraction.

It is worth noticing that fractions are sort of special anyway. The official
syntax is \type {n \over m} and numerator and denominator can be sub formulas.
This is the one case where the parser sort of has to look back, which is tricky
because the machinery is a forward looking one. Therefore, in order to get the
expected styling (or avoid unexpected side effects) one will normally wrap all in
braces as in: \type {{ {n} \over {m} }} which of course kind defeats the simple
syntax which probably is supported for \type {1\over2} kind of usage, so a next
challenge is to make \type {1/2} come out right. All this means that in practice
we have wrappers like \type {\frac} which accidentally in \LUAMETATEX\ can be
defined using forward looking primitives with plenty extra properties driven by
keywords. It also means that fractions as expected by the engine due to wrapping
actually can be a different kind of atom, which can have puzzling side effects
with respect to spacing (because the remapping happens unseen).

Interesting is that adapting \LUAMETATEX\ to a more extensive model was quite
doable, also because the code base had already be made more configurable. Of
course it involved quite a bit of tedious editing and throwing out already nice
and clean code that had taken some effort, but that's the way it is. Of course
more classes also means that some storage properties had to be adapted within the
available space but by sacrificing families that was possible. With 64 potential
classes we now are back to 64 families compared to 7 classes and 256 families in
\LUATEX\ and 7 classes and 16 families in traditional \TEX.

Also interesting is that the new implementation is actually somewhat simpler and
therefore the binary is a tad smaller too. But does all that mean that there were
no pitfalls? Sure there were! It is worth noticing that doing all this reminded
me of the early days of \LUATEX\ development, where Taco and I exchanged binaries
and \TEX\ code in a more or less constant way using Skype. For \LUAMETATEX\ we
used good old mail for files and Mojca's build farm for binaries and Mikael and I
spent many month exchanging information and testing out alternatives on a daily
basis: it is in my opinion the only way to do this and it's fun too. It has been
a lot of work but once we got going there was nothing that could stop us. A side
effect was that there were no updates during this period, which was something
users noticed.

In the spacing matrix there is \type {inner} and internally there's also some
care to be taken of \type {vcenter}. The \type {inner} class is actually shared
with the \type {variable} class which is not so much a real class but more a
signal to the engine that when an alphabetic or numeric character is included that
it has to come from a specific family: upright family zero or math italic family
one in traditional speak. But, what if we don't have that setup? Well, then one
has to make sure that this special class number is not associated (which is no
big deal). It does mean that when we extend the repertoire of classes we
cannot use slot seven. Always keep in mind that classes (and thereby signals) get
assigned to characters (some defaults by the engine, others by the macro
package). It is why in \CONTEXT\ we use abstract class numbers, just in case the
engine gets adapted.

We also cannot use slot eight because that one is a signal too: for a possible
active math character, a feature somewhat complicated by the fact that it should
not interfere with passing around such active characters in arguments. In math
mode where we have lots of macros passing around content, this special class works
around these side effects. We don't need this feature in \CONTEXT\ because
contrary to other macro packages we don't handle primes, pseudo superscripts
potentially followed by other super and subscripts by making the \type {'} an
active character and thereby a macro in math mode. This trickery again closely
relates to preferable input, font properties, and limitations of memory and such
at the time \TEX\ showed up (much has to fit into 8, 16 or 32 bits, so there is
not much room for e.g.\ more than 8 classes). Since we started with \MKIV\ the way
math is dealt with is a bit different than normally done in \TEX\ anyway.

\stopsubject

\startsubject[title=Atom rules]

We can now control the spacing between every atom but unfortunately that is not
good enough. Therefore, we arrive at yet another feature built into the engine:
turning classes into other classes depending on neighbors. And this is precisely
why we have certain classes. Let's quote \quotation {\TEX\ by Topic}: {\em The
cases \type {*} (in the atom spacing matrix) cannot occur, because a \type {bin}
object is converted to \type {ord} if it is the first in the list, preceded by
\type {bin}, \type {op}, \type {open}, \type {punct}, \type {rel}, or followed by
\type{close}, \type {punct}, or \type {rel}; also, a \type{rel} is converted to
\type{ord} when it is followed by \type {close} or \type {punct}.}

We can of course keep these hard coded heuristics but can as well make that bit
of code configurable, which we did. Below is demonstrated how one can set up the
defaults at the \TEX\ end. We use symbolic names for the classes.

\starttyping
\setmathatomrule  \mathbegincode         \mathbinarycode       % old
  \allmathstyles    \mathordinarycode      \mathordinarycode   % new

\setmathatomrule  \mathbinarycode        \mathbinarycode
  \allmathstyles    \mathbinarycode        \mathordinarycode
\setmathatomrule  \mathoperatorcode      \mathbinarycode
  \allmathstyles    \mathoperatorcode       \mathordinarycode
\setmathatomrule  \mathopencode          \mathbinarycode
  \allmathstyles    \mathopencode          \mathordinarycode
\setmathatomrule  \mathpunctuationcode   \mathbinarycode
  \allmathstyles    \mathpunctuationcode   \mathordinarycode
\setmathatomrule  \mathrelationcode      \mathbinarycode
  \allmathstyles    \mathrelationcode      \mathordinarycode

\setmathatomrule  \mathbinarycode        \mathclosecode
  \allmathstyles    \mathordinarycode      \mathclosecode
\setmathatomrule  \mathbinarycode        \mathpunctuationcode
  \allmathstyles    \mathordinarycode      \mathpunctuationcode
\setmathatomrule  \mathbinarycode        \mathrelationcode
  \allmathstyles    \mathordinarycode      \mathrelationcode

\setmathatomrule  \mathrelationcode      \mathclosecode
  \allmathstyles    \mathordinarycode      \mathclosecode
\setmathatomrule  \mathrelationcode      \mathpunctuationcode
  \allmathstyles    \mathordinarycode      \mathpunctuationcode
\stoptyping

Watch the special class with \type {\mathbegincode}. This is actually class 62 so
you don't need much fantasy to imagine that class 63 is \type {\mathendcode}, but
that one is not yet used. In a similar fashion we can initialize the spacing
itself: \footnote {Constant, engine specific, numbers like these are available in
tables at the \LUA\ end so we can change them and users can check that.}

\starttyping
\setmathspacing \mathordcode   \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathordcode   \mathbincode    \allsplitstyles \medmuskip
\setmathspacing \mathordcode   \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathordcode   \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathopcode    \mathordcode    \allmathstyles  \thinmuskip
\setmathspacing \mathopcode    \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathopcode    \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathopcode    \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathbincode   \mathordcode    \allsplitstyles \medmuskip
\setmathspacing \mathbincode   \mathopcode     \allsplitstyles \medmuskip
\setmathspacing \mathbincode   \mathopencode   \allsplitstyles \medmuskip
\setmathspacing \mathbincode   \mathinnercode  \allsplitstyles \medmuskip

\setmathspacing \mathrelcode   \mathordcode    \allsplitstyles \thickmuskip
\setmathspacing \mathrelcode   \mathopcode     \allsplitstyles \thickmuskip
\setmathspacing \mathrelcode   \mathopencode   \allsplitstyles \thickmuskip
\setmathspacing \mathrelcode   \mathinnercode  \allsplitstyles \thickmuskip

\setmathspacing \mathclosecode \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathclosecode \mathbincode    \allsplitstyles \medmuskip
\setmathspacing \mathclosecode \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathclosecode \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathpunctcode \mathordcode    \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathopcode     \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathrelcode    \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathopencode   \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathclosecode  \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathpunctcode  \allsplitstyles \thinmuskip
\setmathspacing \mathpunctcode \mathinnercode  \allsplitstyles \thinmuskip

\setmathspacing \mathinnercode \mathordcode    \allsplitstyles \thinmuskip
\setmathspacing \mathinnercode \mathopcode     \allmathstyles  \thinmuskip
\setmathspacing \mathinnercode \mathbincode    \allsplitstyles \medmuskip
\setmathspacing \mathinnercode \mathrelcode    \allsplitstyles \thickmuskip
\setmathspacing \mathinnercode \mathopencode   \allsplitstyles \thinmuskip
\setmathspacing \mathinnercode \mathpunctcode  \allsplitstyles \thinmuskip
\setmathspacing \mathinnercode \mathinnercode  \allsplitstyles \thinmuskip
\stoptyping

And because we have a few more atom classes this also needs to happen:

\starttyping[style=\tt]
\letmathspacing  \mathactivecode   \mathordinarycode
\letmathspacing  \mathvariablecode \mathordinarycode
\letmathspacing  \mathovercode     \mathordinarycode
\letmathspacing  \mathundercode    \mathordinarycode
\letmathspacing  \mathfractioncode \mathordinarycode
\letmathspacing  \mathradicalcode  \mathordinarycode
\letmathspacing  \mathmiddlecode   \mathopencode
\letmathspacing  \mathaccentcode   \mathordinarycode

\letmathatomrule \mathactivecode   \mathordinarycode
\letmathatomrule \mathvariablecode \mathordinarycode
\letmathatomrule \mathovercode     \mathordinarycode
\letmathatomrule \mathundercode    \mathordinarycode
\letmathatomrule \mathfractioncode \mathordinarycode
\letmathatomrule \mathradicalcode  \mathordinarycode
\letmathatomrule \mathmiddlecode   \mathopencode
\letmathatomrule \mathaccentcode   \mathordinarycode
\stoptyping

With \type {\resetmathspacing} we get an all|-|zero state but that might become
more refined in the future. What is not clear from the above is that there is
also an inheritance mechanism. The three special muskip registers are actually
shortcuts so that changing the register value is reflected in the spacing. When a
regular muskip value is (verbose or as register) that value is sort of frozen.
However, the \type {\inherited} prefix will turn references to registers and
constants into a delayed value: as with the predefined we now have a more dynamic
behavior which means that we can for instance use reserved muskip registers as we
can use the predefined. A bonus is that one can also use regular glue or
dimensions, just in case one wants the same spacing in all styles (a muskip
adapts to the size).

When you look at all the above you might wonder how users are supposed to deal
with math spacing. The answer is that often they can just assume that \TEX\ does
the right thing. If something somehow doesn't feel right, looking at solutions by
others will probably lead a new user to just copy a trick, like injecting a \type
{\thinmuskip}. But it can be that atoms depend on the already applied (or not)
spacing, which in turn depends on values in the atom spacing matrix that probably
only a few users have seen. So, in the end it all boils down to trust in the
engine and one's eyesight combined with hopefully some consistency in adding
space directives and often with \TEX\ it is consistency that makes documents look
right. In \CONTEXT\ we have many more classes even if only a few characters fit in,
like differential, exponential and imaginary.

\stopsubject

\startsubject[title=Fractions again]

We now return to the fraction molecule. With the mechanisms at our disposal we
can change the fixed margins to more adaptive ones:

\starttyping
\inherited\setmathspacing \mathbinarycode   \mathfractioncode
    \allmathstyles \thickermuskip
\inherited\setmathspacing \mathfractioncode \mathbinarycode
    \allmathstyles \thickermuskip
\nulldelimiterspace\zeropoint
$x + \frac{1}{x+2} + x$
\stoptyping

Here \typ {\thickermuskip} is defined as \type {7mu plus 5mu} where the stretch
is the same as a \typ {\thickmuskip} and the width \type {2mu} more. We start out
with three variants, where the last two have \typ {\nulldelimiterspace} set to
\type {0pt} and the first one uses the \type {1.2pt}.

\definecolor[tred]  [r=1,a=1,t=.5]
\definecolor[tgreen][g=1,a=1,t=.5]
\definecolor[tblue] [b=1,a=1,t=.5]

\startlinecorrection
\scale[scale=4000]\bgroup\vbox\bgroup \forgetall
    \bgroup \tgreen \nulldelimiterspace=1.2pt $x + \frac{1}{x+2} + x$\egroup\par
    \bgroup \tred   \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$\egroup\par
    \bgroup \tblue  \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$\egroup\par
\egroup\egroup
\stoplinecorrection

When we now apply the new settings to the last one, and overlay them we get the
following output: the first and last case are rather similar which is why this
effort was started in the first place.

\startlinecorrection
\scale[scale=4000]\bgroup
    \startoverlay
        \bgroup
            \inherited\setmathspacing \mathbinarycode   \mathfractioncode \allmathstyles \thickmuskip
            \inherited\setmathspacing \mathfractioncode \mathbinarycode   \allmathstyles \thickmuskip
            \tgreen \nulldelimiterspace=1.2pt $x + \frac{1}{x+2} + x$
        \egroup
        \bgroup
            \inherited\setmathspacing \mathbinarycode   \mathfractioncode \allmathstyles \thickmuskip
            \inherited\setmathspacing \mathfractioncode \mathbinarycode   \allmathstyles \thickmuskip
            \tred \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$
        \egroup
        \bgroup
            \inherited\setmathspacing \mathbinarycode   \mathfractioncode \allmathstyles \thickermuskip
            \inherited\setmathspacing \mathfractioncode \mathbinarycode   \allmathstyles \thickermuskip
            \tblue \nulldelimiterspace=0.0pt $x + \frac{1}{x+2} + x$
        \egroup
    \stopoverlay
\egroup
\stoplinecorrection

Of course this kind of changes are not upward compatible but as they are tiny
they are not that likely to change the number of lines in a paragraph. In display
mode changes in horizontal dimensions also hav elittle effect.

\startsubject[title=Penalties]

An inline formula can be broken across lines, and for sure there are places where
you don't want to break or prefer to break. In \TEX\ line breaks can be
influenced by using penalties. At the outer level of an inline math formula, we
can have a specific penalty before and after a binary and|/|or relation. The
defaults are such that there are no penalties set, but most macro packages set
the so called \type {\relpenalty} and \type {\binoppenalty} (the \type {op} in
this name does not relate to the operator class) so a value between zero and
1000. In \LUATEX\ we also have \type{\pre} variants of these, so we have four
penalties that can be set, but that is not enough in our new approach.

These penalties are class bound and don't relate to styles, like atom spacing
does. That means that while atom spacing involves $64 \times 64 \times 8$
potential values, an amount that we can manage by using the discussed
inheritance. The inheritance takes less values because which store 4 style values
per class in one number. For penalties we only need to keep $64 \times 2$ in
mind, plus a range of inheritance numbers. Therefore it was decided to also
generalize penalties so that each class can have them. The magic commands are
shown with some useless examples:

\starttyping
\letmathparent \mathdigitcode
    \mathbincode   % pre penalty
    \mathbincode   % post penalty
    \mathdigitcode % options
    \mathdigitcode % reserved
\stoptyping

By default the penalties are on their own, like:

\starttyping
\letmathparent \mathdigitcode
  \mathdigitcode % pre penalty
  \mathdigitcode % post penalty
  \mathdigitcode % options
  \mathdigitcode % reserved
\stoptyping

The options and reserved parent mapping are not (yet) discussed here. Unless
values are assigned they are ignored.

\starttyping
\setmathprepenalty  \mathordcode 100
\setmathpostpenalty \mathordcode 600
\setmathprepenalty  \mathbincode 200
\setmathpostpenalty \mathbincode 700
\setmathprepenalty  \mathrelcode 300
\setmathpostpenalty \mathrelcode 800
\stoptyping

As with spacing, when there is no known value, the parent will be consulted. An unset
penalty has a value of 10000.

After discussing the implications of inline math crossing lines, Mikael and I
decided that there can be two solutions. Both can of course be implemented in
\LUA, but on the other hand, they make good extensions, also because it sort of
standardized it. The first advanced control feature tweaks penalties:

\starttyping
\mathforwardpenalties  2  200 100
\mathbackwardpenalties 2  100  50
\stoptyping

This will add 200 and 100 to the first two math related penalties, and 100 and 50
to the last two (watch out: the 100 will be assigned to the last found one, the
50 to the one before it). As with all things penalty and line break related, you
need to have some awareness of how non|-|linear the badness calculation is as
well of the fact that the tolerance and stretch related parameters play a role
here.

The second tweak is setting \type {\maththreshold} to some value. When set to for
instance \type {40pt}, formulas that take less space than this will be wrapped in
a \type {\hbox} and thereby will never break across a page. \footnote {A future
version might inject severe penalties instead, time will learn.} Actually that
second tweak has a variant so we have three tweaks! Say that we have this sample
formula wrapped in some bogus text and repeat that snippet a lot of times:

\startbuffer[demo]
x xx xxx xxxx $1 + x$ x xx xxx xxxx
\stopbuffer

\typebuffer[demo]

Now look at the example on the next page. You will notice that the red and blue
text have different line breaks. This is because we have given the threshold some
stretch and shrink. The red text has a zero threshold so it doesn't do any magic
at all, while the second has this setup:

\startbuffer
\setupmathematics[threshold=medium]
\stopbuffer

That setting set the threshold to \typ {4em plus 0.75em minus 0.50em} and when
the formula size exceeds the four quads the line break code will use the real
formula width but with the given stretch and shrink. Eventually the calculated
size will be used to repackage the formula. In the future we will also provide a
way to define slack more relative to the size and|/|or number of atoms.

\startpostponing
\startlinecorrection \small
\startoverlay
    {\setupmathematics[threshold=none]%
     \vbox\bgroup
        \darkred
        \dorecurse {40} {\getbuffer[demo]}
     \egroup}
    {\setupmathematics[threshold=medium]%
     \vbox\bgroup
        \darkblue
        \dorecurse {40} {\getbuffer[demo]}
     \egroup}
\stopoverlay
\stoplinecorrection
\stoppostponing

Another way to influence line breaks is to use the two inline math related
penalties that have been added at Mikael's suggestion:

\startbuffer \setupalign[verytolerant]
{\dorecurse{25}{test $\darkred   #1^{#1} + x_{#1}^{#1}$ test }\blank}
{\preinlinepenalty  500 \postinlinepenalty -500
 \dorecurse{25}{test $\darkgreen #1^{#1} + x_{#1}^{#1}$ test }\blank}
{\postinlinepenalty 500 \preinlinepenalty  -500
 \dorecurse{25}{test $\darkblue  #1^{#1} + x_{#1}^{#1}$ test }\blank}
\stopbuffer

\typebuffer

To get an example that shows the effect takes a bit of trial and error because
\TEX\ does a very good job in line breaking. This is why we've set the tolerance
and also use negative penalties.

In addition to the \type {\mathsurround} (kern) and \type {\mathsurroundskip}
(glue) parameters this is a property of the nodes that mark the beginning and end
of an inline math formula.

\blank \getbuffer \blank

\stopsubject

\startsubject[title=Flattening]

The traditional engine has some code for flattening math constructs that in the
end are just one character. So in the end, \type {\tilde {u}} and \type {\tilde
{uu}} become different objects even if both are in fact accents. In fact, when an
accent is constructed there is a special code path for single characters so that
script placement adapts to the shape of that character.

However because of interaction with primes, which themselves are sort of
superscripts and due to the somewhat weird way fonts provide them when it comes
to positioning and sizes, in \CONTEXT\ we already are fooling around a bit with
these characters. For understandable reasons of memory usage, complexity and
eightbitness primes are not a native \TEX\ thing but more something that is
handled at the macro level (although not in \MKIV\ and \LMTX).

In the end it was script placements on (widely) accented math characters that
made us introduced a dedicated \type {\Umathprime} primitive that adds a prime to
a math atom. It permits an uninterupted treatment of scripts while in the final
assembly of the molecule the prime, superscript, subscript and maybe even
prescripts that prime gets squeezed in. Because the concept of primes is missing
in \OPENTYPE\ math an additional font parameter \type {PrimeTopRaisePercent} has
been introduced as well as an \type {\Umathprimeraise} primitive. In retrospect I
should have done that earlier but one tends to stick to the original as much as
possible. However, at some point Mikael and I reached a state where we decided
that proper (clean) engine extensions make way more sense than struggling with
border cases and explaining users why things are so complicated.

The input \type {$ X \Uprimescript{'} ^2 _3 $} gives this:

\startlinecorrection
\startcombination[nx=4,distance=3em,inbetween={\blank[3*medium]}]
    {\switchtobodyfont [modern]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Latin Modern}
    {\switchtobodyfont[cambria]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Cambria}
    {\switchtobodyfont[pagella]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Pagella}
    {\switchtobodyfont [dejavu]\removeunwantedspaces\scale[s=5]{\strut$\showboxes\showglyphs X\Uprimescript{'}^2_3$}} {Dejavu}
\stopcombination
\stoplinecorrection

With \type {\tracingmath = 1} this nicely traces as:

\starttyping
> \inlinemath=
\mathord
.\nucleus
..\mathchar (fam="0,char="58)
.\superscript
..\mathchar (fam="0,char="32)
.\subscript
..\mathchar (fam="0,char="32)
.\primescript
..\mathchar (fam="0,char="27)
\stoptyping

Of course this feature scan also be used for other prime like ornaments and who
knows how it will evolve over time.

You can influence the positioning with \type {\Umathprimesupshift} which adds
some kern between a prime and superscript. The \type {\Umathextraprimeshift}
moves a prime up. The \type {\Umathprimeraise} is a font parameter that defaults
to 25 which means a raise of 25\percent of the height. These are all (still)
experimental parameters.

\stopsubject

\startsubject[title=Fences]

Fences can be good for headaches. Because the math that I (or actually my
colleague) deal with is mostly school math encoded in presentation \MATHML\ (sort
or predictable) or some form of sequential \ASCII\ based input (often rather
messy and therefore unpredictable due to ambiguity) fences are a pain. A \TEX ie
can make sure that left and right fenced are matched. A \TEX ie also knows when
something is an inline parenthesis or when a more high level structure is needed,
for instance when parentheses have to scale with what they wrap. In that case the
\type {\left} and \type {\right} mechanism is used. In arbitrary input missing
one of those is fatal. Therefore, handling of fences in \CONTEXT\ is one of the
more complex sub mechanisms: we not only need to scale when needed, but also
catch asymmetrical usage.

A side effect of the encapsulating fencing construct is that it wraps the content
in a so called inner (as in \type {\mathinner}) which means that we get a box,
and it is a well known property of boxes that they don't break across lines. With
respect to fences, a way out is to not really fence content, but do something
like this:

\starttyping
\left(\strut\right. x + 1 \left.\strut\right)
\stoptyping

and hope for the best. Both pairs are coupled in the sense that their sizes will
match and the strut is what determines the size. So, as long as there is a proper
match of struts all is well, but it is definitely a decent hack. The drawback is
in the size of the strut: if a formula needs a higher one, larger struts have to
be used. This is why in plain \TEX\ we have these commands:

\starttyping[style=\small\tt]
\def\bigl {\mathopen \big } \def\bigm {\mathrel\big } \def\bigr {\mathclose\big }
\def\Bigl {\mathopen \Big } \def\Bigm {\mathrel\Big } \def\Bigr {\mathclose\Big }
\def\biggl{\mathopen \bigg} \def\biggm{\mathrel\bigg} \def\biggr{\mathclose\bigg}
\def\Biggl{\mathopen \Bigg} \def\Biggm{\mathrel\Bigg} \def\Biggr{\mathclose\Bigg}

\def\big #1{{\hbox{$\left#1\vbox to  8.5pt{}\right.\nomathspacing$}}}
\def\Big #1{{\hbox{$\left#1\vbox to 11.5pt{}\right.\nomathspacing$}}}
\def\bigg#1{{\hbox{$\left#1\vbox to 14.5pt{}\right.\nomathspacing$}}}
\def\Bigg#1{{\hbox{$\left#1\vbox to 17.5pt{}\right.\nomathspacing$}}}

\def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt} % renamed
\stoptyping

The middle is kind of interesting because it has relation properties, while the
\type {\middle} introduced in \ETEX\ got open properties, but we leave that
aside.

In \CONTEXT\ we have plenty of alternatives, including these commands, but they
are defined differently. For instance they adapt to the font size. The hard coded
point sizes in the plain \TEX\ code relates to the font and steps available in
there (either by next larger or by extensible). The values thereby need to be
adapted to the chosen body font as well as the body font size. In \MKIV\ and even
better in \LMTX\ we can actually consult the font and get more specific sizes.

But, this section is not about how to get these fixed sizes. Actually, the need
to choose explicitly is not what we want, especially because \TEX\ can size
delimiters so well. So, take this code snippet:

\startbuffer
$ x = \left( \dorecurse{40}{\frac{x}{x+#1} +} x \right) $
\stopbuffer

\typebuffer

% \dostepwiserecurse{0}{25}{1}{
% \begingroup \showmakeup[mathglue] \showglyphs
% \advance\hsize-#1pt\relax \inleftmargin{#1pt}%
% $ x = \left( \dorecurse{20}{\frac{x}{x+##1} +} x \right) $
% \blank \endgroup
% }
When we typeset this inline, as in \inlinebuffer, we get nicely scaled fences but
in a way that permits line breaks. The reason is that the engine has been
extended with a \type {fenced} class so that we can recognize later on,
when \TEX\ comes to injecting spaces and penalties, that we need to unpack the
construct. It is another beneficial side effect of the generalization.

The Plain \TEX\ code can be used to illustrate some of what we discussed before
about fractions. In the next code we use excessive delimiter spacing:

\starttyping
\def\Bigg#1{%  watch the wrapping in a box
  {%
    \hbox {%
        $\normalleft#1\vbox to 17.5pt{}\normalright.\nomathspacing$%
    }%
  }%
}

\nulldelimiterspace0pt
\def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}

$\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$\par

\nulldelimiterspace10pt
\def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}

$\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$\par

\nulldelimiterspace10pt
\def\nomathspacing{\mathsurround0pt}

$\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$\par
\stoptyping

This renders as follows. We explicitly set \type {\nulldelimiterspace} to values
because in \CONTEXT\ it is now zero by default.

\startlinecorrection
    \pushoverloadmode
    \def\Bigg#1{{\hbox{$\normalleft#1\vbox to 17.5pt{}\normalright.\nomathspacing$}}}
    \popoverloadmode
    \startcombination[nx=3,ny=1,distance=3em]
        {\showboxes
         \nulldelimiterspace0pt
         \def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}
         $\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$}
        {\tttf 0pt with reset at end}
        {\showboxes
         \nulldelimiterspace10pt
         \def\nomathspacing{\nulldelimiterspace0pt\mathsurround0pt}
         $\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$}
        {\tttf 10pt with reset at end}
        {\showboxes
         \nulldelimiterspace10pt
         \def\nomathspacing{\mathsurround0pt}
         $\Bigg( 1 + x\Bigg) \quad \Bigg( \frac{1}{x}\Bigg)$}
        {\tttf 10pt without reset at end}
    \stopcombination
\stoplinecorrection

\stopsubject

\startsubject[title=Radicals]

In traditional \TEX\ a radical with degree is defined as macro. That macro does
some measurements and typesets the result in four sizes for a choice. The macro
typesets the degree in a box that contains the degree as formula. There is a
little guesswork going on than with respect to how the radical symbol is shaped
but as we're talking plain \TEX\ here it works out okay because the default font
is well known.

Radicals are a nice example of a two dimensional \quote {extender} but only the
vertical dimension uses the extension mechanism, which itself operates either
horizontally or vertically, although in principle it could both ways. The
horizontal extension is a rule and the fact that the shape is below the baseline
(as are other large symbols) will make the rule connect well: the radical shape
sticks out a little, so one can think of the height reflecting the rule height.
\footnote {When you zoom in you will notice that this is of not always optimal
because of the way the slope touched the rule.} In \OPENTYPE\ fonts there is a
parameter and in \LUATEX\ we use the default rule thickness for traditional
fonts, which is correct for Latin Modern. There are more places in the fonts
where the design relates to this thickness, for instance fraction rules are
supposed to match the minus, but this is a bit erratic if you compare fonts. This
is one of the corrections we apply in the goodie files.

In \OPENTYPE\ the specification of the radical also includes spacing properties
of the degree and that is why we have a primitive in \LUATEX\ that also handles
the degree. It is what we used in \CONTEXT\ \MKIV. But \unknown\ we actually end
up with a situation that compares to the already discussed fraction: there is
space added before a radical when there is a degree. However, because we now have
a radical atom class, we can avoid using that one and use the new pairwise
spacing. Some fuzzy spacing logic in the engine could therefore be removed and we
assume that \type {\Umathradicaldegreebefore} is zero. For the record: the \type
{\Umathradicaldegreeafter} sort of tells how much space there is above the low
part of the root, which means that we can compensate for multi|-|digit degrees.

Zeroing a parameter is something that relates to a font which means that it has
to happen for each math font which in turn can mean a family|-|style combination. In
order to avoid that complication (or better: to avoid tracing clutter) we have a
way to disable a parameter:

\startbuffer
\ruledhbox{$x + \sqrt[123]{b}^1_2$}
\ruledhbox{$x + \sqrt[12] {b}^1_2$}
\ruledhbox{$x + \sqrt[1]  {b}^1_2$}
\ruledhbox{$x + \sqrt     {b}^1_2$}
\stopbuffer

\typebuffer

\startlinecorrection
\startcombination[1*4]
    {\switchtobodyfont[modern]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore0\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 0}}{}
    {\switchtobodyfont[modern]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore1\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 1}}{Latin Modern}
\stopcombination
\stoplinecorrection

One problem with these spacing parameters is that they are inconsistent across
fonts. The Latin Modern has a rather large space before the degree, while Cambria
and Pagella have little. That means that when you prototype a mechanism the
chosen solution can look great but not so much when at some point you use another
font.

\startlinecorrection
\startcombination[1*4]
    {\switchtobodyfont[pagella]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore0\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 0}}{}
    {\switchtobodyfont[pagella]\scale[height=10mm]{\showglyphs\setmathignore\Umathradicaldegreebefore1\getbuffer}}{}
    {\type {\setmathignore \Umathradicaldegreebefore 1}}{Cambria}
\stopcombination
\stoplinecorrection

\stopsubject

\startsubject[title=More fences]

One of the reasons why the \MKII\ and \MKIV\ fence related mechanism is somewhat
complex is that we want a clean solution for filtering fences like parenthesis by
size, something that in the traditional happens via a fake fence pair that
encapsulates a strut of a certain size. In \LMTX\ we use the same approach but
have made the sequence more configurable. In practice that means that the values
1 upto 4 are just that but for some fonts we use the sequence \type {1 3 5 7}.
There was no need to adapt the engine as it already worked quite well.

\stopsubject

\startsubject[title=Integrals]

The Latin Modern fonts have only one size of big operators and one reason can be
that there is no need for more. Another reason can be that there was just no
space in the font. However, an \OPENTYPE\ font has plenty slots available and the
reference font Cambria has integral signs in sizes as well as extensibles.

In \LUATEX\ we already have generic vertical extensibles but that only works well
with specified sizes. And, cheating with delimiters has the side effect that we
get the wrong spacing. In \LUAMETATEX\ however we have ways to adapt the size to
what came or what comes. In fact, it is a mechanism that is available for any atom
that we support. However, it doesn't play well with script and this whole \type {\limits}
and \type {\nolimits} is a bit clumsy so Mikael and I decided that different route had
to be followed. For adaptive large operators we provide this interface:

\startbuffer[sample-1]
$ x + \integral [color=darkred,top={t},bottom={b}] {\frac{1}{x}} = 10 $
\stopbuffer

\startbuffer[sample-2]
$ x + \startintegral [color=darkblue,top={t},bottom={b}]
    \frac{1}{x}
\stopintegral = 10 $
\stopbuffer

\startbuffer[sample-3]
$ x + \startintegral [color=darkgreen,top={t},bottom={b},method=vertical]
    \frac{1}{x}
\stopintegral= 10 $
\stopbuffer

\typebuffer [sample-1,sample-2,sample-3]

This text is not about the user interface so we won't discuss how to define additional
large operators using one|-|liners.

\startlinecorrection
\startcombination[nx=3,ny=1,distance=2em]
    {\scale[s=2]{\getbuffer[sample-1]}} {}
    {\scale[s=2]{\getbuffer[sample-2]}} {}
    {\scale[s=2]{\getbuffer[sample-3]}} {}
\stopcombination
\stoplinecorrection

The low level \LUAMETATEX\ implementation handles this input:

\starttyping
\Uoperator          \Udelimiter "0 \fam "222B {top} {bottom} {...}
\Uoperator   limits \Udelimiter "0 \fam "222B {top} {bottom} {...}
\Uoperator nolimits \Udelimiter "0 \fam "222B {top} {bottom} {...}
\stoptyping

plus the usual keywords that fenced accept, because after all, this is just a
special case of fencing.

Currently these special left operators are implemented as a special case of
fences because that mechanism does the scaling. It means that we need a (bogus)
right fence, or need to brace the content (basically create an atom). When no
right fence is found one is added automatically. Because there is no real
fencing, right fences are removed when processing takes place. When you specify a
\type {class} that one will be used for the left and right spacing, otherwise we
have open|/|close spacing.

\stopsubject

\startsubject[title=Going details]

When the next feature was explored Mikael tagged it as math micro typography and
the reason is that you need not only to set up the engine for it but also need to
be aware of this kind of spacing. Because we wanted to get rid of this script spacing
that the font imposes we configured \CONTEXT\ with:

\starttyping
\setmathignore\Umathspacebeforescript\plusone
\setmathignore\Umathspaceafterscript \plusone
\stoptyping

This basically nils all these tiny spaces. But the latest configuration has this
instead:

\starttyping
% \setmathignore \Umathspacebeforescript\zerocount % default
% \setmathignore \Umathspaceafterscript \zerocount % default

\mathslackmode \plusone

\setmathoptions\mathopcode      \plusthree
\setmathoptions\mathbinarycode  \plusthree
\setmathoptions\mathrelationcode\plusthree
\setmathoptions\mathopencode    \plusthree
\setmathoptions\mathclosecode   \plusthree
\setmathoptions\mathpunctcode   \plusthree
\stoptyping

This tells the engine to convert these spaces into what we call slack: disposable
kerns at the edges. But it also converts these kerns into a glue component when
possible. As with all these extensions it complicates the machinery but users
will never see that. Now, the last six lines do the magic that made us return to
honoring the spaces: we can tell the engine to ignore this slack when there are
specific classes at the edges. These options are a bitset and \type {1} means
\quotation {no slack left} and \type {2} means \quotation {no slack right} so
\type {3} sets both.

\startbuffer
\def\TestSlack#1%
  {\vbox\bgroup
      \mathslackmode\zerocount
      \hbox\bgroup
         \setmathignore\Umathspacebeforescript\zerocount
         \setmathignore\Umathspaceafterscript \zerocount
         #1
      \egroup
      \vskip-.9\lineheight
      \hbox\bgroup\red
        \setmathignore\Umathspacebeforescript\plusone
        \setmathignore\Umathspaceafterscript \plusone
         #1
      \egroup
   \egroup}

\startcombination[nx=3]
    {\showglyphs\TestSlack{$f^2 >     $}} {}
    {\showglyphs\TestSlack{$    > f^^2$}} {}
    {\showglyphs\TestSlack{$f^2 > f^^2$}} {}
\stopcombination
\stopbuffer

\typebuffer

\startlinecorrection
\scale[width=\textwidth]{\getbuffer}
\stoplinecorrection

Because this overall niling is not granular enough a while later we introduced a
way to set this per class, as is demonstrated in the next example.

\startbuffer
\def\TestSlack#1%
  {\vbox\bgroup
      \mathslackmode\plusone
      \hbox\bgroup\red
        \setmathignore\Umathspacebeforescript\zerocount
        \setmathignore\Umathspaceafterscript \zerocount
        #1
      \egroup
      \vskip-.9\lineheight
      \hbox\bgroup\green
        \setmathoptions\mathrelationcode \zerocount
        #1
      \egroup
      \vskip-.9\lineheight
      \hbox\bgroup\blue
        \setmathoptions\mathrelationcode \plusthree
        #1
      \egroup
   \egroup}

\startcombination[nx=3]
    {\showglyphs\TestSlack{$f^2 >     $}} {}
    {\showglyphs\TestSlack{$    > f^^2$}} {}
    {\showglyphs\TestSlack{$f^2 > f^^2$}} {}
\stopcombination
\stopbuffer

\typebuffer

\startlinecorrection
\scale[width=\textwidth]{\getbuffer}
\stoplinecorrection

Of course we need to experiment a lot with real documents and it might take a
while before all this is stable (in the engine and in \CONTEXT). And as we don't
need to conform to the decades old golden \TEX\ math standards we have some
degrees of freedom in this: for Mikael and me it is pretty much a visual thing
where we look closely at large samples. Of course in practice details get lost
when we print at 10 point but that doesn't mean we can't provide the best
experience. \footnote {Whenever I look at (my) old (math) school books I realize
that Don Knuth had very good reasons to come up with \TEX\ and, it being hard to
beat, \TEX\ still sets the standard!}

\stopsubject

\startsubject[title=Ghosts]

As plain \TEX\ has macros like \type {\vphantom} you also find them in macro
packages that came later. These create a boxes that have their content removed
after the dimensions are set. They take space and are invisible but there's also
nothing there.

A variant in the upgraded math machinery are ghosts: these are visible in the
sense that they show up but ignored when it comes to spacing. Here is an example.
The option bit set here tells the engine that we ghost at the right, so we have
ghosts around the relation (it controls where the spacing ends up).

\startbuffer
$
  x
  \mathatom class \mathghostcode                   {!!}
  >
  \mathatom class \mathghostcode options "00000020 {!!}
  1
  \quad
  x
  \mathatom class \mathghostcode                   {\hbox{\smallinfofont ord}}
  >
  \mathatom class \mathghostcode options "00000020 {\hbox{\smallinfofont dig}}
  1
$
\stopbuffer

\typebuffer

You never know when this comes in handy but it fits in the new, more granular
approach to spacing. The code above shows that it's just a class, this time with
number \number\mathghostcode.

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

\stopsubject

\startsubject[title=Struts]

In order to get consistent spacing the \CONTEXT\ macro package makes extensive
use of struts in text mode as well as math mode. The normal way to implement that is
either an empty box or a zero width rule, both with a specifically set height
and depth. In \CONTEXT\ \MKII\ and \MKIV\ (and for a long time in \LMTX\ too) they
were rules so that we could visualize them: they get some width and kerns
around them to compensate for that.

In order to not let them interfere with spacing we could wrap them into a ghost
atom but it is kind of ugly. Anyway, before we had these ghost atoms an
alternative to struts was already implemented: a special kind of rule. The reason is
that I wanted a cleaner and more predictable way to adapt struts to the math style
uses and sometimes predicting that is fragile. What we want is a delayed assignment of
dimensions.

We have two solutions. The first one uses two math parameters that themselves
adapt to the style, as do other parameters: \type {\Umathruleheight} and \type
{\Umathruledepth}. The other solution relates a font (or family) and character
with the strut rule which is then used as measure for the height and depth. Just
for the record: this also works in text mode, which is why a recent \LMTX\ also
does use that for struts now. The optional visualization is just part of the
regular visualization mechanism in \CONTEXT\ which already had provisions for
struts. A side effect of this is that the rule primitives now accept three more
keywords: \type {font}, \type {fam} and \type {char}, in addition to the already
present traditional ones \type {width}, \type {height} and \type {depth}, the
(backend) margin ones \type {left} (or \type {top}) and \type {right} (or \type
{bottom}) options, as well as \type {xoffset} and \type {yoffset}). The command
that creates a rule with subtype \type {strut} is simply \type {\srule}. Because
struts are rather macro package specific I leave it to this.

One positive side effect is that we could simplify the \CONTEXT\ fraction mechanism
a bit. Over time control over the (font driven) gaps was introduced but that is
not really needed because we zero the gaps anyway. There was also a tolerance
mechanism which again was not used. However, for skewed fractions we do use the new
tolerance mechanism as well as gap control.

\stopsubject

\startsubject[title=Atoms]

Now that we have generic atoms (\type {\mathatom}) another, sometimes confusing aspect
of the math parsing can be solved. Take this:

\starttyping
\def\MyBin{\mathbin{\tt mybin}}
$ x ^ \MyBin _ \MyBin $
\stoptyping

The parser just doesn't like that which means that one has to use

\starttyping
\def\MyBin{\mathbin{\tt mybin}}
$ x ^ {\MyBin} _ {\MyBin} $
\stoptyping

or:

\starttyping
\def\MyBin{{\mathbin{\tt mybin}}}
$ x ^ \MyBin _ \MyBin $
\stoptyping

But the later has side effects: it creates a list that can influence spacing. It
is for that reason that we do accept atoms where they were not accepted before.
Of course that itself can have side effects but at least we don't get an error
message. It fits well into the additional (user) classes model. And, given that
in \CONTEXT\ the \type {\frac} command is actually wrapped as \type {\mathfrac}
the next will work too:

\starttyping
$ x^\frac{1}{2} + x^{\frac{1}{2}} $
\stoptyping

but in practice you should probably use the braced version here for clarity.

\stopsubject

\startsubject[title=The \type {vcenter} primitive]

Traditionally this primitive is bound to math but it had already be adapted to also
work in text mode. As part of the upgrade of math we can now also pass all the options
that normal boxed take and we can also cheat with the axis. Here is an example:

\startbuffer
\def\TEST{\hbox\bgroup
    \darkred   \vrule width  2pt height 4pt
    \darkgreen \vrule width 10pt depth  2pt
\egroup}
$
    x  - \mathatom \mathvcentercode {!!!} -
    + \ruledvcenter                           {\TEST}
    + \ruledvcenter                           {\TEST}
    + \ruledvcenter axis 1                    {\TEST}
    + \ruledvcenter xoffset  2pt yoffset  2pt {\TEST}
    + \ruledvcenter xoffset -2pt yoffset -2pt {\TEST}
    + x
$
\stopbuffer

\typebuffer

There was already a vcenter class available before we did this:

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

\stopsubject

\startsubject[title=Text]

Sometimes you want text in math, for instance \type {sin} or \type {cos} but
text in math is not really text:

\startbuffer
$ \setmathspacing\mathordinarycode\mathordinarycode\textstyle 10mu fin(x) $
\stopbuffer

\typebuffer

The result demonstrates that what looks like a word actually becomes three
math atoms:

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

Okay, so how about then wrapping it into a text box:

\startbuffer
$
    \setmathspacing\mathordinarycode\mathordinarycode\textstyle 10mu
    fin(x) \quad \hbox{fin}(x)
$
\stopbuffer

\typebuffer

Here we get:

\startlinecorrection
    \scale[width=\textwidth]{\showglyphs\showmakeup[mathglue]\getbuffer}
\stoplinecorrection

We even get a ligature which might be an indication that we're not using a math
font which indeed is the case: the box is typeset in the regular text font.

\startbuffer
\def\Test#1%
  {\setmathspacing\mathordinarycode\mathordinarycode\textstyle 5mu
   $\showglyphs
   #1% style
   {\tf fin} \quad
   \hbox{fin} \quad
   \mathatom class \mathordinarycode textfont {fin}
   \mathatom class \mathordinarycode textfont {\tf fin}
   \mathatom class \mathordinarycode textfont {\hbox{fin}}
   \mathatom class \mathordinarycode mathfont {\hbox{fin}}
   $}
\stopbuffer

\typebuffer \getbuffer

When we feed this macro with the \type {\textstyle}, \type {\scriptstyle} and \type
{\scriptscriptstyle} we get:

\startlinecorrection
    \startcombination[1*3]
        {\scale[scale=3000]{\Test\textstyle        }} {text}
        {\scale[scale=3000]{\Test\scriptstyle      }} {script}
        {\scale[scale=3000]{\Test\scriptscriptstyle}} {scriptscript}
    \stopcombination
\stoplinecorrection

Here you see a new atom option action: \type {textfont} which does as much as
setting the font to the current family font and the size to the one used in the
style. For the record: you only get ligatures when they are configured and
provided by the font (and as math is a script itself it is unlikely to work).
\footnote {The existing mechanisms in \CONTEXT\ already dealt with this but it is
nevertheless nice to have it as a clean engine feature.}

\stopsubject

\startsubject[title=Tracing]

I won't discuss the tracing features in \CONTEXT\ here but for sure the
visualizer helps a lot in figuring out all this. In \LUAMETATEX\ we carry a bit
more information with the resulting nodes so we can provide more details, for
instance about the applied spacing and penalties. Some is shown in the examples.
A more recent tracing feature is this:

\starttyping
\tracingmath   1
\tracingonline 1
$
    \mathord (
    \mathord {(}
    \mathord \Udelimiter"4 0 `(
    \Udelimiter"4 0 `(
$
\stoptyping

That gives us on the console:

\starttyping
7:3: > \inlinemath=
7:3: \mathord
7:3: .\nucleus
7:3: ..\mathchar (fam="0,char="28)
7:3: \mathord
7:3: .\nucleus
7:3: ..\mathlist
7:3: ...\mathopen
7:3: ....\nucleus
7:3: .....\mathchar (fam="0,char="28)
7:3: \mathord
7:3: .\nucleus
7:3: ..\mathchar (fam="0,char="28)
7:3: \mathopen
7:3: .\nucleus
7:3: ..\mathchar (fam="0,char="28)
\stoptyping

A tracing level of 2 will spit out some information about applied spacing and
penalties between atoms (when set) and level 3 will show the math list before the
first and second pass (a mix of nodes and noads) we well as the result (nodes) plus
return some details about rules, spacing and penalties applied.

\stopsubject

\startsubject[title=Is there more?]

The engine already provides the option to circumvent the side effect of a change
in a parameter acting sort of global: the last value given is also the one that a
second pass starts with. The \type {\frozen} prefix will turn settings into local
ones but that's another (already old) topic. There are many such improvements and
options not mentioned here but you can find them mentioned and explained in older
development stories. A lot has been around for a while but not been applied in
\CONTEXT\ yet.

When \TEX\ was written one important property (likely related to memory
consumption) is that node lists have only forward pointers. That means that the
state of preceding material has to be kept track of: there is no going (or
looking) back. In \LUATEX\ we have double linked lists so in principle we can try
to be more clever but so far I decided not to touch the math machinery in that
way. But who knows what comes next.

\stopsubject

\startsubject[title=Those italics]

Right from the start of \LUATEX\ it became clear that the fact that \TEX\ assumes
the actual width of glyphs to be incremented by the italic correction that then
selectively is removed has been an issue. It made for successive attempts to
improve spacing in \CONTEXT\ by providing pseudo features. But, when we moved
from assembled \UNICODE\ math fonts to \quote {real} ones that became messy: what
trick to apply when and even worse where? In the end it are only a very few
shapes that actually are affected in the sense that when we don't deal with them
it looks bad. It also happens that one of those shapes is the italic \quote {f},
a letter that is used frequently in math. It might even be safe to say that the
simple fact that the math italic f has this excessively wrong width and thereby
pretty large italic correction is the cause of many problems.

In the \LMTX\ approach Mikael and I settled on patching shapes in the so called
font goodie files, aka \type {lfg} files and only a handful of entries needed a
treatment. This makes a good care for removing the traditional font code path
from \LUAMETATEX.

\startbuffer
   \dontleavehmode {\tt\fontclass}:
    \start
        \showglyphs \setupinterlinespace[1.2]
        \dostepwiserecurse{`a}{`z}{1}{$\Uchar#1^1_2$ }
        \dostepwiserecurse{`a}{`z}{1}{$\bi\Uchar#1^1_2$ }
        \par
    \stop
\stopbuffer

\start
    \switchtobodyfont[modern]  \getbuffer\blank
    \switchtobodyfont[cambria] \getbuffer\blank
    \switchtobodyfont[pagella] \getbuffer\blank
    \switchtobodyfont[termes]  \getbuffer\blank
    \switchtobodyfont[bonum]   \getbuffer\blank
\stop

One of the other very sloped symbol is the integral, although most fonts have
them more upright than tex has. Of course there are many variants of these
integrals in a math font. Here we also have some font parameters that we can
tune, which is what we do.

\stopsubject

\startsubject[title=Accents]

Accents are common in languages other than English and it's English that \TEX\
was made for. Although the seven bit variant became eight bit handling accents
never was sophisticated and one of the main reasons is of course that one could
use pre|-|built composed characters. The \OPENTYPE\ format brought proper
anchoring (aka marks) to font formats and when \LUATEX\ deals with text those
kick in. In \OPENTYPE\ math however, anchoring is kind of limited to the top
position only. Because the \TEXGYRE\ fonts are based on traditional \TEX\ fonts,
their accents have not become better suited.

\startbuffer
$ \hat{x} \enspace \widehat{x} \enspace \widehat{xx} \enspace \widehat{xxx}
  \enspace \hat{f} \enspace \widehat{f} $
\stopbuffer

\typebuffer

When looking at examples you need to be aware of the fact hat fonts can have been
adapted in the goodie files. \footnote {Extreme examples can be found for Lucida
Bright where we not only have to fix the extensible parts of horizontal braces
but also have to provide horizontal brackets.} So, for instance bounding boxes
and such can differ from the original. Anyway, the previous code in Cambria looks
as follows.

\startlinecorrection
\scale[height=18mm]{\showglyphs\switchtobodyfont[cambria]\inlinebuffer}
\stoplinecorrection

With Latin Modern we get:

\startlinecorrection
\scale[height=18mm]{\showglyphs\switchtobodyfont[modern]\inlinebuffer}
\stoplinecorrection

And Dejavu comes out as:

\startlinecorrection
\scale[height=18mm]{\showglyphs\switchtobodyfont[dejavu]\inlinebuffer}
\stoplinecorrection

As you can see there are some differences. In for instance Latin Modern the shape
of the hat and smallest wide hat are different and the first wide one has zero
dimensions combined with a negative anchor. When an accented character is
followed by a superscript or prime the italic correction of the base kicks in but
that cannot be enough to not let this small wide hat overflow into the script. We
could compensate for it but then we need to know the dimensions. Of course we can
consult the bounding box but it makes no sense to let heuristics enter the
machinery here while we're in the process generalization. One option is to have
two extra parameters that can be used when the width of the accent comes close to
the width of the base (we then assume that zero accent width means that it has
base width) we add an additional kern. In the end we settled for a (semi automatic)
correction option in the goodie files.

There are actually three categories of extensible accents to consider: those that
resemble the ones used in text (like tildes and hats), those wrapping something
(like braces and bracket but also arrows) and rules (that in traditional \TEX\
indeed are rules). In \CONTEXT\ we have different interfaces for each of these
and in order to have a more extensive control. The text related ones are the
simplest and closest to what the engine supports out of the box but even there we
use tweaked glyphs to get better spacing because (of course) fonts have different
and inconsistent spacing in the boundingbox above and below the real shape. This
is again some tweak that we moved from being {\em automatic} to being {\em under
goodie file control}. But this is all too \CONTEXT\ specific to discuss here in
more detail.

\stopsubject

\startsubject[title=Decision time]

After lots of tests Mikael and I came to the conclusion that we're facing the
following situation. When typesetting math most single characters are italic and
we already knew from the start of the \LUATEX\ project that the italics shapes
are problematic when it comes to typesetting math. But it looks like even some
upright characters can have italic correction: in TexGyreBonum for instance the
bold upright \type {f} has italic correction, probably because it then can
(somehow) kern with a following \type {i}. It anyhow assumes no italic correction
to be applied between these characters.

In the end the mixed math font model model got more and more stressed so one
decision was to simply assume fonts to be used that are either Cambria like
\OPENTYPE, or mostly traditional in metrics, or a hybrid of both. It then made
more sense to change the engine control options that we have into ones that
simply enable certain code paths, independent of the fact if a font is \OPENTYPE\
or not. It then become a bit \quotation {crap in, crap out}, but because we
already tweak fonts in the goodie files it's quite okay. Some fonts have bad
metrics anyway or miss characters and it makes no sense to support abandoned
fonts either. Also, when a traditional font is assembled it one can set up the
engine with different flags and we can deal with it as we wish. In the end it is
all up to the macro package to configure things right, which is what we tried to
do for months when rooting out all the artifacts that fonts bring. \footnote {In
previous versions one could configure this per font but that has been dropped.}

That said, the reason why some (fuzzy) mixed model works out okay (also in
\LUATEX) is that proper \OPENTYPE\ fonts use staircase kerns instead of italic
correction. They also have no ligatures and kerns. We also suspect that not that
much attention is paid to the rendering. It's a bit like these \quotation {How
many f's do you count in this sentence?} tests where people tend to overlook
\type {of}, \type {if} and similar short words. Mathematicians loves \type {f}'s
but probably also overlook the occasionally weird spacing and kerning.

A side effect is that mixing \OPENTYPE\ and traditional fonts is also no longer
assumed which in turn made a few (newly introduced) state variables obsolete. Once
everything is stable (including extensions discussed before) some further cleanup
can happen. Another side effect is that one needs to tell the engine what to apply
and where, like this:

\starttyping
\mathfontcontrol\numexpr \zerocount
   +\overrulemathcontrolcode
   +\underrulemathcontrolcode
   +\fractionrulemathcontrolcode
   +\radicalrulemathcontrolcode
   +\accentskewhalfmathcontrolcode
   +\accentskewapplymathcontrolcode
 % + checkligatureandkernmathcontrolcode
   +\applyverticalitalickernmathcontrolcode
   +\applyordinaryitalickernmathcontrolcode
   +\staircasekernmathcontrolcode
 % +\applycharitalickernmathcontrolcode
 % +\reboxcharitalickernmathcontrolcode
   +\applyboxeditalickernmathcontrolcode
   +\applytextitalickernmathcontrolcode
   +\checktextitalickernmathcontrolcode
 % +\checkspaceitalickernmathcontrolcode
   +\applyscriptitalickernmathcontrolcode
   +\italicshapekernmathcontrolcode
\relax
\stoptyping

There might be more control options (also for tracing purposes) and some of the
symbolic (\CONTEXT) names might change for the better. As usual it will take some
years before all is stable but because most users use the latest greatest version
it will be tested well.

After this was decided and effective I also decided to drop the mapping from
traditional font parameters to the \OPENTYPE\ derives engine ones: we now assume
that the later are set. After all, we already did that in \CONTEXT\ for the virtual
assemblies that we started out with in the beginning of \LUATEX\ and \MKIV.

\stopsubject

\startsubject[title=Dirty tricks]

Once you start playing with edge cases you also start wondering if some otherwise
complex things can be done easier. The next macro brings together a couple of
features discussed in previous sections. It also uses two state variables:
\type {\lastleftclass} and \type {\lastrightclass} that hold the most recent
edge classes.

\startbuffer
\tolerant\permanent\protected\def\NiceHack[#1]#:#2% special argument parsing
  {\begingroup
   \setmathatomrule
     \mathbegincode\mathbincode % context constants
     \allmathstyles
     \mathbegincode\mathbincode
   \normalexpanded
     {\setbox\scratchbox\hpack
        ymove \Umathaxis\Ustyle\mathstyle % an additional box property
        \bgroup
          \framed % a context macro
            [location=middle,#1]
            {$\Ustyle\mathstyle#2$}%
        \egroup}%
   \mathatom
     class 32 % an unused class
     \ifnum\lastleftclass <\zerocount\else leftclass  \lastleftclass\fi
     \ifnum\lastrightclass<\zerocount\else rightclass \lastrightclass\fi
     \bgroup
       \box\scratchbox
     \egroup
   \endgroup}
\stopbuffer

\typebuffer \getbuffer

\startbuffer
\def\MyTest#1%
  {$              x #1                        x $\quad
   $              x \NiceHack[offset=0pt]{#1} x $\quad
   $\displaystyle x #1                        x $\quad
   $\displaystyle x \NiceHack[offset=0pt]{#1} x $}

\scale[scale=2000]{\MyTest{>}}            \blank
\scale[scale=2000]{\MyTest{+}}            \blank
\scale[scale=2000]{\MyTest{!}}            \blank
\scale[scale=2000]{\MyTest{+\frac{1}{2}+}}\blank
\scale[scale=2000]{\MyTest{\frac{1}{2}}}  \blank
\stopbuffer

\typebuffer

Of course this is not code you immediately come up with after reading this text,
also because you need to know a bit of \CONTEXT.

\startlinecorrection
\showmakeup[mathglue]\getbuffer
\stoplinecorrection

\stopsubject

\startsubject[title=Final words]

One can argue that all these new features can make a document look better. But
you only have to look at what Don Knuth produces himself to see that one always
could do a good job with \TEX, although maybe at the cost of some extra spacing
directives. It is the fact that \OPENTYPE\ showed up as we as many more math
fonts, all with their own (sometimes surprising) special effects, that made us
adapt the engine. Of course there are also new possibilities that permit better
and more robust macro support. The \TEX book has a chapter on \quotation {the
fine points of mathematics typesetting} for a reason.

There has never been an excuse to produce a bad looking documents. It is all
about care. For sure there is a category of users who are forced to use \TEX, so
they are excused. There are also those who have no eye for typography and rely on
the macro package, so there we can to some extent blame the authors of those
packages. And there are of course the sloppy users, those who don't enter a
revision loop at all. They could as well use any system that in some way can
handle math. One can also wonder in what way massive remote editing as well as
collaborative working on documents make things better. It probably becomes less
personal. At meetings and platforms \TEX\ users like to bash the alternatives but
in the end they are part of the same landscape and when it comes to math they
dominate. Maybe there is less to brawl about then we like: just do your thing and
try to do it as good as possible. Rely on your eyes and pay attention to the
details, which is possible because the engine provided the means. The previous
text shows a few things to pay attention to.

Once all the basics that have to do with proper dimensions, spacing, penalties
and logic are dealt with, we will move on to the more high level constructs. So,
expect more.

\stopsubject

% \setdefaultmathcodes
% $\blackrule\mathatomskip \mathdigitcode \mathdigitcode\textstyle\blackrule$

\stopchapter

\stopcomponent

% \showframe
%
% \showmakeup[penalty]
%
% \startbuffer
%     \dorecurse {50} {
%         test $\darkblue   a +         #1         + b > 2$
%         test $\darkred    a + b +     #1     + c + d > 2$
%         test $\darkgreen  a + b + c + #1 + d + e + f > 2$
%     }
% \stopbuffer
%
% \setuptolerance[verytolerant,stretch]
%
% \setuplayout[width=11cm]
%
% \starttext
%     \start
%         \mathforwardpenalties  0
%         \mathbackwardpenalties 0
%         \getbuffer
%         \par
%     \stop
%     \page
%     \start
%         \mathforwardpenalties  2 -200 -100
%         \mathbackwardpenalties 2 -100  -50
%         \getbuffer
%         \par
%     \stop
%     \page
%     \start
%         \mathforwardpenalties  2  200 100
%         \mathbackwardpenalties 2  100  50
%         \getbuffer
%         \par
%     \stop
%     \page
% \stoptext

% example:
%
%     $ \left( x + 1 \right )^1_2^^3__4 $
%     \blank
%     $ ( x + 1 )^1_2^^3__4 $
%     \blank
%     $ (^^3__4 x + 1 )^1_2 $

% example:
%
% \registerengineclass[digits][dgs]
%
% \newconstant \mathdigitscode \mathdigitscode \mathclassvalue digits
%
% \protected\def\mathdigits{\mathatom\mathdigitscode}
%
% \copymathspacing \mathdigitscode \mathdigitcode
%
% \setmathspacing \mathdigitscode      \mathdigitscode      \allmathstyles 3mu
% \setmathspacing \mathdigitscode      \mathpunctuationcode \allmathstyles 1mu
% \setmathspacing \mathpunctuationcode \mathdigitscode      \allmathstyles 1mu
%
% \startTEXpage[offset=1dk,width=20dk]
%     \showboxes\showmakeup[math]
%     $
%        x
%        =
%        \mathdigits {123}
%        \mathdigits {456} ,
%        \mathdigits {78}
%        =
%        \mathdigits {123} .
%        \mathdigits {456} ,
%        \mathdigits {78}
%     $
% \stopTEXpage

% \starttext
%     \showmakeup[math]
%     $ x \neq x $ \quad $ x \not x $ \quad $ x \eq\not x $ \quad $ x \not\eq x $\par
%     \pushoverloadmode
%     \let\normalnot\not
%     \permanent\protected\def\not#1{#1\normalnot}
%     \popoverloadmode
%     $ x \neq x $ \quad $ x \not x $ \quad $ x \eq\not x $ \quad $ x \not\eq x $\par
% \stoptext

%     $ \not \eq $\par
%     $ \eq \not $\par % gets collapsed

% example:  a_1=b_1+c_1 (for spacing)