↑ set by the engine on this page: "mp-tikz-wasm" infont "cmbx10", Computer Modern Type 1 outlines converted to SVG paths by MetaPost's own backend.

John Hobby's MetaPost 2.11, pdfTeX 1.40 and dvisvgm 3.4 compiled to WebAssembly. MetaPost source in; SVG with real glyph outlines, EPS and structured JSON out — including btex … etex labels typeset by plain TeX or LaTeX. And whole TikZ/PGF documents: LaTeX to DVI to SVG, shadings and pgfplots included. No server, no web fonts, no rendering shortcuts: the output is byte-identical to native mpost and latex + dvisvgm from TeX Live 2025. (The full build adds a fourth engine, LuaTeX, for TikZ graph drawing; it is left out of this single file for size.)

decoding the engine (everything on this page is inlined)…
Live editor

Edit MetaPost, see it typeset

⌘⏎ / Ctrl+Enter
How a label gets typeset

TeX, without a subprocess

Native MetaPost shells out to TeX from the middle of its scanner. WebAssembly cannot, so the TeX step is lifted out of the run:

  1. Scan. The source and every input-ed file are scanned for btex/verbatimtex blocks with a TypeScript port of mpto's lexer, tested byte-for-byte against the C original.
  2. Typeset once. Every block not already in the snippet cache goes into one batched pdfTeX run in DVI mode — one page per block. The formats (plain.fmt, latex.fmt) were built by this same wasm engine.
  3. Convert. MetaPost's own dvitomp, linked into mplib.wasm, turns the DVI into .mpx picture expressions, split per block and cached by a hash of engine, format, preceding verbatimtex chain and body.
  4. Run. MetaPost runs with extensions=1; its make_text callback answers each btex synchronously from the cache. Type 1 fonts become SVG paths (prologues:=3).
  5. Fixpoint. A label the scan could not see (scantokens) misses, comes back as nullpicture, and the run repeats once it has been typeset — LaTeX's own trick for cross-references.

TikZ takes the other road. A TikZ document is not a label but a whole page, so it skips MetaPost entirely: pdfTeX writes a DVI whose \specials carry PGF's drawing commands, and dvisvgm — the reference converter, with its PGF/dvisvgm special handlers, FreeType and potrace — turns each page into SVG with glyph outlines. Same engine, same fonts, same bundles; a different last step.

Numbers

Small enough to inline, fast enough to type into

ArtifactSize
Scenario (Node, M-series Mac)Time
geometry figure, incl. parsing plain.mp14 ms
label("MetaPost") with outlines6 ms
plain TeX label, cold cache115 ms
LaTeX + amsmath, cold cache185 ms
the same, warm cache5 ms
40 labels, cold cache62 ms, one TeX run
40 labels, one edited91 ms, one page

Fidelity

The golden corpus — paths, pens, fills, transforms, clipping, labels, plain-TeX and LaTeX labels, boxes, graph, error recovery — is byte-identical to mpost in EPS and SVG (15 of 15 cases). The mtrap conformance run produces the same figures as native MetaPost 2.11. tex.wasm reproduces the oracle's DVI byte for byte.

Upstream bugs found along the way

  • a process-global static flag in psout.w crashed the second MetaPost instance in a process on any font render;
  • the extensions=1 scanner never matched an etex at the end of a line, and required a space before it (TeX Live's own texnum.mp writes btex$-$etex);
  • the SVG backend printed stroke-miterlimit for filldraw from uninitialised memory;
  • mpto's prologue had a bare % in a printf format — glibc, BSD and musl each did something different.