2657 Commits

Author SHA1 Message Date
Jonas Jenwald
67f3972bf0 Add a private FontInfo helper method for reading array-data (PR 20197 follow-up)
Currently the `bbox`, `fontMatrix`, and `defaultVMetrics` getters duplicate almost the same code, which we can avoid by adding a new helper method (similar to existing ones for reading numbers and strings).

The added `assert` in the new helper method also caught a bug in how the `defaultVMetrics` length was compiled.
2026-03-13 11:21:37 +01:00
Jonas Jenwald
3842936edf Split the src/shared/obj-bin-transform.js file into separate files for the main/worker threads (PR 20197 follow-up)
On the worker-thread only the static `write` methods are actually used, and on the main-thread only class instances are being created.
Hence this, after PR 20197, leads to a bunch of dead code in both of the *built* `pdf.mjs` and `pdf.worker.js` files.

This patch reduces the size of the `gulp mozcentral` output by `21 419` bytes, i.e. `21` kilo-bytes, which I believe is way too large of a saving to not do this.
(I can't even remember the last time we managed to reduce build-size this much with a single patch.)
2026-03-13 11:21:24 +01:00
Tim van der Meij
decbce7b9b
Merge pull request #20856 from Snuffleupagus/fix-font-clearData
Fix the `FontInfo.prototype.clearData` method to actually remove the data as intended (PR 20197 follow-up)
2026-03-12 20:39:02 +01:00
Jonas Jenwald
e88a5652de Fix the FontInfo.prototype.clearData method to actually remove the data as intended (PR 20197 follow-up)
The purpose of PR 11844 was to reduce memory usage once fonts have been attached to the DOM, since the font-data can be quite large in many cases.

Unfortunately the new `clearData` method added in PR 20197 doesn't actually remove *anything*, it just replaces the font-data with zeros which doesn't help when the underlying `ArrayBuffer` itself isn't modified.
The method does include a commented-out `resize` call[1], but uncommenting that just breaks rendering completely.

To address this regression, without having to make large or possibly complex changes, this patch simply changes the `clearData` method to replace the internal buffer/view with its contents *before* the font-data.
While this does lead to a data copy, the size of this data is usually orders of magnitude smaller than the font-data that we're removing.

---

[1] Slightly off-topic, but I don't think that patches should include commented-out code since there's a very real risk that those things never get found/fixed.
At the very least such cases should be clearly marked with `// TODO: ...` comments, and should possibly also have an issue filed about fixing the TODO.
2026-03-12 18:15:42 +01:00
Jonas Jenwald
9aa1ce8f14 Move the PagesMapper class into its own file
The `PagesMapper` class currently makes up one third of the `src/display/display_utils.js` file size, and since its introduction it's grown (a fair bit) in size.
Note that the intention with files such as `src/display/display_utils.js` was to have somewhere to place functionality too small/simple to deserve its own file.
2026-03-11 12:28:13 +01:00
calixteman
9d093d9607
Merge pull request #20626 from nicolo-ribaudo/images-right-click
Add support for right-clicking on images (bug 1012805)
2026-03-11 11:45:51 +01:00
Tim van der Meij
44a63549b0
Merge pull request #20831 from calixteman/internal_viewer
Add a new internal viewer to explore the structure of PDF files.
2026-03-10 20:48:40 +01:00
Tim van der Meij
15e58f3912
Merge pull request #20830 from Snuffleupagus/validateRangeRequestCapabilities-fix-tests
Improve the `validateRangeRequestCapabilities` unit-tests
2026-03-10 20:23:14 +01:00
Jonas Jenwald
5ef582fb20 Use optional chaining a little bit more in the src/display/api.js file
That format is preferred where possible, since it leads to ever so slightly shorter code overall.
2026-03-10 15:51:05 +01:00
Nicolò Ribaudo
4f7a025e21
Separate bbox tracking from dependencies tracking
When recording bboxes for images, it's enough to record their
clip box / bounding box without needing to run the full bbox
tracking of the image's dependencies.
2026-03-10 14:51:03 +01:00
Nicolò Ribaudo
886c90d1a5
Add support for right-clicking on images
This patch adds right-click support for images in the PDF, allowing
users to download them. To minimize memory consumption, we:
- Do not store the images separately, and instead crop them out of the
  PDF page canvas
- Only extract the images when needed (i.e. when the user right-clicks
  on them), rather than eagery having all of them available.

To do so, we layer one empty 0x0 canvas per image, stretched to cover
the whole image, and only populate its contents on right click.
These images need to be inside the text layer: they cannot be _behind_
it, otherwise they would be covered by the text layer's container and
not be clickable, and they cannot be in front of it, otherwise they
would make the text spans unselectable.

This feature is managed by a new preference, `imagesRightClickMinSize`:
- when it's set to `-1`, right-click support is disabled
- when set to `0`, all images are available for right click
- when set to a positive integer, only images whose width and height are
  greater than or equal to that value (in the PDF page frame of
  reference) are available for right click.

This features is disabled by default outside of MOZCENTRAL, as it
significantly degrades the text selection experience in non-Firefox
browsers.
2026-03-10 14:51:03 +01:00
Jonas Jenwald
873378b718
Merge pull request #20836 from Snuffleupagus/FontFaceObject-fix-asserts
Fix the `disableFontFace` and `fontExtraProperties` asserts in the `FontFaceObject` constructor (PR 20197 follow-up)
2026-03-09 20:08:58 +01:00
Jonas Jenwald
9f69617109 Fix the disableFontFace and fontExtraProperties asserts in the FontFaceObject constructor (PR 20197 follow-up)
In PR 19548 these checks were added to ensure that the font-data sent from the worker-thread *always* include correct `disableFontFace` and `fontExtraProperties` data.

For some reason PR 20197 then changed the code such that these checks became effectively pointless, since these properties are now checked after the fact *and* the new getters provide fallback values.
2026-03-09 18:00:11 +01:00
Jonas Jenwald
8bbb7c88d3 Change the AnnotationLayer.prototype.getEditableAnnotations method to return an iterator
This method is only used with loops, and it should be a tiny bit more efficient to use an iterator directly rather than first iterating through the underlying `Map` to create a temporary `Array` that we finally iterate through at the call-site.
2026-03-09 16:11:21 +01:00
calixteman
9d81fafa8c
Add a new internal viewer to explore the structure of PDF files.
The one from pdf.js.utils is a bit too old: a lot of bugs have been fixed
in the code that parses PDF files since then.
It's just an internal development tool, so it doesn't need to be perfect,
but it should be good enough to be useful.
2026-03-09 14:16:12 +01:00
Calixte Denizet
0e48c16c3c
Add a UI to undo cut/delete and cancel a copy (bug 2021352, bug 2010832)
This happens in a bar on top of the thumbnails sidebar.
The label depending on the selected thumbnails is fixed.
2026-03-09 10:44:11 +01:00
Jonas Jenwald
a1b769caea Improve the validateRangeRequestCapabilities unit-tests
A number of these unit-tests didn't actually cover the intended code-paths, since many of them *accidentally* matched the "file size is smaller than two range requests"-check.

The patch also updates `validateRangeRequestCapabilities` to use return-value names that are consistent with the class fields used in the various stream implementations.
2026-03-08 18:28:50 +01:00
Jonas Jenwald
1f69cf964c Ensure that percent === NaN is consistently reported by the onProgress callback
With these changes `0`, `NaN`, `null`, and `undefined` in the `total`-property all result in `percent === NaN` being reported by the callback, since previously e.g. `0` would result in `percent === 100` being reported unconditionally which doesn't make a lot of sense.

Also, remove the "indeterminate" loadingBar (in the viewer) if the `PDFDocumentLoadingTask` fails since there won't be any more data arriving and displaying the animation thus seems wrong.
2026-03-08 10:21:55 +01:00
Jonas Jenwald
0c514b008b Use Response.prototype.bytes() more in the code-base (PR 20651 follow-up) 2026-03-07 15:50:36 +01:00
calixteman
ce5f34ba13
Merge pull request #20780 from wooorm/wooorm/dismiss-popups
Add support for dismissing comment popups with click outside
2026-03-04 15:24:29 +01:00
Calixte Denizet
d90530b86c
Add the pages organization actions in the Firefox context menu (bug 2018138) 2026-03-04 09:02:39 +01:00
Calixte Denizet
a474e81b8a
Add a way to extract some pages from a pdf (bug 2019682)
The user has to select some pages and then click on the "Save As" menu item in the Manage menu.
If they modify the structure of the pdf (deleted, moved, copied pages), they have to use the usual
save button.
2026-03-03 21:39:13 +01:00
Titus Wormer
8b4f9048cf
Add support for dismissing comment popups with click outside
This solves [bug 1989406](https://bugzilla.mozilla.org/show_bug.cgi?id=1989406).
(“The user should be able to dismiss the in-content message displayed by clicking somewhere else in the PDF”)
There’s a good gif there that shows the problematic behavior.

In the thread, there are also mentions of 2 similar but slightly separate problems:

* clicking on another highlight should also dismiss
* the mention that hitting the escape key does not dismiss

I found the last point, the escape key, to work already (first test case here).
But this PR solves the main bug (second test case) and the adjacent one
(third test case).
It works by using the existing `unselectAll` handling.
2026-03-03 11:14:22 +01:00
Jonas Jenwald
e3a7c0779d Fix the broken regular expression in the decode helper in the getPdfFilenameFromUrl function (issue 20664)
This will ignore filenames that become effectively empty, i.e. ones that are only ".pdf" and nothing more.

*Please note:* While this passes all existing unit-tests, I don't know if this is necessarily the "correct" solution here.
2026-02-27 15:19:43 +01:00
Jonas Jenwald
82fc2c94f0 Include transfers correctly in the "GetOperatorList" message (PR 16588 follow-up)
Currently the transfers aren't actually being used with the "GetOperatorList" message, since the placement of the parameter is wrong; note the method signature: 909a700afa/src/shared/message_handler.js (L219-L229)
This goes back to PR 16588, which added the transfers parameter, and unfortunately we all missed that :-(

Simply fixing the parameter isn't enough however, since that broke printing of Stamp-editors (and possibly others). The solution here is to *not* transfer data during printing, given that a single `PrintAnnotationStorage` instance is being used for all pages.
2026-02-25 15:55:43 +01:00
Tim van der Meij
4ecbd0cbe2
Merge pull request #20726 from Snuffleupagus/getOrInsertComputed-fewer-functions
Reduce allocations and function creation when using `getOrInsert` and `getOrInsertComputed`
2026-02-24 23:32:36 +01:00
Jonas Jenwald
0d4e587a5f Reduce allocations when using Map.prototype.getOrInsert() with Arrays
Change all these cases to use `Map.prototype.getOrInsertComputed()` instead, in combination with a helper function for creating the `Array`s (similar to the previous patch).
2026-02-24 09:03:32 +01:00
Jonas Jenwald
2e07715c9d Reduce function creation when using Map.prototype.getOrInsertComputed()
With the exception of the first invocation the callback function is unused, which means that a lot of pointless functions may be created.
To avoid this we introduce helper functions for simple cases, such as creating `Map`s and `Objects`s.
2026-02-24 08:58:28 +01:00
calixteman
15e7a551ab
Reset transfer functions when entering in a new group
It fixes #20722.
2026-02-23 22:37:20 +01:00
Jonas Jenwald
e2c8fc6140 Use Map.prototype.getOrInsertComputed() in the src/display/api.js file 2026-02-22 21:01:13 +01:00
Jonas Jenwald
c81904ac0a Use Map.prototype.getOrInsertComputed() in the src/display/canvas.js file 2026-02-22 17:55:51 +01:00
Jonas Jenwald
ab8e67ecff Use Map.prototype.getOrInsert() in the src/display/annotation_layer.js file 2026-02-22 17:54:17 +01:00
Jonas Jenwald
bfe265ad31 Use Map.prototype.getOrInsertComputed() in the editorStats getter 2026-02-22 15:10:02 +01:00
Jonas Jenwald
0d8bc689b9 Add missing license header in src/display/canvas_dependency_tracker.js 2026-02-21 13:26:20 +01:00
Jonas Jenwald
c7bdf5b508 Use Map.prototype.getOrInsertComputed() in the ensureDebugMetadata helper
Also, shorten the function by using optional chaining.
2026-02-21 12:02:45 +01:00
Jonas Jenwald
34f27187f8 Reduce duplication when parsing searchParams in the getPdfFilenameFromUrl function
Currently we essentially "duplicate" the same code for parsing the `values` and `keys` of the `searchParams`, which seems a little unnecessary.

To be able to parse the `searchParams` from the end, we currently create an Array (from the Iterator) and then reverse it before finally looping through it. Here the latter two steps can be replaced with the `Array.prototype.findLast()` method instead.

*Please note:* I completely understand if this patch is rejected, on account of being less readable than the current code.
2026-02-19 17:37:12 +01:00
Calixte Denizet
d755fba96a
Add support for deleting, cutting, copying and pasting pages (bug 2010830, 2010831) 2026-02-18 16:43:00 +01:00
Jonas Jenwald
336cda0c64 Remove unused CanvasGraphics properties (PR 700 follow-up)
These are probably a copy-and-paste mistake, since they appear to have been unused already in PR 700 all the way back in 2011.
2026-02-17 21:36:08 +01:00
Jonas Jenwald
6323afab46 Convert the PDFObjects class to use a Map internally
This patch also adds unconditional `Map.prototype.getOrInsertComputed()` usage, which should be fine since it's [supported in the latest browsers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/getOrInsertComputed#browser_compatibility) and it'll be polyfilled (via core-js) in the `legacy` builds.
2026-02-17 09:42:27 +01:00
Jonas Jenwald
170599f1e7 Enable the unicorn/prefer-class-fields ESLint plugin rule
This leads to slightly shorter code[1] when initializing classes, and in some cases we can even remove the constructors, which shouldn't hurt; see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-class-fields.md

It's probably possible to also change a lot of these class fields to private ones[2], however it's often difficult to tell at a glance if that's safe hence this patch only does this for the `PDFRenderingQueue`.

---

[1] This reduces the size of the `gulp mozcentral` output by 999 bytes, for a mostly mechanical code change.

[2] That sort of re-factoring should generally be done separately, on a class-by-class basis, to reduce the risk of regressions.
2026-02-14 12:33:34 +01:00
calixteman
45c7805daf
Fix types to make "gulp typestest" succeeding 2026-02-13 22:34:04 +01:00
Jonas Jenwald
520928719c Move and re-use the stripPath helper function more
There's a couple of spots that essentially re-implement that function.
2026-02-13 17:38:21 +01:00
calixteman
fa28ca1468
Merge pull request #20651 from Snuffleupagus/Response-bytes
Start using `Response.prototype.bytes()` in the code-base
2026-02-13 10:31:54 +01:00
calixteman
ae9fc13d8f
Merge pull request #20649 from calixteman/bug2015385
Ends the current drawing session when closing the tab (bug 2015385)
2026-02-13 08:27:16 +01:00
calixteman
1b20ba5c3f
Ends the current drawing session when closing the tab (bug 2015385) 2026-02-12 22:21:55 +01:00
Jonas Jenwald
722f1ffbc6 Remove type === "arraybuffer" support from the fetchData helper function
After the previous patch there's no longer any call-site using that type.
2026-02-12 11:23:28 +01:00
Jonas Jenwald
8ba83e73fa Start using Response.prototype.bytes() in the code-base
In all cases where we currently use `Response.prototype.arrayBuffer()` the result is immediately wrapped in a `Uint8Array`, which can be avoided by instead using the newer `Response.prototype.bytes()` method; see https://developer.mozilla.org/en-US/docs/Web/API/Response/bytes
2026-02-12 11:20:05 +01:00
Jonas Jenwald
c1b824f2e5 Convert PDFPageProxy.prototype.getTextContent to an asynchronous method
This is a tiny bit shorter, which cannot hurt.
2026-02-11 19:14:10 +01:00
calixteman
4b4ab10c54
Set a pages mapper per loaded document
It fixes #20629.
2026-02-08 21:09:27 +01:00
Jonas Jenwald
0306e6c7ed Re-use the getArrayBuffer helper from src/display/fetch_stream.js with PDFNodeStreamReader and PDFNodeStreamRangeReader
Given that the Node.js code uses standard `ReadableStream`s now, see PR 20594, it can use the same `getArrayBuffer` as the Fetch API implementation.

Also, change the `getArrayBuffer` fallback case to an Error (rather than a warning) since that should never actually happen.
2026-02-08 13:20:55 +01:00