1580 Commits

Author SHA1 Message Date
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
Calixte Denizet
34516bcec3 Vertically center the glyphs in comb text fields 2026-06-20 18:47:24 +02:00
Jonas Jenwald
bade1f3190 Add a unit-test for relative URI actions specified as /Name instances
The following branch was added to fix issue 4159, however looking at the coverage data it's not actually tested; see 59df671552/src/core/catalog.js (L1866-L1869) and 59df671552/blob/src/core/catalog.js (L1866)
2026-06-19 23:58:50 +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
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
Calixte Denizet
5432642250 Adjust the 'BaseException' unit-test for the 'Error.stack' changes in Firefox
Firefox 154 no longer walks the prototype chain in the `Error.stack`
getter, so `BaseException`-derived instances return an empty string
rather than the prototype `Error`'s stack (see bug 1946559).
2026-06-16 21:30:41 +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
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
calixteman
35d275d3b1
Merge pull request #18907 from calixteman/bug1802506
Use the checkboxes and radio button appearances as defined in the pdf to render them in the annotation layer (bug 1802506)
2026-06-12 22:04:29 +02:00
Calixte Denizet
069b757998 Use the checkboxes and radio button appearances as defined in the pdf to render them in the annotation layer (bug 1802506)
The idea is to generate two operator lists for the Yes/Off states and render them on a separate canvas.
These canvases are then attached the annotation and we modify their display depending on the input state.

It fixes #18021.
2026-06-12 20:10:56 +02:00
Jonas Jenwald
131d6b7d38 Handle corrupt PDFs that lack /Kids array and just inline the /Page dictionary (issue 21436)
This basically extends PR 9549 to the fallback `getAllPageDicts` method, which didn't exist at the time, in order to support more cases of corrupt PDF documents.
2026-06-12 12:04:58 +02:00
Jonas Jenwald
f3f5acc418 Fix the unit-tests for on-demand password handling of encrypted attachments (issue 21425)
These unit-tests used a PDF that prompted for password on document load, which meant that the on-demand password handling wasn't actually being tested as intended.

Updating the unit-tests also caused the "re-prompts for encrypted attachments after incorrect passwords" test to fail, since the `INCORRECT_PASSWORD` password reason was being accidentally "swallowed" in the worker-thread.
2026-06-10 23:08:34 +02:00
calixteman
ce08a803c4
Merge pull request #21416 from calixteman/drop-css-unsafe-inline
Drop 'unsafe-inline' from the CSP style-src directives
2026-06-09 23:16:38 +02:00
calixteman
a13f2aa793
Merge pull request #21413 from calixteman/improve_comb
Improve rendering of comb text fields
2026-06-09 23:10:49 +02:00
Calixte Denizet
fe5eb0f779
Improve rendering of comb text fields
Center each glyph within its comb cell instead of left-aligning it,
both in the HTML annotation layer and in the printed/saved appearance,
to match Acrobat. Cell width is now the single source of truth via the
--comb-width CSS variable, and field text-alignment (center/right) is
applied as a whole-cell --comb-offset that stays in sync on input,
blur, resetform and updatefromsandbox. The field no longer grows on
focus; trailing letter-spacing is clipped and cell dividers are drawn
on focus.
2026-06-09 22:15:40 +02:00
Calixte Denizet
5ca6026d80
Drop 'unsafe-inline' from the CSP style-src directives
The print service injected the per-PDF `@page { size }` rule as an inline
<style> element, which required 'unsafe-inline' on style-src-elem.

Inject it through a constructable CSSStyleSheet attached to
document.adoptedStyleSheets instead. Constructable stylesheets aren't
subject to style-src's inline restrictions in browsers.
2026-06-09 22:08:08 +02:00
Jonas Jenwald
ea139e7df1 [api-minor] Convert getAttachments to return data in a Map
Compared to regular `Object`s there's a number of advantages to using `Map`s:
 - They support "proper" iteration.
 - They have a simple way to check for the existence of data.
 - They have a simple/efficient way to check the number of elements.

If this functionality was added today, I cannot imagine that we'd choose an `Object` for this sort of data.
Furthermore, in PR 21351 the data returned by `getAttachments` changed slightly and third-party users will need to update their code anyway (hence why `[api-minor]` should be fine here).
2026-06-09 10:17:23 +02:00
Tim van der Meij
81f15c3437
Merge pull request #21390 from Snuffleupagus/getDocument-binary-string-unit-test
Add a unit-test for passing a binary string to `getDocument`
2026-06-06 19:46:45 +02:00
Tim van der Meij
f4d6b4ef85
Merge pull request #21391 from Snuffleupagus/getDocument-Node-fs-unit-test
Add a unit-test for passing a filesystem URL-string (in Node.js) to `getDocument`
2026-06-06 19:45:26 +02:00
Jonas Jenwald
a5333f2a92 Add a unit-test for passing a binary string to getDocument
This format is obviously not very efficient however it's been supported since "forever" and there's even examples using, hence it seems like a good idea to actually test this.
2026-06-06 14:37:25 +02:00
Jonas Jenwald
08b704d4b1 Add one more unit-test case for invalid email domains in the Autolinker class
This improves coverage for a branch of the `Autolinker` class that wasn't previously tested.
2026-06-06 11:57:22 +02:00
Jonas Jenwald
a7d32f4518 Add a unit-test for passing a filesystem URL-string (in Node.js) to getDocument
This improves coverage for a part of the API that previously wasn't tested.
2026-06-05 23:17:11 +02:00
calixteman
173e083c71
Merge pull request #21350 from calixteman/kb_shortcuts_l10n
Match editor keyboard shortcuts by event.code as a fallback
2026-06-05 17:19:17 +02:00
Tim van der Meij
23ea0810d9
Merge pull request #21379 from calixteman/dedup_stream_merging
Deduplicate shared font/image streams when merging PDFs
2026-06-04 20:58:22 +02:00
Jonas Jenwald
dc602ae543 Extend the AppOptions unit-tests to also cover the EVENT_DISPATCH option-kind 2026-06-04 17:51:41 +02:00
Titus Wormer
4db9e45b8c
Add support for /AuthEvent, on-demand decryption
Normally entire PDFs are encrypted (or not).
But it is also possible to only encrypt attachments.
It is then also possible to *only* prompt for a password when the user opens
them.

In the existing flow, prompting for passwords happens because things are decrypted.
A specific error is thrown, caught, and the user is prompted.
To keep this flow working, this PR changes to decrypting attachments on demand,
instead of eagerly.
This sounds logical: to not read attachments on startup.

I’ve extensively tested this, not only with regular attachments, but also with outline items
and attachments in annotations.

This PR builds on GH-21234.
It’s an alternative to the naïve GH-20732.

Closes GH-20049.
2026-06-03 16:44:57 +02:00
Calixte Denizet
836a08084e Match editor keyboard shortcuts by event.code as a fallback
So that Ctrl+A, Ctrl+Z, etc. still fire on non-US keyboard layouts where
the physical "A" key produces a non-Latin character (Cyrillic, Greek,
some AZERTY combinations, ...). KeyboardManager now tries event.key first
and falls back to a US-layout translation of event.code (KeyA => a,
Digit1 => 1, Numpad1 => 1) when no shortcut is bound on event.key.

Also refactors KeyboardManager to store modifiers as a bitmask instead
of a serialized string, and treats a shortcut array without any
"mac+"-prefixed entry as applying on all platforms, letting us drop the
redundant "mac+X" duplicates of bare "X" entries across the editor code.
2026-06-03 10:13:41 +02:00
Calixte Denizet
1a7821ab13 Deduplicate shared font/image streams when merging PDFs
Identical embedded fonts and images across the merged documents are now
written once and shared, instead of being copied per source file.
And avoid to compress already compressed stream with Brotli.
2026-06-02 22:08:21 +02:00
Jonas Jenwald
06439a95c3 Update the StringStream constructor to accept an optional dictionary argument
There's currently some amount of `StringStream` usage where the `dict`-parameter is manually assigned, and by updating the signature of the constructor this can be avoided.
2026-05-31 11:36:32 +02:00
calixteman
c7a32c3db6
Merge pull request #21343 from calixteman/issue9437
Clamp out-of-range BlueScale to Adobe's valid window
2026-05-29 08:58:05 +02:00
Calixte Denizet
600986b51d Allow inserting an image as a new page when editing a PDF
Image files dropped on or selected via the thumbnail viewer's
"add file" picker are now accepted alongside PDFs and inserted
as synthetic pages sized to the document's modal page dimensions.

The image-encoding helper previously embedded in StampAnnotation has
moved to src/core/editor/pdf_images.js so it can be shared between
stamp annotations and page synthesis.
2026-05-28 22:11:13 +02:00
calixteman
389853d473
Merge pull request #21336 from calixteman/issue15292
Parse CID-keyed Type 1 fonts instead of falling back to a system font
2026-05-28 21:45:30 +02:00
Titus Wormer
45cdb5d3e8
Add support for encrypted attachments
This PR is related to GH-20732, which is about `AuthEvent` (to delay
promting for a password), but instead adds the actual support for
encrypted attachments.
“Encrypted attachments” means that the main things are plain text.
Note that some PDF viewers, like Preview/QuickLook/Safari or Chrome,
do not support attachments at all.
Note that the file checked into the tests is the same as
`output-no-auth-event.pdf` referenced in
<https://github.com/mozilla/pdf.js/issues/20139#issuecomment-3952462166>.

Closes GH-20139.
2026-05-28 10:30:37 +02:00
calixteman
385b1ca412 Clamp out-of-range BlueScale to Adobe's valid window
Fonts that ship a BlueScale outside the range AFDKO considers valid
for their zone heights (0.5/maxZoneHeight <= BlueScale <= 1/maxZoneHeight)
cause Firefox's CFF rasterizer to misalign overshooting glyphs against
flat-topped ones at body sizes.
Clamp into that window, only apply the lower clamp when BlueScale is
also smaller than the default, so foundry fonts that pair the default
0.039625 with small zones are untouched.

Fixes #9437.
2026-05-26 21:24:51 +02:00
calixteman
e1de5c30b5 Parse CID-keyed Type 1 fonts instead of falling back to a system font
It fixes #15292.

PDFs can embed a CID-keyed Type 1 program (Adobe TechNote 5014,
CIDFontType 0) under /Subtype /CIDFontType0 + /FontFile. Its binary
CIDMap/SubrMap layout has no eexec block, so Type1Font's eexec-only
parser used to fall through and trigger the work-around added in
PR #15397.
Split the constructor and parse the binary CIDMap, SubrMap
and charstrings (encrypted with the standard Type 1 charstring cipher)
through the existing Type1CharString.convert + CFF wrap pipeline.

Only single-FDArray fonts are supported; the StartData length is
clamped to the stream's remaining bytes before allocating.
2026-05-26 17:49:56 +02:00
Tim van der Meij
d1c85f87f7
Merge pull request #21330 from calixteman/fix_regex
Enable 'eslint-plugin-regexp' and fix existing findings
2026-05-25 18:22:21 +02:00
Calixte Denizet
8f85e3f20b Load the predefined CMap for composite fonts that omit the FontDescriptor
and add font substitutions for the standard Acrobat CJK families.
2026-05-25 14:44:48 +02:00
Calixte Denizet
7bda0fc97c Enable 'eslint-plugin-regexp' and fix existing findings
Enable the recommended preset and fix or per-line-disable the 78
findings it surfaces. Most are equivalent rewrites, intentional
patterns (control chars, the whatwg email regex, autolinker URL regex)
keep their behavior via targeted disables.
2026-05-25 14:31:55 +02:00
Calixte Denizet
9391296036 Recover CFF FontBBox with negative coordinates encoded as unsigned 16-bit
It fixes #21312.
2026-05-25 08:36:18 +02:00
Jonas Jenwald
74471651c7 Extend unit-test coverage for the getPdfFilenameFromUrl helper function
Currently there's a couple of branches, specifically for dealing with corrupt URLs, that are not covered by tests.
2026-05-21 14:03:32 +02:00
calixteman
deb532334f
Merge pull request #21290 from calixteman/issue20633
Recover CFF private dict defaults zeroed by Ghostscript
2026-05-17 21:57:16 +02:00
calixteman
cd8a78c4e2
Recover CFF private dict defaults zeroed by Ghostscript
It fixes the issue #20633.
2026-05-17 20:51:35 +02:00
Jonas Jenwald
7f2bb0e991 Add a couple of very basic ColorConverters unit-tests
These tests could obviously be improved/extended, but it's at least a start to ensure that `ColorConverters` is tested since it's used in both the annotation-layer and the scripting-implementation.
2026-05-16 17:17:41 +02:00
Jonas Jenwald
e8f07d7ca3 [api-minor] Move the getXfaPageViewport helper into the XfaLayer class
This small helper function only exists to support printing of XFA documents, in the viewer, hence it seems like a good idea to (ever so slightly) reduce the official API surface a little bit.
2026-05-16 12:31:53 +02:00
Jonas Jenwald
eda97fe8fc Move the PageViewport class into its own file
This is necessary to prevent import cycles with the next patch.

It also shouldn't hurt to reduce the size of `src/display/display_utils.js` a little bit, since utility-files have a tendency to increase in size over time.
2026-05-16 12:31:40 +02:00
Jonas Jenwald
e5330f06fa Move the stringToPDFString helper function into the src/core/string_utils.js file
Given that this function is only ever used during *parsing* of the PDF document, which happens in the worker-thread, this has always added (a little bit of) dead code in the built `pdf.mjs` file.
2026-05-15 12:10:30 +02:00
Jonas Jenwald
153cef615e Move a couple of src/core/ string helper functions into their own file
Given that the various utility-files naturally increase in size over time, it shouldn't hurt to shorten `src/core/core_utils.js` a little bit by moving a few of its string helper functions to their own file.
2026-05-15 11:49:54 +02:00
Jonas Jenwald
949497a3c4 Add a simple API unit-test for /BrotliDecode
This is a new feature in PDF documents, hence it shouldn't hurt to complement the existing ref-test with a simple unit-test as well.
This should also improve test coverage for the `external/` folder, which can't hurt since the other external decoders are already fairly well covered.
2026-05-14 15:44:42 +02:00
Tim van der Meij
26dc195a65
Collect coverage information for the integration tests
Note that for the integration tests the coverage information ends up
being processed in the Node.js context where `window` is not available,
so we use `globalThis` instead for the function that merges individual
test's coverage information into the global object because that is
available in all contexts we support. For clarity we also rename said
function since we're not exclusively dealing with `window` nor worker
data anymore.
2026-05-14 12:34:12 +02:00