Klasický TeX i pdfTeX mají omezení na nejvýše 16 matematických rodin fontů v jednom vzorečku. OPmac pomocí ams-math.tex
nebo tx-math.tex
alokuje staticky (pro celý dokument) 12 resp. 14 rodin. Můžete jich staticky alokovat méně a dynamicky doplnit jen potřebné rodiny v rámci každého jednotlivého vzorečku. Pak můžete mít v dokumentu libovolné množství matematických rodin, jen omezení 16 rodin na vzoreček pochopitelně zůstává.
Vytvoříme makro \dfam{jméno-rodiny}
, které se uvnitř vzorečku chová jako \fam=číslo
, ale rodinu alokuje dynamicky. Dále vytvoříme makro
\dmathchardef\sekvence třída{jméno-rodiny}kód
které deklaruje \sekvenci
podobně jako \matchardef
, ale odpovídající rodina se automaticky alokuje jen, pokud je \sekvence
ve vzorečku použita. Pro příklad předpokládejme, že není staticky zavedena rodina eufm pro frakturu a rsfs pro skript. Pak je možné na začátku dokumentu deklarovat:
% obecně: \sdef{dfam:jméno-rodiny}{jméno-fontu-jako-v-\loadmathfamily}
\sdef{dfam:fractur}{eufm} \def\fractur{\dfam{fractur}}
\sdef{dfam:script}{rsfs} \def\script{\dfam{script}}
% ...
\dmathchardef\cosi 0{fractur}00 % znak třídy 0 kódu 00 (hex) z rodiny fractur
% ...
a následně to použít:
$a \times {\script B} = {\fractur C}$, a taky $ \beta = \cosi^2 $.
V ukázce jsou dva vzorečky. Vedle staticky zavedených rodin jsou v prvním vzorečku navíc dynamicky alokovány rodiny rsfs a eufm a ve druhém jen rodina eufm.
Implementace je následující
\chardef\numfamilies=\count18 % počet staticky linkovaných rodin
\everymath={\dfamstart} \everydisplay{\dfamstart} \def\dfamlist{}
\def\dfamstart{\aftergroup\dfamreset \let\dfamstart=\relax}
\def\dfamreset{\global\count18=\numfamilies \gdef\dfamlist{}}
\def\dfam#1{\relax
\expandafter\ifx\csname dfam:#1\endcsname \relax
\opwarning{dynamic math family "#1" is not declared}%
\else
\isinlist\dfamlist{,#1,}\iftrue \else
\begingroup \def\wlog##1{}%
\csname newfam\expandafter\endcsname \csname dmn:#1\endcsname
\globaldefs=1
\loadmathfamily{\csname dmn:#1\endcsname} {\csname dfam:#1\endcsname}
\endgroup
\global\addto\dfamlist{,#1,}%
\tmpnum=\csname dmn:#1\endcsname
\ifnum \tmpnum<10 \sxdef{dmh:#1}{\the\tmpnum}\else
\advance\tmpnum by-10
\sxdef{dmh:#1}{\ifcase\tmpnum A\or B\or C\or D\or E\or F\fi}%
\fi\fi
\fam=\csname dmn:#1\endcsname\relax
\fi
}
\def\dmathchar#1#2#3#4{\relax
\ifnum#1=0{\fi % aby fungovalo 2^\cosi bez nutnosti psát 2^{\cosi}
\isinlist\dfamlist{,#2,}\iftrue\else\begingroup\dfam{#2}\endgroup\fi
\mathchar"#1\csname dmh:#2\endcsname#3#4
\ifnum#1=0}\fi
}
\def\dmathchardef #1#2#3#4#5{\def#1{\dmathchar#2{#3}#4#5}}
\addprotect\dfam \addprotect\dmathchar
Jednotlivé rodiny se zavádějí pomocí \loadmathfamily
až podle potřeby a globálně. Jména zavedených rodin se ukládají do \dfamlist
. Sekvence \dmn:jméno
obsahuje číslo rodiny a \dmh:jméno
obsahuje totéž číslo jako hexa číslici. Na konci každého vzorečku se hodnoty týkající se dynamicky zavedených rodin resetují pomocí \dfamreset
. Vnořené matematické vzorečky (např. \hbox{...$vzorec$...}
uvnitř vzorce) tyto hodnoty neresetují, protože je přechodně nastaveno \dfamstart
na \relax
.
Při použití \dfam
se doporučuje snížit počet staticky zavedených rodin jen na často používané předefinováním maker \normalmath
a \boldmath
a odpovídajícím snížením čísla \count18
. Rodiny 0, 1, 2 a 3 musejí nutně zůstat staticky zavedené, protože TeX potřebuje jejich metriky v každém vzorečku.
Má-li rodina bold variantu, je možné ji deklarovat následujícím způsobem:
\newif \ifboldmath \boldmathfalse
\addto\normalmath{\boldmathfalse} \addto\boldmath{\boldmathtrue}
% příklad eufm a eufb:
\sdef{dfam:fractur}{\ifboldmath eufb\else eufm\fi}