unicode-math
unicode-math copied to clipboard
Discrepancies in font size selection
Description
The font size selected don't honor \DeclareMathSizes as set in the LaTeX kernel and differ according to the main document size.
Check/indicate
- [x] Relevant for XeTeX
- [x] Relevant for LuaTeX
- [x] Issue tracker has been searched for similar issues?
- [x] https://tex.stackexchange.com/q/438296/4427
Minimal example demonstrating the issue
\documentclass[12pt]{article}
\usepackage{unicode-math}
\newwrite\report
\immediate\openout\report=\jobname.rep
\makeatletter
\newcommand{\test}[1]{%
\begingroup
#1\check@mathfonts
\immediate\write\report{\string#1--\f@size pt}%
\immediate\write\report{\fontname\textfont0}%
\immediate\write\report{\fontname\scriptfont0}%
\immediate\write\report{\fontname\scriptscriptfont0}%
\endgroup
}
\makeatother
\begin{document}
\test{\normalsize}
\test{\large}
\test{\Large}
\end{document}
Further details
When compiled, the .rep file will contain
\normalsize--12pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT; at 12.0pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=0; at 8.41483pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=1; at 5.97688pt
\large--14.4pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT; at 14.4pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=0; at 7.0pt
\Large--17.28pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT; at 17.28pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT; at 12.0pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;
If 12pt is changed into 10pt, the sizes will be reported as
\normalsize--10pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=0; at 7.01236pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=1; at 4.98074pt
\large--12pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT; at 12.0pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=0; at 8.0pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=0; at 6.0pt
\Large--14.4pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT; at 14.4pt
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;
[latinmodern-math.otf]:mode=base;script=math;language=DFLT;+ssty=0; at 7.0pt
I think Will Robertson has mentioned this problem back in 2015 in his TeX.SX answer and I think I know where this go wrong.
The problem is with the following implementation in um-code-fontparam.dtx (Lines 290–297, as of 2018/12/11):
\cs_new:Nn \@@_fontdimen_to_percent:nN
{
\fp_eval:n { \dim_to_decimal:n { \fontdimen #1 #2 } * 65536 / 100 }
}
\cs_new:Nn \@@_fontdimen_to_scale:nN
{
\fp_eval:n { \@@_fontdimen_to_percent:nN {#1} #2 * \f@size } pt
}
Apparently, \dim_to_decimal:n produces a result which is rounded by TeX to four or five decimal places (The LaTeX3 Interfaces, Chapter XIX.7, as of 2018/12/11). So we could just follow the math:
-
For first-level script size.
- The
\fontdimen10of Latin Modern Math is70. - The result of
\dim_to_decimal:nis70 / 65536 = 0.00107. - The result of
\@@_fontdimen_to_percent:nNis0.00107 * 65536 / 100 = 0.7012352.
This explains the
8.41483ptand7.01236ptfor12ptand10ptarticles, respectively. - The
-
For second-level script size.
- The
\fontdimen11of Latin Modern Math is50. - The result of
\dim_to_decimal:nis50 / 65536 = 0.00076. - The result of
\@@_fontdimen_to_percent:nNis0.00076 * 65536 / 100 = 0.4980736.
This explains the
5.97688ptand4.98074ptfor12ptand10ptarticles, respectively. - The
IMHO, it is perhaps better to use
\fp_eval:n { \dim_to_decimal:n { 65536 \fontdimen #1 #2 } / 100 }
BTW, I think unicode-math intentionally ignores the LaTeX kernel \DeclareMathSizes and uses OpenType parameters ScriptPercentScaleDown and ScriptScriptPercentScaleDown instead, but only at \normalsize for some reasons.
A full example illustrating my proposed fix:
% !TeX program = XeLaTeX
\documentclass[12pt]{article}
\usepackage{unicode-math}
\ExplSyntaxOn
\cs_set:Nn \__um_fontdimen_to_percent:nN
{
\fp_eval:n { \dim_to_decimal:n { 65536 \fontdimen #1 #2 } / 100 }
}
\ExplSyntaxOff
\newwrite\report
\immediate\openout\report=\jobname.rep
\makeatletter
\newcommand{\test}[1]{%
\begingroup
#1\check@mathfonts
\immediate\write\report{\string#1--\f@size pt}%
\immediate\write\report{\fontname\textfont0}%
\immediate\write\report{\fontname\scriptfont0}%
\immediate\write\report{\fontname\scriptscriptfont0}%
\endgroup
}
\makeatother
\begin{document}
\test{\normalsize}
\test{\large}
\test{\Large}
\end{document}
With 12pt, in .rep I get
\normalsize--12pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;" at 12.0pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=0;" at 8.4pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=1;" at 6.0pt
\large--14.4pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;" at 14.4pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;"
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=0;" at 7.0pt
\Large--17.28pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;" at 17.28pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;" at 12.0pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;"
With 10pt, in .rep I get
\normalsize--10pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;"
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=0;" at 7.0pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=1;" at 5.0pt
\large--12pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;" at 12.0pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=0;" at 8.0pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=0;" at 6.0pt
\Large--14.4pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;" at 14.4pt
"[latinmodern-math.otf]/OT:script=math;language=DFLT;"
"[latinmodern-math.otf]/OT:script=math;language=DFLT;+ssty=0;" at 7.0pt
Yeah!!!
Thanks, this looks great to me. Sorry I can’t analyse this in detail right now — does this address the issue entirely or is it only part of the solution?
It depends…
- To me, the fix addresses this issue entirely in addition with my comment about
unicode-mathoverwriting\DeclareMathSizesat\normalsize. - However, the original intent of this issue appears to be asking
unicode-mathto honor the legacy\DeclareMathSizes, thus is partly addressed.
Given that pre-multiplying 65536 results in accurate point sizes, this issue may be closed if you think that the overwriting is “by design” (i.e., we should ignore the legacy \DeclareMathSizes and use OTF parameters instead).
@RuixiZhang42 — thanks, I see what you mean. I think the default should be to use the font-specific scaling present in the font metadata itself (i.e., override \DeclareMathSizes by default). But... users should have a way to override (do you agree @eg9, ?). I'll leave it open to decide what the best interface for this would be.
Perhaps unicode-math should do something like \DeclareMathSizes{0}{0}{0}, then when \setmathfont runs it checks to see whether the user has called \DeclareMathSizes and if so uses the now-updated values; otherwise use the data from the font.
Alternatively, I could deprecate \DeclareMathSizes (have it call an error or warning) and just make the override one of the keyval options for \setmathfont with something like [math-sizes={12}{7}{5}].
Or both! Thoughts?