Skip to content

SVG exports with mathtext render incorrectly in browsers and VSCode #95

Description

@gsan211

Describe the bug

Saving a figure that contains matplotlib mathtext (e.g. r"$\alpha$ (effect size)") to SVG produces a visually broken result in any browser-based SVG renderer (VSCode preview, web browsers). Characters in mixed math/text labels overlap or are incorrectly spaced. The same
figure looks correct in the Jupyter notebook inline preview.

To reproduce

import arcadia_pycolor.mpl as apc_mpl
import matplotlib.pyplot as plt

apc_mpl.setup()

fig, ax = plt.subplots()
ax.set_xlabel(r"$\alpha$ (effect size)")
ax.set_ylabel(r"$R^2$")
ax.plot([1, 2, 3], [1, 4, 9])

apc_mpl.save_figure("test.svg", size="half_square")

Open test.svg in VSCode or any browser. The x- and y-axis labels are garbled.

Root cause

Two possible interacting issues:

  1. Font name compaction breaks browser font lookup.
    _fix_svg_fonts_for_illustrator replaces 'Atkinson Hyperlegible Next' (CSS family name, with spaces) with 'AtkinsonHyperlegibleNext' (PostScript name, compact). Illustrator resolves fonts by PostScript name, but browsers resolve by CSS family name. After the fix runs, browsers cannot find the font and fall back to a system default.

  2. Mathtext pre-positions every character individually.
    When a label mixes mathtext and regular text, matplotlib's SVG backend emits each character as a separate with an explicit x offset calculated from Atkinson's glyph metrics. When the browser substitutes a fallback font with different character widths, those pre-calculated offsets are wrong and the text overlaps. This is why the problem only surfaces with mathtext — ordinary labels are stored as a single string and tolerate font substitution gracefully.

Workaround

import matplotlib as mpl
mpl.rcParams['svg.fonttype'] = 'path'
mpl.rcParams['mathtext.default'] = 'regular'

svg.fonttype = 'path' embeds all glyphs as vector paths, eliminating font lookup entirely. mathtext.default = 'regular' makes math characters use the same Atkinson font as surrounding text instead of DejaVu Sans, ensuring visual consistency. The trade-off is that text becomes outlined paths in Illustrator and is no longer live-editable.

Environment

  • arcadia-pycolor version: 0.7.3
  • matplotlib version: 3.10.0
  • Platform: Linux

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions