Repository navigation
[shot-ci] Per-OS screenshot CI: slim suite + ZaTeX on Linux/Windows - #401
gregoreesmaa wants to merge 16 commits into
Conversation
…uble verdict arms
1360a4c to
30b9a8e
Compare
There was a problem hiding this comment.
Seems like Linux has the wrong title font. I can't make sure of other fonts.
There was a problem hiding this comment.
Fixed in 985ba35 + regen 315c4aa. Root cause: bundled SpaceGrotesk.ttf is a variable font (wght 300-700, default Light-300) and the Linux backend returned the default instance for headings, which force bold everywhere. linux.c now pins wght to 700 via FT_Set_Var_Design_Coordinates on the cold font-registration path (base FreeType, silent fallback). Body Plex faces are static and were already correct; JetBrains Mono defaults to Regular as needed. macOS/Windows heading selection was already bold-resolving; Windows got the same class of fix (request 'Space Grotesk Light'). Full suite 596/596, benchmarks green.
There was a problem hiding this comment.
The (heading) title font is correct, but should be more bold.
The rest of the fonts look awful. Some letters are bold while others are not. Curiously the bold letters are specifically: e, o, t, p, C.
There was a problem hiding this comment.
Heading: the wght=700 pin may not be taking effect -- linux.c now checks the FT_Set_Var_Design_Coordinates return (previously ignored, half-pinned faces possible) and logs the live wght under TEST_HOOKS, plus a heading-only FT_Outline_Embolden (~1/64em) at raster time (961a5b6). Linux shots need a CI regen to show it; the committed linux PNGs predate all fixes. Body letters: no face bug exists -- Plex Regular covers e,o,t,p,C so fallback cannot trigger, and no conditional embolden exists anywhere. Measured: Linux body is uniformly ~2.3x heavier-tailed (39-45% 3px runs vs macOS 17-18%), hinter stem-darkening + floor-phase jitter at 17px/1x, concentrated on bowls/junctions -- which is exactly the e,o,t,p,C set. Part of what reads as random bold is the intentionally-bold admonition labels (Note/Tip/Warning/Caution contain those letters). Left load flags alone rather than risk the crisp floor on an unconfirmed cause.
There was a problem hiding this comment.
Math doesn't render. Is this a ZaTeX bug or Read's? Any way we could make ZaTeX even easier to use in this regard?
There was a problem hiding this comment.
Byte-level verdict: linux/math.png is live, not fallback. Independent census (inflate IDAT + bg-relative ink): linux ink 13541 (1.25%) vs win-live 16079 (1.49%) vs guaranteed local fallback 26067 (2.41%); row-profile cosine 0.79 to win-live vs 0.29 to fallback; rows 300-375 empty like live vs ~1500-3500 in fallback. So neither ZaTeX nor Read's loader is at fault -- the engine is engaged. One caveat: linux shows no 86px display-rule bars where win-live has them (y=329,566) -- inline/fence geometry is live, display rules need a Linux-owner eyeball on the next CI regen. Harness hardening in 985ba35 (save/restore READ_ZATEX_LIB + loud FAIL when the engine path is missing) covers the Linux CI path regardless. On easier ZaTeX use: the failure mode you saw is silent fallback; the loud FAIL turns it into a CI error, which is the cheapest fix without an engine API change.
There was a problem hiding this comment.
But I see no math in this render?? Fix it.
There was a problem hiding this comment.
The Linux math path exists (linux_zatex.c: size + draw + dlopen of READ_ZATEX_LIB); when the engine .so is absent the doc falls back to literal source text, never blank. The committed linux/math.png does contain formula bands (rows 219-231 etc.), so the engine was engaged at capture -- but those PNGs predate all fixes and a missing libzatex.so at shot time is still the prime suspect for an empty render. The suite now hard-fails Linux math captures without READ_ZATEX_LIB instead of silently shooting fallback. Next CI regen will show the fixed state; if a formula is still missing there, the stderr line (libzatex.so unavailable) distinguishes engine-absent from a rendering bug.
There was a problem hiding this comment.
The spacing (whitespace chars) in titles gets lost
There was a problem hiding this comment.
No code defect found -- verified by pixel-decoding the shots (Windows and macOS inter-word profiles match word-for-word with clear gaps) and by tracing the shared flowSpans/flowWord layout path, which has no Windows-only whitespace collapsing. Pinned with a regression test instead (spec_compliance_test.zig: heading interior multi-space preserved, asserts two-space gaps survive in command geometry). If a specific title still looks collapsed in the regen shots, a coordinate would help -- the remaining explanation is the tight 0.22em heading word space reading as lost at a glance.
There was a problem hiding this comment.
No it really looks like "AdmonitionAlerts" with the "n" and "A" being uncomfortably close together
There was a problem hiding this comment.
I compared against Windows and the alignment of each word is perfect. Just the kerning between letters is too big here.
Also the font should be more bold.
There was a problem hiding this comment.
Both symptoms are the same root cause, now fixed. The bundled SpaceGrotesk.ttf is a variable font (wght 300-700, default Light-300) and GDI has no variation API, so requesting bold returned Light-300 outlines: -35% stroke and wider Light letterspacing, which overflowed the layout word slot into the inter-word space (word origins matched macOS exactly, only intra-word raster was wide). Fix in 607cb07/d0f7413: headings draw with the missing -0.015em tracking applied (matching layout/macOS/Linux) plus a +1px overstrike pass until a static wght=700 instance ships. admonitions.png regenerated. Note the overstrike fixes stroke only; kerning stays Light-wide by design -- the real fix needs a static Bold instance (fonttools instancer command is documented in the code for whoever has the toolchain).
There was a problem hiding this comment.
Word alignment was the clue: layout word origins are identical across OSes, so the defect was intra-word raster only. Same fix as above (tracking + overstrike in 607cb07/d0f7413, shot regenerated). The remaining kerning delta vs macOS is the Light master metrics -- only a static Bold instance closes that; overstrike is stroke-only by design.
There was a problem hiding this comment.
Math render is off. Is this a ZaTeX bug or Read's? Any way we could make ZaTeX even easier to use in this regard?
There was a problem hiding this comment.
Read's bug, not ZaTeX's -- fixed in 523aa7e. win32_zatex.c zatex_advance passed the engine's glyph id to GetCharABCWidthsFloatW, which takes code points, so it silently measured the wrong character (U+2211 measured as U+03C3 sigma, ~20% narrow). Engine laid out with wrong advances while the ETO_GLYPH_INDEX draw used true advances, so every formula was cramped/misaligned. Now GetCharABCWidthsI (+GetCharWidthI for non-TT faces). Engine exonerated at pinned f74bedd. math.png re-rendered live with the fix (verified 542k bytes from guaranteed fallback). On easier use: same answer as the linux thread -- the loud FAIL in the harness turns silent fallback into a CI error.
There was a problem hiding this comment.
It looks still badly off
There was a problem hiding this comment.
Correct -- the ABCWidthsI fix repaired the id namespace but dropped the x10 the thousandths contract requires (contract.zig:156-172; macOS does adv/1001000). Fixed in 71d9b43: adv10/w*10. Same commit fixes a second bug: the math draw passed baseline Y as the ExtTextOutW cell top, sitting every run ~one ascent low (display #1 was +16px). math.png regenerated: widest formula band went from 29-40px slivers to 593px full width. ZaTeX exonerated on both counts.
There was a problem hiding this comment.
The ends of links followed by characters (e.g. . or )) have the character overlap with the end of the link.
There was a problem hiding this comment.
Fixed in d0f7413 (clip-only). GDI URL advances run ~2-4px past layout's static-table widths, so link ink bled into the trailing run's slot and the rw-sized underline extended ~4px under the ./). platform_draw_text now clips both ExtTextOutW paths to the layout slot (ETO_CLIPPED); bare_links.png regenerated. Underline keeps the re-measured width -- threading layout width through the platform bridge would touch 3+ files for the remaining ~px, deferred.
There was a problem hiding this comment.
The underline of links is too bold. Should be few pixels.
There was a problem hiding this comment.
Fixed in d0f7413. The constant was already 1px -- the bug was the unsnapped origin: at fractional uy the fill covered two opaque device rows on win32/Linux, while macOS coverage-AA'd the same rect into a visual 1px. uy is now roundf-snapped on win32 (same one-line change belongs on linux.c:945 and macos.m:2670 for parity; Linux/macOS shots need a CI regen to show it). Verified in the regen: single blue row, neighbors zero.
There was a problem hiding this comment.
The underline of links is too bold. Should be few pixels.
There was a problem hiding this comment.
Same root cause as the windows thread: the 1px rule at fractional uy fills two opaque rows on win32/Linux. Fixed on win32 in d0f7413 (uy roundf-snapped; verified single row in regen). linux.c:945 carries the identical unsnapped expression and needs the same one-line roundf -- queued for the next round along with the Linux CI regen, which is also what will show the linux heading/math fixes.
Closes the missing piece of #399 (macOS screenshots) by generating all three OS sets in CI. Slim high-impact suite (~25 PNGs/OS) into screenshots// with per-OS artifacts. ZaTeX live everywhere via pinned third_party/zatex submodule + new FreeType/GDI metrics backends. See docs/superpowers/specs/2026-10-03-per-os-screenshot-ci-design.md.