Serve png mode from mathoid

* Use the exactly same routines to deliver png images that are used in
  mathml mode.
* Change the output to use mathoids png image rather than the mathml
  and svg output.
* Locally tested on Firefox and Chrome: Depending on the mode either
  the SVG or the PNG path is used.

Bug: T74240
Change-Id: I4b1cac92eb9a02190f316faab6621940951603d5
This commit is contained in:
Moritz Schubotz (physikerwelt) 2018-05-18 19:08:51 +02:00
parent 22d63b1973
commit b5cf0e0b77
No known key found for this signature in database
GPG Key ID: 73D26C61BAB32E94
9 changed files with 2369 additions and 1850 deletions

View File

@ -31,7 +31,8 @@
"MathValidator": "src/MathValidator.php",
"MathFormatter": "src/MathFormatter.php",
"MathWikidataHook": "src/MathWikidataHook.php",
"MathMLRdfBuilder": "src/MathMLRdfBuilder.php"
"MathMLRdfBuilder": "src/MathMLRdfBuilder.php",
"MathPng": "src/MathPng.php"
},
"DefaultUserOptions": {
"math": "mathml"

View File

@ -78,8 +78,12 @@ class MathGenerateTests extends Maintenance {
$i = 0;
foreach ( array_slice( $allEquations, $offset, $length, true ) as $input ) {
$output = MathRenderer::renderMath( $input[1], $input[2], 'png' );
$output = preg_replace( '#src="(.*?)/(([a-f]|\d)*).png"#', 'src="\2.png"', $output );
$parserTests[] = [ (string)$input[1], $output ];
$output = preg_replace( '#src="(.*?)/(([a-f]|\d)*)"#', 'src="\2"', $output );
$parserTests[] = [
'input' => (string)$input[1],
'params' => $input[2],
'output' => $output
];
$i++;
echo '.';
}

View File

@ -15,6 +15,7 @@ class MathMathML extends MathRenderer {
protected $defaultAllowedRootElements = [ 'math' ];
protected $restbaseInputTypes = [ 'tex', 'inline-tex', 'chem' ];
protected $restbaseRenderingModes = [ 'mathml', 'png' ];
protected $allowedRootElements = [];
protected $hosts;
@ -26,6 +27,9 @@ class MathMathML extends MathRenderer {
*/
private $svgPath = false;
/** @var string|bool */
private $pngPath = false;
private $mathoidStyle;
public function __construct( $tex = '', $params = [] ) {
@ -104,7 +108,7 @@ class MathMathML extends MathRenderer {
$this->setPurge( true );
}
if ( in_array( $this->inputType, $this->restbaseInputTypes ) &&
$this->mode == 'mathml'
in_array( $this->mode, $this->restbaseRenderingModes )
) {
if ( !$this->rbi ) {
$this->rbi =
@ -116,6 +120,7 @@ class MathMathML extends MathRenderer {
$this->mathml = $rbi->getMathML();
$this->mathoidStyle = $rbi->getMathoidStyle();
$this->svgPath = $rbi->getFullSvgUrl();
$this->pngPath = $rbi->getFullPngUrl();
} elseif ( $this->lastError === '' ) {
$this->doCheck();
}
@ -351,6 +356,9 @@ class MathMathML extends MathRenderer {
* @return Title|string
*/
private function getFallbackImageUrl( $noRender = false ) {
if ( 'png' === $this->getMode() && $this->pngPath ) {
return $this->pngPath;
}
if ( $this->svgPath ) {
return $this->svgPath;
}
@ -399,7 +407,7 @@ class MathMathML extends MathRenderer {
* is false the class name will be calculated by getClassName
* @return string XML the image html tag
*/
private function getFallbackImage( $noRender = false, $classOverride = false ) {
protected function getFallbackImage( $noRender = false, $classOverride = false ) {
$attribs = [
'src' => $this->getFallbackImageUrl( $noRender )
];

19
src/MathPng.php Normal file
View File

@ -0,0 +1,19 @@
<?php
/**
* MediaWiki math extension
*
* @copyright 2002-2018 various MediaWiki contributors
* @license GPL-2.0-or-later
*/
class MathPng extends MathMathML {
public function __construct( $tex = '', array $params = [] ) {
parent::__construct( $tex, $params );
$this->setMode( 'png' );
}
public function getHtmlOutput() {
return $this->getFallbackImage();
}
}

View File

@ -167,7 +167,7 @@ abstract class MathRenderer {
$renderer = new MathSource( $tex, $params );
break;
case 'png':
$renderer = new MathTexvc( $tex, $params );
$renderer = new MathPng( $tex, $params );
break;
case 'latexml':
$renderer = new MathLaTeXML( $tex, $params );

View File

@ -293,6 +293,16 @@ class MathRestbaseInterface {
return $this->getUrl( "media/math/render/svg/{$this->hash}", false );
}
/**
* Gets a publicly accessible link to the generated SVG image.
* @return string
* @throws MWException
*/
public function getFullPngUrl() {
$this->calculateHash();
return $this->getUrl( "media/math/render/png/{$this->hash}", false );
}
/**
* @return string
*/

View File

@ -125,7 +125,7 @@ class MathMathMLTest extends MediaWikiTestCase {
$t = new Title( "test" );
$res = $p->parse( '[[test|<math forcemathmode="png">a+b</math>]]', $t, $po )->getText();
$this->assertContains( '</a>', $res );
$this->assertContains( '.png', $res );
$this->assertContains( 'png', $res );
}
/**

File diff suppressed because it is too large Load Diff

View File

@ -24,74 +24,36 @@
* @license GPL-2.0-or-later
*/
class MathCoverageTest extends MediaWikiTestCase {
protected static $hasTexvc;
protected static $texvcPath;
public static function setUpBeforeClass() {
global $wgTexvc;
if ( is_executable( $wgTexvc ) ) {
wfDebugLog( __CLASS__, " using build in texvc from "
. "\$wgMathTexvcCheckExecutable = $wgTexvc" );
# Using build-in
self::$hasTexvc = true;
self::$texvcPath = $wgTexvc;
} else {
# Attempt to compile
wfDebugLog( __CLASS__, " compiling texvc..." );
$cmd = 'cd ' . dirname( __DIR__ ) . '/math; make --always-make 2>&1';
wfShellExec( $cmd, $retval );
if ( $retval === 0 ) {
self::$hasTexvc = true;
self::$texvcPath = dirname( __DIR__ ) . '/math/texvc';
wfDebugLog( __CLASS__, ' compiled texvc at ' . self::$texvcPath );
} else {
wfDebugLog( __CLASS__, ' ocaml not available or compilation of texvc failed' );
}
}
}
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp() {
parent::setUp();
if ( ! self::$hasTexvc ) {
$this->markTestSkipped( "No texvc installed on server" );
} else {
$this->setMwGlobals( 'wgTexvc',
self::$texvcPath );
}
}
/**
* Loops over all test cases provided by the provider function.
* Compares each the rendering result of each input with the expected output.
* @dataProvider provideCoverage
*/
public function testCoverage( $input, $output ) {
public function testCoverage( $input, $options, $output ) {
// TODO: Make rendering mode configurable
// TODO: Provide test-ids
// TODO: Link to the wikipage that contains the reference rendering
$this->assertEquals(
$this->normalize( $output ),
$this->normalize( MathRenderer::renderMath( $input, [], 'png' ) ),
"Failed to render $input"
$this->normalize( MathRenderer::renderMath( $input, $options, 'png' ) ),
"Failed to render ${input}"
);
}
/**
* Gets the test-data from the file ParserTest.json
* @return string[] [ $input, $output ] where $input is the test input string
* @return array where $input is the test input string
* and $output is the rendered html5-output string
*/
public function provideCoverage() {
return json_decode( file_get_contents( __DIR__ . '/ParserTest.json' ) );
$testcases = json_decode( file_get_contents( __DIR__ . '/../ParserTest.json' ), true );
// uncomment for fast testing
// $testcases = array_slice($testcases,0,3);
return $testcases;
}
private function normalize( $input ) {
return preg_replace( '#src="(.*?)/(([a-f]|\d)*).png"#', 'src="\2.png"', $input );
return preg_replace( '#src="(.*?)/(([a-f]|\d)*)"#', 'src="\2"', $input );
}
}