From 83c78dbfa8f2f532b22ba10cebca2a67c0fac8ef Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Thu, 18 Jan 2024 18:36:03 +0100 Subject: [PATCH] Make the caret visible in the text layer in caret browsing mode In order to do that we must change the text layer opacity to 1 but it has several implications: - the selection color must have an alpha component, - the background color of the span used for highlighted words must have an alpha component either, but now the opacity is 1 we can use some backdrop-filters in HCM making the highlighted words more visible. - fix a regression caused by #17196: the css variable --hcm-highlight-filter has to live under the #viewer element because in HCM it's overwritten by js at this level, hence links annotations for example didn't have the right colors when hovered. --- src/display/base_factory.js | 2 +- src/display/display_utils.js | 83 +++++++++++++++++++------------- web/annotation_layer_builder.css | 1 - web/pdf_page_view.js | 11 +++++ web/pdf_viewer.css | 5 ++ web/pdf_viewer.js | 11 +++++ web/text_layer_builder.css | 25 +++++++--- 7 files changed, 96 insertions(+), 42 deletions(-) diff --git a/src/display/base_factory.js b/src/display/base_factory.js index c6da0791c1f78..70457ff203edd 100644 --- a/src/display/base_factory.js +++ b/src/display/base_factory.js @@ -30,7 +30,7 @@ class BaseFilterFactory { return "none"; } - addHighlightHCMFilter(fgColor, bgColor, newFgColor, newBgColor) { + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { return "none"; } diff --git a/src/display/display_utils.js b/src/display/display_utils.js index 8380212413888..2ff337ee7ce40 100644 --- a/src/display/display_utils.js +++ b/src/display/display_utils.js @@ -57,17 +57,7 @@ class DOMFilterFactory extends BaseFilterFactory { #document; - #hcmFilter; - - #hcmKey; - - #hcmUrl; - - #hcmHighlightFilter; - - #hcmHighlightKey; - - #hcmHighlightUrl; + #_hcmCache; #id = 0; @@ -81,6 +71,10 @@ class DOMFilterFactory extends BaseFilterFactory { return (this.#_cache ||= new Map()); } + get #hcmCache() { + return (this.#_hcmCache ||= new Map()); + } + get #defs() { if (!this.#_defs) { const div = this.#document.createElement("div"); @@ -161,16 +155,28 @@ class DOMFilterFactory extends BaseFilterFactory { addHCMFilter(fgColor, bgColor) { const key = `${fgColor}-${bgColor}`; - if (this.#hcmKey === key) { - return this.#hcmUrl; + const filterName = "base"; + let info = this.#hcmCache.get(filterName); + if (info?.key === key) { + return info.url; } - this.#hcmKey = key; - this.#hcmUrl = "none"; - this.#hcmFilter?.remove(); + if (info) { + info.filter?.remove(); + info.key = key; + info.url = "none"; + info.filter = null; + } else { + info = { + key, + url: "none", + filter: null, + }; + this.#hcmCache.set(filterName, info); + } if (!fgColor || !bgColor) { - return this.#hcmUrl; + return info.url; } const fgRGB = this.#getRGB(fgColor); @@ -183,7 +189,7 @@ class DOMFilterFactory extends BaseFilterFactory { (fgColor === "#000000" && bgColor === "#ffffff") || fgColor === bgColor ) { - return this.#hcmUrl; + return info.url; } // https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_Colors_and_Luminance @@ -203,7 +209,7 @@ class DOMFilterFactory extends BaseFilterFactory { const table = map.join(","); const id = `g_${this.#docId}_hcm_filter`; - const filter = (this.#hcmHighlightFilter = this.#createFilter(id)); + const filter = (info.filter = this.#createFilter(id)); this.#addTransferMapConversion(table, table, table, filter); this.#addGrayConversion(filter); @@ -223,22 +229,33 @@ class DOMFilterFactory extends BaseFilterFactory { filter ); - this.#hcmUrl = `url(#${id})`; - return this.#hcmUrl; + info.url = `url(#${id})`; + return info.url; } - addHighlightHCMFilter(fgColor, bgColor, newFgColor, newBgColor) { + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`; - if (this.#hcmHighlightKey === key) { - return this.#hcmHighlightUrl; + let info = this.#hcmCache.get(filterName); + if (info?.key === key) { + return info.url; } - this.#hcmHighlightKey = key; - this.#hcmHighlightUrl = "none"; - this.#hcmHighlightFilter?.remove(); + if (info) { + info.filter?.remove(); + info.key = key; + info.url = "none"; + info.filter = null; + } else { + info = { + key, + url: "none", + filter: null, + }; + this.#hcmCache.set(filterName, info); + } if (!fgColor || !bgColor) { - return this.#hcmHighlightUrl; + return info.url; } const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this)); @@ -294,8 +311,8 @@ class DOMFilterFactory extends BaseFilterFactory { return arr.join(","); }; - const id = `g_${this.#docId}_hcm_highlight_filter`; - const filter = (this.#hcmHighlightFilter = this.#createFilter(id)); + const id = `g_${this.#docId}_hcm_${filterName}_filter`; + const filter = (info.filter = this.#createFilter(id)); this.#addGrayConversion(filter); this.#addTransferMapConversion( @@ -305,12 +322,12 @@ class DOMFilterFactory extends BaseFilterFactory { filter ); - this.#hcmHighlightUrl = `url(#${id})`; - return this.#hcmHighlightUrl; + info.url = `url(#${id})`; + return info.url; } destroy(keepHCM = false) { - if (keepHCM && (this.#hcmUrl || this.#hcmHighlightUrl)) { + if (keepHCM && this.#hcmCache.size !== 0) { return; } if (this.#_defs) { diff --git a/web/annotation_layer_builder.css b/web/annotation_layer_builder.css index 80d9c72749f7f..4e5694c4a5009 100644 --- a/web/annotation_layer_builder.css +++ b/web/annotation_layer_builder.css @@ -28,7 +28,6 @@ --input-disabled-border-color: GrayText; --input-hover-border-color: Highlight; --link-outline: 1.5px solid LinkText; - --hcm-highlight-filter: invert(100%); .textWidgetAnnotation :is(input, textarea):required, .choiceWidgetAnnotation select:required, diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 08c8e23e1e02d..1df2f360e2a16 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -284,6 +284,17 @@ class PDFPageView { this._container?.style.setProperty( "--hcm-highlight-filter", pdfPage.filterFactory.addHighlightHCMFilter( + "highlight", + "CanvasText", + "Canvas", + "HighlightText", + "Highlight" + ) + ); + this._container?.style.setProperty( + "--hcm-highlight-selected-filter", + pdfPage.filterFactory.addHighlightHCMFilter( + "highlight_selected", "CanvasText", "Canvas", "HighlightText", diff --git a/web/pdf_viewer.css b/web/pdf_viewer.css index 3c8a2927106b3..d28c21af55a71 100644 --- a/web/pdf_viewer.css +++ b/web/pdf_viewer.css @@ -62,6 +62,11 @@ --scale-factor: 1; padding-bottom: var(--pdfViewer-padding-bottom); + + --hcm-highlight-filter: none; + @media screen and (forced-colors: active) { + --hcm-highlight-filter: invert(100%); + } } .pdfViewer .canvasWrapper { diff --git a/web/pdf_viewer.js b/web/pdf_viewer.js index 5a6efac1645cf..54cf661407fbf 100644 --- a/web/pdf_viewer.js +++ b/web/pdf_viewer.js @@ -884,12 +884,23 @@ class PDFViewer { this.viewer.style.setProperty( "--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter( + "highlight", "CanvasText", "Canvas", "HighlightText", "Highlight" ) ); + this.viewer.style.setProperty( + "--hcm-highlight-selected-filter", + pdfDocument.filterFactory.addHighlightHCMFilter( + "highlight_selected", + "CanvasText", + "Canvas", + "HighlightText", + "ButtonText" + ) + ); } for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { diff --git a/web/text_layer_builder.css b/web/text_layer_builder.css index 3d03dc5536741..d0536676c70b0 100644 --- a/web/text_layer_builder.css +++ b/web/text_layer_builder.css @@ -18,12 +18,13 @@ text-align: initial; inset: 0; overflow: hidden; - opacity: 0.25; + opacity: 1; line-height: 1; text-size-adjust: none; forced-color-adjust: none; transform-origin: 0 0; z-index: 2; + caret-color: CanvasText; &.drawing { touch-action: none; @@ -47,17 +48,25 @@ /*#endif*/ .highlight { - --highlight-bg-color: rgb(180 0 170); - --highlight-selected-bg-color: rgb(0 100 0); + --highlight-bg-color: rgb(180 0 170 / 0.25); + --highlight-selected-bg-color: rgb(0 100 0 / 0.25); + --highlight-backdrop-filter: none; + --highlight-selected-backdrop-filter: none; + --mix-blend-mode: exclusion; @media screen and (forced-colors: active) { - --highlight-bg-color: Highlight; - --highlight-selected-bg-color: ButtonText; + --highlight-bg-color: transparent; + --highlight-selected-bg-color: transparent; + --highlight-backdrop-filter: var(--hcm-highlight-filter); + --highlight-selected-backdrop-filter: var( + --hcm-highlight-selected-filter + ); } margin: -1px; padding: 1px; background-color: var(--highlight-bg-color); + backdrop-filter: var(--highlight-backdrop-filter); border-radius: 4px; &.appended { @@ -78,14 +87,16 @@ &.selected { background-color: var(--highlight-selected-bg-color); + backdrop-filter: var(--highlight-selected-backdrop-filter); } } ::selection { /*#if !MOZCENTRAL*/ - background: blue; + background: rgba(0 0 255 / 0.25); /*#endif*/ - background: AccentColor; /* stylelint-disable-line declaration-block-no-duplicate-properties */ + /* stylelint-disable-next-line declaration-block-no-duplicate-properties */ + background: color-mix(in srgb, AccentColor, transparent 75%); } /* Avoids https://github.com/mozilla/pdf.js/issues/13840 in Chrome */