fix(pdf): clear a minimum font size per line block, and only where one bites - #753
Merged
Conversation
andiwand
force-pushed
the
fix/pdf-matrix-run-font-size
branch
2 times, most recently
from
August 27, 2026 21:44
384d4d6 to
ee1dcb7
Compare
…e bites A minimum font size clamps a uniform run just as it clamps a matrix-placed one, so both need the blow-up — but a constant 48 charged every block for it, laying a page of body text out at 400-900pt. A block is now laid out at the 24px floor only when its own `font-size` falls under it, and scales back by exactly that much: the uniform path through a `z` class, the matrix one through its own matrix. At or above the floor the factor is 1 and the block is emitted byte for byte as it was. The clamp reads the specified size, so zoom does not move the floor. Rendered with a minimum font size set, every page checked now matches its own unclamped render pixel for pixel. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0169dUoxqhqfi7ZU5ei8b9ov
andiwand
force-pushed
the
fix/pdf-uniform-run-font-size
branch
from
August 27, 2026 21:54
abf7cb5 to
2bed5c9
Compare
andiwand
added a commit
that referenced
this pull request
Aug 28, 2026
#753 lays a line block out at the 24px floor only where its own font size falls under it, which moved 25 public and 785 private pdf pages. Every one carries the same text in the same place — only the glyph rasterisation differs, checked page by page against the old reference. The pins also pick up the comment `resources/document.css` grew after #748 was regenerated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KiPhteiEmPp8iPQLBfnthA
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
Stacked on #752.
#752 lays a matrix-placed run out large and scales it down, because a producer
writing
1 Tfgets afont-sizeany minimum clamps. A minimum clamps auniform run just the same, so both paths need it — but doing it with a
constant
48charges every block for it and lays a page of body text out at400–900pt.
What this does
A line block is laid out at the 24px floor only when its own
font-sizefalls under it, and scales back by exactly that much: the uniform path
through a new
zclass, the matrix path through its own matrix. At or abovethe floor the factor is 1 and the block is emitted byte for byte as before —
no transform, no
z, nothing.text_local_scale = 48→text_floor_pt = 18(24px, the largest minimum achrome user can set; an android webview defaults to 8px) plus
local_scale(font_size_pt).run_geometrygoes back to the natural matrix and size; each layer appliesits own block's scale. Size is already in the visual and single-layer flow
keys, so the factor is constant per block there; the selection layer groups
by frame rather than size, so it carries the scale as block state and a run
joining a block is measured in that block's space.
.tno longer carries a transform.The clamp reads the specified size, not the zoomed one — verified against
--blink-settings=minimumFontSizeat zoom 1 / 0.5 / 0.25 — sobody's fitzoom does not move the floor.
Verification
Each page rendered with and without a browser minimum font size, diffed
against the unclamped render (the truth):
with_form.pdfphd-agreement.pdfsvg_background_with_page_rotation_issue402.pdfCasio_WVA-M650-7AJF.pdfmova-viax-500-user-manual-de.pdfgeneve_1564.pdfWith no minimum set, text lands in the same place at the same size; 0.2–0.9% of
pixels differ from glyph rasterization (the browser rasterizes e.g. 18pt scaled
by 0.667 rather than 12pt). A magnified crop confirms identical positions and
metrics.
Against the constant 48 on
978-3-030-65771-0.pdf: maxfont-size60pt ratherthan 2880pt, html 9.74 MB rather than 10.15 MB, 28 scale classes rather than
one transform on all ~25 000 line blocks. Load, scroll frame times and zoom
steps are unchanged across all three variants.
Note
Nearly every pdf's output changes, so
test/data/reference-outputneedsregenerating and the pointer advanced.