Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ The release run heads these entries with the version and opens a fresh

## Unreleased

- **Fix**: marking text in a pdf view left the selection one handle, because a
run of the selection layer clipped the end that handle belongs to. Nothing
clips a run now, so both handles show and the mark can be adjusted.

- **Fix**: selecting text in a pdf view hid the words it selected. The
`::selection` background v7.2.0 states is `Highlight`, which is opaque, and
the layer carrying it paints over the glyph layer. It is see-through now, so
Expand Down
20 changes: 11 additions & 9 deletions src/odr/internal/html/pdf_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1787,8 +1787,8 @@ class HtmlServiceImpl final : public HtmlService {
out.out() << ".g{user-select:none}";
// Selection-layer fallback font: `size-adjust` shrinks a local system
// font under the PDF-derived `.sr`/`.sg` widths. CSS justify only ever
// *adds* spacing, so undershooting is free while overshooting overflows
// and is clipped — hence the deliberately low config default. With no
// *adds* spacing, so undershooting is free while overshooting spills out
// of the run — hence the deliberately low config default. With no
// fonts configured `.i` falls through to plain `sans-serif`.
if (const std::vector<std::string> &fonts =
config().pdf_dual_layer_fallback_fonts;
Expand Down Expand Up @@ -1825,15 +1825,17 @@ class HtmlServiceImpl final : public HtmlService {
<< ".i::selection,.i *::selection"
"{color:transparent;background-color:rgba(70,130,220,.32);"
"background-color:color-mix(in srgb,Highlight 45%,transparent)}";
// Selection-layer run span. `overflow:hidden` clips a wider system font;
// Selection-layer run span. No clip: a system font wider than the pdf
// advance spills, and a webview draws no selection handle for an end it
// cannot see. The clip also carried the y alignment, so state it:
// `.t`'s zero-height strut puts the line box bottom on the baseline.
// `.t`'s inherited `pre` blocks wrapping while preserving a run's own
// leading/trailing space, which is real PDF content.
out.out() << ".sr{display:inline-block;text-align:justify;"
"text-align-last:justify;text-justify:inter-character;"
"overflow:hidden}";
// Selection-layer gap spacer. `overflow:hidden` matches `.sr`: an
// inline-block baseline-aligns to its bottom margin edge only when
// overflow isn't visible, so without it the spacer shifts in y.
out.out() << ".sr{display:inline-block;vertical-align:bottom;"
"text-align:justify;text-align-last:justify;"
"text-justify:inter-character}";
// Selection-layer gap spacer. It holds only a space, so no handle can
// land in it and the clip is free, along with the y alignment it gives.
out.out() << ".sg{display:inline-block;overflow:hidden}";
// A lone space cannot be justified to its box, so pad the advance and let
// the width clip it: else every word break shows a sliver of white.
Expand Down
Loading