250 Commits

Author SHA1 Message Date
Calixte Denizet
806f9c1cee Disable printing when enablePermission is true and the pdf isn't allowed to be printed (bug 1978985) 2025-07-30 19:29:01 +02:00
Calixte Denizet
636ff503ff [Editor] Add the possibility to add Popup annotations (bug 1976724)
It's a first big step.
This patch contains a new modal dialog to let the user edit/update a Popup
2025-07-15 22:39:16 +02:00
Calixte Denizet
6d2c6cfc9f [Editor] Allow to change the editor mode when selecting the corresponding editor (bug 1975538)
For example, selecting an ink editor just after having created a freetext will switch to ink mode.
2025-07-03 23:27:34 +02:00
Calixte Denizet
c22a425b04 [Editor] When an annotation is added, announce it if the user is using a screen reader (bug 1975264) 2025-07-03 16:53:01 +02:00
Calixte Denizet
1225c1e39a Add a pref in order to cap the canvas area to a factor of the window one (bug 1958015)
This way it helps to reduce the overall canvas dimensions and make the rendering faster.
The drawback is that when scrolling, the page can be blurry in waiting for the rendering.

The default value is 200% on desktop and will be 100% for GeckoView.
2025-05-09 13:57:16 +02:00
Calixte Denizet
ecc56a61e6 Don't update the visible canvas at 60 fps (bug 1936605)
Instead, we update the visible canvas every 500ms.
With large canvas, updating at 60fps lead to a lot gfx transactions and it can take a lot of time.
For example, with wuppertal_2012.pdf on Windows, displaying it at 150% takes around 14 min !!! without
this patch when it takes only around 14 sec with. Even at 30% it helps to improve the performance
by around 20%.
2025-04-29 18:35:21 +02:00
Jonas Jenwald
af3d13c22d Use the MathClamp helper function more in the web/ folder (PR 19617 follow-up)
There's one more spot that I missed in PR 19617.
2025-04-26 11:09:52 +02:00
Jonas Jenwald
74ab29544e
Merge pull request #19701 from Snuffleupagus/enableAutoLinking-true
[api-minor] Enable `enableAutoLinking` by default
2025-03-25 18:18:08 +01:00
Jonas Jenwald
abcddb51e0 [api-minor] Enable enableAutoLinking by default
It's already enabled by default in Firefox, and since there's no open issues regarding auto-linking I suppose that we can attempt to enable it unconditionally.
2025-03-21 11:49:03 +01:00
Jonas Jenwald
028e4f7ea8 [api-minor] Add a basic AbortSignal.any polyfill in PDF.js legacy builds
This is an admittedly very basic polyfill, to allow us to remove a bunch of inline feature testing, that I've thrown together based on reading https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static and related MDN articles.

Compared to PR 19218 it's obviously much more "primitive", however the implementation is simple and it doesn't suffer from any licensing issues (since I wrote the code myself).
2025-03-18 10:54:49 +01:00
Nicolò Ribaudo
a1dc46aa9d
Do not constantly render the detail canvas on zoom
When zooming, we should skip rendering the detail canvas until the
zoom is done, similarly to how normal page rendering is delayed.
To do so is enough to skip details view while zooming, since the
main view rendering that already happens after the delay will also
trigger rendering of the detail views.
2025-03-07 12:38:52 +01:00
Jonas Jenwald
9f9de4508c [api-minor] Limit the maximum canvas width/height, in addition to its total area (bug 1943094)
Browsers not only limit the maximum total canvas area, but additionally also limit their maximum width/height which affects PDF documents with e.g. very tall and narrow pages.
To address this we add a new `maxCanvasDim` viewer-option, which in Firefox will use a browser preference, such that both the total canvas area and the width/height will affect when CSS-zooming is used.
2025-03-04 15:23:45 +01:00
Jonas Jenwald
71ad9fd0b7 Abort various timeouts, in PDFViewer, when closing the document (PR 19128 follow-up)
Looking at recent integration-test logs there's occasionally warnings about trying to invoke `PDFViewer.prototype.update` too late, which probably started with PR 19128 (see log excerpt below).
Given that we already had another timeout before that PR the problem was pre-existing, but it seems to trigger more easily now.

```
JavaScript warning: http://127.0.0.1:42333/build/generic/web/viewer.mjs, line 12668: Script terminated by timeout at:
update@http://127.0.0.1:42333/build/generic/web/viewer.mjs:12668:9
@http://127.0.0.1:42333/build/generic/web/viewer.mjs:12373:12
setTimeout handler*_scrollUpdate@http://127.0.0.1:42333/build/generic/web/viewer.mjs:12371:29
viewAreaElementScrolled@http://127.0.0.1:42333/build/generic/web/viewer.mjs:154:15
FrameRequestCallback*debounceScroll@http://127.0.0.1:42333/build/generic/web/viewer.mjs:140:18
EventListener.handleEvent*watchScroll@http://127.0.0.1:42333/build/generic/web/viewer.mjs:165:19
PDFViewer@http://127.0.0.1:42333/build/generic/web/viewer.mjs:11777:19
_initializeViewerComponents@http://127.0.0.1:42333/build/generic/web/viewer.mjs:15081:23
initialize@http://127.0.0.1:42333/build/generic/web/viewer.mjs:14931:16
async*run@http://127.0.0.1:42333/build/generic/web/viewer.mjs:15227:16
webViewerLoad@http://127.0.0.1:42333/build/generic/web/viewer.mjs:17078:24
@http://127.0.0.1:42333/build/generic/web/viewer.mjs:17082:3
```
2025-02-25 13:11:51 +01:00
Nicolò Ribaudo
dc5d6aad8a
Avoid degrading scroll performance due to the detail view
When scrolling quickly, the constant re-rendering of the detail view
significantly affects rendering performance, causing Firefox to
not render even the _background canvas_, which is just a static canvas
not being re-drawn by JavaScript.

This commit changes the viewer to only render the detail view while
scrolling if its rendering hasn't just been cancelled. This means that:
- when the user is scrolling slowly, we have enough time to render the
  detail view before that we need to change its area, so the user always
  sees the full screen as high resolution.
- when the user is scrolling quickly, as soon as we have to cancel a
  rendering we just give up, and the user will see the lower resolution
  canvas. When then the user stops scrolling, we render the detail view
  for the new visible area.
2025-02-21 10:00:57 -08:00
Nicolò Ribaudo
458b2ee402
[api-minor] Render high-res partial page views when falling back to CSS zoom (bug 1492303)
When rendering big PDF pages at high zoom levels, we currently fall back
to CSS zoom to avoid rendering canvases with too many pixels. This
causes zoomed in PDF to look blurry, and the text to be potentially
unreadable.

This commit adds support for rendering _part_ of a page (called
`PDFPageDetailView` in the code), so that we can render portion of a
page in a smaller canvas without hiting the maximun canvas size limit.

Specifically, we render an area of that page that is slightly larger
than the area that is visible on the screen (100% larger in each
direction, unless we have to limit it due to the maximum canvas size).
As the user scrolls around the page, we re-render a new area centered
around what is currently visible.
2025-02-21 10:00:55 -08:00
Calixte Denizet
68451fe17e [Editor] Populate the 'Add signature' menu with the saved signatures (bug 1947828) 2025-02-13 15:59:57 +01:00
calixteman
2d773cb773
Merge pull request #19110 from ryzokuken/autolink-demo
Enable automatic URL linking (bug 1019475)
2025-02-06 16:53:48 +01:00
Calixte Denizet
fa25ab9c13 [Editor] Add a new dialog for the signature editor (bug 1945574) 2025-02-05 23:00:38 +01:00
Ujjwal Sharma
61ba1ea48c Enable automatic URL linking
Automatically detect links in the text content of a file and automatically
generate link annotations at the appropriate locations to achieve
automatic link detection and hyperlinking.
2025-02-05 16:56:54 +01:00
Jonas Jenwald
3b4758a400 [Editor] Ensure that highlightSelection waits until we've fully updated the editing-mode (issue 19369)
With the changes in PR 18843 the `AnnotationEditorUIManager.prototype.updateMode` method is now asynchronous, which we need to take into account when dispatching the "annotationeditormodechanged" event.
2025-01-23 13:46:39 +01:00
Calixte Denizet
4ed7f7f1ee [Editor] Add the ability to resize an editor in using a pinch gesture 2024-12-14 19:39:51 +01:00
Ujjwal Sharma
dd82d78a2d Pop open a message when user deletes an annotation
When a user deletes any number of annotations, they are notified of the action
by a popup message with an undo button. Besides that, this change reuses the
existing messageBar CSS class from the new alt-text dialog as much as possible.
2024-12-03 11:03:15 +01:00
Jonas Jenwald
e1760aab8d Use the stopEvent helper function everywhere possible 2024-11-28 13:25:56 +01:00
Jonas Jenwald
31b0a496fd Remove the temporary "visibilitychange" listener, in PDFViewer, with AbortSignal.any()
This is similar to a lot of other code, where we've been replacing explicit `removeEventListener`-calls.
Given the somewhat limited availability of `AbortSignal.any()`, see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static#browser_compatibility), this event listener will no longer be immediately removed in older browsers (however that should be fine).
2024-10-08 15:38:31 +02:00
Jonas Jenwald
b7ae92c11c Remove the PDFViewer.annotationEditorMode setter event listeners with AbortSignal.any() 2024-10-03 15:57:46 +02:00
Jonas Jenwald
d86f94a3db Use the "pageColorsBackground" option as background-color for non-loaded pages (issue 18680)
This should prevent non-loaded pages from flashing white in e.g. high contrast mode (HCM).
2024-09-12 21:15:15 +02:00
Jonas Jenwald
9e0c6ef476 Handle the "switchannotationeditorparams" event in the editor-code (issue 18196)
The problem seems to be caused by the browser trying to "restore" editing input-elements, in the various toolbars, to their previous values when the tab is re-opened.

Hence the simplest solution appears to be to move the event handling into the editor-code, which is also less code overall, since the listener thus won't be registered early enough for the problem to appear.
2024-08-13 15:29:55 +02:00
Jonas Jenwald
da9cfe7781 Check that AbortSignal.any() is supported in PDFViewer too (PR 18586 follow-up)
Without this patch the viewer may break on load, since the check added in PR 18586 only applies to the toolbar.
2024-08-09 16:48:44 +02:00
Jonas Jenwald
c0bf3d3c94 [Editor] Remove event listeners with AbortSignal.any()
There's a fair number of event listeners in the editor-code that we're currently removing "manually", by keeping references to their event handler functions.
This was necessary since we have a "global" `AbortController` that applies to all event listeners used in the editor-code, however it's now possible to combine multiple `AbortSignal`s; please see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static

Since this functionality is [fairly new](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static#browser_compatibility) the viewer will check that `AbortSignal.any()` is available before enabling the editing-functionality.
(It should hopefully be fairly straightforward, famous last words, for users to implement a polyfill to allow editing in older browsers.)

Finally, this patch also adds checks and test-only asserts to ensure that we don't add duplicate event listeners in various editor-code.
2024-08-09 11:24:34 +02:00
Calixte Denizet
a81b071d2d [Editor] Load the model when the user switch to the stamp editing mode 2024-08-02 17:14:09 +02:00
Calixte Denizet
32d09276f0 [Editor] Add a new dialog for alt-text settings (bug 1909604)
This patch adds a new entry in the secondary menu in order to open a dialog to let the user:
 - disables the alt-text generation thanks to a ML model;
 - deletes the alt-text model downloaded in Firefox;
 - disabled the new alt-text flow.
2024-08-01 21:34:50 +02:00
Calixte Denizet
6dd75c0e62 [Editor] When in non-editing mode, add a new editor only once the editing mode has switched
Switching to an editing mode can be asynchronous (e.g. if an editable annotation exists on a
visible page), so we must add a new editor only when the page rendering is done.
2024-07-15 21:04:52 +02:00
Calixte Denizet
dfccc8ffd9 [Editor] Add an option to use the new 'add an image' flow (bug 1907207)
UX team designed in a new flow we'll implement soon and we want to be able to
make an experiment to be able to compare current flow vs the new one.
2024-07-12 16:28:48 +02:00
Calixte Denizet
d27efb43cd [Editor] Wait for 'pagerendered' to switch to editing mode
The focus can potentially be stolen when the DOM is modified when adding
a new canvas element for the page being redrawn.
2024-07-10 11:29:42 +02:00
Calixte Denizet
68175323f1 [Editor] Make sure everything is cleaned up when we switch to annotation editor mode 2024-07-02 16:54:19 +02:00
Calixte Denizet
64635f3b35 [api-minor][Editor] When switching to editing mode, redraw pages containing editable annotations
Right now, editable annotations are using their own canvas when they're drawn, but
it induces several issues:
 - if the annotation has to be composed with the page then the canvas must be correctly
   composed with its parent. That means we should move the canvas under canvasWrapper
   and we should extract composing info from the drawing instructions...
   Currently it's the case with highlight annotations.
 - we use some extra memory for those canvas even if the user will never edit them, which
   the case for example when opening a pdf in Fenix.

So with this patch, all the editable annotations are drawn on the canvas. When the
user switches to editing mode, then the pages with some editable annotations are redrawn but
without them: they'll be replaced by their counterpart in the annotation editor layer.
2024-07-02 14:11:40 +02:00
Jonas Jenwald
97686c410c Improve how the wait-cursor is toggled when copying all text
- Use a CSS rule to display the wait-cursor during copying. Since copying may take a little while in long documents, there's a theoretical risk that something else could change the cursor in the meantime and just resetting to the saved-cursor could thus be incorrect.

 - Remove the `interruptCopyCondition` listener with an AbortController, since that's slightly shorter code.
2024-06-14 10:06:27 +02:00
Calixte Denizet
ff6180a4c9 Add an option to enable/disable hardware acceleration (bug 1902012) 2024-06-12 18:41:07 +02:00
Calixte Denizet
018649f13b Switch to page-scrolling mode when the pdf has more than 10000 pages (bug 1895050) 2024-05-31 15:35:26 +02:00
Calixte Denizet
4430b6b703 Disconnect the resize observer and remove scroll listener when unbinding window events 2024-05-30 22:09:52 +02:00
Nicolò Ribaudo
b7933d8750
Add origin parameter to updateScale
This parameter allows defining which point should remain
fixed while scaling the document. It can be used, for example,
to implement "zoom around the cursor" or "zoom around
pinch center".

The logic was previously implemented in `web/app.js`, but
moving it to the viewer scaling utilities themselves makes it
easier to implement similar zooming functionalities in
other embedders.
2024-05-28 16:19:47 +02:00
Nicolò Ribaudo
161c7045f6
Unify increaseScale/decreaseScale logic as updateScale
`updateScale` receives a `drawingDelay`, a `scaleFactor` and/or a number of `steps`.
If `scaleFactor` is a positive number different from `1` the current scale is multiplied by
that number. Otherwise, if `steps` if a positive integer the current scale is multiplied by
`DEFAULT_SCALE_DELTA` `steps` times. Finally, if `steps` is a negative integer, the
current scale is divided by `DEFAULT_SCALE_DELTA` `abs(steps)` times.
2024-05-28 14:02:39 +02:00
Jonas Jenwald
469738c1ce Remove event listeners with signal in web/pdf_viewer.js 2024-05-08 16:07:43 +02:00
Jonas Jenwald
f6cd03955b [api-minor] Move the page reference/number caching into the API
Rather than having to handle this *manually* throughout the viewer, this functionality can instead be moved into the API which simplifies the code slightly.
2024-04-29 18:54:06 +02:00
Jonas Jenwald
e4d0e84802 [api-minor] Replace the PromiseCapability with Promise.withResolvers()
This replaces our custom `PromiseCapability`-class with the new native `Promise.withResolvers()` functionality, which does *almost* the same thing[1]; please see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers

The only difference is that `PromiseCapability` also had a `settled`-getter, which was however not widely used and the call-sites can either be removed or re-factored to avoid it. In particular:
 - In `src/display/api.js` we can tweak the `PDFObjects`-class to use a "special" initial data-value and just compare against that, in order to replace the `settled`-state.
 - In `web/app.js` we change the only case to manually track the `settled`-state, which should hopefully be OK given how this is being used.
 - In `web/pdf_outline_viewer.js` we can remove the `settled`-checks, since the code should work just fine without it. The only thing that could potentially happen is that we try to `resolve` a Promise multiple times, which is however *not* a problem since the value of a Promise cannot be changed once fulfilled or rejected.
 - In `web/pdf_viewer.js` we can remove the `settled`-checks, since the code should work fine without them:
     - For the `_onePageRenderedCapability` case the `settled`-check is used in a `EventBus`-listener which is *removed* on its first (valid) invocation.
     - For the `_pagesCapability` case the `settled`-check is used in a print-related helper that works just fine with "only" the other checks.
 - In `test/unit/api_spec.js` we can change the few relevant cases to manually track the `settled`-state, since this is both simple and *test-only* code.

---
[1] In browsers/environments that lack native support, note [the compatibility data](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers#browser_compatibility), it'll be polyfilled via the `core-js` library (but only in `legacy` builds).
2024-04-01 11:42:37 +02:00
Calixte Denizet
a4aca8a20d Increase the maxCanvasPixels value to 2 ** 25 2024-03-25 17:57:23 +01:00
Calixte Denizet
b4267cd294 [Editor] Add a floating button close to the selected text to highlight it (bug 1867742)
For now keep this feature behind a pref in order to make some experiments before
deciding to enable it.
2024-03-12 15:06:46 +01:00
Jonas Jenwald
3c78ff5fb0 [api-minor] Implement basic support for OptionalContent Usage dicts (issue 5764, bug 1826783)
The following are some highlights of this patch:
 - In the Worker we only extract a *subset* of the potential contents of the `Usage` dictionary, to avoid having to implement/test a bunch of code that'd be completely unused in the viewer.

 - In order to still allow the user to *manually* override the default visible layers in the viewer, the viewable/printable state is purposely *not* enforced during initialization in the `OptionalContentConfig` constructor.

 - Printing will now always use the *default* visible layers, rather than using the same state as the viewer (as was the case previously).
   This ensures that the printing-output will correctly take the `Usage` dictionary into account, and in practice toggling of visible layers rarely seem to be necessary except in the viewer itself (if at all).[1]

---
[1] In the unlikely case that it'd ever be deemed necessary to support fine-grained control of optional content visibility during printing, some new (additional) UI would likely be needed to support that case.
2024-03-12 13:18:15 +01:00
Calixte Denizet
46416bb131 [Editor] Add the possibility to query some ML stuff to guess an alt text for an image
It's only for an experimental purpose.
2024-02-20 21:29:33 +01:00
Jonas Jenwald
97c2ce9da0 Ensure that GenericL10n works if the locale files cannot be loaded
- Ensure that localization works in the GENERIC viewer, even if the necessary locale files cannot be loaded.
   This was the behaviour prior to the introduction of Fluent, and it seems worthwhile to keep that (especially since we already bundle the en-US strings anyway).

 - Let the `GenericL10n`-implementation use the *bundled* en-US strings directly when no language is provided.

 - Remove the `NullL10n`-implementation, and simply fallback to `GenericL10n`, to reduce the maintenance burden of viewer-components localization.

 - Indirectly, given the previous point, stop exporting `NullL10n` in the viewer-components since it's now removed.
   Note that it was never really intended to be used directly and only existed as a fallback.

*Please note:* This doesn't affect the Firefox PDF Viewer, thanks to the use of import maps.
2024-01-31 14:07:11 +01:00