Add mathfraktur rendering for chrome

Chrome and similar browsers do not support the
mathvariant attribute that can be used to change
math fonts conveniently. Like for mathcal there is
a table that can be used to translate from latin
to mathfraktur chars.

Bug: T378433
Change-Id: Id8c3e121ed104ba3f08329b4151a7e3bec699754
This commit is contained in:
physikerwelt 2024-10-29 11:30:51 +01:00
parent cc5c21dd54
commit 63b47f21ef
No known key found for this signature in database
GPG key ID: FCC793EFFA5FB13C
5 changed files with 75 additions and 7 deletions

View file

@ -788,12 +788,19 @@ class BaseParsing {
$state = []; $state = [];
// Unicode fixes for the operators // Unicode fixes for the operators
if ( $mathvariant == Variants::DOUBLESTRUCK ) { switch ( $mathvariant ) {
$state = [ "double-struck-literals" => true ]; case Variants::DOUBLESTRUCK:
} elseif ( $mathvariant == Variants::CALLIGRAPHIC ) { $state = [ "double-struck-literals" => true ];
$state = [ "calligraphic" => true ]; break;
} elseif ( $mathvariant == Variants::BOLDCALLIGRAPHIC ) { case Variants::CALLIGRAPHIC:
$state = [ "bold-calligraphic" => true ]; $state = [ "calligraphic" => true ];
break;
case Variants::BOLDCALLIGRAPHIC:
$state = [ "bold-calligraphic" => true ];
break;
case Variants::FRAKTUR:
$state = [ "fraktur" => true ];
break;
} }
if ( $node instanceof Fun1nb ) { if ( $node instanceof Fun1nb ) {

View file

@ -149,6 +149,36 @@ class MMLParsingUtil {
return self::matchAlphanumeric( $inputString, $map ); return self::matchAlphanumeric( $inputString, $map );
} }
public static function mapToFrakturUnicode( $inputString ): string {
$res = '';
$specialCases = [ 'C' => 'ℭ',
'H' => 'ℌ',
'I' => 'ℑ',
'R' => 'ℜ',
'Z' => 'ℤ' ];
foreach ( mb_str_split( $inputString ) as $chr ) {
// see https://www.w3.org/TR/mathml-core/#fraktur-mappings
if ( isset( $specialCases[$chr] ) ) {
$res .= $specialCases[$chr];
continue;
}
if ( $chr >= 'A' && $chr <= 'Z' ) {
$code = self::addToChr( $chr, '1D4C3' );
$res .= '&#x' . $code . ';';
} elseif ( $chr >= 'a' && $chr <= 'z' ) {
$code = self::addToChr( $chr, '1D4BD' );
$res .= '&#x' . $code . ';';
} else {
$res .= $chr;
}
}
return $res;
}
private static function addToChr( $chr, $base ): string {
return strtoupper( dechex( mb_ord( $chr ) + hexdec( $base ) ) );
}
public static function matchAlphanumeric( $inputString, $map ) { public static function matchAlphanumeric( $inputString, $map ) {
// Replace each character in the input string with its caligraphic Unicode equivalent // Replace each character in the input string with its caligraphic Unicode equivalent
return preg_replace_callback( '/[A-Za-z0-9]/u', static function ( $matches ) use ( $map ) { return preg_replace_callback( '/[A-Za-z0-9]/u', static function ( $matches ) use ( $map ) {

View file

@ -34,7 +34,7 @@ class Literal extends TexNode {
public function changeUnicodeFontInput( $input, $state ) { public function changeUnicodeFontInput( $input, $state ) {
/** /**
* In some font modifications, it is required to explicitly use unicode * In some font modifications, it is required to explicitly use Unicode
* characters instead of (only) attributes in MathML to indicate the font. * characters instead of (only) attributes in MathML to indicate the font.
* This is mostly because of Chrome behaviour. I.e. see: https://phabricator.wikimedia.org/T352196 * This is mostly because of Chrome behaviour. I.e. see: https://phabricator.wikimedia.org/T352196
*/ */
@ -42,6 +42,8 @@ class Literal extends TexNode {
return MMLParsingUtil::mapToDoubleStruckUnicode( $input ); return MMLParsingUtil::mapToDoubleStruckUnicode( $input );
} elseif ( isset( $state["calligraphic"] ) ) { } elseif ( isset( $state["calligraphic"] ) ) {
return MMLParsingUtil::mapToCaligraphicUnicode( $input ); return MMLParsingUtil::mapToCaligraphicUnicode( $input );
} elseif ( isset( $state["fraktur"] ) ) {
return MMLParsingUtil::mapToFrakturUnicode( $input );
} }
return $input; return $input;
} }

View file

@ -15,6 +15,16 @@ use MediaWikiUnitTestCase;
* @covers \MediaWiki\Extension\Math\WikiTexVC\TexVC * @covers \MediaWiki\Extension\Math\WikiTexVC\TexVC
*/ */
class MMLRenderTest extends MediaWikiUnitTestCase { class MMLRenderTest extends MediaWikiUnitTestCase {
public function testMathFRakUnicode() {
$input = "\\mathfrak{O}, \\mathfrak{K}, \\mathfrak{t}, \\mathfrak{C}";
$mathMLtexVC = $this->generateMML( $input );
$this->assertStringContainsString( '&#x1D512;', $mathMLtexVC );
$this->assertStringContainsString( '&#x1D50E;', $mathMLtexVC );
$this->assertStringContainsString( '&#x1D531;', $mathMLtexVC );
$this->assertStringContainsString( '&#x212D;', $mathMLtexVC );
}
public function testMathCalUnicode() { public function testMathCalUnicode() {
$input = "\\mathcal{O}, \\mathcal{K}, \\mathcal{t}, \\mathcal{c}"; $input = "\\mathcal{O}, \\mathcal{K}, \\mathcal{t}, \\mathcal{c}";
$mathMLtexVC = $this->generateMML( $input ); $mathMLtexVC = $this->generateMML( $input );

View file

@ -29,4 +29,23 @@ class MMLParsingUtilTest extends MediaWikiUnitTestCase {
$this->assertNull( $result ); $this->assertNull( $result );
} }
public function testUnicode_afr() {
$result = MMLParsingUtil::mapToFrakturUnicode( 'a' );
$this->assertEquals( '&#x1D51E;', $result );
}
public function testUnicode_bfr() {
$result = MMLParsingUtil::mapToFrakturUnicode( 'B' );
$this->assertEquals( '&#x1D505;', $result );
}
public function testUnicode_Cfr() {
$result = MMLParsingUtil::mapToFrakturUnicode( 'C' );
$this->assertEquals( '&#x0212D;', $result );
}
public function testUnicodeUtf8Input() {
$result = MMLParsingUtil::mapToFrakturUnicode( '𝔄' );
$this->assertEquals( '𝔄', $result );
}
} }