I've got a problem with converting MathJax SVGs to PDF using mPDF.
HTML is just a simple formula from mPDF example:
\[ \left( \sum_{k=1}^n a_k b_k \right)^2 \leq \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n b_k^2 \right) \]
which should be rendered as:
But of course on final PDF file there's nothing.
HTML is send by POST to PHP file
$path = (getenv('MPDF_ROOT')) ? getenv('MPDF_ROOT') : __DIR__;
require_once $path . '/vendor/autoload.php';
$mpdf = new \Mpdf\Mpdf(['debug' => false, 'allow_output_buffering' => true]);
$sizeConverter = new \Mpdf\SizeConverter($mpdf->dpi, $mpdf->default_font_size);
if (strpos($_REQUEST['bodydata'], 'id%3D%22MathJax_SVG_Hidden%22') === false) {
die('Hacking attempt');
}
$html = $_POST['bodydata'];
$html = urldecode($html);
preg_match('/<svg[^>]*>\s*(<defs.*?>.*?<\/defs>)\s*<\/svg>/', $html, $m);
$defs = $m[1];
$html = preg_replace('/<svg[^>]*>\s*<defs.*?<\/defs>\s*<\/svg>/', '', $html);
$html = preg_replace('/(<svg[^>]*>)/', "\\1" . $defs, $html);
preg_match_all('/<svg([^>]*)style="(.*?)"/', $html, $m);
for ($i = 0; $i < count($m[0]); $i++) {
$style = $m[2][$i];
preg_match('/width: (.*?);/', $style, $wr);
$w = $sizeConverter->convert($wr[1], 0, $mpdf->FontSize) * $mpdf->dpi / 25.4;
preg_match('/height: (.*?);/', $style, $hr);
$h = $sizeConverter->convert($hr[1], 0, $mpdf->FontSize) * $mpdf->dpi / 25.4;
$replace = '<svg' . $m[1][$i] . ' width="' . $w . '" height="' . $h . '" style="' . $m[2][$i] . '"';
$html = str_replace($m[0][$i], $replace, $html);
}
if ($_POST['PDF'] === 'PDF') {
$stylesheet = '
img {
vertical-align: middle;
}
.MathJax_SVG_Display {
padding: 1em 0;
}
#mpdf-create {
display: none;
}
';
$mpdf->WriteHTML($stylesheet, 1);
$mpdf->WriteHTML($html);
$mpdf->Output();
}
exit;
It's copy of: official mPDF example, pretty buggy, before POST request JS copy 'width' and 'height' attribute to 'styles' attribute so mPDF can correctly read it.
Generated SVG:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="35.62ex" height="7.841ex" style="vertical-align: -3.082ex; width: 35.62ex; height: 7.841ex;" viewBox="0 -2049.4 15336.2 3376.2"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xlink:href="#MJSZ4-28"></use><g transform="translate(792,0)"><use xlink:href="#MJSZ2-2211" x="0" y="0"></use><g transform="translate(85,-1110)"><use transform="scale(0.707)" xlink:href="#MJMATHI-6B" x="0" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-3D" x="521" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-31" x="1300" y="0"></use></g><use transform="scale(0.707)" xlink:href="#MJMATHI-6E" x="721" y="1627"></use><g transform="translate(1611,0)"><use xlink:href="#MJMATHI-61" x="0" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMATHI-6B" x="748" y="-213"></use></g><g transform="translate(2609,0)"><use xlink:href="#MJMATHI-62" x="0" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMATHI-6B" x="607" y="-213"></use></g></g><use xlink:href="#MJSZ4-29" x="4300" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-32" x="7202" y="2090"></use><use xlink:href="#MJMAIN-2264" x="5824" y="0"></use><g transform="translate(6880,0)"><use xlink:href="#MJSZ4-28"></use><g transform="translate(792,0)"><use xlink:href="#MJSZ2-2211" x="0" y="0"></use><g transform="translate(85,-1110)"><use transform="scale(0.707)" xlink:href="#MJMATHI-6B" x="0" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-3D" x="521" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-31" x="1300" y="0"></use></g><use transform="scale(0.707)" xlink:href="#MJMATHI-6E" x="721" y="1627"></use><g transform="translate(1611,0)"><use xlink:href="#MJMATHI-61" x="0" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-32" x="748" y="488"></use><use transform="scale(0.707)" xlink:href="#MJMATHI-6B" x="748" y="-463"></use></g></g><use xlink:href="#MJSZ4-29" x="3401" y="0"></use></g><g transform="translate(11241,0)"><use xlink:href="#MJSZ4-28"></use><g transform="translate(792,0)"><use xlink:href="#MJSZ2-2211" x="0" y="0"></use><g transform="translate(85,-1110)"><use transform="scale(0.707)" xlink:href="#MJMATHI-6B" x="0" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-3D" x="521" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-31" x="1300" y="0"></use></g><use transform="scale(0.707)" xlink:href="#MJMATHI-6E" x="721" y="1627"></use><g transform="translate(1611,0)"><use xlink:href="#MJMATHI-62" x="0" y="0"></use><use transform="scale(0.707)" xlink:href="#MJMAIN-32" x="607" y="488"></use><use transform="scale(0.707)" xlink:href="#MJMATHI-6B" x="607" y="-463"></use></g></g><use xlink:href="#MJSZ4-29" x="3301" y="0"></use></g></g></svg>
And of course warnings:
[29-Dec-2017 21:42:39 UTC] PHP Notice: Undefined index: x in D:\Praca\ENVIROMENTS\laragon-apache\laragon\www\wp-content\plugins\szalpdf\pdf\vendor\mpdf\mpdf\src\Image\Svg.php on line 3027
[29-Dec-2017 21:42:39 UTC] PHP Notice: Undefined index: y in D:\Praca\ENVIROMENTS\laragon-apache\laragon\www\wp-content\plugins\szalpdf\pdf\vendor\mpdf\mpdf\src\Image\Svg.php on line 3027
[29-Dec-2017 21:42:39 UTC] PHP Notice: Undefined index: w in D:\Praca\ENVIROMENTS\laragon-apache\laragon\www\wp-content\plugins\szalpdf\pdf\vendor\mpdf\mpdf\src\Image\Svg.php on line 3027
[29-Dec-2017 21:42:39 UTC] PHP Notice: Undefined index: h in D:\Praca\ENVIROMENTS\laragon-apache\laragon\www\wp-content\plugins\szalpdf\pdf\vendor\mpdf\mpdf\src\Image\Svg.php on line 3027
[29-Dec-2017 21:42:39 UTC] PHP Warning: Division by zero in D:\Praca\ENVIROMENTS\laragon-apache\laragon\www\wp-content\plugins\szalpdf\pdf\vendor\mpdf\mpdf\src\Tag.php on line 4015
It's probably error with reading viewBox data but even with rigid values PDF file seems to be empty. Without errors, just ignores SVG. I've been sitting with this since yesterday and I'm still in the same place. MathJax is must have here. I'm considering changing the mPDF to something else but I prefer to avoid it.
No ideas, I'm stuck.
Latest MathJax /
mPDF v7.0.0 /
PHP: 7.1.1 /
PHP GD2 extension enabled
So, I figured it out. If someone was looking for an answer (we're talking now about mPDF MathJaxProcess.php file)
Examples are totally broken.
After fixing above mPDF should work with MathJax correctly. I'm also sanitizing SVGs before sending form. By sanitizing i mean:
Pretty messy JS code for that, but you'll get the idea.
We're skipping first SVG in our loop and that's because it has only definitions that will be copied directly into SVG tag in PHP script.
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG">
MathJax.Hub.Register.StartupHook("End",function () {
var list = document.getElementsByTagName("svg");
for (var i = 1; i < list.length; i++) {
var w = list[i].getAttribute("width");
var h = list[i].getAttribute("height");
list[i].style.width = w;
list[i].style.height = h;
list[i].removeAttribute("focusable");
list[i].removeAttribute("aria-hidden");
list[i].removeAttribute("role");
}
var gList = document.getElementsByTagName("g");
for (var i = 0; i < gList.length; i++) {
gList[i].setAttribute("fill", "#000");
}
document.querySelectorAll(".MJX_Assistive_MathML").forEach(function(a){
a.remove()
});
document.getElementById("bodydata").value=encodeURIComponent(document.body.innerHTML);
var el = document.getElementById("pdfform");
el.submit();
});
</script>
Edit: If you've got broken svg in chrome or firefox: When rendering from Firefox mPDF expects parameter viewbox When rendering from Chrome mPDF expects parameter viewBox It's case sensitive. I was hunting this bug from a week now.