diff --git a/CHANGELOG.md b/CHANGELOG.md index 8788cbc33..b1e909d60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ The release run heads these entries with the version and opens a fresh ## Unreleased +- **Fix**: selecting text in a pdf view showed the invisible layer that carries + it, as a second set of glyphs over the drawn ones. That layer now stays + transparent under `::selection`. + ## v7.1.0 - 2026-09-19 - The pdf view reports the pending annotation count on diff --git a/src/odr/internal/html/pdf_file.cpp b/src/odr/internal/html/pdf_file.cpp index 2846b386a..ba3330e15 100644 --- a/src/odr/internal/html/pdf_file.cpp +++ b/src/odr/internal/html/pdf_file.cpp @@ -1817,6 +1817,9 @@ class HtmlServiceImpl final : public HtmlService { } // Transparent text for the selection layer line blocks. out.out() << ".i{color:transparent;font-family:sf,sans-serif}"; + // A selection paints text in the highlight's own colour, which beats + // `transparent` and shows this layer over the glyph layer it stands for. + out.out() << ".i::selection,.i *::selection{color:transparent}"; // Selection-layer run span. `overflow:hidden` clips a wider system font; // `.t`'s inherited `pre` blocks wrapping while preserving a run's own // leading/trailing space, which is real PDF content. @@ -2287,6 +2290,11 @@ class HtmlServiceImpl final : public HtmlService { // height, while clipping nothing (the space is transparent). out.out() << ".sp{display:inline-block;" "color:transparent;vertical-align:baseline}"; + // A selection paints text in the highlight's own colour, which beats + // `transparent`. `*` reaches a run's own span and a search `mark`. + out.out() << ".i::selection,.i *::selection," + ".ov::selection,.ov *::selection," + ".sp::selection,.sp *::selection{color:transparent}"; // A hit in the overlay is clipped away with it, so the glyphs it belongs // to carry the highlight instead - the whole run of them, which is as // narrow as the overlay can say. @@ -2859,6 +2867,10 @@ class HtmlServiceImpl final : public HtmlService { } if (class_used[1]) { rule("fn", "color:transparent;"); + // The same guard for a line the embedded font makes invisible; the dual + // layer's `fnN` rides a `user-select:none` run and needs none. + font_styles += ".fn" + n + "::selection,.fn" + n + + " *::selection{color:transparent}"; } }