Skip to content

Commit

Permalink
Mathvariant fixes (#2292)
Browse files Browse the repository at this point in the history
* Be careful about propogating the correct font when synthesizing math tokens

* Omit mathvariant=normal when it's the default

* Cleanup test cases for missing/erroneous/redundant font or mathvariant declarations

* Add class ltx_mathvariant_xxx to MathML tokens whenever the mathvariant cannot be handled by pure Unicode

* Add fallback CSS classes for unhandled mathvariants

* Update testcase for additional css classes

* Don't add CSS class for mathvariant=normal

* Avoid mathvariant on m:mtext (only use css); avoid visible css effects on formatting chars (eg. InvisibleTimes,etc)

* Update testcase for simplified mathml

* clarify comment
  • Loading branch information
brucemiller authored Jan 5, 2024
1 parent 169d04c commit 3b56185
Show file tree
Hide file tree
Showing 17 changed files with 96 additions and 62 deletions.
13 changes: 8 additions & 5 deletions lib/LaTeXML/MathParser.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1168,10 +1168,10 @@ sub Absent {
return New('absent'); }

sub InvisibleTimes {
return New('times', "\x{2062}", role => 'MULOP', font => LaTeXML::Common::Font->new()); }
return New('times', "\x{2062}", role => 'MULOP'); }

sub InvisibleComma {
return New(undef, "\x{2063}", role => 'PUNCT', font => LaTeXML::Common::Font->new()); }
return New(undef, "\x{2063}", role => 'PUNCT'); }

# Get n-th arg of an XMApp.
# However, this is really only used to get the script out of a sub/super script
Expand Down Expand Up @@ -1406,19 +1406,22 @@ sub Fence {
return InterpretDelimited(New($op, undef, ($decl_id ? (decl_id => $decl_id) : ())), @stuff); } }

# Compose a complex relational operator from two tokens, such as >=, >>
# (similar to CatSymbols, but specialized to relops)
sub TwoPartRelop {
my ($op1, $op2) = @_;
$op1 = Lookup($op1);
$op2 = Lookup($op2);
my $m1 = p_getTokenMeaning($op1);
my $m2 = p_getTokenMeaning($op2);
my $m1 = p_getTokenMeaning($op1);
my $m2 = p_getTokenMeaning($op2);
my $font = p_getAttribute($op1, '_font');
my $meaning;
if ($m1 eq $m2) {
$meaning = "much-$m1"; }
else {
$meaning = "$m1-or-$m2"; }
my $content = $op1->textContent . $op2->textContent;
return ['ltx:XMTok', { role => "RELOP", meaning => $meaning }, $content]; }
return ['ltx:XMTok', { role => "RELOP", meaning => $meaning, ($font ? (_font => $font) : ()) },
$content]; }

# NOTE: It might be best to separate the multiple Formulae into separate XMath's???
# but only at the top level!
Expand Down
7 changes: 4 additions & 3 deletions lib/LaTeXML/Package.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1619,7 +1619,8 @@ sub defmath_rewrite {

sub defmath_common_constructor_options {
my ($cs, $presentation, %options) = @_;
my $sizer = inferSizer($options{sizer}, $options{reversion});
my $sizer = inferSizer($options{sizer}, $options{reversion});
my $presentation_s = $presentation && ToString($presentation);
return (
alias => $options{alias} || $cs->getString,
(defined $options{reversion} ? (reversion => $options{reversion}) : ()),
Expand All @@ -1645,8 +1646,8 @@ sub defmath_common_constructor_options {
stretchy => $options{stretchy},
operator_stretchy => $options{operator_stretchy},
font => ($options{mathstyle}
? sub { LookupValue('font')->merge(mathstyle => $options{mathstyle})->specialize($presentation); }
: sub { LookupValue('font')->specialize($presentation); }),
? sub { LookupValue('font')->merge(mathstyle => $options{mathstyle})->specialize($presentation_s); }
: sub { LookupValue('font')->specialize($presentation_s); }),
lpadding => $options{lpadding},
rpadding => $options{rpadding} },
scope => $options{scope}); }
Expand Down
4 changes: 3 additions & 1 deletion lib/LaTeXML/Package/LaTeX.pool.ltxml
Original file line number Diff line number Diff line change
Expand Up @@ -3875,7 +3875,9 @@ DefPrimitive('\@array@bindings [] AlignmentTemplate', sub {
if ($str != 1) {
$$attr{rowsep} = Dimension(($str - 1) . 'em'); }
alignmentBindings($template, 'math', attributes => $attr);
MergeFont(mathstyle => 'text');
if (my $font = LookupValue('font')) {
if (($font->getMathstyle || 'text') eq 'display') {
MergeFont(mathstyle => 'text'); } }
Let("\\\\", '\@alignment@newline');
Let('\lx@intercol', '\lx@math@intercol');
return; });
Expand Down
13 changes: 8 additions & 5 deletions lib/LaTeXML/Package/TeX.pool.ltxml
Original file line number Diff line number Diff line change
Expand Up @@ -6859,14 +6859,15 @@ DefConstructor('\lx@hack@bordermatrix{}', sub {
my $n = scalar(@rows) - 1;
$col1->setAttribute(rowspan => $n);
$coln->setAttribute(rowspan => $n);
my $pfont = $STATE->lookupValue('font')->specialize('(');
$document->appendTree($col1,
['ltx:XMWrap', { depth => $d },
['ltx:XMTok', { role => 'OPEN', height => 0, depth => $d, yoffset => $md }, '('],
['ltx:XMTok', { height => $h, yoffset => $md }, ' ']]); # Effectively, a strut
['ltx:XMTok', { role => 'OPEN', height => 0, depth => $d, yoffset => $md, font => $pfont }, '('],
['ltx:XMTok', { height => $h, yoffset => $md, font => $pfont }, ' ']]); # Effectively, a strut
$document->appendTree($coln,
['ltx:XMWrap', {},
['ltx:XMTok', { role => 'CLOSE', height => 0, depth => $d, yoffset => $md }, ')'],
['ltx:XMTok', { height => $h, yoffset => $md }, ' ']]);
['ltx:XMTok', { role => 'CLOSE', height => 0, depth => $d, yoffset => $md, font => $pfont }, ')'],
['ltx:XMTok', { height => $h, yoffset => $md, font => $pfont }, ' ']]);
return; },
reversion => '#1');

Expand Down Expand Up @@ -7291,7 +7292,9 @@ DefConstructor('\lx@apply OptionalKeyVals:XMath {}{}',
DefConstructor('\lx@symbol OptionalKeyVals:XMath {}',
"<ltx:XMTok $XMath_attributes>#2</ltx:XMTok>",
reversion => '#2',
afterDigest => sub { XMath_copy_keyvals(@_); });
afterDigest => sub {
$_[1]->setFont($_[1]->getArg(2)->getFont);
XMath_copy_keyvals(@_); });

# Wrap the contents in an ltx:XMWrap, to stand as a single subtree & providing attributes
# The ltx:XMWrap may be collapsed, later, by parsing
Expand Down
21 changes: 15 additions & 6 deletions lib/LaTeXML/Post/MathML.pm
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use LaTeXML::Util::Unicode;
use LaTeXML::Post;
use LaTeXML::Common::Font;
use List::Util qw(max);
use base qw(LaTeXML::Post::MathProcessor);
use base qw(Exporter);
use base qw(LaTeXML::Post::MathProcessor);
use base qw(Exporter);
our @EXPORT = (
qw( &DefMathML ),
qw( &pmml &pmml_scriptsize &pmml_smaller
Expand Down Expand Up @@ -703,6 +703,8 @@ sub stylizeContent {
elsif (!$variant) { $variant = 'normal'; } } # must say so explicitly.
elsif ($font && !$variant) {
Warn('unexpected', $font, undef, "Unrecognized font variant '$font'"); $variant = ''; }
elsif ($variant eq 'normal') { # normal is default for any other tokens, so omit
$variant = undef; }
# Should we map to Unicode's Plane 1 blocks for Mathematical Alphanumeric Symbols?
# Only upper & lower case latin & greek, and also numerals can be mapped.
# For each mathvariant, and for each of those 5 groups, there is a linear mapping,
Expand All @@ -713,13 +715,15 @@ sub stylizeContent {
my $u_variant = $variant
&& ($plane1hack ? $plane1hackable{$variant}
: ($plane1 ? $variant : undef));
my $u_text = $u_variant && unicode_convert($text, $u_variant);
my $u_text = ($tag ne 'm:mtext') && $u_variant && unicode_convert($text, $u_variant);
if ((defined $u_text) && ($u_text ne '')) { # didn't remap the text ? Keep text & variant
$text = $u_text;
$variant = ($plane1hack && ($variant ne $u_variant) && ($variant =~ /^bold/)
? 'bold' : undef); } # Possibly keep variant bold
# Use class (css) to patchup some weak translations
if (!$font) { }
if ($text =~ /^\p{Format}*$/) { # Only Formatting (eg. InvisibleTImes) (or empty)
$font = $variant = $color = $bgcolor = $opacity = undef; } # Needs no viz. styling attributes
elsif (!$font) { }
elsif ($font =~ /caligraphic/) {
# Note that this is unlikely to have effect when plane1 chars are used!
$class = ($class ? $class . ' ' : '') . 'ltx_font_mathcaligraphic'; }
Expand All @@ -729,15 +733,20 @@ sub stylizeContent {
$class = ($class ? $class . ' ' : '') . 'ltx_font_oldstyle'; }
elsif ($font =~ /smallcaps/) {
$class = ($class ? $class . ' ' : '') . 'ltx_font_smallcaps'; }
elsif ($variant && ($variant ne 'normal')) { # Any left-over mathvariant? Punt to CSS
$class = ($class ? $class . ' ' : '') . 'ltx_mathvariant_' . $variant; }
if ($tag eq 'm:mtext') {
$variant = undef; }

if ($opacity) {
$cssstyle = ($cssstyle ? $cssstyle . ';' : '') . "opacity:$opacity"; }

# Now, look up any OperatorDictionary properties
my %props = ($tag eq 'm:mo' ? opdict_lookup($text, $role) : ());

# Resolve stretch & size
$stretchy = undef if ($tag ne 'm:mo'); # Only allowed on m:mo!
$size = undef if $stretchy; # Ignore size, if we're stretching.
$stretchy = undef if ($tag ne 'm:mo'); # Only allowed on m:mo!
$size = undef if $stretchy; # Ignore size, if we're stretching.
my $stretchyhack = undef;
if ($text =~ /^[\x{2061}\x{2062}\x{2063}]*$/) { # invisible get no size or stretchiness
$stretchy = $size = undef; }
Expand Down
16 changes: 16 additions & 0 deletions lib/LaTeXML/resources/CSS/LaTeXML.css
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,22 @@ span.ltx_framed { display:inline-block; text-indent:0; } /* avoid padding/
.ltx_font_smallcaps { font-variant: small-caps; font-style:normal; }
.ltx_font_oldstyle { font-variant-numeric: oldstyle-nums; }
.ltx_font_mathcaligraphic { font-family: "Lucida Calligraphy", "Zapf Chancery","URW Chancery L"; }
/* Fallbacks for when content+mathvariant cannot be mapped to Unicode */
.ltx_mathvariant_italic { font-style: italic; }
.ltx_mathvariant_bold { font-weight: bold; }
.ltx_mathvariant_bold-italic { font-style: italic; font-weight: bold; }
.ltx_mathvariant_sans-serif { font-family: sans-serif; }
.ltx_mathvariant-bold-sans-serif { font-family: sans-serif; font-weight: bold; }
.ltx_mathvariant-sans-serif-italic { font-family: sans-serif; font-style: italic; }
.ltx_mathvariant-bold-sans-serif-italic { font-family: sans-serif; font-style: italic; font-weight: bold; }
.ltx_mathvariant_monospace { font-family: monospace; }
/* Can we say anything generic about double-struck, script or fraktur ? */
.ltx_mathvariant_double-struck { font-weight: bold; }
.ltx_mathvariant_script { font-family: "Lucida Calligraphy", "Zapf Chancery","URW Chancery L", cursive; }
.ltx_mathvariant_bold-script { font-family: "Lucida Calligraphy", "Zapf Chancery","URW Chancery L", cursive; font-weight: bold; }
.ltx_mathvariant-fraktur { }/* ??? */
.ltx_mathvariant_bold-fraktur { font-weight: bold; }

/*
.ltx_font_mathscript { ? }
Expand Down
8 changes: 4 additions & 4 deletions t/alignment/listing.xml
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ and with messed up braces <text class="ltx_lst_numbers_left ltx_lstlisting"><tex
<XMTok role="SUBSCRIPTOP" scriptpos="post1"/>
<XMTok font="italic" role="UNKNOWN">a</XMTok>
<XMApp>
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMTok font="italic" fontsize="70%" role="UNKNOWN">i</XMTok>
<XMTok font="italic" fontsize="70%" role="UNKNOWN">j</XMTok>
</XMApp>
Expand Down Expand Up @@ -565,7 +565,7 @@ and with messed up braces <text class="ltx_lst_numbers_left ltx_lstlisting"><tex
<XMTok role="SUBSCRIPTOP" scriptpos="post1"/>
<XMTok font="italic" role="UNKNOWN">a</XMTok>
<XMApp>
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMTok font="italic" fontsize="70%" role="UNKNOWN">i</XMTok>
<XMTok font="italic" fontsize="70%" role="UNKNOWN">j</XMTok>
</XMApp>
Expand Down Expand Up @@ -622,7 +622,7 @@ and with messed up braces <text class="ltx_lst_numbers_left ltx_lstlisting"><tex
<XMTok role="SUBSCRIPTOP" scriptpos="post1"/>
<XMTok font="italic" role="UNKNOWN">a</XMTok>
<XMApp>
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMTok font="italic" fontsize="70%" role="UNKNOWN">i</XMTok>
<XMTok font="italic" fontsize="70%" role="UNKNOWN">j</XMTok>
</XMApp>
Expand Down Expand Up @@ -671,7 +671,7 @@ and with messed up braces <text class="ltx_lst_numbers_left ltx_lstlisting"><tex
<XMTok role="SUBSCRIPTOP" scriptpos="post1"/>
<XMTok role="UNKNOWN">a</XMTok>
<XMApp>
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok font="upright" meaning="times" role="MULOP">⁢</XMTok>
<XMTok fontsize="70%" role="UNKNOWN">i</XMTok>
<XMTok fontsize="70%" role="UNKNOWN">j</XMTok>
</XMApp>
Expand Down
8 changes: 4 additions & 4 deletions t/alignment/plainmath.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
</XMCell>
<XMCell rowspan="2">
<XMWrap depth="6.8pt">
<XMTok depth="6.8pt" font="italic" height="0" role="OPEN" yoffset="-6.8pt">(</XMTok>
<XMTok font="italic" height="6.8pt" yoffset="-6.8pt"> </XMTok>
<XMTok depth="6.8pt" height="0" role="OPEN" yoffset="-6.8pt">(</XMTok>
<XMTok height="6.8pt" yoffset="-6.8pt"> </XMTok>
</XMWrap>
</XMCell>
<XMCell align="center">
Expand All @@ -66,8 +66,8 @@
</XMCell>
<XMCell rowspan="2">
<XMWrap>
<XMTok depth="6.8pt" font="italic" height="0" role="CLOSE" yoffset="-6.8pt">)</XMTok>
<XMTok font="italic" height="6.8pt" yoffset="-6.8pt"> </XMTok>
<XMTok depth="6.8pt" height="0" role="CLOSE" yoffset="-6.8pt">)</XMTok>
<XMTok height="6.8pt" yoffset="-6.8pt"> </XMTok>
</XMWrap>
</XMCell>
</XMRow>
Expand Down
4 changes: 2 additions & 2 deletions t/babel/numprints.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1212,7 +1212,7 @@ vs.
<XMDual>
<XMTok color="#0000FF" font="italic" meaning="123456.23e1" role="NUMBER">123456.23e1</XMTok>
<XMApp color="#0000FF">
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMText><text align="right" width="68.3pt"><Math mode="inline" tex="\textstyle 123{,}456" text="list@(123, 456)" xml:id="S3.p6.m3.m1">
<XMath>
<XMDual>
Expand Down Expand Up @@ -1317,7 +1317,7 @@ vs.
<XMDual>
<XMTok color="#0000FF" font="italic" meaning="14561234.562e12" role="NUMBER">14561234.562e12</XMTok>
<XMApp color="#0000FF">
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMText><text align="right" width="68.3pt"><Math mode="inline" tex="\textstyle 14{,}561{,}234" text="list@(14, 561, 234)" xml:id="S3.p6.m6.m1">
<XMath>
<XMDual>
Expand Down
2 changes: 1 addition & 1 deletion t/complex/si.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2877,7 +2877,7 @@ Some text <break/><Math mode="inline" tex="4\text{\,}\mathrm{m}\text{\,}{\mathrm
<XMTok lpadding="0pt" meaning="arcminute" role="UNKNOWN">′</XMTok>
</XMApp>
<XMApp>
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMTok meaning="6" role="NUMBER">6</XMTok>
<XMTok font="italic" width="0pt">.</XMTok>
<XMTok lpadding="0pt" meaning="arcsecond" role="UNKNOWN">″</XMTok>
Expand Down
2 changes: 1 addition & 1 deletion t/daemon/formats/lexmath.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Also <math id="p4.m3" class="ltx_Math" alttext="\mathit{func}" display="inline">

<tbody><tr class="ltx_equation ltx_eqn_row ltx_align_baseline">
<td class="ltx_eqn_cell ltx_eqn_center_padleft"></td>
<td class="ltx_eqn_cell ltx_align_center"><math id="S0.Ex3.m1" class="ltx_Math" alttext="\int_{0}^{\infty}x\,dx=\text{zero, \it yes 0}" display="block"><semantics><mrow><mrow><msubsup><mo>∫</mo><mn>0</mn><mi mathvariant="normal">∞</mi></msubsup><mrow><mi>x</mi><mo lspace="0.170em">⁢</mo><mrow><mo rspace="0em">𝑑</mo><mi>x</mi></mrow></mrow></mrow><mo>=</mo><mrow><mtext>zero, </mtext><mtext mathvariant="italic">yes 0</mtext></mrow></mrow><annotation encoding="application/x-llamapun">∫ start_POSTSUBSCRIPT 0 end_POSTSUBSCRIPT start_POSTSUPERSCRIPT ∞ end_POSTSUPERSCRIPT italic_x italic_d italic_x = zero, italic_yes italic_0</annotation></semantics></math></td>
<td class="ltx_eqn_cell ltx_align_center"><math id="S0.Ex3.m1" class="ltx_Math" alttext="\int_{0}^{\infty}x\,dx=\text{zero, \it yes 0}" display="block"><semantics><mrow><mrow><msubsup><mo>∫</mo><mn>0</mn><mi mathvariant="normal">∞</mi></msubsup><mrow><mi>x</mi><mo lspace="0.170em">⁢</mo><mrow><mo rspace="0em">𝑑</mo><mi>x</mi></mrow></mrow></mrow><mo>=</mo><mrow><mtext>zero, </mtext><mtext class="ltx_mathvariant_italic">yes 0</mtext></mrow></mrow><annotation encoding="application/x-llamapun">∫ start_POSTSUBSCRIPT 0 end_POSTSUBSCRIPT start_POSTSUPERSCRIPT ∞ end_POSTSUPERSCRIPT italic_x italic_d italic_x = zero, italic_yes italic_0</annotation></semantics></math></td>
<td class="ltx_eqn_cell ltx_eqn_center_padright"></td></tr></tbody>
</table>
</div>
Expand Down
4 changes: 2 additions & 2 deletions t/fonts/mathcolor.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<p><Math mode="inline" tex="r{\color[rgb]{0,1,0}g\color[rgb]{1,1,0}y}" text="r * g * y" xml:id="p2.m1">
<XMath>
<XMApp color="#FF0000">
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMTok font="italic" role="UNKNOWN">r</XMTok>
<XMTok color="#00FF00" font="italic" role="UNKNOWN">g</XMTok>
<XMTok color="#FFFF00" font="italic" role="UNKNOWN">y</XMTok>
Expand All @@ -29,7 +29,7 @@
<p><text color="#FF0000">R <Math mode="inline" tex="r\mbox{R}{\color[rgb]{0,1,0}g\mbox{G}\color[rgb]{1,1,0}y\mbox{Y}}r\mbox{R}" text="r * [R] * g * [G] * y * [Y] * r * [R]" xml:id="p3.m1">
<XMath>
<XMApp>
<XMTok meaning="times" role="MULOP">⁢</XMTok>
<XMTok color="#000000" meaning="times" role="MULOP">⁢</XMTok>
<XMTok font="italic" role="UNKNOWN">r</XMTok>
<XMText>R</XMText>
<XMTok color="#00FF00" font="italic" role="UNKNOWN">g</XMTok>
Expand Down
Loading

0 comments on commit 3b56185

Please sign in to comment.