My ultimate goal is to save rendered presentation MathML to a .PNG file. Knowing just enough about programming to be dangerous :-) there may be a better way to do this...I am drawing the equation on a canvas element, then trying to save the canvas element as a .PNG. I started with code found here -- -- and modified as follows:

<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" style="border:2px solid black;" width="200" height="200">
</canvas>

<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var data = "<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'>" +
        "<foreignObject width='100%' height='100%'>" +
        "<div xmlns='http://www.w3.org/1998/Math/MathML'     style='fontsize:40px'>" +
        "<math>" +
        "<mtable>" +
        "<mtr>" +
        "<mtd columnalign='right'>" +
            "<mn>2</mn>" +
            "<mi>x</mi>" +
            "<mo>+</mo>" +
            "<mn>3</mn>" +
            "<mo>−</mo>" +
            "<mn>3</mn>" +
         "</mtd>" +
         "<mtd columnalign='center'> " +              
            "<mo>=</mo>" +
        "</mtd>" +
        "<mtd columnalign='left'> " +              
            "<mn>9</mn>" +
            "<mo>−</mo>" +
            "<mn>3</mn>" +
         "</mtd>" +
        "</mtr>" +
        "</mtable>" +
        "</math>" +
        "</div>" +
        "</foreignObject>" +
        "</svg>";

var svg = new (self.BlobBuilder || self.MozBlobBuilder || self.WebKitBlobBuilder);
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
svg.append(data);
var url = DOMURL.createObjectURL(svg.getBlob("image/svg+xml;charset=utf-8"));
img.onload = function() {
    ctx.drawImage(img, 0, 0);
    DOMURL.revokeObjectURL(url);
    window.open(canvas.toDataURL('image/png'));
};
img.src = url;

</script>

</body>
</html>

I am getting a "Security error" with no code. I have tested with Firefox, Chrome, Safari, and Internet Explorer. Running a local Apache server. Do we think the canvas is dirty, even though, according to the Mozilla doc above, its not supposed to be? Any other way to do this? Thanks in advance...

Dani AI

Generated

A short expert note tying the replies together: the SecurityError seen by is the classic symptom of a "tainted" canvas — browsers will block calls like toDataURL() or getImageData() after drawing SVG content that uses foreignObject or any cross-origin resource, because those cases can leak page data. Many browsers explicitly treat SVGs containing embedded HTML/MathML as risky and refuse export. (developer.mozilla.org)

A practical client-side approach that avoids that trap is to render MathML into a pure SVG (no foreignObject) and then rasterize that SVG to the canvas. MathJax can convert MathML to standalone SVG (paths), which you can turn into a Blob, load into an Image, draw to canvas, and then call toDataURL(). Example sketch (keep external fonts/resources out of the SVG):

const svgNode = await MathJax.mathml2svgPromise(mathmlString);
const svgString = svgNode.outerHTML;
const blob = new Blob([svgString], {type: 'image/svg+xml'});
const url = URL.createObjectURL(blob);
const img = new Image();
img.onload = () => { ctx.drawImage(img,0,0); const png = canvas.toDataURL('image/png'); URL.revokeObjectURL(url); };
img.src = url;

MathJax documents the conversion APIs and SVG output options. (docs.mathjax.org)

If client-side conversion is not suitable, render on the server: mathjax-node (or MathJax in Node) can produce SVG/PNG, or run a headless browser (Puppeteer) to render and screenshot. For client-side SVGs that still need rasterizing, libraries like canvg can draw SVG into canvas without using foreignObject. Always verify that any fonts or images referenced by the SVG are same-origin or embedded, since cross-origin fonts/images will re-taint the canvas. (github.com)

Recommended Answers

All 6 Replies

Member Avatar for Member #120589

I don't think tthat svg supports mathml inside it (yet). However, I came across this (in python) - I don't know if it's any use:

had a further look and found that Chrome does not provide native support for MathML and that IE9 can't run the MathPlayer plug-in.

Thanks for the link, and for taking a look at my question -- I can see the mathML rendered in the canvas. The PNG just does not get created successfully.

Member Avatar for Member #120589

The fontsize needs to be font-size . Perhaps that will make a difference? What browser are you using?

Well, the font certainly got larger :-), but unfortunately, still no .PNG. I'm tried it with Firefox, Internet Explorer, and Chrome under a local Apache server with a Windows 7 PC...

I'll check these out...thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.