153 Commits

Author SHA1 Message Date
Jonas Jenwald
8121bc0dd2 Remove a tiny bit of unnecessary "rgba" parsing in the getRGB function
This obviously won't matter in practice, however it seems more "correct" to only extract the necessary number of color components rather than slicing off excess ones at the end.
2026-03-29 12:13:59 +02: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
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
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
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
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
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
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
calixteman
4b4ab10c54
Set a pages mapper per loaded document
It fixes #20629.
2026-02-08 21:09:27 +01:00
Jonas Jenwald
bfd17b2586
Merge pull request #20615 from Snuffleupagus/transport-onProgress
Report loading progress "automatically" when using the `PDFDataTransportStream` class, and remove the `PDFDataRangeTransport.prototype.onDataProgress` method
2026-02-01 22:36:43 +01:00
Jonas Jenwald
586e85888b Change all relevant BasePDFStream implementations to take an actual URL instance
Currently this code expects a "url string", rather than a proper `URL` instance, which seems completely unnecessary now. The explanation for this is, as so often is the case, "historical reasons" since a lot of this code predates the general availability of `URL`.
2026-02-01 18:21:13 +01:00
Jonas Jenwald
76dabeddb3 Limit the Math.sumPrecise polyfill to non-MOZCENTRAL builds
After https://bugzilla.mozilla.org/show_bug.cgi?id=1985121 this functionality is now guaranteed to be available in Firefox.
Unfortunately general browser support is still somewhat lacking; see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sumPrecise#browser_compatibility

Also, while unrelated, use the `MathClamp` helper in the `applyOpacity` function.
2026-02-01 18:20:29 +01:00
Calixte Denizet
dd6a0c6cf4
Add a manage button in the thumbnail view in order to save an edited pdf (bug 2010830) 2026-01-26 18:09:07 +01:00
Calixte Denizet
806133379e
Refactor a bit page mapping stuff in order to be able to support delete/copy pages 2026-01-26 16:53:52 +01:00
calixteman
029cae2ad4 Don't use firstChild/lastChild when getting elements (follow-up of #20447) 2025-11-22 21:10:32 +01:00
Calixte Denizet
bb2a1126e6 Use a binary format for the glyph paths
We used a SVG string which can be pass to the Path2D ctor but it's a bit slower than
building the path step by step.
Having numerical data instead of a string will help the font data serialization.
2025-10-16 15:52:51 +02:00
Calixte Denizet
634bef5fb4 Use a dichotomy to find a color with a good contrast ratio
It helps to reduce the number of iterations so it makes the algorithm
slightly faster in general.
2025-09-13 15:45:00 +02:00
Calixte Denizet
7f85c00ee6 Make sure that a good constrast ratio is respected when darkening/lightening a color 2025-09-11 21:29:28 +02:00
Calixte Denizet
35c909843b Add a new function renderRichText to be used in the annotation layer
and which will be used in order to make the contents of the new popup used for comments.
2025-09-04 22:27:31 +02:00
Calixte Denizet
ca280399c2 [Editor] Use the color of the annotation for the background of the comment button 2025-09-02 21:17:08 +02:00
Calixte Denizet
0ec503e5ef Add a function changeLightness in order to change the lightness of a RGB color 2025-08-30 21:18:12 +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
b97cee2ab5 Correctly handle files with a hash sign in their names (bug 1894166)
It fixes #19990.
2025-06-20 09:21:41 +02:00
Jonas Jenwald
d5c534fb83 Reduce duplication when computing the maximum canvas pixels
*This is something that occurred to me when reviewing the latest PDF.js update in mozilla-central.*

Currently we duplicate essentially the same code in both the `OutputScale.prototype.limitCanvas` and `PDFPageDetailView.prototype.update` methods, which seems unnecessary, and to avoid that we introduce a new `OutputScale.capPixels` method that is used to compute the maximum canvas pixels.
2025-05-10 20:12:38 +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
Jonas Jenwald
ae1cbc6a9e Use the light-dark CSS function in the viewer (issue 17780)
This removes the need for (most) separate `@media (prefers-color-scheme: dark)` blocks when defining colors values, and also provides a simple way of forcing use of either the light or dark theme.

Please refer to https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark and https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme

*NOTE:* To support this in older browsers, we utilize a [PostCSS plugin](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-light-dark-function).
2025-04-23 15:31:39 +02:00
Jonas Jenwald
c852e877d8 Change Util.applyInverseTransform to use the point-argument as an in/out parameter
This will help reduce the total number of Array allocations, which cannot hurt.
2025-04-01 23:03:44 +02:00
Jonas Jenwald
fa643bb22f Change Util.applyTransform to use the point-argument as an in/out parameter
This will help reduce the total number of Array allocations, which cannot hurt, and also allows us to remove the `Util.applyTransformInPlace` method.
2025-04-01 23:03:36 +02:00
Jonas Jenwald
319d239f41 Add an OutputScale static method to get the devicePixelRatio
Currently we lookup the `devicePixelRatio`, with fallback handling, in a number of spots in the code-base.
Rather than duplicating code we can instead add a new static method in the `OutputScale` class, since that one is now exposed in the API.
2025-03-12 21:07:06 +01:00
Jonas Jenwald
fc22d3afc7 Support the maxCanvasPixels option in the thumbnails code
This addresses an inconsistency in the viewer, since the thumbnails don't respect the `maxCanvasPixels` option.
Note that, as far as I know, this has not lead to any bugs since the thumbnails render with a fixed (and small) width, however it really cannot hurt to address this (especially after the introduction of the `maxCanvasDim` option).

To support this a new `OutputScale`-method was added, to avoid having to duplicate code in multiple files.
2025-03-10 14:12:07 +01:00
Jonas Jenwald
c2e33307b1 Introduce some URL.parse() usage in the code-base
This (fairly new) static method allows parsing URLs without having to wrap `new URL(...)` calls within `try...catch` blocks, thus simplifying the code; see https://developer.mozilla.org/en-US/docs/Web/API/URL/parse_static

For older browsers/environments the functionality will be polyfilled, but *only* in `legacy` builds, via `core-js`; see https://github.com/zloirock/core-js?tab=readme-ov-file#url-and-urlsearchparams

*Please note:* This is currently limited to the `src/`- and `web/`-folders, such that we don't break development/testing, since the functionality is not available in all Node.js versions that we support; see https://developer.mozilla.org/en-US/docs/Web/API/URL/parse_static#browser_compatibility
2025-02-15 19:10:36 +01:00
Jonas Jenwald
bd05b255fa [api-major] Apply the userUnit using CSS, to fix the text/annotation layers (bug 1947248)
Rather than modifying the "raw" dimensions of the page, we'll instead apply the `userUnit` as an *additional* scale-factor via CSS.

*Please note:* It's not clear to me if this solution is fully correct either, or if there's other problems with it, but it at least *appears* to work.

---

With these changes, the following CSS variables are now assumed to be available/set as necessary: `--total-scale-factor`, `--scale-factor`, `--user-unit`, `--scale-round-x`, and `--scale-round-y`.
2025-02-11 14:36:06 +01:00
Calixte Denizet
2c737bc420 Move the array containing the supported image mime types in display_utils
and make it available for the viewer (it'll be used in the signature UI).
2025-01-30 15:35:17 +01:00
Jonas Jenwald
c6e3fc4fe6 Take the userUnit into account in the PageViewport class (issue 19176) 2024-12-08 15:51:04 +01:00
Calixte Denizet
e695d04ca2 [Editor] Disallow to have multiple pointers while dragging an editor
It'll let the user dragging with two fingers.
2024-11-27 19:41:13 +01:00
Jonas Jenwald
af3c1f2a0d Enable the ESLint no-console rule in parts of the code-base
The purpose of these changes is to make it more difficult to accidentally include logging statements, used during development and debugging, when submitting patches for review.

For (almost) all code residing in the `src/` folder we should use our existing helper functions to ensure that all logging can be controlled via the `verbosity` API-option.

For the `test/unit/` respectively `test/integration/` folders we shouldn't need any "normal" logging, but it should be OK to print the *occasional* warning/error message.

Please find additional details about the ESLint rule at https://eslint.org/docs/latest/rules/no-console
2024-11-14 12:41:39 +01:00
Jonas Jenwald
4e12906061 Move the various DOM-factories into their own files
- Over time the number and size of these factories have increased, especially the `DOMFilterFactory` class, and this split should thus aid readability/maintainability of the code.

 - By introducing a couple of new import maps we can avoid bundling the `DOMCMapReaderFactory`/`DOMStandardFontDataFactory` classes in the Firefox PDF Viewer, since they are dead code there given that worker-thread fetching is always being used.

 - This patch has been successfully tested, by running `$ ./mach test toolkit/components/pdfjs/`, in a local Firefox artifact-build.

*Note:* This patch reduces the size of the `gulp mozcentral` output by `1.3` kilo-bytes, which isn't a lot but still cannot hurt.
2024-11-01 13:31:28 +01:00
Jonas Jenwald
df696063b9 Change the BaseCMapReaderFactory fetch-helper to return a Uint8Array
This moves more functionality into the base-class, rather than having to duplicate that in the extending classes.
For consistency, also updates the `BaseStandardFontDataFactory` and introduces more `async`/`await` in various relevant code.
2024-10-21 13:20:18 +02:00
Jonas Jenwald
8afc542ae2 Move the regular expression caching into the PDFDateString class
This code is old enough that it pre-dates availability of private class fields, hence why this wasn't done originally.
2024-10-11 15:34:58 +02:00
Jonas Jenwald
bb302dd993 [api-minor] Pass CanvasFactory/FilterFactory, rather than instances, to getDocument
This unifies the various factory-options, since it's consistent with `CMapReaderFactory`/`StandardFontDataFactory`, and ensures that any needed parameters will always be consistently provided when creating `CanvasFactory`/`FilterFactory`-instances.

As shown in the modified example this may simplify some custom implementations, since we now provide the ability to access the `CanvasFactory`-instance used with a particular `getDocument`-invocation.
2024-09-23 11:26:30 +02:00
Calixte Denizet
46fac8b2c1 [Editor] Take into account the device pixel ratio when drawing an added image
Fixes #18626.
2024-09-16 14:48:26 +02:00
Calixte Denizet
68332ec236 Avoid to have a white line around the canvas
The canvas must have the same dims as the page in order to avoid to see the page
background.
2024-09-07 20:12:29 +02:00
Jonas Jenwald
4c45948bc4 Fix DOMFilterFactory.#createUrl in MOZCENTRAL builds (18417 PR follow-up)
Somehow I managed to mess up the URL creation relevant to e.g. MOZCENTRAL builds, which is breaking the pending PDF.js update in mozilla-central; sorry about that!

To avoid future issues, we'll now always check if absolute filter-URLs are necessary regardless of the build-target.
2024-07-15 14:10:59 +02:00
Jonas Jenwald
50a5a15088 Create absolute filter-URLs when needed in DOMFilterFactory (issue 18406)
This functionality is purposely limited to development mode and GENERIC builds, since it's unnecessary in e.g. the *built-in* Firefox PDF Viewer, and will only be used when a `<base>`-element is actually present.

*Please note:* We also have tests in mozilla-central that will *indirectly* ensure that relative filter-URLs work as intended in the Firefox PDF Viewer, see https://searchfox.org/mozilla-central/source/toolkit/components/pdfjs/test/browser_pdfjs_filters.js

---

To test that the issue is fixed, the following code can be used:

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <base href=".">
  <title>base href (issue 18406)</title>
</head>
<body>

<ul>
  <li>Place this code in a file, named `base_href.html`, in the root of the PDF.js repository</li>
  <li>Run <pre>npx gulp dist-install</pre></li>
  <li>Run <pre>npx gulp server</pre></li>
  <li>Open <a href="http://localhost:8888/base_href.html">http://localhost:8888/base_href.html</a> in a browser</li>
  <li>Compare rendering with <a href="http://localhost:8888/web/viewer.html?file=/test/pdfs/issue16287.pdf">http://localhost:8888/web/viewer.html?file=/test/pdfs/issue16287.pdf</a></li>
</ul>

<canvas id="the-canvas" style="border: 1px solid black; direction: ltr;"></canvas>

<script src="/node_modules/pdfjs-dist/build/pdf.mjs" type="module"></script>

<script id="script" type="module">
  //
  // If absolute URL from the remote server is provided, configure the CORS
  // header on that server.
  //
  const url = '/test/pdfs/issue16287.pdf';

  //
  // The workerSrc property shall be specified.
  //
  pdfjsLib.GlobalWorkerOptions.workerSrc =
    '/node_modules/pdfjs-dist/build/pdf.worker.mjs';

  //
  // Asynchronous download PDF
  //
  const loadingTask = pdfjsLib.getDocument(url);
  const pdf = await loadingTask.promise;
  //
  // Fetch the first page
  //
  const page = await pdf.getPage(1);
  const scale = 1.5;
  const viewport = page.getViewport({ scale });
  // Support HiDPI-screens.
  const outputScale = window.devicePixelRatio || 1;

  //
  // Prepare canvas using PDF page dimensions
  //
  const canvas = document.getElementById("the-canvas");
  const context = canvas.getContext("2d");

  canvas.width = Math.floor(viewport.width * outputScale);
  canvas.height = Math.floor(viewport.height * outputScale);
  canvas.style.width = Math.floor(viewport.width) + "px";
  canvas.style.height = Math.floor(viewport.height) + "px";

  const transform = outputScale !== 1
    ? [outputScale, 0, 0, outputScale, 0, 0]
    : null;

  //
  // Render PDF page into canvas context
  //
  const renderContext = {
    canvasContext: context,
    transform,
    viewport,
  };
  page.render(renderContext);
</script>

</body>
</html>
```
2024-07-11 11:30:45 +02:00
Calixte Denizet
ff6180a4c9 Add an option to enable/disable hardware acceleration (bug 1902012) 2024-06-12 18:41:07 +02:00
Jonas Jenwald
a790f2df5d [api-minor] Remove the unused onlyStripPath option from the getFilenameFromUrl helper function 2024-05-03 08:29:41 +02:00
Calixte Denizet
82989e6790 [api-minor] Remove the use of (get/put)ImageData when drawing SMasks (bug 1874013)
and implement then in using some SVG filters and composition.
Composing in using destination-in in order to multiply RGB components by
the alpha from the mask isn't perfect: it'd be a way better to natively have
alpha masks support, it induces some small rounding errors and consequently
computed RGB are approximatively correct.
In term of performance, it's a real improvement, for example, the pdf in
issue #17779 is now rendered in few seconds.
There are still some room for improvement, but overall it should be a way
better.
2024-05-01 15:40:44 +02:00
Jonas Jenwald
33c5ef349e Simplify the XMLHttpRequest-branch in the fetchData helper function (PR 17277 follow-up) 2024-02-21 23:00:24 +01:00