ci(test): run every embedded font through OTS - #806
Merged
Conversation
OTS is the sanitizer every browser puts in front of an `@font-face`, and it is far stricter than FreeType or fontTools: a font it rejects is dropped whole and the text renders as tofu. #613, two thirds of #660 and #702 all shipped that way and were all found by eye. `test/scripts/check_fonts.py` pulls every `data:font/...;base64` payload out of the generated html, sanitizes each distinct one once and names the html file and the `font-family` of any OTS refuses. The `test` job runs it over `build/test/output` right after `odr_test`. No browser, no reference output — which is the point, since a regression already in the reference output is invisible to the comparison and #660 in fact sat there. Over today's corpus: 765 distinct fonts, 8492 embeddings, none rejected, in eight seconds. Part 1 of #765. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018cMYRXLJdiCkH65Jm2W9B5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Part 1 of #765 — the cheap, deterministic half.
OTS is the sanitizer every browser puts in front of an
@font-face, and it is far stricter than FreeType or fontTools: a font it rejects is dropped whole and every glyph renders as tofu.font_is_usable(html/pdf_file.cpp) only probes that our own encode path does not throw; whether OTS accepts the bytes we then emit has never been checked anywhere. #613, two thirds of #660 and #702 all shipped that way and were all found by eye.What lands
test/scripts/check_fonts.py <dir>walks the html, pulls out everydata:font/...;base64payload, sanitizes each distinct one once (the same font is embedded in every page of a document) and, on a rejection, names the html file, thefont-family, and OTS's own reason.The
testjob runs it overbuild/test/outputright afterodr_test, next to the existinghtml-tidy/compare-htmlsteps.opentype-sanitizer==9.2.0joins the pip install; the script falls back toots-sanitizeon PATH.The point of doing it this way: it needs no browser and no reference output, so it cannot be papered over by regenerating that — which is how #660 came to sit in the reference unnoticed.
Verification
Over today's corpus output:
in 8 seconds.
And with one font's first table tag clobbered, to prove it is not vacuous:
Not in this PR
Part 2 of the issue — the glyph-level oracle comparing
gs -sDEVICE=txtwriteagainst the html's text — and the stronger "assert it insideodr_testovertest/src/internal/font/" variant. Both are worth doing and neither blocks this.CI-only, so no
CHANGELOG.mdentry.