7952 Commits

Author SHA1 Message Date
Jonas Jenwald
8a2c112c20 Simplify the Annotation.prototype.setAppearance method a tiny bit
It's not necessary to check if the /AS entry exists first, and it can just be fetched directly, since in that case the existing "is stream"-check won't be true anyway.

Also, move the `appearance` field definition to the top of the class instead.
2026-06-24 10:42:38 +02:00
Jonas Jenwald
f07a106529 Include the catalog instance in the annotationGlobals data
The `FileAttachmentAnnotation` and `MediaAnnotation` code needs to (synchronously) access a `catalog` method, which leads to unnecessarily verbose code.
This can be avoided by including the `catalog` instance in the `annotationGlobals` data, which is safe since it already includes data that's fetched asynchronously from the `catalog` instance.
2026-06-24 10:42:38 +02:00
calixteman
e6539f6516
Merge pull request #21490 from calixteman/screen_rendition
Add support for Screen annotations playing embedded media
2026-06-23 21:34:30 +02:00
Calixte Denizet
d8ea2afe47 Add support for Screen annotations playing embedded media
Screen annotations whose rendition action resolves to an embedded audio/video
file now play through the same play-button overlay as RichMedia.
Factor the shared resolution logic into a MediaAnnotation base (used by both RichMedia and Screen).

It fixes #6078 and #2787.
2026-06-23 20:48:35 +02:00
Tim van der Meij
4117b75a10
Merge pull request #21486 from Snuffleupagus/getTextContent-sink-fixes
Improve the `sink` handling in `getTextContent` for Highlight annotations (PR 20019 follow-up)
2026-06-23 20:02:34 +02:00
Jonas Jenwald
813d1949ba
Merge pull request #21491 from Snuffleupagus/readCmapTable-sort-last
Sort the mappings *last* in the `readCmapTable` function (PR 19321 follow-up)
2026-06-23 16:01:09 +02:00
Jonas Jenwald
9ca13c9a23 Sort the mappings *last* in the readCmapTable function (PR 19321 follow-up)
This improves performance of `issue19319.pdf` even more, and locally the rendering time of the second page goes from ~300 ms to ~250 ms, since we avoid sorting a bunch of duplicate entries.
2026-06-23 13:51:37 +02:00
Jonas Jenwald
09c9f7f2fe Remove the AnnotationEditorUIManager and IdManager test-only reset methods (PR 19809 follow-up)
These test-only methods became unused in PR 19809.
2026-06-23 12:09:12 +02:00
Calixte Denizet
d537f5ba4b
Add support for RichMedia annotations
Render `/Subtype /RichMedia` annotations so embedded video and audio can
be played in the viewer.

The core layer parses the `RichMediaContent` dictionary to locate the
primary playable asset and its MIME type. The display layer overlays a
play button on the annotation's poster; clicking it swaps in a
`<video>`/`<audio>` element backed by a `blob:` URL. Presentation mode
lets events reach the media controls instead of advancing the page.

It fixes #2787.
2026-06-22 21:27:52 +02:00
Tim van der Meij
b6469341c1
Merge pull request #21485 from calixteman/bug2046659
Use AES256 for V=5 documents with a mislabeled AESV2 crypt filter (bug 2046659)
2026-06-22 20:44:48 +02:00
Tim van der Meij
7ac6dff4b7
Merge pull request #21483 from calixteman/issue21430
Reset alpha before drawing a colored glyph in type 3 font
2026-06-22 20:40:55 +02:00
Jonas Jenwald
22871eef23 Improve the sink handling in getTextContent for Highlight annotations (PR 20019 follow-up)
Currently there's a couple of issues related to the `sink` handling:
 - The `Page.prototype.extractTextContent` method is invoked with options that it doesn't actually use; note 1ddf6449ac/src/core/document.js (L669-L676)

 - When parsing "nested" textContent, i.e. /Form /XObjects, we end up wrongly treating repeated /XObjects as empty for the annotations use-case since `enqueue` is never invoked; note 1ddf6449ac/src/core/evaluator.js (L3439) and 1ddf6449ac/src/core/evaluator.js (L3449-L3451)

 - The `getTextContent` method might become ever so slightly slower by having to defer parsing at every step, given the "bad" fallback value when comparing with the `TEXT_CONTENT_CHUNK_SIZE` constant (in the API), note 1ddf6449ac/src/display/api.js (L1705) and 1ddf6449ac/src/core/evaluator.js (L3566)

 - Having the `sink` now be effectively optional, in the `getTextContent` method, does complicate the code slightly overall.

To address these things this patch ensures that a `sink` will always be available, by re-using the `sinkWrapper` structure from the "nested" textContent case, and with reasonable default values.
2026-06-22 14:56:17 +02:00
Calixte Denizet
7f7e63333d Use AES256 for V=5 documents with a mislabeled AESV2 crypt filter (bug 2046659)
Some producers wrongly set the crypt filter CFM to AESV2 for V=5 documents;
per the spec these must be decrypted with AES256 using the file encryption key directly.
2026-06-22 14:54:24 +02:00
calixteman
1ddf6449ac
Merge pull request #21478 from calixteman/comb-field-vertical-centering
Vertically center the glyphs in comb text fields
2026-06-22 09:57:55 +02:00
calixteman
623e6d9476
Reset alpha before drawing a colored glyph in type 3 font
It fixes #21430.
2026-06-21 23:06:43 +02:00
Jonas Jenwald
9c9b465fd2 A couple of small tweaks of the StructElementNode.prototype.mathML getter
- Use `FileSpec.pickPlatformItem` when getting the fileStream, to ensure that /EF-entries are handled in a consistent way across the code-base.

 - Combine a couple of the data-validation steps, to reduce a tiny bit of duplication. Also, use the `isDict` helper a little more.

 - Finally, avoid using a temporary variable when returning data in the `Page.prototype.getStructTree` method.
2026-06-21 22:47:13 +02:00
Tim van der Meij
8ebc2382e3
Merge pull request #21479 from Snuffleupagus/Annotation-#setOptionalContent-MissingDataException
Don't swallow `MissingDataException`s in the `Annotation.prototype.#setOptionalContent` method (PR 21313 follow-up)
2026-06-21 19:11:54 +02:00
Tim van der Meij
38daede697
Merge pull request #21481 from Snuffleupagus/metadata-isDict
Use the `isDict` helper in the `Catalog.prototype.metadata` getter
2026-06-21 19:10:54 +02:00
Tim van der Meij
86b901fcde
Merge pull request #21470 from Snuffleupagus/AnnotationEditorUIManager-rm-isSelected
Remove the unused `AnnotationEditorUIManager.prototype.isSelected` method
2026-06-21 19:09:32 +02:00
Jonas Jenwald
a46ee2b647 Use the isDict helper in the Catalog.prototype.metadata getter 2026-06-21 12:26:21 +02:00
Jonas Jenwald
bd6541864b Don't swallow MissingDataExceptions in the Annotation.prototype.#setOptionalContent method (PR 21313 follow-up)
Unless the entire document has been loaded, the dictionary lookups in `parseMarkedContentProps` may throw `MissingDataException`s and in that case we need to re-parse the current Annotation rather than ignoring the optionalContent.
2026-06-21 09:13:33 +02:00
Calixte Denizet
34516bcec3 Vertically center the glyphs in comb text fields 2026-06-20 18:47:24 +02:00
Jonas Jenwald
00e1aabe93 Remove unnecessary explicit return statements in CanvasGraphics.prototype.showText 2026-06-19 10:58:14 +02:00
Jonas Jenwald
786019eb0d Remove the unused AnnotationEditorUIManager.prototype.isSelected method
According to the coverage data this method is unused, see e20c810dd4/blob/src/display/editor/tools.js (L2552), and searching through the entire code-base reveals no call-site invoking an `isSelected` method.
2026-06-18 23:21:53 +02:00
calixteman
e20c810dd4
Merge pull request #21469 from calixteman/issue21466
Avoid too long BlueScale value when rewriting a CFF font
2026-06-18 21:43:05 +02:00
calixteman
07d4c1018a
Avoid too long BlueScale value when rewriting a CFF font
It fixes #21466.
2026-06-18 20:48:13 +02:00
Jonas Jenwald
b4b0a3fa04 Remove the unused ImageData branch in the putBinaryImageData function
This branch isn't covered by any tests, and looking at the two existing call-sites we only ever pass in a `CanvasRenderingContext2D` interface to this function.
Based on the git history this branch was added in PR 3312, however as far as I can tell it doesn't actually appear to have been necessary even back then!?
2026-06-18 18:22:55 +02:00
Jonas Jenwald
a443a635a1 Remove the unused HTMLElement branch in the paintInlineImageXObject method
This branch isn't covered by any tests, and as far as I can tell it's been unused ever since PR 11601 which simplified the JPEG image handling.
Prior to that we'd create an `Image` instance in one case, see [this code](https://github.com/mozilla/pdf.js/pull/11601/changes#diff-082d6b37ad01db7ac97cc07c6ddb0dc52040484c5ef91b110b072f50144d9f39L2312-L2314), which is why that branch was necessary since `new Image()` creates a `HTMLImageElement` instance which in itself is an instance of `HTMLElement`; note [this](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image) respectively [this](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement).
2026-06-18 17:47:26 +02:00
Calixte Denizet
9d9fb06d7f Re-derive annotation attachment content from the xref after cleanup
Annotation-local attachments (those not in the catalog `/Names` tree) were
resolved through a dictionary cache that `Catalog.cleanup` clears, so their
content became unreachable once the idle cleanup had run.

Encode the reference of the embedded content in the attachment id and re-fetch
it from the xref on demand instead of caching the dictionary, so the content
stays reachable without anything having to survive cleanup.

It fixes a regression introduced by #21351.
2026-06-18 16:03:32 +02:00
calixteman
eae42379f2
Merge pull request #21462 from calixteman/bluescale-small-zones
Don't clamp BlueScale up when a font genuinely has small zones
2026-06-16 21:52:25 +02:00
Tim van der Meij
8bc13d502b
Merge pull request #21459 from Snuffleupagus/PDFEditor-ternary-Dict-set
Use ternary expressions to shorten code in `src/core/editor/pdf_editor.js`
2026-06-16 20:50:05 +02:00
calixteman
bc99fc0678
Don't clamp BlueScale up when a font genuinely has small zones
The lower BlueScale clamp from #21343 guarded foundry fonts via
`blueScale < DEFAULT_BLUE_SCALE`, but that lets a near-default value
(e.g. 0.037) with small zones get raised to `0.5 / maxZoneHeight`. On
macOS' Core Text rasterizer this collapses the overshooting glyphs, so
most text disappears (not reproducible on Linux/Windows).
2026-06-16 19:34:48 +02:00
Calixte Denizet
082ad21387 Draw non-isolated blend-mode groups against their backdrop (bug 1873345)
A non-isolated transparency group must blend with its backdrop, but a group
containing a blend mode was forced onto a transparent intermediate canvas;
e.g. a /Multiply highlight then painted opaquely over the text behind it,
 making that text invisible.
2026-06-16 15:09:39 +02:00
Jonas Jenwald
6c0ad865c6 Use ternary expressions to shorten code in src/core/editor/pdf_editor.js
This makes setting a few Dictionary entries a little bit shorter, which shouldn't hurt.
(Part of this code isn't fully covered by tests, so it improves overall code coverage as well.)
2026-06-16 11:50:53 +02:00
Tim van der Meij
7f7b38b424
Merge pull request #21457 from Snuffleupagus/GetAnnotationsByType-rm-page-check
Remove unneeded check in the "GetAnnotationsByType" worker-thread handler
2026-06-15 21:41:10 +02:00
Tim van der Meij
7d3ec9da1e
Merge pull request #21456 from Snuffleupagus/rm-classNamesForOutlining
Remove the unused `HighlightOutline.prototype.classNamesForOutlining` getter
2026-06-15 20:46:32 +02:00
Calixte Denizet
2550b91be9 Resolve checkbox/radio export values from the 'Opt' entry
For checkbox and radio button fields, the export value can differ from the
appearance-state name: the field's inheritable `Opt` array holds the real
export values (used for non-Latin text, or values shared between buttons).
We previously exposed the appearance-state name as the export value.
2026-06-15 18:23:26 +02:00
Jonas Jenwald
d9e4cc5f65 Remove unneeded check in the "GetAnnotationsByType" worker-thread handler
Given that the Promise returned by the `PDFDocument.prototype.getPage` method *always* resolves with a `Page` instance, checking that the page is defined isn't necessary; note 3a09329113/src/core/document.js (L1702-L1723)

Furthermore the `Page.prototype.collectAnnotationsByType` method is asynchronous, and thus it always returns a Promise, hence it's "pointless" to fallback to return an empty Array.
2026-06-15 13:12:47 +02:00
Jonas Jenwald
f781ac33da Remove the unused HighlightOutline.prototype.classNamesForOutlining getter
This was added in PR 18972 and it became unused in PR 19085, however it was accidentally left behind.
2026-06-15 12:02:46 +02:00
Tim van der Meij
0ea67ed96f
Upgrade eslint-plugin-unicorn to version 66.0.0
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v66.0.0
doesn't indicate any breaking changes that should impact us.

However, improved rules do require a small number of changes here:

- The `prefer-array-some` rule no longer reports a false positive after
  https://github.com/sindresorhus/eslint-plugin-unicorn/issues/3198 got
  fixed, so the ignore line that was added in commit 68a5ec1 is removed.

- The `prefer-ternary` rule triggers on more cases now, in particular
  `let` declarations with `if` reassignments, so a number of changes are
  made to make it pass again.

- The `prefer-at` rule triggers on more cases now, in particular
  `substring` calls that just extract a single character, so one change
  is made to make it pass again.
2026-06-14 20:20:34 +02:00
Tim van der Meij
ed1b2f91be
Merge pull request #21440 from Snuffleupagus/putBinaryImageData-convertRGBToRGBA
Use the `convertRGBToRGBA` helper with RGB images in `putBinaryImageData`
2026-06-14 14:20:11 +02:00
Jonas Jenwald
e1c930adfe Add an integration-test for merging a corrupt PDF
Currently when opening a PDF document the following code is used, where `checkFirstPage`/`checkLastPage` helps detect XRef corruption; note 86a18bd5fe/src/core/worker.js (L167-L176)

However when merging a PDF into an existing document the parsing is only "partial"; note 86a18bd5fe/src/core/worker.js (L632-L634)

It seems a little strange to not support corrupt PDFs in a consistent manner in the code-base, hence this patch adds a new `BasePdfManager` helper that handles all the relevant parsing/checking and re-uses that when merging PDFs.
2026-06-14 09:49:23 +02:00
Tim van der Meij
68a5ec1403
Upgrade eslint-plugin-unicorn to version 65.0.1
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v65.0.0
doesn't indicate any breaking changes that should impact us.

However, there is one false positive, possibly introduced by patch
https://github.com/sindresorhus/eslint-plugin-unicorn/pull/3028:

```
src/core/xfa/factory.js
  104:54  error  Prefer `.some(…)` over `.find(…)`  unicorn/prefer-array-some
```

This is incorrect because on this line we're not dealing with an array
but with a `FontFinder` instance instead (and that doesn't have a
`.some()` method), so we ignore the rule for this line.
2026-06-13 19:33:50 +02:00
Jonas Jenwald
c88f0bba04 Reduce duplication when invoking finishWorkerTask
By utilizing `Promise.prototype.finally()` more it's possible to avoid a bit of duplication when invoking `finishWorkerTask`.
2026-06-13 16:52:47 +02:00
Jonas Jenwald
55c8516944 Use the convertRGBToRGBA helper with RGB images in putBinaryImageData
This removes a little bit of code duplication, which only exist since the `src/display/canvas.js` code pre-dates the helper function by many years.

Note: Given that `OffscreenCanvas` is enabled by default there's currently not a lot of test coverage for this code-path, hence the added browser-test.
2026-06-13 13:14:50 +02:00
Tim van der Meij
e75a7cfd62
Merge pull request #21441 from Snuffleupagus/JpegImage-isSourcePDF-conditional
Re-factor the `isSourcePDF` handling in the `JpegImage` class
2026-06-13 12:48:00 +02:00
Tim van der Meij
5f8f6b1e40
Merge pull request #21439 from Snuffleupagus/more-getOrInsertComputed
Use `Map.prototype.getOrInsertComputed()` more in the code-base
2026-06-13 12:44:51 +02:00
Jonas Jenwald
ec1e94423b Re-factor the isSourcePDF handling in the JpegImage class
This functionality was added specifically for the standalone image-decoders, and by utilizing the pre-processor we can reduce the amount of "unnecessary" code in the regular builds.

Also, shorten a few loop variables a little bit since less code is always good.
2026-06-13 10:59:02 +02:00
Jonas Jenwald
5873e1cbc0
Merge pull request #21431 from Snuffleupagus/more-isDict
Use the `isDict` helper function in a few more places
2026-06-12 23:32:22 +02:00
Jonas Jenwald
ffa7ac7a91 Use Map.prototype.getOrInsertComputed() more in the code-base 2026-06-12 23:21:16 +02:00