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.
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.
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.
This method has been completely unused for many years, possibly as far back as PR 8030, hence we can avoid shipping a little bit of dead code.
*Note:* If there's any third-party code depending on it, updating it ought to be as simple as changing
```javascript
const r = viewport.convertToViewportRectangle(rect);
```
into
```javascript
const r = [
...viewport.convertToViewportPoint(rect[0], rect[1]),
...viewport.convertToViewportPoint(rect[2], rect[3])
];
```
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.
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.
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).
When a read-only field (which has its own canvas) is updated by the
sandbox while its page isn't rendered, showElementAndHideCanvas
isn't called, so once the page is finally rendered the field still
shows its outdated canvas instead of the new value.
Replace the imperative canvas/element toggling with a `sandboxModified`
class, set from the annotation storage both at render time and on
sandbox updates, and let the CSS show the element and hide the canvas.
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.
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.
There's currently a few EventBus listeners that aren't marked as "internal", however I'm assuming that they probably should be (e.g. to reduce the risk of intermittent failures in the integration-tests).
Currently the viewer uses semi-private `EventBus.prototype.{_on, _off}` methods, to try and ensure that all internal viewer state is updated *before* any "external" listeners are invoked.
For all use-cases outside of the viewer, e.g in the integration-tests, the `EventBus.prototype.{on, off}` methods are supposed to be used instead.
Unfortunately this isn't currently enforced in any way, except (hopefully) during review, and generally speaking it's not really possible to prevent the semi-private methods being used (e.g. by third-party users).
Hence this patch adds a new `INTERNAL_EVT` property which is *not* exposed anywhere (neither in the API nor globally), and whose value is generated at build-time, that the viewer uses to mark its `EventBus` listeners are internal.
This allows us to remove the semi-private `EventBus` methods, which helps to simplify that class a little bit.
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.
I happened to notice that the way the `OptionalContentConfig`-data handled in the PR that implements worker-rendering leaves a lot to be desired:
- The way that the optional content state is handled is not correct, since that PR collects the "effective visibility" of the optional content groups rather than their *actual* internal state.
- The necessary `OptionalContentConfig`-data is collected piecemeal in the API, which leads to quite frankly very messy code that's hard to read and will be even harder to maintain.
The solution to all of these issues seem really simple though, just add a couple of `OptionalContentConfig` methods that serialize/de-serialize the necessary data.
In the API calling `optionalContentConfig.serializable` will get *all* of the needed data for transferring to the worker-renderer, and once received there calling `OptionalContentConfig.fromSerializable(/* transferred data here */)` will create an `OptionalContentConfig` instance with the correct internal state.
As part of this patch, to avoid increasing bundle-size unnecessarily, a couple of existing methods are stubbed out when the `OptionalContentConfig` class ends up in a worker-file (since they're unused there).
This part assumes that the new worker-renderer is built correctly, note how the existing `pdf.worker.mjs` is handled in 03eda70d7e/gulpfile.mjs (L539-L545)
(*Note:* Submitting a PR was a lot faster than trying to provide review comments, since writing this commit message took longer than writing the patch.)
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.
Fixes#21259.
Reset letter-spacing and word-spacing on the text layer and hidden measurement canvas so inherited page styles do not affect text layer alignment. Add an integration regression test for inherited spacing.
In many/most PDF documents every glyph will require that the character BBox has scaling/offset applied, which can be made a tiny bit more efficient. In particular:
- Avoid creating one additional temporary Array for every glyph.
- Simplify the helper function, since there's no skew-components.
References <https://bugzilla.mozilla.org/show_bug.cgi?id=1879559>
(“In HCM, the text selection is barely visible”).
Continues work from @calixteman who had a partial patch.
This PR improves viewer text-selection highlighting by rendering
selection shapes in the draw layer.
* add selection overlay rendering in the draw layer
* significant code relates to selections spanning multiple text
layers/pages, and edges/end-of-content boundaries
* clear selection on rotate/scale/scroll/spread changes
My main question is: how should it appear?
I don’t have access to the Figma file linked on bugzilla.
In the CSS (`draw_layer-builder.css`) there are 3 blocks:
* default
* `@supports` for browsers supporting `backdrop-filter`
* `forced-colors` mode
So it’s possible to design for those (or more).
Personally, the `backdrop-filter: invert(1)` is the most contrast,
so perhaps it’s better to use something else as the default,
and to use `invert(1)` if high contrast mode is used (maybe with a
`prefers-contrast` media query instead)?
This method is completely unused in the worker-thread, and it only has a single call-site in the main-thread.
By moving this helper into the `src/display/canvas_dependency_tracker.js` file, the size of the `gulp mozcentral` bundle is reduced by `1220` bytes.
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.
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.
This method is unused in the worker-thread and has only *a single* call-site in the main-thread, which can be trivially replaced with the `getCurrentTransform` helper function.
PR #21101 narrowed `compose()`'s `clearRect` from full canvas to the
caller-supplied dirty box. That leaves pixels outside the current
dirty box on the SMask scratch canvas between `compose()` calls;
subsequent draws into scratch are then source-over-blended on top of
those leftovers, so the output depends on the cumulative draw history
rather than just the current draw.
Set layout-neutral styles at the creation sites for the hidden TextLayer
canvas and PDFViewer copy element rather than relying on the shared
web/pdf_viewer.css rule.
This keeps the helper elements invisible and out of layout when viewer CSS
selectors are scoped or omitted, and removes the obsolete hiddenCanvasElement
class and shared CSS rule.
It fixes#18032.
Only use the special inner-backdrop compositing path for nested non-isolated groups that actually need isolation.
This preserves the parent/page backdrop for simple nested groups inside knockout groups, preventing later group
compositing from erasing existing backdrop content.
In the `DrawingEditor.prototype.#createDrawOutlines` method the l10n-id was being "generated", which is bad for maintainability since searching for l10n-id becomes more difficult and the `gulp check_l10n` script actually warns about this.
Hence, similar to e.g. the resizer localization, let's define the `a11yAlert` l10n-ids *once* and provide shorthands for accessing them.
In a knockout (KO) group each painting operator ("element") composites against
the group's initial backdrop instead of accumulating onto prior elements
of the same group. The backend renders each element to a per-group pooled
temp canvas (keyed off `#groupStackMeta`), builds a binary alpha mask via
a new `feFuncA` filter (`addKnockoutFilter`), `destination-out`s the
group canvas through that mask, restores the initial backdrop into the
cleared footprint for non-isolated groups (cropped to the same mask so
sparse groups don't bleed the whole rectangle), and finally paints the
element on top with the parent's blend mode. Path / clip / transform ops
are mirrored back to the group canvas via `mirrorContextOperations` so
graphics state stays in sync between elements; only the raster pixels
land on the temp canvas.
The temp canvas is forced to source-over for the element raster (`multiply`
on a transparent backdrop would zero the color) and the original GCO is
restored before `copyCtxState` writes back, so the parent's blend mode
survives for the final composite.
Also handled:
- Nested KO groups (the level is incremented for KO, reset to 0 for
non-KO subgroups so an ancestor KO doesn't leak in).
- Non-isolated non-KO subgroups inside a KO parent (`hasInnerBackdrop`
path: blend the elements against the subgroup's running backdrop for
color, mask with the elements-only canvas).
- Soft masks installed inside a KO element (`applySMaskInPlace` in
`compose`, which runs the SMask destination-in directly on the temp
canvas; the existing blit-to-suspended step is gated by `if (!ctx)`).
- Type-3 text, shading fills, image-mask groups, inline images and the
solid-color mask path: each is wrapped in `#begin/#endKnockoutElement`.
- `endDrawing` cleanup so cancelled rendering doesn't leak pooled
canvases or stale knockout state.
This is a left-over from very old code, which pre-dates the introduction of the `PDFDocumentLoadingTask` and it's nothing more than an alias for its `destroy` method.
Given that `PDFDocumentProxy` already provides a way to access the underlying `PDFDocumentLoadingTask` instance, it shouldn't be necessary to have an alias for one of its methods.
*Please note:* For any existing code relying on the removed method, updating it should be as simple as replacing `pdfDocument.destroy()` with `pdfDocument.loadingTask.destroy()`.
---
[1] If the `PDFDocumentProxy` class was added today, there's no chance that it'd include a `destroy` method.