Skip to content

fix(html): a selection no longer paints the pdf's hidden text layer - #907

Merged
andiwand merged 2 commits into
mainfrom
fix/pdf-selection-paints-hidden-text
Sep 20, 2026
Merged

andiwand merged 2 commits into
mainfrom
fix/pdf-selection-paints-hidden-text

Conversation

@andiwand

@andiwand andiwand commented Sep 20, 2026 •

Copy link
Copy Markdown
Member

A pdf view draws its glyphs in one layer and keeps the real Unicode in another, which is color:transparent so that it can be selected and copied without being seen. A browser paints selected text in the highlight's own foreground colour, and that overrides transparent: as soon as the reader selects anything, the hidden glyphs appear on top of the drawn ones, in a substitute font and at their own advances.

The invisible classes now state color:transparent for ::selection too, so a selection paints its background and nothing else.

  • the dual layer's .i (and its run spans)
  • the single layer's .i, .ov and .sp
  • the per-font .fnN that an embedded font's invisible run carries

How it was found

Reported against the Android app: selecting text in a pdf makes a second, offset copy of the words appear. Measured in the app's WebView, and reproduced in chromium with a two-layer page - one box with the rule and one without.

Nothing renders differently, so the reference output is unchanged.

A pdf view draws its glyphs in one layer and keeps the real Unicode in
another, which is `color:transparent` so that it can be selected and
copied without being seen. A browser paints selected text in the
highlight's own foreground colour, and that overrides `transparent`: as
soon as the reader selected anything, the hidden glyphs appeared on top
of the drawn ones, in a substitute font and at their own advances.

The invisible classes now state `color:transparent` for `::selection`
too, so a selection paints its background and nothing else. This covers
the dual layer's `.i`, the single layer's `.i`, `.ov` and `.sp`, and the
per-font `.fnN` an embedded font's invisible run carries.

Checked in chromium, and against the Android app's WebView on a pdf whose
hidden layer was visible before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJJdfqpnVCKBNHXjAVxSou
andiwand added a commit that referenced this pull request Sep 20, 2026
Not for merge: this branch only exists so CI assembles an AAR carrying PR #907 and PR #908 together, for a device test.
`::selection` matches the element that paints the text, not its ancestors.
In the single layer `.i` and `.fnN` sit on the line block, so a run that
carries a `margin-left` span, and a `mark` inside `.ov` or `.sp`, kept the
highlight's own colour. The rules now take the descendants too, as the dual
layer's `.i *::selection` already did.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149gFxhkvKTBQidz6brU8Vt
@andiwand
andiwand merged commit e1e2dce into main Sep 20, 2026
25 checks passed
@andiwand
andiwand deleted the fix/pdf-selection-paints-hidden-text branch September 20, 2026 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant