Skip to content

Re-enable tests when building wasm wheels - #32141

Draft
QuLogic wants to merge 2 commits into
matplotlib:mainfrom
QuLogic:wasm-tests
Draft

Re-enable tests when building wasm wheels#32141
QuLogic wants to merge 2 commits into
matplotlib:mainfrom
QuLogic:wasm-tests

Conversation

@QuLogic

@QuLogic QuLogic commented Jul 30, 2026

Copy link
Copy Markdown
Member

PR summary

See title; WIP.

AI Disclosure

None

PR quality check

  • [n/a] Use an expressive title, e.g. "Fix title font property precedence"
  • New and changed code is tested
  • [n/a] Plotting related features are demonstrated in an example
  • [n/a] New features and API changes have release notes
  • [n/a] Documentation complies with general and docstring guidelines

@QuLogic QuLogic added the CI: Run cibuildwheel Run wheel building tests on a PR label Jul 30, 2026
@QuLogic

QuLogic commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

So I didn't expect this to pass; just confirming it's broken on CI just as it is locally. What's confusing to me is that 99% of the failures are in test_mathtext.py; the only other failure is test_ft2font.py::test_fallback_last_resort (which isn't mathtext). No other test files that use mathtext fail.

Based on debugging locally, some differences arise here:

for font, size, glyph_index, slant, extend, dx, dy in glyphs: # dy is upwards.
font.set_size(size, self.dpi)
font._set_transform(
(0x10000 * np.array([[cos, -sin], [sin, cos]])
@ [[extend, extend * slant], [0, 1]]).round().astype(int),
[round(0x40 * (x + dx * cos - dy * sin)),
# FreeType's y is upwards.
round(0x40 * (self.height - y + dx * sin + dy * cos))]
)
bitmap = font._render_glyph(
glyph_index, load_flags,
RenderMode.NORMAL if gc.get_antialiased() else RenderMode.MONO)
buffer = bitmap.buffer
if not gc.get_antialiased():
buffer *= 0xff
# draw_text_image's y is downwards & the bitmap bottom side.
self._renderer.draw_text_image(
buffer,
bitmap.left, int(self.height) - bitmap.top + buffer.shape[0],
0, gc)

The transform set on the font is the same (once scaled to fixed-precision ints), but after rendering the glyph, the bitmap is one pixel off (either in x/y or sometimes in size as well.)

@QuLogic

QuLogic commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

The transform set on the font is the same (once scaled to fixed-precision ints), but after rendering the glyph, the bitmap is one pixel off (either in x/y or sometimes in size as well.)

I managed to find test_mathtext.py::test_mathtext_rendering[png-mathtext-stix-2] which has no moved elements but still fails.

@QuLogic

QuLogic commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

I did not verify all tests, but I'm leaning towards the problem specifically being with STIX fonts as (aside from the tests that are specifically about STIX) the images that fail all have e.g., scaled parentheses/radicals/etc from one of those fonts. No tests outside of test_mathtext use STIX (I added an exception to the code to confirm this).

Comparing DejaVu Sans, STIXSizThreeSymReg and LastResortHE-Regular with fontTools, it looks like DejaVu has unitsPerEm=2048 while STIX is 1000. Unfortunately, Last Resort is also 2048, so it's not some kind of lower resolution grid problem.

The OS/2 table in DejaVu is version 1 while STIX is 2 and Last Resort is 4. I think this just means there are additional fields for metrics and should not affect rendering algorithms (outside of which metric to choose.)

The other difference is that the DejaVu header has flags that say it a) has instructions that may depend on point size and b) instructions may alter the advance width (i.e., glyphs may not be spaced exactly the same distance apart depending on font size.) Along those line, it also has the prep (Control Value Program), fpgm (Font Program) and cvt (Control Value Table) tables and several glyphs have custom instructions (over the normal contours), which the other fonts don't.

DejaVu also has a kern (Kerning) table, but that shouldn't matter as it only affects consecutive glyphs from the same font. There are a few other tables that DejaVu and STIX both have that Last Resort doesn't, so they may or may not be relevant; e.g., the gasp (Grid-fitting and Scan-conversion Procedure Table) is not in Last Resort, so maybe FreeType's default rules for that are not consistent, but since STIX has it, that seems unlikely.

So I edited out all the glyph instructions, and the prep, fpgm, and cvt tables and re-compiled DejaVu Sans with fontTools, then regenerated the test images with the new font. When I run these mathtext tests on wasm, then 132 tests fail (which I believe is almost all of the DejaVu Sans tests). This does seem to narrow down the issue to how FreeType positions glyphs that don't have instructions (or possibly, depending on what these instructions do, glyphs that have no internal snapping of some sort.)

@QuLogic

QuLogic commented Aug 1, 2026

Copy link
Copy Markdown
Member Author

I've pushed a change to add more debug logging from FreeType. This is where I get confused though because there is no trace of any debug logging from the TrueType driver code, and yet somehow the glyphs are loaded and rendered. Not only that, even if I explicitly patch in a printf in the driver code to load_glyph, it doesn't appear anywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend: agg CI: Run cibuildwheel Run wheel building tests on a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant