# OpTeX - tips, tricks, howto

This page includes solutions of various tasks when OpTeX is used. Each solution would be small'', it means you can see whole solution at once in your www browser. The constellation of each solution is similar: user description followed by macro code followed by explanation of the macro code. User can copy and paste the macro code to his/her document simply by the mouse.

If there exists any tip from you, OpTeX user, don't hesitate please and send me it. I'll welcome it and save it here (with the author of the solution mentioned).

OPmac tricks can be used too but re-implementation of the code is probably needed because OPmac uses different internal macros than OpTeX. The important OPmac tricks will be re-implemented here soon.

Note that several OPmac tricks are implemented directly into OpTeX:

• \colordef does colors mixing.
• \morecolors reads color names from xcolor package.
• \transformbox applies linear transformations.
• \oval, \circle create colored oval or circle around text.
• \clipinoval, \clipincircle declare clipping path for images.
• \hisyntax performs syntax highlighting for C, Python, TeX, html and XML languages.
• \draft and \showlabels can be used for printing labels in draft mode.
• Options in key=value dictionaries.
• \lipsum prints the text Lorem ipsum dolor sit.
• \mathbox creates a \hbox in math list with size-context.
• \numberedpar helps with creating numbered Theorems, Definitions etc.
• \inspic syntax allows alternative \inspic{filename.ext} without space separator.
• \inkinspic inludes pictures with labels generated by Inkscape.
• \crlp is implemented for tables.
• Tables to given width.
• Variations of paragraphs with p declarator.
• Vertical centered text in more rows in tables.
• Eqbox: equal width of boxes across whole document.
• \slides style allows to create presentations.
• \usebib reads directly .bib databases without any external program.
• Index allows hyperlinked pages and alternative page lists.

Fonts

## Micro-typography: font expanding, hanging punctuation

LuaTeX supports "microtypography features": slight font expanding when the paragraph line is stretched and hanging punctuation. You can enable this using primitives \pdffontexpand+\adjustspacing and \rpcode,\lpcode+\protrudechars. Example:

\pdffontexpand\_tenrm 30 20 5   % font expanding configured for \_tenrm

\chardef\hyph=\hyphenchar\_tenrm
\rpcode\_tenrm\hyph=310  \rpcode\_tenrm\.=200 \rpcode\_tenrm\,=200
\lpcode\_tenrm\“=400 \rpcode\_tenrm\”=400  % hanging punctuation configured for \_tenrm
\protrudechars=2                             % hanging puctuation activated


You can start from this example and modify it for your needs.

Note that the example above has its limitations, see this comment.

You can use mte.opm package where the data for microtypographic extensions are already prepared and ready for use.

(0058) -- P. O. 2020-04-16

## Text size changed to the desired width

We prepare the macro \scaleto size {text} which prints “text” in the current font, but rescaled so that the width of “text” is the given size.

\def\scaleto#1#{\def\tmp{#1}\scaletoA}
\def\scaletoA#1{\setbox0=\hbox{{#1}}%
\edef\tmp{\expr{\bp{\tmp}/\bp{\wd0}}}%
\transformbox{\pdfscale{\tmp}{\tmp}}{#1}}

\scaleto 7cm {text} % the "text" has 7cm width


The desired dimension is saved to the \tmp macro and \scaletoA does the real work. It saves the text to \hbox 0 and calculate the coefficient of scaling as \tmp/\wd0. This coefficient is saved to \tmp again and used in the \transformbox{\pdfscale}{} macro.

You can compare the solution of similar task in OPmac trick 027. You can see that we have more powerful tools for calculation than in OPmac: \bp converts the dimension to Adobe points and \expr calculates the ratio.

If you are using a font family with optical sizes, then we need to scale to right optical size. Then we can use \scaletof size {text}.

\def\scaletof#1#{\def\tmp{#1}\scaletofA}
\def\scaletofA#1{\setbox0=\hbox{{#1}}%
\edef\tmpa{\expr{\bp{\tmp}/\bp{\wd0}}}%
\scaletoA{\setfontsize{mag\tmpa}\currvar#1}}


The \setfontsize{mag factor} is calculated, where the factor is the scale ratio calculated and saved in the \tmpa. When the font is changed then the result is not exactly the desired width, because new font have a little different proportions. So previous \scaletoA is called again to reach the exact accuracy.

(0011) -- P. O. 2020-05-06

## More than 1300 icons from Awesome5 fonts

The TeX distribitions include OTF fonts FontAwesome5Free-Solid-900, FontAwesome5Brands-Regular-400 and FontAwesome5Free-Regular-400 with icons (dingbats) like keyboard, house, faces etc. See the documentation from fontawesome5 LaTeX package where all these dingbats are listed. We want to use them. The following macro code does it:

\initunifonts  % we need to load OTF fonts
\font\tenfafree      =[FontAwesome5Free-Solid-900]
\font\tenfabran      =[FontAwesome5Brands-Regular-400]
\font\tenfafreeregul =[FontAwesome5Free-Regular-400]
\protected\def\faregul#1{{\let\tenfafree=\tenfafreeregul #1}}
\protected\def\fafree{\tenfafree\resizethefont}
\protected\def\fabran{\tenfabran\resizethefont}
\def\__fontawesome_def_icon:nnnnn#1#2#3#4#5{%
\ifx^#1^\else
\getfourtokens\tmp#3\relax
\protected\edef#1{{\csname fa\tmp\endcsname \char#5}}%
\fi
}
\def\getfourtokens#1#2#3#4#5#6\relax{\def#1{#2#3#4#5}}
\input fontawesome5-mapping.def
\__fontawesome_def_icon:nnnnn{\faWifi}{wifi}{free3}{213}{"F1EB}


Now, you can use all control sequences listed in the fontawesome5 documentation. For example \faHouseUser, \faAngry, \faApple, etc. The alternative syntax like \faIcon{Angry} is not supported. A few icons are in its "regular" variants. They are listed as \faAngry[regular] in the fontawesone5 documentation. These icons are available by the \faregul prefix in uour macro, i.e. \faregul\faAngry.

Notice to the implementation. The three fonts with dingbats are loaded as \tenfafree, \tenfabran and \tenfafreeregul. The third one includes the "regular" variants. The macros \fafree amd \fabran select these fonts at current size used by Font Selection System from OpTeX.

We need to read the mapping from names to the font codes. It is saved in the fontawesome5-mapping.def. The set of \__fontawesome_def macros are used here. We define such macro in order to read this mapping and then we do \input fontawesome5-mapping.def.

Of course, if Marcel Krüger make changes in the fontawesome5-mapping.def file syntax, we must to redeclare our macros. I hope that this syntax is more or less stable.

You can compare the complexity of macros in the LaTeX implemenation with these 16 lines of plain TeX macros. Only TeX primitives are used here (and two OpTeX macros \initunifonts and \resizethefont). This is one of reasons why I like plain TeX.

(0012) -- P. O. 2020-05-08

## Emoji characters used directly in text

We want to write:

\fontfam[lm]

Is it OK? 👍 Yes.


and the current font is used for the text, but emoji font is used for the emoticon. The following code implements this.

\initunifonts
\rm


The "fallback" font feature is used and set globally for all fonts. This feature loads and uses fonts from given font list (declared by the luaotfload.add_fallback Lua function) if the character is missing in the current font. The falback font is loaded at the same size as the current font.

Note: we need not to load emoji package.

(0062) -- P. O. 2021-04-25

## Fonts with non-Unicode encoding

OpTeX does not prefer such fonts but sometimes there are a reason to use them. For example the font slabikar (with hand written letters continuously binded one with other) was created in 1997 in pre-Unicode epoch. We can use such font if the following file is prepared:

\def\charenc #1 #2 {\catcode#1=13 \bgroup \lccode\~=#1 \lowercase{\egroup \chardef~=#2}}

\def\csfenc{%
\charenc á 225 % a-acute
\charenc Á 193 % A-acute
\charenc ä 228 % a-diaeresis
\charenc Ä 196 % A-diaeresis
\charenc č 232 % c-caron
\charenc Č 200 % C-caron
...
etc.
}


See csf-enc.tex for full version of such file. Then you can use it:

\input csf-enc
\pdfmapline{=slabikar slabikar ≤slabikar.pfb}
\font\s=slabikar at20pt

{\s\csfenc Tady píšu fontem slabikář česky.}
\bye


The letters are set as active but they can be used in \edef or \write without expanding them because their meanig is not macro but chardef constant.

We don't want to fall to the encodings hell. So, such encoding file is here only as an example. It can be a part of an old non-Unicode encoded fonts, but such files will be never the part of OpTeX package. The hyphenation patterns cannot work properly when such fonts are used.

(0018) -- P. O. 2020-05-25

## Marking parts of text

We can use standard marking by {\it italic}, {\bf bold}, {\bi bold italic} or {\em emphasized text}. If you want to do something more special, then the following OPmac macros work without any change in OpTeX:

• \ul{text} for underlining text (splittable to more lines) like in the soul LaTeX package, see OPmac trick 0063
• Overlining can be done by the same macro when \uline macro is redefined.
• Leterspacing referred in OPmac trick 0063 need not be done by this macro because we have more robust letterspacing implemented as font feature, se section 2.13.10 in the OpTeX documentation.
• \hyphenprocess from OPmac trick 0065 can be used to implement hyphenation feature to the \ul macro.
• Background colored (splitabble to more lines) text by OPmac trick 0085 can be printed. Use \coltext\ColorA\ColorB{text}.
• See also the following trick (OpTeX trick 0064) for information about achieving font effects with LuaTeX attributes.

(0044) -- P. O. 2021-02-08

## Font effects using attributes

You can set printing outlines of characters directly and simply by

\pdfliteral{1 Tr .3 w}TEXT\pdfliteral{0 Tr 0 w}


but it cannot span more pages and it does not respect TeX grouping. There is another possibility shown in this trick.

Setting of color is based on attributes in OpTeX v1.04+. We can use similar mechanism to achieve other font/rule effects, with different PDF graphics operators. For example we can achieve font outlines this way:

Normal, {\outlinefont{.15}outlined}, {\outlinefont{.3}more outlined}.


which produces:

To achieve these effects we must first introduce a Lua mechanism:

\directlua{
local node_id  = node.id
local glyph_id = node_id("glyph")
local rule_id  = node_id("rule")
local glue_id  = node_id("glue")
local hlist_id = node_id("hlist")
local vlist_id = node_id("vlist")
local disc_id  = node_id("disc")

local direct       = node.direct
local todirect     = direct.todirect
local tonode       = direct.tonode
local getfield     = direct.getfield
local setfield     = direct.setfield
local getlist      = direct.getlist
local setlist      = direct.setlist
local getattribute = direct.get_attribute
local insertbefore = direct.insert_before
local copy         = direct.copy
local traverse     = direct.traverse

local token_getmacro = token.get_macro

local pdfliteral = optex.directpdfliteral

function register_pre_shipout_injector(name, attribute_name, namespace, default)
local current
local default = default or 0
local attribute = assert(registernumber(attribute_name))
for n, id, subtype in traverse(head) do
if id == hlist_id or id == vlist_id then
% nested list, just recurse
setlist(n, injector(getlist(n)))
elseif id == disc_id then
% only replace part is interesting at this point
local replace = getfield(n, "replace")
if replace then
setfield(n, "replace", injector(replace))
end
elseif id == glyph_id or id == rule_id
or (id == glue_id and getleader(n)) then
local new = getattribute(n, attribute) or 0
if new ~= current then
local literal = token_getmacro(namespace..new)
current = new
end
end
end
end

current = default
end, name)
end
}


Then we can define the font effects as we please:

\newattribute \fntoutattr
\newcount \fntoutcnt \fntoutcnt=1 % allocations start at 1
\def\outlinefont#1{\fntoutattr=
\ifcsname fntout::#1\endcsname \lastnamedcs\relax \else
\fntoutcnt
\sxdef{fntout::#1}{\the\fntoutcnt}%
\sxdef{fntout:\the\fntoutcnt}{#1 w 1 Tr}%
\incr \fntoutcnt
\fi
}
\sdef{fntout:0}{0 w 0 Tr}
\directlua{
register_pre_shipout_injector("fntout", "fntoutattr", "fntout:")
}


The core idea is the same as with colors (see the OpTeX documentation) – we use attributes to mark typesetting material and just before shipout we postprocess, injecting PDF literals where necessary. But unlike with colors, which are specialized (e.g. stroke vs non-stroke), we define a generic Lua function generator that can inject any PDF literals we want.

Each distinct font outline width maps to a single number that is used as the attribute value. Similarly, the inverse mapping maps the attribute values to PDF literals. Special attribute value of “0” designates the default effect – this is e.g. what returns the graphics state to normal after TeX group ends. Other effects are allocated starting at number 1.

The TeX user interface consists of \outlinefont, they essentially just set the attribute to the right attribute value (allocating new one if necessary).

We also add to \_resetcolor which is what the default OpTeX output routine uses to achieve clean slate for headers / footers.

Name of the effect, the attribute name and the macro prefix for PDF literals are passed to the Lua side in order to generate the associated PDF literal injector.

The literals for font outlines activate the outline style (“1 Tr”) and set the outline width with “⟨number⟩ w”.

If you want to use other default value of an effect, you need to change the mapping of attribute value 0 and also need to force inject a PDF literal on the start of each page (this is normally not done, because it would be wasteful). The first can be easily done by using a couple of \sdefs. The second can be achieved by passing an invalid attribute value (e.g. -1) as the initial (which forces the initial injection no matter what).

Sadly outline fonts don't work with colors.

(0064) -- M. Vlasák 2021-07-14

Lists

## List items multi-numbered at arbitrary level

We declare the \style m (multi-numbered) of the list. The items are numbered similarly as sections, i.e. 1., 2. 2.1, 2.2, 2.2.1, 2.2.2, 2.2.3 etc. We create macro \keepstyle which propagates the current style to all sub-levels. So:

\begitems \style m \keepstyle  % prints:
* First                        % 1. First
* Second                       % 2. Second
\begitems
* Second-A                   %   2.1 Second-A
* Second-B                   %   2.2 Second-B
\enditems
* Third                        % 3. Third
\enditems


The implementation:

\def\iprefix#1{}
\sdef{_item:m}{\iprefix.\the\itemnum. }
\def\keepstyle{\_defaultitem=\_printitem}


The \iprefix is saved at the start of \begitems (in the \_setlistskip macro) and it is used in deeper levels of lists. There can be arbitrary nesting levels.

(0047) -- P. O. 2021-02-17

## Depth of the list given by number of *

We daclere the macro \easylist which enables to give the list level simply by the number of * used as a prefix. We need not to specify nesting \begitems...\enditems. So, if we use the \style m and \keepstyle from previous OpTeX trick 0047, then the following input:

\begitems \easylist \style m \keepstyle
* First proposition.
** Interesting comment.
*** A note on the comment.
*** Another note.
**** By the way...
***** This is a subsub...-proposition.
* Let’s start something new...
\enditems


gives exactly the same output as documented at the page 2 of the LaTeX package easylist (see texdoc easylist).

The implementation:

\def\countlist{\tmpnum=1 \countlistA}
\def\countlistA{\futurelet\next\countlistB}
\def\countlistB{\ifx\next\aast \ea\countlistC\else \ea\countlistD \fi}
\def\countlistC#1{\incr\tmpnum \countlistA}
\def\countlistD{%
\ifnum\tmpnum>\ilevel \fornum \ilevel..\tmpnum-1 \do{\_begitems\easylist}\else
\ifnum\tmpnum<\ilevel \fornum \tmpnum..\ilevel-1 \do{\_enditems}\fi\fi
\_startitem}
\def\enditems{\fornum 1..\ilevel \do{\_enditems}}


Another application. We set given style for each used level:

\everylist={\ifcase\ilevel\or \style X \or \style x \else \style - \fi}
\begitems \easylist
* Main one
* Main two
** sub-item
*** sub-sub-item
\enditems


(0048) -- P. O. 2021-02-17

Verbatim

## Code blocks like in Markdown

Code blocks are frequently used in Markdown. They are displayed as an auto-sized, shaded, rounded-corner box around a word. We can redefine the \_printinverbatim macro in order to do it:

\def\_printinverbatim#1{%
\ovalparams{\lwidth=0pt \lcolor=\LightGrey \fcolor=\LightGrey}%
\inoval{\setbox0=\hbox{#1}\ht0=1.35ex \dp0=.15ex \box0}}
\verbchar

This text is printed as a code& {block}.


The \inoval macro is used for shaded rounded-corner box. The \vphantom{ly} gives a strut inside the text. The height and depth of the text is set to the constant values in order all ovals have the same height plus depth.

(0009) -- P. O. 2020-05-02

## Inline verbatim in macro parameters

We know that inline verbatim in maro parameters does not work:

\def\p#1{print: "#1"}
\verbchar

\p{test: \relax x~& fin.} % error (misplaced align tab)


The reason of this error: the parameter text is tokenized when the parameter is read. The first  is run after this parameter is completely read. It changes catcodes but nothing is read directly from file at this time, so such catcode setting is ineffective.

We know that the usage of \code{...} is 100% working, but we must escape each TeX sensitive character: \p{test: \code{\\relax x\~\&} fin.}.

There is a method for "protecting" the macro parameter without escaping the TeX sensitive characters. Use \verbi as a prefix before usage of the macro:

\def\verbi#1{\def\tmp{#1}\begingroup \verbC \verbG}
\def\verbii#1#2#{\def\tmp{#1#2}\verbiiA}
\def\verbC{\catcode\\=12 \catcode\#=12 \catcode\%=12 }
\def\verbG#1{\endgroup \tmp{\scantextokens{#1}}}

\verbchar
\def\p#1{print: "#1"}

\verbi\p{aha \relax!@#$%^& uff~ mluff} \verbii\table{cc}{ a & \table \cr b & & }  The \verbii can be used before \table macro or similar macros where the second parameter is important. Implementaton note: We read the parameter first with category codes set by \verbC. The \endgroup in the \verbG restores the original category codes and the macro parameter is represented by \scantextokens{#1}. When this parameter is processed then the current category codes are used again. The \verbii macro read parameters like \verbii\table pxto10cm{cc}{...}. This is the reason of the existence of the \verbiiA auxiliary macro. This solution doesn't work in special cases when there are unpaired braces {} in the verbatim parameter and with macros where the scanned parameter is pre-processed. Only \code{...} is 100% working. Compare the complexity of the cprotect.sty LaTeX package with this 5-line solution. (0017) -- P. O. 2020-05-22 ## Algorithms printed as pseudo-codes The LaTeX package bundle algorithms enables to create algorithms formatted by controlled way (pseudo-codes). We create here something similar, but writing the sources is much more confortable than in LaTeX because the source is more similar to the printed result and without useless control sequences. Our pseudo-code is written between \begtt\algol and \endtt as usual verbatim text. The key-words mentioned at pages 1--8 in the algorithms LaTeX documentation are written directly in our source code and they are printed in bold font automatically. If you want to print another word in bold use a pair of !...!, i.e. write !word!. Texts between dollars$...$are interpreted in math mode. All input characters between$...$are non-verbatim, i.e. the math mode is interpreted as usual. Other text (outside math mode) is printed verbatim but in Roman font. The example shown at pages 9--10 of algorithms documentation can be prepared by: \begtt \algol Require:$n ≥ 0$Ensure:$y = x^ny ← 1X ← xN ← n$while$N ≠ 0$do if$N$is even then$X_{\rm new} ← X × XN ← N/2$else {$N$is odd}$y ← y × XN ← N − 1$end if end while \endtt  Note that the brackets {...} in our example are interpreted in normal TeX way in math mode:$X_{\rm new}$but they are printed verbatim outside math mode: else {$N$is odd}. You can use symbols like ←, they makes your source code more readable. Or you can use common math control sequences in math mode, \leftarrow in this case. The implementation of the \algol macro is based on hi-syntax macros of OpTeX: \newtoks \_hisyntaxalg \_hisyntaxalg = { \_hicolor K \bf % Keywords \foreach {Require:}{Ensure:}{Input:} {while}{do}{if}{then}{else}{end}{function}{return}{print} {for}{all}{range}{continue}{repeat}{until}{loop} {not}{and}{or}{xor}{true}{false} \do {\replthis{\n#1\n}{\z K{#1}}} } \def\algolmath#1${\catcodetable\_optexcatcodes \scantextokens{#1}$} \bgroup \lccode~=! \lowercase{\egroup \def\algolbf#1~}{{\bf#1}} \def\algol{\catcode$=3
\everymath={\algolmath}%
\def\_ttfont{\rm}%
\hisyntax{ALG}%
}


You can use \var{variable_name} inside the math mode. The variable_name is printed in italics.

You can add \replthis{:=}{\leftarrow} to the \_hisyntaxalg declaration if you want to write more legible $y := 1$ instead of $y \leftarrow 1$ in your source code. (We assume that you don't write the character ← directly due to a limitation of your keyboard or your text editor.) Or you can try to colorize your pseudo-code...

Another tip: You can change the indentation of printed result by adding

   \def\_indent{\_quitvmode \def\_dsp{ }\_spacefactor=2000\xspaceskip=.7em }


to the \_hisyntax declaration. Each indentation space in the source will have given \xspaceskip width in the output.

(0078) -- P. O. 2022-04-24

## Verbatim lines referenced in text

We implement possibility to refer lines printed by \begtt...\endtt if these lines are numbered by \ttline>=0. User needs to select a character unused in the verbatim text (the § in the following example) and use \ttlineref this-character in the header after \begtt and the same character can be used in the verbatim text followed by [label]. Of course, you can use more such labels in single verbatim block. When the verbatim environment is closed then the \lref[label] expands to the the corresponding line number where the [label] was used. For example:

\ttline=0
\begtt \ttlineref §
first line
second special line §[spec]
third line
\endtt

Note that the line \lref[spec] is very interesting.


The string §[spec] in this example is not printed in the verbatim environment, it saves only the label [spec] for later use. The \lref[spec] expands to 2 in our example.

The following code implements this feature but only backward references (for sake of simplicity).

\def\ttlineref#1{\adef#1[##1]{\setlref{##1}}}
\protected\def\setlref#1{\sxdef{ttlin:#1}{\the\ttline}}
\def\lref[#1]{\trycs{ttlin:#1}{??}}


You can use the same labels in following verbatim blocks. They are silently rewritten by new line numbers. We suppose that the \lref[label] are used immediately after printed verbatim block and only with labels really declared in previous verbatim block.

You can use this trick with combination of previous OpTeX trick 0078

(0079) -- P. O. 2022-04-25

Graphics

We can use \input tikz and color gradients support from this package. But there is another approach: create a color gradient in an interactive vector editor (Inkscape, for example) and use it. You can create arbitrary rectangle with color gradient in it and save such image to (say) my-gradient.pdf.

Then you can draw a rule with 1pt thickness of this gradient by

\hbox{\picwidth=\hsize \picheight=1pt \inspic{my-gradient.pdf}}


If you want to use gradients to another graphic objects, then it may be more complicated. For example gradiented oval boundary with text in it:

\newdimen\ovalw  \newdimen\ovalh
\ovalw=8cm \ovalh=15cm

\raise5mm\hbox{\kern1mm
\inoval[\roundness=4mm \fcolor=\White \lcolor=\White]
{\raise\dimexpr\ovalh-1cm\hbox to\dimexpr\ovalw-1cm{}}}}}

\raise\dimexpr\ovalh-1cm\vtop{\hsize=\dimexpr\ovalw-1cm\noindent #1}}}



The \clipinoval is used first with my-gradient.pdf. Then a slightly smaller white oval is drawn over it. Only the boundary remains visible. Finally, the text is printed in it.

(0024) -- P. O. 2020-06-05

## Curved arrows

We prepare the macro

\arrowcc x0 y0 {cx0 cy0 cx1 cy1} x1 y1 (dx1 dy1) {Text}


which draws the curve from x0 y0 to x1 y1 ended by arrow spike. The part {cx0 cy0 cx1 cy1} can be empty, i. e. {}. The line is drawn in such case. The numbers {cx0 cy0 cx1 cy1} give the control points of a Bézier curve. At the end of the arrow is printed the "Text" shifted by dx1 dy1. The numbers cx0 cy0 cx1 cy1 x1 y1 are relative to the origin x0 y0. This origin is relative to the current typesetting point. All numbers are in bp units by default. The macro \arrowccparams can include the additional settings (color, line width, etc.). The macro \arrowccspike includes the drawing of the arrow spike and you can redefine it.

\vglue5cm
\def\arrowccparams{1 0 0 rg 1 0 0 RG}  % red color is initialized

Pokus \arrowcc 0 10 {-30 20 -30 50} 20 50 (3 -3) {Text 1}
dále \arrowcc 0 -3 {} 40 -30 (3 -3) {Text 2}
a ještě \arrowcc 0 2 {10 20 20 30} 40 40 (3 -2) {Text 3}.


creates:

The implementation is exacltly the same as in OPmac trick 0062 but the calculation of direction of the spikes is re-implemented using more simple and straightforward lua code.

\def\arrowccspike{2 0 m -5 2 l -5 -2 l h f}
\def\arrowcc #1 #2 #3 #4 #5 (#6)#7{%
\if^#3^\preparerotdata(0 0) (#4 #5)\else \preparedirection #3 (#4 #5)\fi
% x0 y0 {cx1 cy1 cx2 cy2} x1 y1 (dx1 dy1) {Text}
\pdfsave\rlap{\pdfliteral{%
.7 w \arrowccparams\space 1 0 0 1 #1 #2 cm 0 0 m
\if ^#3^#4 #5 l \else #3 #4 #5 c \fi S
1 0 0 1 #4 #5 cm  q \rotdata\space 0 0 cm \arrowccspike\space Q}%
\if^#7^\else\pdfliteral{1 0 0 1 #6 cm}\hbox{#7}\fi}\pdfrestore
}
\def\preparedirection #1 #2 #3 #4 {\preparerotdata(#3 #4) }
\def\arrowccparams{}

\def\preparerotdata (#1 #2) (#3 #4){\edef\rotdata{\rotcm (#1 #2) (#3 #4)}}
\def\rotcm (#1 #2) (#3 #4){\directlua{%
local x=(#3)-(#1)
local y=(#4)-(#2)
local norm = math.sqrt(x*x+y*y)
if norm==0 then tex.print('1 0 0 1')
else tex.print(string.format('\_pcent.3f \_pcent.3f \_pcent.3f \_pcent.3f',%
x/norm, y/norm, -y/norm, x/norm))
end
}}


The macro \rotcm takes vector (#3,#4)-(#1,#2) and prepares cm matrix data for rotation in the direction of given vector. The data is stored in \rotdata macro using \preparerotdata (for lines) or \preparedirection (for Bézier curves). Then \rotdata is used inside \pdfliteral parameter.

(0037) -- P. O. 2021-02-05

## Text around a circle

We create a macro \circletext {radius}{angle}{TEXT}{correction} which prints TEXT around a circle with given radius. First letter of the TEXT starts at given angle. The fourth parameter declares a correction between letter pairs because the standard kerning table is deactivated when printing around circle. The TEXT runs clockwise when the radius is positive (the center of the circle is below the letters). When the radius parameter is negative then TEXT runs anticlockwise and the center of the circle is above the letters. The macro creates a typesetting material with zero dimensions, the center of the circle is at the current typesetting point. For example

\hbox{%
\circletext {1.7cm} {212}  {{$\bullet$} UNIVERSITAS CAROLINA PRAGENSIS {$\bullet$}}
{\spaceskip=.5em \kpcirc TA{-.1}\kpcirc NA{-.05}}
\circletext {-1.7cm} {237} {Facultas MFF}
{\kpcirc Fa{-.1}}
}


The fourth parameter correction can include the declaration of word space (using \spaceskip=...) and the space corrections between declared pairs of letters using \kpcirc AB{num}: \kern num (in em units) is inserted between each pair of letters AB. Note that the example includes a "composed object" – $\bullet$. Such object must be enclosed by braces.

Letterspacing can be set by \def\circletextS{\kern value}. No letterspacing is set by default.

The \circletext macro can be defined by

\def\circletext#1#2#3#4{\hbox\bgroup
\edef\tmpc{\expr{-57.295779/\bp{#1}}}% -(Pi/180)/R
\setbox0=\hbox{\ifdim#1<0pt X\fi}% lap letters by X height if R<0
\edef\tmpa{\expr{\ifdim#1<0pt \else-\fi90+#2}}%
\def\tmpb{{}#3}\replstring\tmpb{ }{{ }}#4% spaces => {spaces}
\pdfsave \pdfrotate{\tmpa}%
\expandafter\circletextA\tmpb\relax
}
\def\circletextA#1{\ifx#1\relax\pdfrestore\egroup\ignorespaces\else
\ifx^#1^\else \setbox0=\hbox{#1\circletextS}%
\ismacro\l{0}\iffalse
\edef\l{\expr{\l+\bp{.5\wd0}}}%
\pdfrotate{\expr{\tmpc*\l}}%
\fi
\edef\l{\bp{.5\wd0}}%
\vbox to0pt{\vss\hbox to0pt{\hss#1\hss}\null}%
\fi
\expandafter\circletextA\fi
}
\def\kpcirc#1#2#3{\replstring\tmpb{#1#2}{#1{\kern#3em}#2}}
\def\circletextS{}


The code from OPmac trick 0109 is re-implemeted here. The calculation is done by \expr and \bp macros. The \l macro means the lenght of typeset text and \tmpc is coefficinet which converts such length to the angular measure in degrees.

(0038) -- P. O. 2021-02-05

## Ignoring pictures when \inspic is processed

Pictures may take more size in the resulting PDF. We may want to disable their loading when a draft of our document is created. Or we may want to sent the source code to a colleague for experimenting, but without picture files. Both cases can be solve by \ignoreinspic macro. When it is used at the beginning of the document then all pictures loaded by \inspic have following features:

• If the given picture file exists then \inspic loads it only in order to get its natural sizes (height and width) but the picture is not printed. The gray rectangle with the same sizes (calculated from \picwidth, \picheight values and from the natural sizes) is printed instead and the name of the picture file is appended. The real picture is not embedded to the PDF file, so the file keeps its small size.
• If the given picture file does not exist then the virtual natural sizes of a non-existent image are taken from \nopicw and \nopicratio macros. The \nopicw gives the natural width and the \nopicratio gives the ratio width/height. The real sizes are calculated from \picwidth, \picheight and the virtual natural sizes (as \inspic normally does it) and a gray rectangle is printed. The text "NONE: file-name" is appended, where the file-name is the non existent picture file name given by the argument of \inspic.

Implementation:

\def\nopicw{5cm}
\def\nopicratio{1.7}

\let\inspicBori=\_inspicB
\def\inspicBnew#1{%
\isfile{#1}\iftrue
\edef\filename{\the\picdir#1}%
\setbox0=\hbox\bgroup\inspicBori{#1}% \egroup is in \inspicBori
\else
\edef\filename{NONE: \the\picdir#1}%
\ifdim\picheight=0pt \picheight=\expr{1/\nopicratio}\picwidth \fi
\ifdim\picwidth=0pt \picwidth=\nopicratio\picheight \fi
\ifdim\picwidth=0pt \picwidth=\nopicw\relax \picheight=\expr{1/\nopicratio}\picwidth \fi
\setbox0=\hbox to\picwidth{\vbox to\picheight{}\hss}%
\fi
{\LightGrey \vrule height\ht0 width\wd0\Black\raise1ex\llap{\filename\ }}\egroup
}
\def\ignoreinspic{\let\_inspicB=\inspicBnew}


The internal \_inspicB macro is re-defined when \ingnoreinspic is used. It loads the image to box0 (using the orginal \inspic macro) and uses only its dimensions. The contents of box0 is thrown away when the group is left. Note, that \inspic starts with \hbox\bgroup, so the final \egroup leaves its group. When the file does not exists then more calculatons are done and box0 is constructed with calculated dimensions.

(0053) -- P. O. 2021-04-04

## Keystrokes using special images

We create a macro \keystroke{text}. Similar macro is provided by keystroke.sty LaTeX package. For example

\keystroke{Q} \keystroke{E} \keystroke{R} \keystroke{T} \keystroke{Y}\par
\keystroke{PgUp} \keystroke{Enter}


gives following result:

The implementation:

\newdimen\keysize \keysize=1.3em
\newbox\keylbox  \newbox\keymbox  \newbox\keyrbox
\setbox\keylbox=\hbox{\picheight=\keysize \inspic{keystroke_left.pdf}}
\setbox\keymbox=\hbox{\picheight=\keysize \inspic{keystroke_middle.pdf}}
\setbox\keyrbox=\hbox{\picheight=\keysize \inspic{keystroke_right.pdf}}

\def\keystroke#1{\setbox0=\hbox{\setfontsize{mag.77}\sans\rm#1}%
\leavevmode \lower.2\keysize \hbox{\copy\keylbox
\tmpdim=\wd\keymbox
\ifdim\wd0>\tmpdim \tmpdim=\wd0 \fi
\ifdim\tmpdim>\wd\keymbox
\pdfsave \pdfscale{\expr{\bp{\tmpdim}/\bp{\wd\keymbox}}}{1}%
\rlap{\copy\keymbox}\pdfrestore
\else \rlap{\copy\keymbox}\fi
\raise.33\keysize \hbox to\tmpdim{\hss\box0\hss}\copy\keyrbox}%
}


There are three images: left side, middle and right side. These images are part of the keystroke.sty LaTeX package. We print the middle image in its natural width W if the text used on keystroke has its width less than W. The text is centered to the W size. If the text width is greater than W then we print the middle image with \pdfscale{tw/W}{1} where tw is the width of the text. It means that the middle image is deformed to its new width in order to include whole text. The left and right images are not deformed.

(0070) -- P. O. 2022-02-24

We define a macro \shadedframe {text paragraph} which creates the text in a shadedframe with the width given by \hsize. For example
\shadedframe {
{\bf Title}:
rweyu fiw wi ewyur uwr rwu wruwr rwu rwur uw qu fiw wi ewyur uwr rwu
wruwr rwu rwur uw q fiw wi ewyur uwr rwu wruwr rwu rwur uw qwr.
}


outputs to

The implementation is based on the macro \frame and measuring boxes and adding boxes with given dimensions.

\newdimen\shadewidth
\vvkern=4pt \hhkern=4pt \shadewidth=4pt \rulewidth=1pt \hsize=4cm % default values
\Grey % frame color
\setbox0=\hbox{\frame{\vbox{\Black \noindent\ignorespaces#1}}}%
\edef\htzo{\the\ht0}\edef\wdzo{\the\wd0}%
\hbox{\vbox{\hbox{\rlap{\Yellow\vrule height\ht0 width\wd0 depth\dp0}\box0}%
}}


This problem is a good material for example how to create the macro with optional key/value paraeters, see section 2.10 in OpTeX manual.

\def\shadedframedefaults{% defaults:
frame-color=\Grey,       % color of frame rules
text-color=\Black,       % color ot text inside the frame
bg-color=\Yellow,        % background color inside the frame
rule-width=1pt,          % width of rules used in the frame
v-margins=4pt,           % vertical space between text and frame
h-margins=4pt,           % horizontal space between text and frame
text-width=4cm,          % width of the text inside the frame
}
\vvkern=\kv{v-margins}\hhkern=\kv{h-margins}%
\rulewidth=\kv{rule-width}\hsize=\kv{text-width}\relax
\kv{frame-color}%
\setbox0=\hbox{\frame{\vbox{\kv{text-color}\noindent\ignorespaces#1}}}%
\edef\htzo{\the\ht0}\edef\wdzo{\the\wd0}%
\hbox{\vbox{\hbox{\rlap{\kv{bg-color}\vrule height\ht0 width\wd0 depth\dp0}\box0}%
\egroup
}


For example,

\shadedframe [bg-color=\Blue, text-color=\White, text-width=6cm] {text}


is now possible.

(0071) -- P. O. 2022-02-28

## Frames with rounded corners

We create the macro \roundframe {Title}{Text} for making colored frames with rounded corners. For example

\roundframe {Title here}
gs sgls fsglfs gfsl fglf gfs rtyr rire wrurey.}


creates:

The frame shown above was created with following parameters settings:

\def\fmtfirst  #1{\kern2pt\noindent\strut\White\bf #1\parstrut\kern1pt}
\def\fmtsecond #1{\kern3pt\noindent\strut\Black\rm #1\parstrut\kern1pt}
\def\betweenfirstsecond {\Yellow\hrule height2pt}
\roundframeparams {\hsize=6cm \leftskip=3mm \rightskip=3mm \corners=3mm
\parindent=0pt \let\titlecolor=\Blue \let\bodycolor=\LightGrey
}


The \fmtfirst declares formating of title part, the \fmtsecond declares formatting of text body part. The macro \betweenfirstsecond is used between title and body. \roundframeparams sets next parameters used localy when the frame is created. The \corners is diameter of rounded corners. The \titlecolor and \bodycolor are background colors of appropriate parts. The macro \bgoval need not be defined. If undefined then there are no additional effects which can be achieved by printing backgroud \inoval. We need it if we want to have \shadow=Y or \lwidth positive.

The implementation looks like this:

\newdimen\corners  \newtoks\roundframeparams
\def\parstrut{\par\kern-\prevdepth\kern\dp\strutbox}
\def\twobox#1#2#3#4{%
\vbox{%
\setbox0=\vbox{\fmtfirst{#2}}%
\hbox{\rlap{#1\vrule height\ht0 depth\dp0 width\wd0}\box0}
\setbox0=\vbox{\fmtsecond{#4}}%
\betweenfirstsecond \nointerlineskip
\hbox{\rlap{#3\vrule height\ht0 depth\dp0 width\wd0}\box0}
}%
}
\def\roundframe#1#2{{%
\the\roundframeparams \roundness=\corners
\setbox0=\twobox\titlecolor{#1}\bodycolor{#2}%
\setbox1=\vbox to\dimexpr\ht0-2\corners{}\wd1=\dimexpr\wd0-2\corners\relax
\hbox{\ifx\bgoval\undefined \else \raise\corners\rlap{\bgoval}\fi
\clipinoval .5\wd0 .5\ht0 \wd0 \ht0 {\box0}}%
}}


Note that we need not tikz:). Only OpTeX macros \clipinoval and \inoval are used. The macro \twobox \color{title}\color{text} prints the colored parts of the frame with sharp corners. Then the macro \clipinoval does rounded corners. If we need additional effects then we print \inoval as a part of \bgoval macro. It is printed at the background and with empty box1.

(0073) -- P. O. 2022-03-03

## Adding ornaments to the background

We create pages decorated by ornaments like shown here. There is a LaTeX package pgfornament which makes an interface between pgf library (which provides huge amount of ornaments) and user. This package is designed only for LaTeX, so we choose appropriate ornament from pages 15--23 from pfgornament documentation and print it via LaTeX. For example:

\documentclass{article}
\usepackage{pgfornament}
\begin{document}
\pagestyle{empty}
\begin{tikzpicture}
\pgfornament[width=2cm]{61} % ornament 61 is choosen
\end{tikzpicture}
\end{document}


Apply pdfcrop output.pdf ornam.pdf in order to create cropped PDF image. This image will be used in our OpTeX document. The advantage is that we need not load whole tikz into our document, only single pdf file. For example, the background with four ornaments in the corners of the page can be declared as follows:

\newbox\ornament

\newdimen\pgdist \pgdist=1mm
\pgbackground={
\setbox0=\hbox to\dimexpr \pdfpagewidth-2\pgdist
{\copy\ornament \hfil \rotbox{-90}{\copy\ornament}}
\moveright\pgdist \vbox to\pdfpageheight{
\kern\pgdist
\vbox to0pt{\copy0 \vss}
\vss
\vbox to0pt{\vss \rotbox{180}{\box0}}
\kern\pgdist
}
}
\footlinedist=50pt


The \pgdist is the distance between ornament border and page border. It is set to 1mm here but warning: common laser printers are not able to print images so close to the edge of the paper.

(0080) -- P. O. 2022-05-05

## Moving OpTeX's colors to TikZ environment

The macros for colors have different concept in OpTeX and in Tikz. In OpTeX, you can define a color macro for example by

\def\myColor{\setcmykcolor 1 0 .5 0}


or you can do color mixing by \colordef. On the other hand, Tikz uses the LaTeX concept where colors are defined as words (no control sequences) by \definecolor{myColor}{rgb}{data} and only rgb is supported by \definecolor.

Suppose, we have all colors prepared by OpTeX's macros and now we want to use them in a TikzPicture. For example:

\load [tikz]

\cmykcolordef\myColor{.5\Red + .7\Yellow}  % preparing colors in OpTeX

\tikzcolorlet {myColor} \myColor  % propagating the same color to TikZ

\tikzpicture [fill=myColor]
\fill (0,0) -- (1,0) -- (1,1) -- cycle;
\endtikzpicture


The example above does color mixing in cmyk by OpTeX macros, create \myColor as cmyk color and then puts this color to TikZ by \tikzcolorlet. No conversions are done, the same color in the same color space is used in TikZ. The color spaces cmyk, rgb and grey are supported.

The \tikzcolorlet macro is implemented here:

\def\tikzcolorlet #1#2{\ea\tikzcolorletA #2{#1}}
\def\tikzcolorletA #1#2{%
\def\next {\tikzcolorletgrey}%
\ifx#1\setcmykcolor \def\next{\tikzcolorletcmyk}\fi
\ifx#1\setrgbcolor  \def\next{\tikzcolorletrgb}\fi
\next #2
}
\def\tikzcolorletcmyk #1 #2 #3 #4 {\tikzcolorletB{cmyk}{#1,#2,#3,#4}}
\def\tikzcolorletrgb  #1 #2 #3    {\tikzcolorletB{rgb}{#1,#2,#3}}
\def\tikzcolorletgrey #1          {\tikzcolorletB{gray}{#1}}
\catcode\@=11
\def\tikzcolorletB #1#2#3{\sdef{\string\color@#3}{\xcolor@{}{}{#1}{#2}}}
\catcode\@=12


TikZ needs to define a macro \\color@colorName as

\xcolor@{}{}{color-space}{comma-separated-data}


and the code above does this job.

(0083) -- P. O. 2022-05-18

Math

## \bbchar from AMS fonts when Unicode math font is used

When \fontfam[] is used and \noloadmath is not declared then a relevant math font from Unicode math fonts is loaded too. The single font includes more math alphabets together: math italics, roman, calligraphic, fractur, greek letters, bbchars etc.

Maybe, your opinion about ideal black board letters (\bbchar's) is influneced by the traditional AMS fonts and it is different than the opinion of font designer of the used Unicode math font (Latin Modern math font is typical example of this case). Then you can return to the AMS \bbchars using the following code after the first \fontfam[] command loads the Unicode math font.

\addto\_normalmath{\_loadmathfamily 5 msbm }
\def\bbchar{\fam5 \_rmvariables}


We need to add \_loadmathfamily 5 to \_normalmath and \_boldmath in order to load 8 bit version of math fonts as family 5 (5 is the first unused math family when Unicode math font is loaded). Then we re-define \bbchar macro as family5 selector and mathcodes of letters must be "normal" (not Unicoded) when this 8bit font is used (this is done by the \_rmvariables macro).

(0001) -- P. O. 2020-04-09

## More comfortable writing of matrices

It is quite strenuous to put the characters & between every item of a matrix. In particular, when we are writing a huge amount of matrices. But we can simplify our writing (and reading of the source text too) using the \replstring macro. We create the \x macro which can be used as a prefix before macros such as \matrix and \pmatrix. If it is used then user can write spaces instead of ampersands.

\def\x#1#2{\def\tmpb{#2}\replstring\tmpb{ }{&}\_ea#1\_ea{\tmpb}}

$$\x\pmatrix{x_1 x_2 x_3\cr 12 11 10} = \left[\x\matrix{12 11 10\cr y_1 y_2 y_3}\right]$$


(0010) -- P. O. 2020-04-09

## Bigger outer parentheses automatically set

Sometimes we need to typeset something like f(b+((c+d)(e+f))\cdot g) and we want to set outer parentheses bigger than the inner ones because this is a traditional typographical rule. We can write $f\Bigl(b+\bigl((c+d)(e+f)\bigr)\cdot g\Bigl)$ in our TeX source, but this makes the source less clear. The macro \biglr defined here is able to do such a task automatically. You can write:

$\biglr f(b+((c+d)(e+f))\cdot g) \biglr$


All material between the \biglr pair is scanned by TeX and the appropriate \bigl, \bigr, \Bigl etc. are added before parentheses () automatically.

\def\biglr#1\biglr{%
\def\biglrL{}\tmpnum=0 \def\biglrM{0}%
\def\tmpb{#1}\replstring\tmpb{(}{\biglrC(}\replstring\tmpb{)}{\biglrC)}%
\ea\biglrA\tmpb\biglrC.%
}
\ifx.#2\tmpnum=\biglrM\relax \biglrL
\ea \biglrA\fi}
\def\biglrD{\ifcase\tmpnum \or\ea\bigl\or \ea\Bigl\or \ea\biggl \else \ea\Biggl\fi}
\def\biglrE{\ifcase\tmpnum \or\ea\bigr\or \ea\Bigr\or \ea\biggr \else \ea\Biggr\fi}


Note that the \biglr scanner is active only at outer level of braces {}. And it is not usable when you are using fractions or other big objects inside parentheses in display style. Use \left, \right primitives in such situations.

(0026) -- P. O. 2020-06-30

## Text fonts in math mode

When you write 13 or $13$ then the digits are (typically) rendered from different fonts: from text font in first case and from math font in second one. Sometimes you want to use only text fonts in both cases. Suppose that you have a text font without visually compatible math font. Then you may want to use a-z, A-Z, 0-9 and some other characters from text font in math mode instead from math font. The following trick does this (compare this with the mathastext.sty package used in LaTeX).

We assume that the Unicode math font is loaded already and now, we want to typeset characters mentioned above from text font in math mode. Try this:

\loadmath{texgyretermes-math} % Math font is loaded: texgyretermes-math, just for testing
\fontfam[Heros]               % Text font is loaded: texgyreheros, just for testing

% Test:
Heros in text, 13, but $Termes-math, 13$. It is visually incompatible.

\_def\_xsetmathfamily#1 #2 #3{\_resizefont{#2}#3\_setmathfamily #1 #3}

\_xsetmathfamily    5 rm \_tenrm
\_xsetmathfamily    6 it \_tenit
}%
\_xsetmathfamily    5 bf \_tenbf
\_xsetmathfamily    6 bi \_tenbi
}
\def\_rmdigits    {\_umathrange{0-9}75\_digitrmO}
\def\_rmvariables {\_umathrange{A-Z}75\_ncharrmA \_umathrange{a-z}75\_ncharrma}
\def\_itdigits    {\_umathrange{0-9}76\_digitrmO}
\def\_itvariables {\_umathrange{A-Z}76\_ncharrmA \_umathrange{a-z}76\_ncharrma}

% Default settings:
\_normalmath              % reloads math fonts incuding families 5, 6.
\_rmdigits \_itvariables  % Upright digits, slanted variables

\_def\textcharsinmath #1#2 {\_ifx\_end#2\_else
\_Umathcode #1=#2 5 #1\_relax \_ea\textcharsinmath\_fi}

% Characters !?*,.:;+-=()[]/<>| are printed from math family 5, i.e. normal text font
\textcharsinmath !5 ?5 *2 ,6 .0 :6 ;6 +2 −2 =3 (4 )5 [4 ]5 /0 <3 >3 |0 .\end
\Umathcode - = 2 5 "2212   % Minus in math mode created by the hyphen character
\Umathcode \{ = 4 5 \{    % \{ and \} must have mathcode from fam 5
\Umathcode \} = 5 5 \}
\Udelcode  \{ = 1 \{      % and delcode from fam 1 (math font)
\Udelcode  \} = 1 \}
\edef\{{\csstring\{}  \edef\}{\csstring\}}

% Test:
Heros in text and in math: $Heros-math: 13, M = -(3!) + y_5$.


The code above reloads the same Unicode math font but moreover, it loads the currently used \rm and \it text fonts as math family 5 and 6. The digits are rendered from family 5 and variables from family 6 instead of from the math fonts. The characters specified by \textcharsinmath, i.e. ! ? * , . : + - = ( ) [ ] < > | \{ and \}, are printed from family 5 too. Other math symbols are printed from original Unicode math font.

If you have loaded a special text font by \font primitive, i.e. \font\foo=something, then you can set this font as family 5 by

\_addto\_normalmath{%
\_setmathfamily    5 \foo
}


Note that \_setmathfamily (no \_xsetmathfamily) is used with only two parameters: family number and the font switch.

(0027) -- P. O. 2020-07-09

## Equation marks in atypical cases

We want to put equation marks \eqmark in more lines in display mode when we are using macros not designed for such case. For example in the lines of \case macro:

$$f(x) = \cases{0 & for x<0\toright\eqmark \cr 1 & otherwise\toright\eqmark }$$


This puts the equation marks to the right margin in each line generated by the \case macro. The \toright\eqmark is used here. Analogically, \toleft\eqmark puts the equation mark to the left margin. The \toright, \toleft macrs are based on the OpTeX trick 0020 where the \setpos and \posx macros are defined.

\newcount\tomarginno
\def\toright#1{\_incr\tomarginno {\setpos[tr:\the\tomarginno]%
\rlap{\kern-\posx[tr:\the\tomarginno]\kern\hoffset\kern\hsize\llap{#1}}}}
\def\toleft#1{\_incr\tomarginno {\setpos[tr:\the\tomarginno]%
\rlap{\kern-\posx[tr:\the\tomarginno]\kern\hoffset\rlap{#1}}}}


The parameter #1 is shifted to the right/left margin in the second run of TeX because we need to know the absolute position of the current point and we shift it to the right margin.

(0028) -- P. O. 2020-07-10

## Equation marks for sub-equations

Sometime we want to declare a bunch of equations with the same numeric equation marks but with different suffixes, for example (1.1a), (1.1b). We create a macro \subeqmark suffix. The \subeqmark a starts the bunch of equations with a new number. Following \subeqmark b, \subeqmark c etc. uses the same equation number, they differ only by given suffixes. For example

\eqalignno{ x + 2y + 3z &= 600 & \subeqmark a \cr 12x + y - 3z &= 7 & \subeqmark b[label] \cr 4x - y + 5z &= -5 & \subeqmark c \cr }
See equation~\ref[label].
$$a^2 + b^2 = c^2 \eqno \eqmark$$


prints the system of equations with numbers (1a), (1b), (1c) and the (1b) is referenced in the text. The next Pythagorean theorem has number (2).

The implementation is simple:

\def \_thednum    {(\the\_dnum\dnumpost)}
\def\dnumpost{}
\def\subeqmark#1{\def\dnumpost{#1}\ifx a#1\else \decr\_dnum\fi \eqmark}


(0074) -- P. O. 2022-03-08

Unicode math font should include all math characters needed in the document. But it is not generally true. Try to load a Unicode math font using \loadmath{[math-font]} followed by \input print-unimath.opm and you can see empty slots. They are unsupported by loaded math font.

Maybe, another Unicode math font supports another slots. You can combine more than one math font in single document. For example, you have loaded Garamond-Math font and you have found that \triangleq isn't supported. Then you can load additional Unicode math font by \addUmathfont and you can re-declare \triangleq in order this additional font is used for such character. Example:

\fontfam [EBGaramond]  % Garamond family including Garamond-Math is loaded
\resetmathchars \stix \triangleq ; % \triangleq will use STIX

Test: $a \triangleq b$. % All is in Garamond only \triangleq in STIX.


If you want to set whole math alphabet to be used from additional font, you can modify \cal, \frak, \bbchar etc. macros:

\addto\cal{\fam\stix} % calligraphic will be used from STIX


The \resetmathchars accepts a list of control sequences mentioned in the table printed by \input print-unimath.opm. Its syntax is

\resetmathchars family-name list-of-math-sequences ;
example:
\resetmathchars \stix \stareq \triangleq \veeeq \wedgeq ;


The implementation of \addUmathfont and \resetmathchars macros were moved to the OpTeX format from version 1.7+. Use them directly. If you have older OpTeX version you can declare:

\def\resetmathchars #1{\chardef\mafam=#1\relax \xargs \resetmathcharX}
\def\resetmathcharX#1{\ea\resetmathcharY
\directlua{tex.print(string.format("\pcent08X", \the#1))}#1}
\def\resetmathcharY#1#2#3#4#5#6#7#8#9{% #9 is given \math-sequence
\Umathchardef #9\numexpr"#3/2\relax \mafam "#4#5#6#7#8
\Umathcode "#4#5#6#7#8=\numexpr"#3/2\relax \mafam "#4#5#6#7#8
}
\def\addUmathfont #1#2#3#4#5#6{% #1: fam (will be set), #2#3: normal font, #4#5: bold font
\ifx\_ncharrmA\undefined \errmessage{basic Unicode math font must be loaded first}\fi
\ifx\relax#4\relax
\else
\fi
\_normalmath
\wterm{MATH-FONT: added #1=\the#1, normal: "#2", \ifx"#4"\else bold: "#4"\fi}
}


The \addUmathfont has six parameters: family-name {normal-font}{features} {bold-font}{features} {factor}. If "bold-font" is empty then faked bold constructed from normal-font is used. The factor is decimal number for size corrections. If it is empty then factor=1. The math families are allocated from 101, 102 etc., i.e. macro programmer can use the numbers 16..99 for direct addressing (note that 0..4 are reserved by TeX, 5..15 are reserved by OpTeX).

The \resetmathchars macro saves the value of family-name to \mafam and applies \resetmathcharX to each math-sequence given in the list. The \resetmathcharX runs \directlua which returns the value of the math-sequence in 8-digits hexa number. First two digits give the family number (unsed), next digit is math-type multiplied by two and the rest is the Unicode slot number. The \resetmathcharY reads these digits and re-sets the given math-sequence by the \Umathchardef primitive and the code by the \Umathcode primitive.

This trick was inspired by a question at StackExchange, but I recommend to use my answer (wipet's answer) in this case becuase combination of basic equal sign from Garamond with other equal signs from STIX doesn't look good in single formula.

(0030) -- P. O. 2020-12-02

## Empty math slots from another math font

The previous OpTeX trick implements a macro for loading more Unicode math fonts and gives a macro \resetmathchars for setting individual math characters as characters from the newly loaded math font. Now we implement a method for doing \resetmathchars for all math characters which are missing in the basic math setting. For example, we use \fontfam[lm] and \input print-unimath.opm shows that doszens slots are empty. We can use \addUmathfont for STIXMath-Regular font where almost all slots are supported. Now, we need to fill all empty slots by characters from STIXMath-Regular:

\fontfam[lm]

% fills empty slots from \stix font:
\fillemptyslots \stix

% Testing the result:
\input print-unimath.opm


The \fillemptyslots macro is implemented here. We need to use macros \resetmathcharX and \resetmathcharY from the previous OpTeX trick:

\def\UnicodeMathSymbol#1#2#3#4{%
\isinlist{\relax\mathord\mathop\mathbin\mathrel\mathpunct}#3\iftrue
\def\mathsequence{#2}%
\isinlist\intoperators#2\iftrue
\edef\mathsequence{\csname\csstring#2op\endcsname}%
\fi
{\tracinglostchars=0 \global\setbox0=\hbox{$\mathsequence$}}%
\ifdim\wd0=0pt \ea\resetmathcharX \mathsequence \fi
\fi
}
\def\intoperators{\int\iint\iiint\oint\oiint\oiiint
\intclockwise\varointclockwise\ointctrclockwise\sumint\iiiint\intbar\intBar
\fint\pointint\sqint\intlarhk\intx\intcap\intcup\upint\lowint
}
\def\fillemptyslots#1{\chardef\mafam=#1\relax \input unimath-table.opm }


The macro defines the macro \UnicodeMathSymbol used in unimath-table.opm and then does \input of this file. All \mahtord,\matop,\mathbin,\mathrel and \mathpunct characters are checked and if they give an empty box then they are completed from the new math font. Integrals are defined as macros (see \_intwithnolimits in unimath-codes.opm), so corresponding \...op control sequences are checked and completed.

(0082) -- P. O. 2022-05-15

## Original \cal from Computer Modern fonts

When \fontfam[lm] is used then LatinModern-Math Unicode font is used for math. The different calligraphic shapes are here than Knuth designed for his Computer Modern fonts. If you want to use his original calligraphic glyphs after \fontfam[lm], then you can use \orical instead \cal and the macro \orical is defined here:

\addto\_normalmath{%
\_loadmathfamily 5 cmsy % CM Standard symbols
}
\_normalmath
\def\orical{\fornumA..Z\do{\Umathcode##1 "0 "5 ##1 }}

% For example:
\def\P{{\orical P}} % powerset


The new math family (5 in our case) is declared in the internal \_normalmath macro. This must be done after \fontfam[lm]. Then the \orical macro sets (locally) approriate math codes for all characters A..Z: the class is zero (Ord character], the family is 5 and the code slot is the ASCII code of given letter.

(0077) -- P. O. 2022-04-19

## Intelligent \dots like in AMSTeX

AMSTeX provides \dots macro which works by the context. If it is surrounded by symbols like + - = then it works like \cdots, if it is surrounded by comma or similar symbols then it works like \ldots. The OPmac trick 0084 shows one implementation of this feature, but it works only in non-Unicode math. So, we show another solution.

\def\declbasemathchars#1{\foreach#1\do{\sxdef{dots:\meaning##1}{}}}
\def\dots{\relax \ifmmode \ea\specdots \else \_dots \fi}
\def\specdots{\futurelet\next\specdotsA}
\def\specdotsA{\ifcsname dots:\meaning\next\endcsname \ldots
\else \ischaracter\next \iftrue \cdots
\else \ea\specdotsB\scantextokens\ea{\meaning\next}\sepU\Umathchar\sepU\end \fi\fi}
\def\specdotsB#1\Umathchar#2\sepU#3\end{\ifx^#1^\specdotsC#2\sepU \else \ldots \fi}
\def\specdotsC"#1"#2"#3\sepU{%
\ifcase#1 \ldots\or \cdots\or \cdots\or \cdots\or \cdots\or \cdots\else \ldots \fi}
\def\ischaracter#1\iftrue{\ea\ischaracterA\scantextokens\ea{\meaning#1}character {}\end}
\def\ischaracterA#1character #2#3\end{%
\ifx\relax#2\relax \cs{iffalse\ea}\else \cs{iftrue\ea}\fi}

\declbasemathchars{, . ; :}

% Test:
$a_1,\dots,a_n$\quad $a_1+\dots+a_n$
\bye


The macro \dots is re-defined here in math mode. It reads the following token and does \cdots or \ldots. If the following token is a single letter then it uses \ldots. If the following token is a single character not listed in the \declbasemathchars parameter then it uses \cdots. If it is listed in \declbasemathchars paremater then it uses \ldots. If the next token is a control sequence declared by \Umathchardef then it uses \cdots for classes Op, Bin, Rel, Open, Close and \ldots for other classes. In other cases, it uses \ldots.

The \declbasemathchars can be used more than once, the list of declared characters are appended when second and more \declbasemathchars is used.

(0045) -- P. O. 2021-02-12

## Vertical bars and more math shortcuts

Writing $|x|$ in the source code works but $|-1|$ or $|\sin x|$ gives bad spaces, because | is Ord and it should be Open at the left and Close at the right side. But typing something more complicated in the math source is annoying. We define | as math active character which gives right spacing. Moreover, we can type $||x||$ for norm with righ spacing.

\mathcode|="8000
\def\autovert{\isnextchar|{\autoVertA}{\autovertA}}
\def\autoVertA|#1||{\mathopen{}\mathclose{\left\Vert #1\right\Vert}}
\def\autovertA#1|{\mathopen{}\mathclose{\left\vert #1\right\vert}}
{\catcode|=13 \global\let|=\autovert}


You can try to write $|-1|$ or $||x-y||$. Moreover, the vertical bars are resizable because the |#1| is defined as

\mathopen{}\mathclose{\left\vert#1\right\vert}.


Do you want more shortcuts? For example, if you write <= then it should be automatically transformed to Unicode character ≤ in your text editor. Then OpTeX is able to read it and your math source keeps clear. But, if such a feature is not available in your text editor then you can implement this intelligence at macro level. You write

$$a <= b <= c ==> a <= c$$


and you get:

You can use macos from OPmac trick 0149, they are working in OpTeX too.

(0061) -- P. O. 2021-04-19

Tables

## Colored cells in the table

We create the macro \colortab which can be used in \thistable declaration. When this macro is applied then tha background of each cell can be cloered by chosen color. If the first item in the cell data is color switcher then this color is used for the background of the cell. For example:

   ... & \Blue Text &        ... % blue background and black text
... & \Green \Red  Text & ... % green background and red text
... & \relax \Blue Text & ... % blue text and default background


The color of the background will stretch as spaces in the common cells in normal table, i.e. C declarator means that colored space will stretch from both sides, L declarator means right stretching and R declarator means left stretching. The spaces from \tabiteml and \tabitemr are colored too.

If \cellcolor sequence is set by \let to the color (example \let\cellcolor=\Yellow) then this color is used as default background. If the \cellcolor is undefined then default background is transparent.

You can insert the white space between columns by nonzero \tabskip and you can insert the white space between lines by \noalign{\kern...}. Example:

\thistable={\colortab              % colored cells activated
\tabstrut={\lower4pt\vbox to15pt{}}        % lines dimensions
\tabskip=2pt \everycr={\noalign{\kern2pt}} % spaces between cells
\let\cellcolor=\Yellow % default background color
}
\table{clr}{first item      & second & \Blue \White third item \cr
next long item  & \Red X & \Green       YES }

creates the table:

Implementation:

\def\tabdC{\futurelet\next\setcellcolor##\end\hfil\hfil}
\def\tabdL{\futurelet\next\setcellcolor##\end\relax\hfil}
\def\tabdR{\futurelet\next\setcellcolor##\end\hfil\relax}
\def\tabdP#1{\futurelet\next\setcellcolor##\end\vtop
{\hsize=#1\relax \baselineskip=\normalbaselineskip
\lineskiplimit=0pt \noindent\tmp\_unsskip\lower\dp\_tstrutbox\hbox{}}}
\def\colortab{\tablinespace=0pt \let\_paramtabdeclarep=\tabdP
\let\_tabdeclarec=\tabdC \let\_tabdeclarel=\tabdL \_let\_tabdeclarer=\tabdR}
\def\setcellcolor{%
\ifx\next\_setcolor \expandafter\setcellcolorC\else \expandafter\setcellcolorD\fi}
\def\setcellcolorC\_setcolor#1#2#3#4\end#5#6{%
\ifx#5\vtop \def\tmp{#4}%
\setbox0=\hbox{\the\tabiteml\vtop{\localcolor#6}\the\tabitemr}%
\the\tabstrut {\localcolor\_setcolor{#1}{#2}{#3}\vrule width\wd0}\kern-\wd0 \box0
\else
\setbox0=\hbox{\the\tabiteml\localcolor#4\_unsskip\the\tabitemr}%
{\localcolor\_setcolor{#1}{#2}{#3}%
\kern-\wd0 \box0
\ifx#6\hfil
\fi
}
\def\setcellcolorD{\ifx\cellcolor\undefined \let\next=\setcellcolorN
\else \def\next{\_ea\_ea\_ea\setcellcolorC\cellcolor}%
\fi \next
}
\def\setcellcolorN#1\end#2#3{#2\the\tabiteml{\localcolor#1\unskip}\the\tabitemr#3}

\def\multispanc#1#2#3{\multispan{#1}%
\_ea\_ea\_ea\cellcolexp#2#3\end\hfil\hfil\ignorespaces}
\def\cellcolexp{\futurelet\next\setcellcolor}


The \setcellcolor macro scans the first token from the cell data. The macro works in declaration part of the \halign, so the first token is scanned as the first unexpandable token after expansion. This token is \_setcolor when color macro is presented here. If this is true then the \setcellcolorC macro is executed, #1, #2 and #3 are the \_setcolor parameters #4 is the text of the item, #5 and #6 decide the align style. This macro measures the cell text in the box0 and does the colored background using \leaders. If the first token isn't \_setcolor then the macro \setcellcolorD decides if \cellcolor is defined. If it is true then \setcellcolorC is execuded (with partially expanded \cellcolor as parameter). Else \setcellcolorN is executed. This macro doesn't print any background.

The \multispanc Num \Color {text} can be used for multispan cells, see OPmac trick 103.

(0004) -- P. O. 2020-04-10

## Colored lines in the table

We can see the trend to use colored tables like this:

The table above can be created by the \table macro from OpTeX:

\thistable={\tabiteml={\quad}\tabitemr={\quad}}
\frame{\table{llllll}{\crx
aa & bb & cc & dd & ee & ff \crx
gg & hh & ii & jj & kk & ll \crx
mm & nn & oo & pp & qq & rr \crx
ss & tt & uu & vv & ww & xx \crx
ab & cd & ef & gh & ij & kl \crx
mn & op & qr & st & uv & wx}}


We need to define the \crx macro which inserts the grey rule before each odd line into the vertical list:

\newcount\tabline  \tabline=1
\def\crx{\crcr \ifodd\tabline \colortabline \else\noalign{\hrule height0pt}\fi
\def\colortabline{\noalign{\localcolor\LightGrey
\hrule height\ht\strutbox depth\dimexpr\dp\strutbox +2\tablinespace\relax
\kern-\dimexpr\ht\strutbox+\dp\strutbox +2\tablinespace}}


The \tabline counter counts the lines in the table and inserts the grey backgroud for each odd \tabline. The last line must not be terminated by \crx macro.

(0005) -- P. O. 2020-04-10

## Tables like in booktabs package

The orthodox advocates of LaTeX booktabs package don't like the table formats from the example above and they point out that I am loser because I don't know that the vertical rules in the table are out. Only horizontal rules are allowed but not double rules. And less rules is better than more. They have the following example in the documentation:

we can create such table by OpTeX and without booktabs package:

\thistable={\tabiteml={}\tabitemr={}\rulewidth=.2pt}