fix(html): scale the text with the fit, where webkit holds it back - #811
Merged
Conversation
Webkit reads a css `zoom` as a scale the reader asked for and holds text at the size it would have had without one, so `fit_width_by_view` fitted the page box and left the type at its natural measure. It states that compensation as `text-size-adjust` divided by the zoom, so the script now states the zoom back as the percentage. Blink reads the same percentage as a plain multiplier, so a probe decides whether to state it at all. Closes #761. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018cMYRXLJdiCkH65Jm2W9B5
andiwand
force-pushed
the
fix-viewport-webkit-text-scale
branch
from
September 2, 2026 20:47
c259500 to
89f6798
Compare
andiwand
enabled auto-merge (squash)
September 2, 2026 20:58
andiwand
disabled auto-merge
September 2, 2026 21:08
andiwand
added a commit
to opendocument-app/OpenDocument.test.output
that referenced
this pull request
Sep 3, 2026
Regenerated for opendocument-app/OpenDocument.core#811, which advanced the private pin and left this one behind. Every view's `@media print` block resets `text-size-adjust` beside the zoom, and `viewport.js` states the applied zoom as that percentage where webkit needs it. On screen nothing moves: the rule is print-only and the property is inert in blink. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013bF15rJXQB1Jo3g3CJZCcQ
andiwand
added a commit
that referenced
this pull request
Sep 3, 2026
#811 gave every view a print-only `text-size-adjust` reset and rewrote `viewport.js`, and advanced the private pin only. `compare-html` renders what is not byte-identical, so the public compare went from rendering nothing to rendering all 411 files, where the pdf and svg views screenshot nondeterministically — two pdf pages came out "different" on main. The reverted `docx` reference on the output repo's main belongs to a branch that has not landed; it returns with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013bF15rJXQB1Jo3g3CJZCcQ
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
Closes #761.
What was wrong
Not the meta tag, and not the script failing to run. In
fit_width_by_viewon iOS the view does fit:body{zoom:0.4867}is applied,odr.getZoom()returns 0.49, the A4 page box lands at the screen width. The type does not follow.Webkit reads a css
zoomas a scale the reader asked for and holds text at the size it would have had without one. It expresses that throughtext-size-adjust, dividing the stated percentage by the zoom:text-size-adjustunderzoom:kauto— the default, and what we shipnoneor100%1/kk·100%So #761's "heading unchanged, body text ~2×, reflowed" is a correctly fitted page with the text left behind. The same held for
odr.setZoom, which was equally wrong on iOS.The change
viewport_jsstates the zoom back as the percentage whenever it applies one. Blink reads the same percentage as a plain multiplier —50%underzoom:0.5halves the text a second time — so a probe at startup measures whether stating it holds the type, and it is only stated where it does.@media printresets it beside the zoom.apply()and the startup block go through onezoomBody, which also restates a zoom the css stated (viewport_width,initial_zoom), so those pages carry the adjustment too.Measured
iPhone 17 Pro / iOS 26 simulator, Pixel 9 Pro / Chrome 139 emulator, desktop Chrome, macOS WebKit — a WKWebView harness serving the emitted html, plus
test/browser/viewport.--odr-fit:view, the sample ODT, after:text-size-adjuststaysauto, page fitted, type exact — unchanged.tests.htmlall passed; both top-level banners PASS.odr_test --gtest_filter='html*:*Html*': 346 passed, 6 pre-existing skips.Reference output
The print rule and
viewport.jschanged, so every emitted document moves by that one rule — on screen nothing does.compare-html --driver chromeover the private corpus: the differing set is not reproducible run to run (4, then 3, then 1 file, same pair of trees), and splitting the change proves it — the reference against the new script alone matches all files, the print rule alone flakes. Pre-existing rasterisation noise, not this change.Regenerated anyway, so the reference stays what the renderer emits:
resources/viewport.js; nothing else moved. Pushed asbcea37b, andtest/data.cmakeadvances to it.d456f47, the regen for the unlanded docx: a floating drawing renders inline, and a table's borders are dropped unless they sit on the cell #803, so a regen from this branch would revert docx: a floating drawing renders inline, and a table's borders are dropped unless they sit on the cell #803's docx output, and pinning a commit that contains docx: a floating drawing renders inline, and a table's borders are dropped unless they sit on the cell #803 would fail CI on a main that has no docx: a floating drawing renders inline, and a table's borders are dropped unless they sit on the cell #803. Its pin stays at3dcc4fb; the reference renders identically to what this branch emits, so CI is green either way, and docx: a floating drawing renders inline, and a table's borders are dropped unless they sit on the cell #803 picks the rule up in its own regen.Two findings not acted on here
text-size-adjustcannot defeat it (16px atzoom:0.25→ 36px; 40px → 40px). At the deepest fits this floors table text — 12pt at zoom 0.487 renders at 9px instead of 7.8px, laying the sample out 9% taller. Non-table text is unaffected.automaticmode on iOS, webkit boosts body text — 12pt → 23px, 16pt → 24px, the sample 1949px tall against 1702px. iOS renders therefore do not match the reference renders. A statictext-size-adjust:100%in the shipped css fixes it and is a measured no-op in Blink, but it also makes an A4 page's body text genuinely tiny on a phone, so it is left out of a bug fix.Not covered by the browser checks
page.html's 400 identical lines do not produce the cluster shape that triggers the inflation, so a check added there detected only the 9px floor and was dropped. The limitation is recorded in the harness README instead; the oracle is a real document served to a real webkit.