2013-09-20 09:25:41 +02:00
|
|
|
/* Copyright 2012 Mozilla Foundation
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2021-12-14 23:59:17 +01:00
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
/** @typedef {import("../src/display/optional_content_config").OptionalContentConfig} OptionalContentConfig */
|
2021-12-15 13:54:29 +01:00
|
|
|
/** @typedef {import("./event_utils").EventBus} EventBus */
|
2021-12-14 23:59:17 +01:00
|
|
|
/** @typedef {import("./interfaces").IL10n} IL10n */
|
Fix Viewer API definitions and include in CI
The Viewer API definitions do not compile because of missing imports and
anonymous objects are typed as `Object`. These issues were not caught
during CI because the test project was not compiling anything from the
Viewer API.
As an example of the first problem:
```
/**
* @implements MyInterface
*/
export class MyClass {
...
}
```
will generate a broken definition that doesn’t import MyInterface:
```
/**
* @implements MyInterface
*/
export class MyClass implements MyInterface {
...
}
```
This can be fixed by adding a typedef jsdoc to specify the import:
```
/** @typedef {import("./otherFile").MyInterface} MyInterface */
```
See https://github.com/jsdoc/jsdoc/issues/1537 and
https://github.com/microsoft/TypeScript/issues/22160 for more details.
As an example of the second problem:
```
/**
* Gets the size of the specified page, converted from PDF units to inches.
* @param {Object} An Object containing the properties: {Array} `view`,
* {number} `userUnit`, and {number} `rotate`.
*/
function getPageSizeInches({ view, userUnit, rotate }) {
...
}
```
generates the broken definition:
```
function getPageSizeInches({ view, userUnit, rotate }: Object) {
...
}
```
The jsdoc should specify the type of each nested property:
```
/**
* Gets the size of the specified page, converted from PDF units to inches.
* @param {Object} options An object containing the properties: {Array} `view`,
* {number} `userUnit`, and {number} `rotate`.
* @param {number[]} options.view
* @param {number} options.userUnit
* @param {number} options.rotate
*/
```
2021-08-25 18:44:06 -04:00
|
|
|
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
|
2021-12-14 23:59:17 +01:00
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
/** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */
|
Fix Viewer API definitions and include in CI
The Viewer API definitions do not compile because of missing imports and
anonymous objects are typed as `Object`. These issues were not caught
during CI because the test project was not compiling anything from the
Viewer API.
As an example of the first problem:
```
/**
* @implements MyInterface
*/
export class MyClass {
...
}
```
will generate a broken definition that doesn’t import MyInterface:
```
/**
* @implements MyInterface
*/
export class MyClass implements MyInterface {
...
}
```
This can be fixed by adding a typedef jsdoc to specify the import:
```
/** @typedef {import("./otherFile").MyInterface} MyInterface */
```
See https://github.com/jsdoc/jsdoc/issues/1537 and
https://github.com/microsoft/TypeScript/issues/22160 for more details.
As an example of the second problem:
```
/**
* Gets the size of the specified page, converted from PDF units to inches.
* @param {Object} An Object containing the properties: {Array} `view`,
* {number} `userUnit`, and {number} `rotate`.
*/
function getPageSizeInches({ view, userUnit, rotate }) {
...
}
```
generates the broken definition:
```
function getPageSizeInches({ view, userUnit, rotate }: Object) {
...
}
```
The jsdoc should specify the type of each nested property:
```
/**
* Gets the size of the specified page, converted from PDF units to inches.
* @param {Object} options An object containing the properties: {Array} `view`,
* {number} `userUnit`, and {number} `rotate`.
* @param {number[]} options.view
* @param {number} options.userUnit
* @param {number} options.rotate
*/
```
2021-08-25 18:44:06 -04:00
|
|
|
|
[api-minor] Introduce a new `annotationMode`-option, in `PDFPageProxy.{render, getOperatorList}`
*This is a follow-up to PRs 13867 and 13899.*
This patch is tagged `api-minor` for the following reasons:
- It replaces the `renderInteractiveForms`/`includeAnnotationStorage`-options, in the `PDFPageProxy.render`-method, with the single `annotationMode`-option that controls which annotations are being rendered and how. Note that the old options were mutually exclusive, and setting both to `true` would result in undefined behaviour.
- For improved consistency in the API, the `annotationMode`-option will also work together with the `PDFPageProxy.getOperatorList`-method.
- It's now also possible to disable *all* annotation rendering in both the API and the Viewer, since the other changes meant that this could now be supported with a single added line on the worker-thread[1]; fixes 7282.
---
[1] Please note that in order to simplify the overall implementation, we'll purposely only support disabling of *all* annotations and that the option is being shared between the API and the Viewer. For any more "specialized" use-cases, where e.g. only some annotation-types are being rendered and/or the API and Viewer render different sets of annotations, that'll have to be handled in third-party implementations/forks of the PDF.js code-base.
2021-08-08 14:36:28 +02:00
|
|
|
import {
|
2022-11-21 17:15:39 +01:00
|
|
|
AbortException,
|
[api-minor] Introduce a new `annotationMode`-option, in `PDFPageProxy.{render, getOperatorList}`
*This is a follow-up to PRs 13867 and 13899.*
This patch is tagged `api-minor` for the following reasons:
- It replaces the `renderInteractiveForms`/`includeAnnotationStorage`-options, in the `PDFPageProxy.render`-method, with the single `annotationMode`-option that controls which annotations are being rendered and how. Note that the old options were mutually exclusive, and setting both to `true` would result in undefined behaviour.
- For improved consistency in the API, the `annotationMode`-option will also work together with the `PDFPageProxy.getOperatorList`-method.
- It's now also possible to disable *all* annotation rendering in both the API and the Viewer, since the other changes meant that this could now be supported with a single added line on the worker-thread[1]; fixes 7282.
---
[1] Please note that in order to simplify the overall implementation, we'll purposely only support disabling of *all* annotations and that the option is being shared between the API and the Viewer. For any more "specialized" use-cases, where e.g. only some annotation-types are being rendered and/or the API and Viewer render different sets of annotations, that'll have to be handled in third-party implementations/forks of the PDF.js code-base.
2021-08-08 14:36:28 +02:00
|
|
|
AnnotationMode,
|
2024-09-15 20:40:01 +02:00
|
|
|
OutputScale,
|
2021-09-20 10:10:57 +02:00
|
|
|
PixelsPerInch,
|
2022-11-21 18:48:37 +01:00
|
|
|
setLayerDimensions,
|
2022-12-14 13:19:41 +01:00
|
|
|
shadow,
|
[api-minor] Introduce a new `annotationMode`-option, in `PDFPageProxy.{render, getOperatorList}`
*This is a follow-up to PRs 13867 and 13899.*
This patch is tagged `api-minor` for the following reasons:
- It replaces the `renderInteractiveForms`/`includeAnnotationStorage`-options, in the `PDFPageProxy.render`-method, with the single `annotationMode`-option that controls which annotations are being rendered and how. Note that the old options were mutually exclusive, and setting both to `true` would result in undefined behaviour.
- For improved consistency in the API, the `annotationMode`-option will also work together with the `PDFPageProxy.getOperatorList`-method.
- It's now also possible to disable *all* annotation rendering in both the API and the Viewer, since the other changes meant that this could now be supported with a single added line on the worker-thread[1]; fixes 7282.
---
[1] Please note that in order to simplify the overall implementation, we'll purposely only support disabling of *all* annotations and that the option is being shared between the API and the Viewer. For any more "specialized" use-cases, where e.g. only some annotation-types are being rendered and/or the API and Viewer render different sets of annotations, that'll have to be handled in third-party implementations/forks of the PDF.js code-base.
2021-08-08 14:36:28 +02:00
|
|
|
} from "pdfjs-lib";
|
2017-03-28 01:07:27 +02:00
|
|
|
import {
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
approximateFraction,
|
2024-09-05 17:05:22 +02:00
|
|
|
calcRound,
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
DEFAULT_SCALE,
|
2024-06-07 14:08:43 +02:00
|
|
|
floorToDivide,
|
2021-12-15 13:54:29 +01:00
|
|
|
RenderingStates,
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
TextLayerMode,
|
2020-01-02 12:00:16 +01:00
|
|
|
} from "./ui_utils.js";
|
[api-minor] Remove the `annotationEditorLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationEditorLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 14:21:51 +01:00
|
|
|
import { AnnotationEditorLayerBuilder } from "./annotation_editor_layer_builder.js";
|
[api-minor] Remove the `annotationLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:34:55 +01:00
|
|
|
import { AnnotationLayerBuilder } from "./annotation_layer_builder.js";
|
2024-02-20 10:50:28 +01:00
|
|
|
import { AppOptions } from "./app_options.js";
|
2024-11-12 11:26:32 +05:30
|
|
|
import { Autolinker } from "./autolinker.js";
|
2024-12-11 13:54:50 +01:00
|
|
|
import { BasePDFPageView } from "./base_pdf_page_view.js";
|
2023-11-22 19:02:42 +01:00
|
|
|
import { DrawLayerBuilder } from "./draw_layer_builder.js";
|
2024-01-30 18:32:35 +01:00
|
|
|
import { GenericL10n } from "web-null_l10n";
|
2024-12-11 13:58:52 +01:00
|
|
|
import { PDFPageDetailView } from "./pdf_page_detail_view.js";
|
2023-02-05 16:13:18 +01:00
|
|
|
import { SimpleLinkService } from "./pdf_link_service.js";
|
[api-minor] Remove the `structTreeLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `structTreeLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:43:09 +01:00
|
|
|
import { StructTreeLayerBuilder } from "./struct_tree_layer_builder.js";
|
2022-07-28 17:59:03 +02:00
|
|
|
import { TextAccessibilityManager } from "./text_accessibility.js";
|
[api-minor] Remove the `textHighlighterFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `textHighlighterFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:55:23 +01:00
|
|
|
import { TextHighlighter } from "./text_highlighter.js";
|
[api-minor] Remove the `textLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `textLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-07 00:09:14 +01:00
|
|
|
import { TextLayerBuilder } from "./text_layer_builder.js";
|
[api-minor] Remove the `xfaLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `xfaLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-07 00:13:44 +01:00
|
|
|
import { XfaLayerBuilder } from "./xfa_layer_builder.js";
|
2016-04-08 12:34:27 -05:00
|
|
|
|
2014-09-20 12:21:49 -05:00
|
|
|
/**
|
2014-09-27 13:03:28 -05:00
|
|
|
* @typedef {Object} PDFPageViewOptions
|
2021-10-28 11:57:27 +02:00
|
|
|
* @property {HTMLDivElement} [container] - The viewer element.
|
2016-04-25 17:57:15 -05:00
|
|
|
* @property {EventBus} eventBus - The application event bus.
|
2014-09-27 13:03:28 -05:00
|
|
|
* @property {number} id - The page unique ID (normally its number).
|
2022-08-25 13:36:05 -03:00
|
|
|
* @property {number} [scale] - The page scale display.
|
2014-09-27 13:03:28 -05:00
|
|
|
* @property {PageViewport} defaultViewport - The page viewport.
|
[api-minor] Add support for toggling of Optional Content in the viewer (issue 12096)
*Besides, obviously, adding viewer support:* This patch attempts to improve the general API for Optional Content Groups slightly, by adding a couple of new methods for interacting with the (more complex) data structures of `OptionalContentConfig`-instances. (Thus allowing us to mark some of the data as "private", given that it probably shouldn't be manipulated directly.)
By utilizing not just the "raw" Optional Content Groups, but the data from the `/Order` array when available, we can thus display the Layers in a proper tree-structure with collapsible headings for PDF documents that utilizes that feature.
Note that it's possible to reset all Optional Content Groups to their default visibility state, simply by double-clicking on the Layers-button in the sidebar.
(Currently that's indicated in the Layers-button tooltip, which is obviously easy to overlook, however it's probably the best we can do for now without adding more buttons, or even a dropdown-toolbar, to the sidebar.)
Also, the current Layers-button icons are a little rough around the edges, quite literally, but given that the viewer will soon have its UI modernized anyway they hopefully suffice in the meantime.
To give users *full* control of the visibility of the various Optional Content Groups, even those which according to the `/Order` array should not (by default) be toggleable in the UI, this patch will place those under a *custom* heading which:
- Is collapsed by default, and placed at the bottom of the Layers-tree, to be a bit less obtrusive.
- Uses a slightly different formatting, compared to the "regular" headings.
- Is localizable.
Finally, note that the thumbnails are *purposely* always rendered with all Optional Content Groups at their default visibility state, since that seems the most useful and it's also consistent with other viewers.
To ensure that this works as intended, we'll thus disable the `PDFThumbnailView.setImage` functionality when the Optional Content Groups have been changed in the viewer. (This obviously means that we'll re-render thumbnails instead of using the rendered pages. However, this situation ought to be rare enough for this to not really be a problem.)
2020-08-06 21:01:03 +02:00
|
|
|
* @property {Promise<OptionalContentConfig>} [optionalContentConfigPromise] -
|
|
|
|
* A promise that is resolved with an {@link OptionalContentConfig} instance.
|
|
|
|
* The default value is `null`.
|
2022-08-25 13:36:05 -03:00
|
|
|
* @property {PDFRenderingQueue} [renderingQueue] - The rendering queue object.
|
2019-10-12 16:30:32 +02:00
|
|
|
* @property {number} [textLayerMode] - Controls if the text layer used for
|
2022-01-18 18:09:12 +01:00
|
|
|
* selection and searching is created. The constants from {TextLayerMode}
|
|
|
|
* should be used. The default value is `TextLayerMode.ENABLE`.
|
[api-minor] Introduce a new `annotationMode`-option, in `PDFPageProxy.{render, getOperatorList}`
*This is a follow-up to PRs 13867 and 13899.*
This patch is tagged `api-minor` for the following reasons:
- It replaces the `renderInteractiveForms`/`includeAnnotationStorage`-options, in the `PDFPageProxy.render`-method, with the single `annotationMode`-option that controls which annotations are being rendered and how. Note that the old options were mutually exclusive, and setting both to `true` would result in undefined behaviour.
- For improved consistency in the API, the `annotationMode`-option will also work together with the `PDFPageProxy.getOperatorList`-method.
- It's now also possible to disable *all* annotation rendering in both the API and the Viewer, since the other changes meant that this could now be supported with a single added line on the worker-thread[1]; fixes 7282.
---
[1] Please note that in order to simplify the overall implementation, we'll purposely only support disabling of *all* annotations and that the option is being shared between the API and the Viewer. For any more "specialized" use-cases, where e.g. only some annotation-types are being rendered and/or the API and Viewer render different sets of annotations, that'll have to be handled in third-party implementations/forks of the PDF.js code-base.
2021-08-08 14:36:28 +02:00
|
|
|
* @property {number} [annotationMode] - Controls if the annotation layer is
|
|
|
|
* created, and if interactive form elements or `AnnotationStorage`-data are
|
|
|
|
* being rendered. The constants from {@link AnnotationMode} should be used;
|
|
|
|
* see also {@link RenderParameters} and {@link GetOperatorListParameters}.
|
|
|
|
* The default value is `AnnotationMode.ENABLE_FORMS`.
|
2019-10-12 16:30:32 +02:00
|
|
|
* @property {string} [imageResourcesPath] - Path for image resources, mainly
|
|
|
|
* for annotation icons. Include trailing slash.
|
|
|
|
* @property {number} [maxCanvasPixels] - The maximum supported canvas size in
|
2023-07-24 10:33:08 +02:00
|
|
|
* total pixels, i.e. width * height. Use `-1` for no limit, or `0` for
|
2024-03-25 17:31:15 +01:00
|
|
|
* CSS-only zooming. The default value is 4096 * 8192 (32 mega-pixels).
|
2025-03-04 11:30:54 +01:00
|
|
|
* @property {number} [maxCanvasDim] - The maximum supported canvas dimension,
|
|
|
|
* in either width or height. Use `-1` for no limit.
|
|
|
|
* The default value is 32767.
|
2024-12-11 13:58:52 +01:00
|
|
|
* @property {boolean} [enableDetailCanvas] - When enabled, if the rendered
|
2025-03-04 11:30:54 +01:00
|
|
|
* pages would need a canvas that is larger than `maxCanvasPixels` or
|
|
|
|
* `maxCanvasDim`, it will draw a second canvas on top of the CSS-zoomed one,
|
|
|
|
* that only renders the part of the page that is close to the viewport.
|
|
|
|
* The default value is `true`.
|
2022-05-04 15:37:13 +02:00
|
|
|
* @property {Object} [pageColors] - Overwrites background and foreground colors
|
|
|
|
* with user defined ones in order to improve readability in high contrast
|
|
|
|
* mode.
|
2022-08-25 13:36:05 -03:00
|
|
|
* @property {IL10n} [l10n] - Localization service.
|
2023-09-25 10:56:12 +02:00
|
|
|
* @property {Object} [layerProperties] - The object that is used to lookup
|
[api-minor] Remove the `annotationEditorLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationEditorLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 14:21:51 +01:00
|
|
|
* the necessary layer-properties.
|
2024-06-12 12:51:51 +02:00
|
|
|
* @property {boolean} [enableHWA] - Enables hardware acceleration for
|
|
|
|
* rendering. The default value is `false`.
|
2024-11-12 11:26:32 +05:30
|
|
|
* @property {boolean} [enableAutoLinking] - Enable creation of hyperlinks from
|
2025-03-21 11:35:50 +01:00
|
|
|
* text that look like URLs. The default value is `true`.
|
2014-09-27 13:03:28 -05:00
|
|
|
*/
|
|
|
|
|
2023-09-25 10:56:12 +02:00
|
|
|
const DEFAULT_LAYER_PROPERTIES =
|
|
|
|
typeof PDFJSDev === "undefined" || !PDFJSDev.test("COMPONENTS")
|
|
|
|
? null
|
|
|
|
: {
|
|
|
|
annotationEditorUIManager: null,
|
|
|
|
annotationStorage: null,
|
|
|
|
downloadManager: null,
|
|
|
|
enableScripting: false,
|
|
|
|
fieldObjectsPromise: null,
|
|
|
|
findController: null,
|
|
|
|
hasJSActionsPromise: null,
|
|
|
|
get linkService() {
|
|
|
|
return new SimpleLinkService();
|
|
|
|
},
|
|
|
|
};
|
[api-minor] Remove the `annotationEditorLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationEditorLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 14:21:51 +01:00
|
|
|
|
2024-03-11 17:03:44 +01:00
|
|
|
const LAYERS_ORDER = new Map([
|
|
|
|
["canvasWrapper", 0],
|
|
|
|
["textLayer", 1],
|
|
|
|
["annotationLayer", 2],
|
|
|
|
["annotationEditorLayer", 3],
|
2024-03-21 12:51:08 +01:00
|
|
|
["xfaLayer", 3],
|
2024-03-11 17:03:44 +01:00
|
|
|
]);
|
|
|
|
|
2014-09-27 13:03:28 -05:00
|
|
|
/**
|
2014-09-20 12:21:49 -05:00
|
|
|
* @implements {IRenderableView}
|
|
|
|
*/
|
2024-12-11 13:54:50 +01:00
|
|
|
class PDFPageView extends BasePDFPageView {
|
2021-12-11 16:53:59 +01:00
|
|
|
#annotationMode = AnnotationMode.ENABLE_FORMS;
|
|
|
|
|
2024-12-04 19:34:57 +01:00
|
|
|
#canvasWrapper = null;
|
|
|
|
|
2025-03-21 11:35:50 +01:00
|
|
|
#enableAutoLinking = true;
|
2024-11-12 11:26:32 +05:30
|
|
|
|
2023-07-24 10:33:08 +02:00
|
|
|
#hasRestrictedScaling = false;
|
|
|
|
|
2024-05-21 14:41:07 +02:00
|
|
|
#isEditing = false;
|
|
|
|
|
[api-minor] Remove the `annotationEditorLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationEditorLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 14:21:51 +01:00
|
|
|
#layerProperties = null;
|
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
#needsRestrictedScaling = false;
|
|
|
|
|
2024-12-04 19:34:57 +01:00
|
|
|
#originalViewport = null;
|
|
|
|
|
2022-12-12 14:24:27 +01:00
|
|
|
#previousRotation = null;
|
|
|
|
|
2024-09-05 17:05:22 +02:00
|
|
|
#scaleRoundX = 1;
|
|
|
|
|
|
|
|
#scaleRoundY = 1;
|
|
|
|
|
2023-04-22 13:07:07 +02:00
|
|
|
#textLayerMode = TextLayerMode.ENABLE;
|
|
|
|
|
2025-02-11 11:55:24 +01:00
|
|
|
#userUnit = 1;
|
|
|
|
|
2022-06-27 11:41:37 +02:00
|
|
|
#useThumbnailCanvas = {
|
2023-06-01 18:46:50 +02:00
|
|
|
directDrawing: true,
|
2022-06-27 11:41:37 +02:00
|
|
|
initialOptionalContent: true,
|
|
|
|
regularAnnotations: true,
|
|
|
|
};
|
2022-07-24 13:14:58 +02:00
|
|
|
|
2024-03-11 17:03:44 +01:00
|
|
|
#layers = [null, null, null, null];
|
|
|
|
|
2014-09-27 13:03:28 -05:00
|
|
|
/**
|
|
|
|
* @param {PDFPageViewOptions} options
|
|
|
|
*/
|
2017-05-28 22:44:00 +02:00
|
|
|
constructor(options) {
|
2024-12-11 13:54:50 +01:00
|
|
|
super(options);
|
|
|
|
|
2019-12-27 00:22:32 +01:00
|
|
|
const container = options.container;
|
|
|
|
const defaultViewport = options.defaultViewport;
|
2017-05-28 22:44:00 +02:00
|
|
|
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
this.renderingId = "page" + this.id;
|
[api-minor] Remove the `annotationEditorLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationEditorLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 14:21:51 +01:00
|
|
|
this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2017-08-03 17:24:19 -05:00
|
|
|
this.pdfPage = null;
|
2017-05-28 22:44:00 +02:00
|
|
|
this.pageLabel = null;
|
2014-09-27 13:03:28 -05:00
|
|
|
this.rotation = 0;
|
2017-05-28 22:44:00 +02:00
|
|
|
this.scale = options.scale || DEFAULT_SCALE;
|
2014-09-27 13:03:28 -05:00
|
|
|
this.viewport = defaultViewport;
|
|
|
|
this.pdfPageRotate = defaultViewport.rotation;
|
[api-minor] Add support for toggling of Optional Content in the viewer (issue 12096)
*Besides, obviously, adding viewer support:* This patch attempts to improve the general API for Optional Content Groups slightly, by adding a couple of new methods for interacting with the (more complex) data structures of `OptionalContentConfig`-instances. (Thus allowing us to mark some of the data as "private", given that it probably shouldn't be manipulated directly.)
By utilizing not just the "raw" Optional Content Groups, but the data from the `/Order` array when available, we can thus display the Layers in a proper tree-structure with collapsible headings for PDF documents that utilizes that feature.
Note that it's possible to reset all Optional Content Groups to their default visibility state, simply by double-clicking on the Layers-button in the sidebar.
(Currently that's indicated in the Layers-button tooltip, which is obviously easy to overlook, however it's probably the best we can do for now without adding more buttons, or even a dropdown-toolbar, to the sidebar.)
Also, the current Layers-button icons are a little rough around the edges, quite literally, but given that the viewer will soon have its UI modernized anyway they hopefully suffice in the meantime.
To give users *full* control of the visibility of the various Optional Content Groups, even those which according to the `/Order` array should not (by default) be toggleable in the UI, this patch will place those under a *custom* heading which:
- Is collapsed by default, and placed at the bottom of the Layers-tree, to be a bit less obtrusive.
- Uses a slightly different formatting, compared to the "regular" headings.
- Is localizable.
Finally, note that the thumbnails are *purposely* always rendered with all Optional Content Groups at their default visibility state, since that seems the most useful and it's also consistent with other viewers.
To ensure that this works as intended, we'll thus disable the `PDFThumbnailView.setImage` functionality when the Optional Content Groups have been changed in the viewer. (This obviously means that we'll re-render thumbnails instead of using the rendered pages. However, this situation ought to be rare enough for this to not really be a problem.)
2020-08-06 21:01:03 +02:00
|
|
|
this._optionalContentConfigPromise =
|
|
|
|
options.optionalContentConfigPromise || null;
|
2023-04-22 13:07:07 +02:00
|
|
|
this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
|
2021-12-11 16:53:59 +01:00
|
|
|
this.#annotationMode =
|
[api-minor] Introduce a new `annotationMode`-option, in `PDFPageProxy.{render, getOperatorList}`
*This is a follow-up to PRs 13867 and 13899.*
This patch is tagged `api-minor` for the following reasons:
- It replaces the `renderInteractiveForms`/`includeAnnotationStorage`-options, in the `PDFPageProxy.render`-method, with the single `annotationMode`-option that controls which annotations are being rendered and how. Note that the old options were mutually exclusive, and setting both to `true` would result in undefined behaviour.
- For improved consistency in the API, the `annotationMode`-option will also work together with the `PDFPageProxy.getOperatorList`-method.
- It's now also possible to disable *all* annotation rendering in both the API and the Viewer, since the other changes meant that this could now be supported with a single added line on the worker-thread[1]; fixes 7282.
---
[1] Please note that in order to simplify the overall implementation, we'll purposely only support disabling of *all* annotations and that the option is being shared between the API and the Viewer. For any more "specialized" use-cases, where e.g. only some annotation-types are being rendered and/or the API and Viewer render different sets of annotations, that'll have to be handled in third-party implementations/forks of the PDF.js code-base.
2021-08-08 14:36:28 +02:00
|
|
|
options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
this.imageResourcesPath = options.imageResourcesPath || "";
|
2024-12-11 13:58:52 +01:00
|
|
|
this.enableDetailCanvas = options.enableDetailCanvas ?? true;
|
2024-02-20 10:50:28 +01:00
|
|
|
this.maxCanvasPixels =
|
2024-03-30 12:16:53 +01:00
|
|
|
options.maxCanvasPixels ?? AppOptions.get("maxCanvasPixels");
|
2025-03-04 11:30:54 +01:00
|
|
|
this.maxCanvasDim = options.maxCanvasDim || AppOptions.get("maxCanvasDim");
|
2025-03-21 11:35:50 +01:00
|
|
|
this.#enableAutoLinking = options.enableAutoLinking !== false;
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2024-01-30 18:32:35 +01:00
|
|
|
this.l10n = options.l10n;
|
|
|
|
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
|
|
|
this.l10n ||= new GenericL10n();
|
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2023-03-18 12:09:25 +01:00
|
|
|
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
2022-07-24 15:43:31 +02:00
|
|
|
this._isStandalone = !this.renderingQueue?.hasViewer();
|
2023-06-26 23:12:37 +02:00
|
|
|
this._container = container;
|
2022-07-24 15:43:31 +02:00
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2021-11-06 18:36:49 +01:00
|
|
|
this._annotationCanvasMap = null;
|
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
this.annotationLayer = null;
|
2022-06-01 10:38:08 +02:00
|
|
|
this.annotationEditorLayer = null;
|
2014-09-27 13:03:28 -05:00
|
|
|
this.textLayer = null;
|
2021-03-19 10:11:40 +01:00
|
|
|
this.xfaLayer = null;
|
2021-03-31 15:07:02 -07:00
|
|
|
this.structTreeLayer = null;
|
2023-11-22 19:02:42 +01:00
|
|
|
this.drawLayer = null;
|
2013-09-20 09:25:41 +02:00
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
this.detailView = null;
|
|
|
|
|
2019-12-27 00:22:32 +01:00
|
|
|
const div = document.createElement("div");
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
div.className = "page";
|
|
|
|
div.setAttribute("data-page-number", this.id);
|
2021-03-18 16:10:54 -07:00
|
|
|
div.setAttribute("role", "region");
|
2023-10-19 16:30:57 +02:00
|
|
|
div.setAttribute("data-l10n-id", "pdfjs-page-landmark");
|
|
|
|
div.setAttribute("data-l10n-args", JSON.stringify({ page: this.id }));
|
2014-09-27 13:03:28 -05:00
|
|
|
this.div = div;
|
|
|
|
|
2022-11-21 18:48:37 +01:00
|
|
|
this.#setDimensions();
|
2022-06-12 12:20:25 +02:00
|
|
|
container?.append(div);
|
2022-07-24 13:14:58 +02:00
|
|
|
|
2022-07-24 15:43:31 +02:00
|
|
|
if (
|
2023-03-18 12:09:25 +01:00
|
|
|
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
2022-07-24 15:43:31 +02:00
|
|
|
this._isStandalone
|
|
|
|
) {
|
2022-12-09 14:30:12 +01:00
|
|
|
// Ensure that the various layers always get the correct initial size,
|
|
|
|
// see issue 15795.
|
2023-01-16 19:38:33 +01:00
|
|
|
container?.style.setProperty(
|
2022-12-09 14:30:12 +01:00
|
|
|
"--scale-factor",
|
|
|
|
this.scale * PixelsPerInch.PDF_TO_CSS_UNITS
|
|
|
|
);
|
|
|
|
|
2024-09-02 10:05:09 +02:00
|
|
|
if (this.pageColors?.background) {
|
|
|
|
container?.style.setProperty(
|
|
|
|
"--page-bg-color",
|
|
|
|
this.pageColors.background
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-07-24 13:14:58 +02:00
|
|
|
const { optionalContentConfigPromise } = options;
|
|
|
|
if (optionalContentConfigPromise) {
|
|
|
|
// Ensure that the thumbnails always display the *initial* document
|
2022-06-27 11:41:37 +02:00
|
|
|
// state, for documents with optional content.
|
2022-07-24 13:14:58 +02:00
|
|
|
optionalContentConfigPromise.then(optionalContentConfig => {
|
|
|
|
if (
|
|
|
|
optionalContentConfigPromise !== this._optionalContentConfigPromise
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
2022-06-27 11:41:37 +02:00
|
|
|
this.#useThumbnailCanvas.initialOptionalContent =
|
|
|
|
optionalContentConfig.hasInitialVisibility;
|
2022-07-24 13:14:58 +02:00
|
|
|
});
|
|
|
|
}
|
[api-minor] Re-factor `NullL10n` and remove the hard-coded l10n strings (PR 17115 follow-up)
*Please note:* These changes only affect the GENERIC build, since `NullL10n` is only a stub elsewhere (see PR 17135).
After the changes in PR 17115, which modernized and improved l10n-handling, the `NullL10n`-implementation is no longer a good fallback for the "proper" `L10n`-classes.
To improve this situation, especially for the *standalone* viewer-components, this patch makes the following changes:
- Let the `NullL10n`-implementation extend an actual `L10n`-class, which is constant and lazily initialized, to ensure that it works *exactly* like the "proper" ones.
- Automatically bundle the "en-US" l10n-strings in the build, via the pre-processor, such that we don't need to remember to manually update them.
- Ensure that the *standalone* viewer-components register their DOM-elements for translation, similar to the default viewer, since this will allow future code improvements by using "data-l10n-id"/"data-l10n-args" in most (if not all) parts of the viewer.
- Remove the `NullL10n` from the `AnnotationLayer`, to avoid affecting bundle size too much.
For third-party users that access the `AnnotationLayer`, as exposed in the main PDF.js library, they'll now need to *manually* register it for translation. (However, the *standalone* viewer-components still works given the point above.)
2023-10-19 22:12:46 +02:00
|
|
|
|
|
|
|
// Ensure that Fluent is connected in e.g. the COMPONENTS build.
|
2024-01-30 18:32:35 +01:00
|
|
|
if (!options.l10n) {
|
[api-minor] Re-factor `NullL10n` and remove the hard-coded l10n strings (PR 17115 follow-up)
*Please note:* These changes only affect the GENERIC build, since `NullL10n` is only a stub elsewhere (see PR 17135).
After the changes in PR 17115, which modernized and improved l10n-handling, the `NullL10n`-implementation is no longer a good fallback for the "proper" `L10n`-classes.
To improve this situation, especially for the *standalone* viewer-components, this patch makes the following changes:
- Let the `NullL10n`-implementation extend an actual `L10n`-class, which is constant and lazily initialized, to ensure that it works *exactly* like the "proper" ones.
- Automatically bundle the "en-US" l10n-strings in the build, via the pre-processor, such that we don't need to remember to manually update them.
- Ensure that the *standalone* viewer-components register their DOM-elements for translation, similar to the default viewer, since this will allow future code improvements by using "data-l10n-id"/"data-l10n-args" in most (if not all) parts of the viewer.
- Remove the `NullL10n` from the `AnnotationLayer`, to avoid affecting bundle size too much.
For third-party users that access the `AnnotationLayer`, as exposed in the main PDF.js library, they'll now need to *manually* register it for translation. (However, the *standalone* viewer-components still works given the point above.)
2023-10-19 22:12:46 +02:00
|
|
|
this.l10n.translate(this.div);
|
|
|
|
}
|
2022-07-24 13:14:58 +02:00
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
}
|
|
|
|
|
2024-03-11 17:03:44 +01:00
|
|
|
#addLayer(div, name) {
|
|
|
|
const pos = LAYERS_ORDER.get(name);
|
2024-03-21 12:51:08 +01:00
|
|
|
const oldDiv = this.#layers[pos];
|
2024-03-11 17:03:44 +01:00
|
|
|
this.#layers[pos] = div;
|
2024-03-21 12:51:08 +01:00
|
|
|
if (oldDiv) {
|
|
|
|
oldDiv.replaceWith(div);
|
|
|
|
return;
|
|
|
|
}
|
2024-03-11 17:03:44 +01:00
|
|
|
for (let i = pos - 1; i >= 0; i--) {
|
|
|
|
const layer = this.#layers[i];
|
|
|
|
if (layer) {
|
|
|
|
layer.after(div);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.div.prepend(div);
|
|
|
|
}
|
|
|
|
|
2022-11-21 18:48:37 +01:00
|
|
|
#setDimensions() {
|
2025-02-11 11:55:24 +01:00
|
|
|
const { div, viewport } = this;
|
|
|
|
|
|
|
|
if (viewport.userUnit !== this.#userUnit) {
|
|
|
|
if (viewport.userUnit !== 1) {
|
|
|
|
div.style.setProperty("--user-unit", viewport.userUnit);
|
|
|
|
} else {
|
|
|
|
div.style.removeProperty("--user-unit");
|
|
|
|
}
|
|
|
|
this.#userUnit = viewport.userUnit;
|
|
|
|
}
|
2022-12-27 12:14:42 +01:00
|
|
|
if (this.pdfPage) {
|
|
|
|
if (this.#previousRotation === viewport.rotation) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.#previousRotation = viewport.rotation;
|
2022-12-12 14:24:27 +01:00
|
|
|
}
|
|
|
|
|
2022-11-21 18:48:37 +01:00
|
|
|
setLayerDimensions(
|
2025-02-11 11:55:24 +01:00
|
|
|
div,
|
2022-11-21 18:48:37 +01:00
|
|
|
viewport,
|
|
|
|
/* mustFlip = */ true,
|
|
|
|
/* mustRotate = */ false
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
setPdfPage(pdfPage) {
|
2023-06-26 23:12:37 +02:00
|
|
|
if (
|
|
|
|
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
|
|
|
this._isStandalone &&
|
|
|
|
(this.pageColors?.foreground === "CanvasText" ||
|
|
|
|
this.pageColors?.background === "Canvas")
|
|
|
|
) {
|
|
|
|
this._container?.style.setProperty(
|
2023-11-13 11:18:35 +01:00
|
|
|
"--hcm-highlight-filter",
|
2023-06-26 23:12:37 +02:00
|
|
|
pdfPage.filterFactory.addHighlightHCMFilter(
|
2024-01-18 18:36:03 +01:00
|
|
|
"highlight",
|
|
|
|
"CanvasText",
|
|
|
|
"Canvas",
|
|
|
|
"HighlightText",
|
|
|
|
"Highlight"
|
|
|
|
)
|
|
|
|
);
|
|
|
|
this._container?.style.setProperty(
|
|
|
|
"--hcm-highlight-selected-filter",
|
|
|
|
pdfPage.filterFactory.addHighlightHCMFilter(
|
|
|
|
"highlight_selected",
|
2023-06-26 23:12:37 +02:00
|
|
|
"CanvasText",
|
|
|
|
"Canvas",
|
|
|
|
"HighlightText",
|
|
|
|
"Highlight"
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
this.pdfPage = pdfPage;
|
|
|
|
this.pdfPageRotate = pdfPage.rotate;
|
2013-09-20 09:25:41 +02:00
|
|
|
|
2019-12-27 00:22:32 +01:00
|
|
|
const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
this.viewport = pdfPage.getViewport({
|
2021-09-20 10:10:57 +02:00
|
|
|
scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
rotation: totalRotation,
|
|
|
|
});
|
2022-12-12 14:24:27 +01:00
|
|
|
this.#setDimensions();
|
2017-05-28 22:44:00 +02:00
|
|
|
this.reset();
|
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
destroy() {
|
|
|
|
this.reset();
|
2022-09-05 15:36:04 +02:00
|
|
|
this.pdfPage?.cleanup();
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2013-09-20 09:25:41 +02:00
|
|
|
|
2024-05-21 14:41:07 +02:00
|
|
|
hasEditableAnnotations() {
|
|
|
|
return !!this.annotationLayer?.hasEditableAnnotations();
|
|
|
|
}
|
|
|
|
|
2022-12-14 13:19:41 +01:00
|
|
|
get _textHighlighter() {
|
|
|
|
return shadow(
|
|
|
|
this,
|
|
|
|
"_textHighlighter",
|
[api-minor] Remove the `textHighlighterFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `textHighlighterFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:55:23 +01:00
|
|
|
new TextHighlighter({
|
2022-12-14 13:19:41 +01:00
|
|
|
pageIndex: this.id - 1,
|
|
|
|
eventBus: this.eventBus,
|
2023-09-25 10:56:12 +02:00
|
|
|
findController: this.#layerProperties.findController,
|
2022-12-14 13:19:41 +01:00
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-05-26 12:32:34 +02:00
|
|
|
#dispatchLayerRendered(name, error) {
|
|
|
|
this.eventBus.dispatch(name, {
|
|
|
|
source: this,
|
|
|
|
pageNumber: this.id,
|
|
|
|
error,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-12-14 13:12:49 +01:00
|
|
|
async #renderAnnotationLayer() {
|
2020-08-17 13:19:03 -07:00
|
|
|
let error = null;
|
|
|
|
try {
|
2025-01-21 23:26:20 +01:00
|
|
|
await this.annotationLayer.render({
|
|
|
|
viewport: this.viewport,
|
|
|
|
intent: "display",
|
|
|
|
structTreeLayer: this.structTreeLayer,
|
|
|
|
});
|
2020-08-17 13:19:03 -07:00
|
|
|
} catch (ex) {
|
2024-12-02 13:28:20 +01:00
|
|
|
console.error("#renderAnnotationLayer:", ex);
|
2020-08-17 13:19:03 -07:00
|
|
|
error = ex;
|
|
|
|
} finally {
|
2024-05-26 12:32:34 +02:00
|
|
|
this.#dispatchLayerRendered("annotationlayerrendered", error);
|
2020-08-17 13:19:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-14 13:12:49 +01:00
|
|
|
async #renderAnnotationEditorLayer() {
|
2022-06-01 10:38:08 +02:00
|
|
|
let error = null;
|
|
|
|
try {
|
2025-01-21 23:26:20 +01:00
|
|
|
await this.annotationEditorLayer.render({
|
|
|
|
viewport: this.viewport,
|
|
|
|
intent: "display",
|
|
|
|
});
|
2022-06-01 10:38:08 +02:00
|
|
|
} catch (ex) {
|
2024-12-02 13:28:20 +01:00
|
|
|
console.error("#renderAnnotationEditorLayer:", ex);
|
2022-06-01 10:38:08 +02:00
|
|
|
error = ex;
|
|
|
|
} finally {
|
2024-05-26 12:32:34 +02:00
|
|
|
this.#dispatchLayerRendered("annotationeditorlayerrendered", error);
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-22 19:02:42 +01:00
|
|
|
async #renderDrawLayer() {
|
|
|
|
try {
|
2025-01-21 23:26:20 +01:00
|
|
|
await this.drawLayer.render({
|
|
|
|
intent: "display",
|
|
|
|
});
|
2023-11-22 19:02:42 +01:00
|
|
|
} catch (ex) {
|
2024-12-02 13:28:20 +01:00
|
|
|
console.error("#renderDrawLayer:", ex);
|
2023-11-22 19:02:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-14 13:12:49 +01:00
|
|
|
async #renderXfaLayer() {
|
2021-03-19 10:11:40 +01:00
|
|
|
let error = null;
|
|
|
|
try {
|
2025-01-21 23:26:20 +01:00
|
|
|
const result = await this.xfaLayer.render({
|
|
|
|
viewport: this.viewport,
|
|
|
|
intent: "display",
|
|
|
|
});
|
2022-12-14 13:19:41 +01:00
|
|
|
if (result?.textDivs && this._textHighlighter) {
|
2023-10-25 20:03:07 +02:00
|
|
|
// Given that the following method fetches the text asynchronously we
|
|
|
|
// can invoke it *before* appending the xfaLayer to the DOM (below),
|
|
|
|
// since a pending search-highlight/scroll operation thus won't run
|
|
|
|
// until after the xfaLayer is available in the viewer.
|
2022-12-14 13:12:49 +01:00
|
|
|
this.#buildXfaTextContentItems(result.textDivs);
|
2021-08-18 17:02:29 -07:00
|
|
|
}
|
2021-03-19 10:11:40 +01:00
|
|
|
} catch (ex) {
|
2024-12-02 13:28:20 +01:00
|
|
|
console.error("#renderXfaLayer:", ex);
|
2021-03-19 10:11:40 +01:00
|
|
|
error = ex;
|
|
|
|
} finally {
|
2023-10-25 20:03:07 +02:00
|
|
|
if (this.xfaLayer?.div) {
|
|
|
|
// Pause translation when inserting the xfaLayer in the DOM.
|
|
|
|
this.l10n.pause();
|
2024-03-11 17:03:44 +01:00
|
|
|
this.#addLayer(this.xfaLayer.div, "xfaLayer");
|
2023-10-25 20:03:07 +02:00
|
|
|
this.l10n.resume();
|
|
|
|
}
|
2024-05-26 12:32:34 +02:00
|
|
|
this.#dispatchLayerRendered("xfalayerrendered", error);
|
2021-03-19 10:11:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-21 17:15:39 +01:00
|
|
|
async #renderTextLayer() {
|
2024-05-26 12:11:50 +02:00
|
|
|
if (!this.textLayer) {
|
2022-11-21 17:15:39 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let error = null;
|
|
|
|
try {
|
2025-01-21 23:26:20 +01:00
|
|
|
await this.textLayer.render({
|
|
|
|
viewport: this.viewport,
|
|
|
|
});
|
2022-11-21 17:15:39 +01:00
|
|
|
} catch (ex) {
|
|
|
|
if (ex instanceof AbortException) {
|
|
|
|
return;
|
|
|
|
}
|
2024-12-02 13:28:20 +01:00
|
|
|
console.error("#renderTextLayer:", ex);
|
2022-11-21 17:15:39 +01:00
|
|
|
error = ex;
|
|
|
|
}
|
2024-05-26 12:32:34 +02:00
|
|
|
this.#dispatchLayerRendered("textlayerrendered", error);
|
2022-12-04 00:27:44 +01:00
|
|
|
|
[api-minor] Remove the `structTreeLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `structTreeLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:43:09 +01:00
|
|
|
this.#renderStructTreeLayer();
|
2022-12-04 00:27:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The structure tree is currently only supported when the text layer is
|
|
|
|
* enabled and a canvas is used for rendering.
|
|
|
|
*
|
|
|
|
* The structure tree must be generated after the text layer for the
|
|
|
|
* aria-owns to work.
|
|
|
|
*/
|
|
|
|
async #renderStructTreeLayer() {
|
|
|
|
if (!this.textLayer) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-03 16:49:22 +02:00
|
|
|
const treeDom = await this.structTreeLayer?.render();
|
2024-09-04 16:45:09 +02:00
|
|
|
if (treeDom) {
|
2023-10-27 14:55:12 +02:00
|
|
|
this.l10n.pause();
|
2024-09-04 16:45:09 +02:00
|
|
|
this.structTreeLayer?.addElementsToTextLayer();
|
|
|
|
if (this.canvas && treeDom.parentNode !== this.canvas) {
|
|
|
|
// Pause translation when inserting the structTree in the DOM.
|
|
|
|
this.canvas.append(treeDom);
|
|
|
|
}
|
2023-10-27 14:55:12 +02:00
|
|
|
this.l10n.resume();
|
2022-12-04 00:27:44 +01:00
|
|
|
}
|
2023-02-07 14:38:32 +01:00
|
|
|
this.structTreeLayer?.show();
|
2022-11-21 17:15:39 +01:00
|
|
|
}
|
|
|
|
|
2022-12-14 13:12:49 +01:00
|
|
|
async #buildXfaTextContentItems(textDivs) {
|
2021-08-18 17:02:29 -07:00
|
|
|
const text = await this.pdfPage.getTextContent();
|
|
|
|
const items = [];
|
|
|
|
for (const item of text.items) {
|
|
|
|
items.push(item.str);
|
|
|
|
}
|
2022-12-14 13:19:41 +01:00
|
|
|
this._textHighlighter.setTextMapping(textDivs, items);
|
|
|
|
this._textHighlighter.enable();
|
2021-08-18 17:02:29 -07:00
|
|
|
}
|
|
|
|
|
2025-02-12 12:06:34 +01:00
|
|
|
async #injectLinkAnnotations(textLayerPromise) {
|
|
|
|
let error = null;
|
|
|
|
try {
|
|
|
|
await textLayerPromise;
|
|
|
|
|
|
|
|
if (!this.annotationLayer) {
|
|
|
|
return; // Rendering was cancelled while the textLayerPromise resolved.
|
|
|
|
}
|
|
|
|
await this.annotationLayer.injectLinkAnnotations({
|
|
|
|
inferredLinks: Autolinker.processLinks(this),
|
|
|
|
viewport: this.viewport,
|
|
|
|
structTreeLayer: this.structTreeLayer,
|
|
|
|
});
|
|
|
|
} catch (ex) {
|
|
|
|
console.error("#injectLinkAnnotations:", ex);
|
|
|
|
error = ex;
|
|
|
|
}
|
|
|
|
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
|
|
|
|
this.#dispatchLayerRendered("linkannotationsadded", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
_resetCanvas() {
|
|
|
|
super._resetCanvas();
|
2024-12-04 19:34:57 +01:00
|
|
|
this.#originalViewport = null;
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2013-10-02 09:05:46 -07:00
|
|
|
|
2021-07-23 11:37:38 +02:00
|
|
|
reset({
|
|
|
|
keepAnnotationLayer = false,
|
2022-06-01 10:38:08 +02:00
|
|
|
keepAnnotationEditorLayer = false,
|
2021-07-23 11:37:38 +02:00
|
|
|
keepXfaLayer = false,
|
2022-11-21 17:15:39 +01:00
|
|
|
keepTextLayer = false,
|
2024-12-04 19:34:57 +01:00
|
|
|
keepCanvasWrapper = false,
|
2024-12-11 13:58:52 +01:00
|
|
|
preserveDetailViewState = false,
|
2021-07-23 11:37:38 +02:00
|
|
|
} = {}) {
|
2022-06-01 10:38:08 +02:00
|
|
|
this.cancelRendering({
|
|
|
|
keepAnnotationLayer,
|
|
|
|
keepAnnotationEditorLayer,
|
|
|
|
keepXfaLayer,
|
2022-11-21 17:15:39 +01:00
|
|
|
keepTextLayer,
|
2022-06-01 10:38:08 +02:00
|
|
|
});
|
2019-02-14 18:47:32 +01:00
|
|
|
this.renderingState = RenderingStates.INITIAL;
|
2013-10-02 09:05:46 -07:00
|
|
|
|
2019-12-27 00:22:32 +01:00
|
|
|
const div = this.div;
|
2013-10-02 09:05:46 -07:00
|
|
|
|
2021-07-23 11:37:38 +02:00
|
|
|
const childNodes = div.childNodes,
|
|
|
|
annotationLayerNode =
|
|
|
|
(keepAnnotationLayer && this.annotationLayer?.div) || null,
|
2022-06-01 10:38:08 +02:00
|
|
|
annotationEditorLayerNode =
|
|
|
|
(keepAnnotationEditorLayer && this.annotationEditorLayer?.div) || null,
|
2022-11-21 17:15:39 +01:00
|
|
|
xfaLayerNode = (keepXfaLayer && this.xfaLayer?.div) || null,
|
2024-12-04 19:34:57 +01:00
|
|
|
textLayerNode = (keepTextLayer && this.textLayer?.div) || null,
|
|
|
|
canvasWrapperNode = (keepCanvasWrapper && this.#canvasWrapper) || null;
|
2017-05-28 22:44:00 +02:00
|
|
|
for (let i = childNodes.length - 1; i >= 0; i--) {
|
2019-12-27 00:22:32 +01:00
|
|
|
const node = childNodes[i];
|
2021-07-23 11:37:38 +02:00
|
|
|
switch (node) {
|
|
|
|
case annotationLayerNode:
|
2022-06-01 10:38:08 +02:00
|
|
|
case annotationEditorLayerNode:
|
2021-07-23 11:37:38 +02:00
|
|
|
case xfaLayerNode:
|
2022-11-21 17:15:39 +01:00
|
|
|
case textLayerNode:
|
2024-12-04 19:34:57 +01:00
|
|
|
case canvasWrapperNode:
|
2021-07-23 11:37:38 +02:00
|
|
|
continue;
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2021-11-16 12:36:22 +01:00
|
|
|
node.remove();
|
2024-03-11 17:03:44 +01:00
|
|
|
const layerIndex = this.#layers.indexOf(node);
|
|
|
|
if (layerIndex >= 0) {
|
|
|
|
this.#layers[layerIndex] = null;
|
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
div.removeAttribute("data-loaded");
|
2017-05-28 22:44:00 +02:00
|
|
|
|
2021-07-23 11:37:38 +02:00
|
|
|
if (annotationLayerNode) {
|
2017-05-28 22:44:00 +02:00
|
|
|
// Hide the annotation layer until all elements are resized
|
|
|
|
// so they are not displayed on the already resized page.
|
|
|
|
this.annotationLayer.hide();
|
|
|
|
}
|
2022-06-01 10:38:08 +02:00
|
|
|
if (annotationEditorLayerNode) {
|
|
|
|
this.annotationEditorLayer.hide();
|
|
|
|
}
|
2021-07-23 11:37:38 +02:00
|
|
|
if (xfaLayerNode) {
|
|
|
|
// Hide the XFA layer until all elements are resized
|
|
|
|
// so they are not displayed on the already resized page.
|
|
|
|
this.xfaLayer.hide();
|
|
|
|
}
|
2022-11-21 17:15:39 +01:00
|
|
|
if (textLayerNode) {
|
|
|
|
this.textLayer.hide();
|
|
|
|
}
|
2023-02-07 14:38:32 +01:00
|
|
|
this.structTreeLayer?.hide();
|
2022-11-21 17:15:39 +01:00
|
|
|
|
2024-12-04 19:34:57 +01:00
|
|
|
if (!keepCanvasWrapper && this.#canvasWrapper) {
|
|
|
|
this.#canvasWrapper = null;
|
2024-12-11 13:54:50 +01:00
|
|
|
this._resetCanvas();
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2024-12-11 13:58:52 +01:00
|
|
|
|
|
|
|
if (!preserveDetailViewState) {
|
|
|
|
this.detailView?.reset({ keepCanvas: keepCanvasWrapper });
|
|
|
|
|
|
|
|
// If we are keeping the canvas around we must also keep the `detailView`
|
|
|
|
// object, so that next time we need a detail view we'll update the
|
|
|
|
// existing canvas rather than creating a new one.
|
|
|
|
if (!keepCanvasWrapper) {
|
|
|
|
this.detailView = null;
|
|
|
|
}
|
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2013-10-02 09:05:46 -07:00
|
|
|
|
2024-05-21 14:41:07 +02:00
|
|
|
toggleEditingMode(isEditing) {
|
2025-01-09 18:10:47 +01:00
|
|
|
// The page can be invisible, consequently there's no annotation layer and
|
|
|
|
// we can't know if there are editable annotations.
|
|
|
|
// So to avoid any issue when the page is rendered the #isEditing flag must
|
|
|
|
// be set.
|
|
|
|
this.#isEditing = isEditing;
|
2024-05-21 14:41:07 +02:00
|
|
|
if (!this.hasEditableAnnotations()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.reset({
|
|
|
|
keepAnnotationLayer: true,
|
|
|
|
keepAnnotationEditorLayer: true,
|
|
|
|
keepXfaLayer: true,
|
|
|
|
keepTextLayer: true,
|
2024-12-04 19:34:57 +01:00
|
|
|
keepCanvasWrapper: true,
|
2024-05-21 14:41:07 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
updateVisibleArea(visibleArea) {
|
|
|
|
if (this.enableDetailCanvas) {
|
|
|
|
if (
|
|
|
|
this.#needsRestrictedScaling &&
|
|
|
|
this.maxCanvasPixels > 0 &&
|
|
|
|
visibleArea
|
|
|
|
) {
|
|
|
|
this.detailView ??= new PDFPageDetailView({ pageView: this });
|
|
|
|
this.detailView.update({ visibleArea });
|
|
|
|
} else if (this.detailView) {
|
|
|
|
this.detailView.reset();
|
|
|
|
this.detailView = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-27 17:03:03 +02:00
|
|
|
/**
|
|
|
|
* @typedef {Object} PDFPageViewUpdateParameters
|
|
|
|
* @property {number} [scale] The new scale, if specified.
|
|
|
|
* @property {number} [rotation] The new rotation, if specified.
|
|
|
|
* @property {Promise<OptionalContentConfig>} [optionalContentConfigPromise]
|
|
|
|
* A promise that is resolved with an {@link OptionalContentConfig}
|
|
|
|
* instance. The default value is `null`.
|
|
|
|
* @property {number} [drawingDelay]
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update e.g. the scale and/or rotation of the page.
|
2023-08-31 12:01:33 +02:00
|
|
|
* @param {PDFPageViewUpdateParameters} params
|
2023-04-27 17:03:03 +02:00
|
|
|
*/
|
2022-12-12 14:24:27 +01:00
|
|
|
update({
|
|
|
|
scale = 0,
|
|
|
|
rotation = null,
|
|
|
|
optionalContentConfigPromise = null,
|
|
|
|
drawingDelay = -1,
|
|
|
|
}) {
|
2017-05-28 22:44:00 +02:00
|
|
|
this.scale = scale || this.scale;
|
2021-08-31 17:08:43 +02:00
|
|
|
if (typeof rotation === "number") {
|
|
|
|
this.rotation = rotation; // The rotation may be zero.
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
[api-minor] Add support for toggling of Optional Content in the viewer (issue 12096)
*Besides, obviously, adding viewer support:* This patch attempts to improve the general API for Optional Content Groups slightly, by adding a couple of new methods for interacting with the (more complex) data structures of `OptionalContentConfig`-instances. (Thus allowing us to mark some of the data as "private", given that it probably shouldn't be manipulated directly.)
By utilizing not just the "raw" Optional Content Groups, but the data from the `/Order` array when available, we can thus display the Layers in a proper tree-structure with collapsible headings for PDF documents that utilizes that feature.
Note that it's possible to reset all Optional Content Groups to their default visibility state, simply by double-clicking on the Layers-button in the sidebar.
(Currently that's indicated in the Layers-button tooltip, which is obviously easy to overlook, however it's probably the best we can do for now without adding more buttons, or even a dropdown-toolbar, to the sidebar.)
Also, the current Layers-button icons are a little rough around the edges, quite literally, but given that the viewer will soon have its UI modernized anyway they hopefully suffice in the meantime.
To give users *full* control of the visibility of the various Optional Content Groups, even those which according to the `/Order` array should not (by default) be toggleable in the UI, this patch will place those under a *custom* heading which:
- Is collapsed by default, and placed at the bottom of the Layers-tree, to be a bit less obtrusive.
- Uses a slightly different formatting, compared to the "regular" headings.
- Is localizable.
Finally, note that the thumbnails are *purposely* always rendered with all Optional Content Groups at their default visibility state, since that seems the most useful and it's also consistent with other viewers.
To ensure that this works as intended, we'll thus disable the `PDFThumbnailView.setImage` functionality when the Optional Content Groups have been changed in the viewer. (This obviously means that we'll re-render thumbnails instead of using the rendered pages. However, this situation ought to be rare enough for this to not really be a problem.)
2020-08-06 21:01:03 +02:00
|
|
|
if (optionalContentConfigPromise instanceof Promise) {
|
|
|
|
this._optionalContentConfigPromise = optionalContentConfigPromise;
|
2022-07-24 13:14:58 +02:00
|
|
|
|
2022-06-27 11:41:37 +02:00
|
|
|
// Ensure that the thumbnails always display the *initial* document state,
|
|
|
|
// for documents with optional content.
|
2022-07-24 13:14:58 +02:00
|
|
|
optionalContentConfigPromise.then(optionalContentConfig => {
|
|
|
|
if (
|
|
|
|
optionalContentConfigPromise !== this._optionalContentConfigPromise
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
2022-06-27 11:41:37 +02:00
|
|
|
this.#useThumbnailCanvas.initialOptionalContent =
|
|
|
|
optionalContentConfig.hasInitialVisibility;
|
2022-07-24 13:14:58 +02:00
|
|
|
});
|
[api-minor] Add support for toggling of Optional Content in the viewer (issue 12096)
*Besides, obviously, adding viewer support:* This patch attempts to improve the general API for Optional Content Groups slightly, by adding a couple of new methods for interacting with the (more complex) data structures of `OptionalContentConfig`-instances. (Thus allowing us to mark some of the data as "private", given that it probably shouldn't be manipulated directly.)
By utilizing not just the "raw" Optional Content Groups, but the data from the `/Order` array when available, we can thus display the Layers in a proper tree-structure with collapsible headings for PDF documents that utilizes that feature.
Note that it's possible to reset all Optional Content Groups to their default visibility state, simply by double-clicking on the Layers-button in the sidebar.
(Currently that's indicated in the Layers-button tooltip, which is obviously easy to overlook, however it's probably the best we can do for now without adding more buttons, or even a dropdown-toolbar, to the sidebar.)
Also, the current Layers-button icons are a little rough around the edges, quite literally, but given that the viewer will soon have its UI modernized anyway they hopefully suffice in the meantime.
To give users *full* control of the visibility of the various Optional Content Groups, even those which according to the `/Order` array should not (by default) be toggleable in the UI, this patch will place those under a *custom* heading which:
- Is collapsed by default, and placed at the bottom of the Layers-tree, to be a bit less obtrusive.
- Uses a slightly different formatting, compared to the "regular" headings.
- Is localizable.
Finally, note that the thumbnails are *purposely* always rendered with all Optional Content Groups at their default visibility state, since that seems the most useful and it's also consistent with other viewers.
To ensure that this works as intended, we'll thus disable the `PDFThumbnailView.setImage` functionality when the Optional Content Groups have been changed in the viewer. (This obviously means that we'll re-render thumbnails instead of using the rendered pages. However, this situation ought to be rare enough for this to not really be a problem.)
2020-08-06 21:01:03 +02:00
|
|
|
}
|
2023-06-01 18:46:50 +02:00
|
|
|
this.#useThumbnailCanvas.directDrawing = true;
|
2017-05-28 22:44:00 +02:00
|
|
|
|
2019-12-27 00:22:32 +01:00
|
|
|
const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
|
2017-05-28 22:44:00 +02:00
|
|
|
this.viewport = this.viewport.clone({
|
2022-04-14 12:43:44 +02:00
|
|
|
scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
|
2017-05-28 22:44:00 +02:00
|
|
|
rotation: totalRotation,
|
|
|
|
});
|
2022-12-12 14:24:27 +01:00
|
|
|
this.#setDimensions();
|
2017-05-28 22:44:00 +02:00
|
|
|
|
2022-07-24 15:43:31 +02:00
|
|
|
if (
|
2023-03-18 12:09:25 +01:00
|
|
|
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
2022-07-24 15:43:31 +02:00
|
|
|
this._isStandalone
|
|
|
|
) {
|
2023-06-26 23:12:37 +02:00
|
|
|
this._container?.style.setProperty("--scale-factor", this.viewport.scale);
|
2021-11-06 18:36:49 +01:00
|
|
|
}
|
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
this.#computeScale();
|
|
|
|
|
2023-07-24 10:33:08 +02:00
|
|
|
if (this.canvas) {
|
2024-12-11 13:58:52 +01:00
|
|
|
const onlyCssZoom =
|
|
|
|
this.#hasRestrictedScaling && this.#needsRestrictedScaling;
|
2024-05-13 15:11:38 +02:00
|
|
|
const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
|
2022-12-12 14:24:27 +01:00
|
|
|
|
2023-03-29 10:31:54 +02:00
|
|
|
if (postponeDrawing || onlyCssZoom) {
|
2022-12-12 14:24:27 +01:00
|
|
|
if (
|
|
|
|
postponeDrawing &&
|
2024-05-13 15:11:38 +02:00
|
|
|
!onlyCssZoom &&
|
2022-12-12 14:24:27 +01:00
|
|
|
this.renderingState !== RenderingStates.FINISHED
|
|
|
|
) {
|
|
|
|
this.cancelRendering({
|
|
|
|
keepAnnotationLayer: true,
|
|
|
|
keepAnnotationEditorLayer: true,
|
|
|
|
keepXfaLayer: true,
|
|
|
|
keepTextLayer: true,
|
|
|
|
cancelExtraDelay: drawingDelay,
|
|
|
|
});
|
|
|
|
// It isn't really finished, but once we have finished
|
|
|
|
// to postpone, we'll call this.reset(...) which will set
|
|
|
|
// the rendering state to INITIAL, hence the next call to
|
|
|
|
// PDFViewer.update() will trigger a redraw (if it's mandatory).
|
|
|
|
this.renderingState = RenderingStates.FINISHED;
|
2023-06-01 18:46:50 +02:00
|
|
|
// Ensure that the thumbnails won't become partially (or fully) blank,
|
|
|
|
// if the sidebar is opened before the actual rendering is done.
|
|
|
|
this.#useThumbnailCanvas.directDrawing = false;
|
2022-12-12 14:24:27 +01:00
|
|
|
}
|
|
|
|
|
2021-07-23 11:37:38 +02:00
|
|
|
this.cssTransform({
|
|
|
|
redrawAnnotationLayer: true,
|
2022-06-01 10:38:08 +02:00
|
|
|
redrawAnnotationEditorLayer: true,
|
2021-07-23 11:37:38 +02:00
|
|
|
redrawXfaLayer: true,
|
2022-12-12 14:24:27 +01:00
|
|
|
redrawTextLayer: !postponeDrawing,
|
|
|
|
hideTextLayer: postponeDrawing,
|
2021-07-23 11:37:38 +02:00
|
|
|
});
|
2016-11-18 13:03:49 -06:00
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
// The "pagerendered"-event will be dispatched once the actual
|
|
|
|
// rendering is done, hence don't dispatch it here as well.
|
|
|
|
if (!postponeDrawing) {
|
2024-12-11 13:58:52 +01:00
|
|
|
this.detailView?.update({ underlyingViewUpdated: true });
|
|
|
|
|
|
|
|
this.dispatchPageRendered(
|
|
|
|
/* cssTransform */ true,
|
|
|
|
/* isDetailView */ false
|
|
|
|
);
|
2023-06-01 17:44:14 +02:00
|
|
|
}
|
2016-11-18 13:03:49 -06:00
|
|
|
return;
|
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2024-12-04 19:34:57 +01:00
|
|
|
this.cssTransform({});
|
2021-07-23 11:37:38 +02:00
|
|
|
this.reset({
|
|
|
|
keepAnnotationLayer: true,
|
2022-06-01 10:38:08 +02:00
|
|
|
keepAnnotationEditorLayer: true,
|
2021-07-23 11:37:38 +02:00
|
|
|
keepXfaLayer: true,
|
2022-11-21 17:15:39 +01:00
|
|
|
keepTextLayer: true,
|
2024-12-04 19:34:57 +01:00
|
|
|
keepCanvasWrapper: true,
|
2024-12-11 13:58:52 +01:00
|
|
|
// It will be reset by the .update call below
|
|
|
|
preserveDetailViewState: true,
|
2021-07-23 11:37:38 +02:00
|
|
|
});
|
2024-12-11 13:58:52 +01:00
|
|
|
|
|
|
|
this.detailView?.update({ underlyingViewUpdated: true });
|
|
|
|
}
|
|
|
|
|
|
|
|
#computeScale() {
|
|
|
|
const { width, height } = this.viewport;
|
|
|
|
const outputScale = (this.outputScale = new OutputScale());
|
|
|
|
|
|
|
|
if (
|
|
|
|
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) &&
|
|
|
|
this.maxCanvasPixels === 0
|
|
|
|
) {
|
|
|
|
const invScale = 1 / this.scale;
|
|
|
|
// Use a scale that makes the canvas have the originally intended size
|
|
|
|
// of the page.
|
|
|
|
outputScale.sx *= invScale;
|
|
|
|
outputScale.sy *= invScale;
|
|
|
|
this.#needsRestrictedScaling = true;
|
2025-03-10 14:02:54 +01:00
|
|
|
} else {
|
|
|
|
this.#needsRestrictedScaling = outputScale.limitCanvas(
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
this.maxCanvasPixels,
|
|
|
|
this.maxCanvasDim
|
|
|
|
);
|
2024-12-11 13:58:52 +01:00
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2019-02-14 18:47:32 +01:00
|
|
|
/**
|
|
|
|
* PLEASE NOTE: Most likely you want to use the `this.reset()` method,
|
|
|
|
* rather than calling this one directly.
|
|
|
|
*/
|
2022-06-01 10:38:08 +02:00
|
|
|
cancelRendering({
|
|
|
|
keepAnnotationLayer = false,
|
|
|
|
keepAnnotationEditorLayer = false,
|
|
|
|
keepXfaLayer = false,
|
2022-11-21 17:15:39 +01:00
|
|
|
keepTextLayer = false,
|
2022-12-12 14:24:27 +01:00
|
|
|
cancelExtraDelay = 0,
|
2022-06-01 10:38:08 +02:00
|
|
|
} = {}) {
|
2024-12-11 13:54:50 +01:00
|
|
|
super.cancelRendering({ cancelExtraDelay });
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2022-11-21 17:15:39 +01:00
|
|
|
if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) {
|
2017-05-28 22:44:00 +02:00
|
|
|
this.textLayer.cancel();
|
|
|
|
this.textLayer = null;
|
|
|
|
}
|
2021-07-23 14:14:42 +02:00
|
|
|
if (
|
|
|
|
this.annotationLayer &&
|
|
|
|
(!keepAnnotationLayer || !this.annotationLayer.div)
|
|
|
|
) {
|
Prevent the `annotationLayer` from, in some cases, becoming duplicated on the first page when the document loads
I don't know if this is a regression, but I noticed earlier today that depending on the initial scale *and* sidebar state, the `annotationLayer` of the first rendered page may end up duplicated; please see screen-shot below.
[screen-shot]
I can reproduce this reliable with e.g. https://arxiv.org/pdf/1112.0542v1.pdf#zoom=page-width&pagemode=bookmarks.
When the document loads, rendering of the first page begins immediately. When the sidebar is then opened, that forces re-rendering which thus aborts rendering of the first page.
Note that calling `PDFPageView.draw()` will always, provided an `AnnotationLayerFactory` instance exists, call `AnnotationLayerBuilder.render()`. Hence the events described above will result in *two* such calls, where the actual annotation rendering/updating happens asynchronously.
For reasons that I don't (at all) understand, when multiple `pdfPage.getAnnotations()` promises are handled back-to-back (in `AnnotationLayerBuilder.render()`), the `this.div` property seems to not update in time for the subsequent calls.
This thus, at least in Firefox, result in double rendering of all annotations on the first page.
Obviously it'd be good to find out why it breaks, since it *really* shouldn't, but this patch at least provides a (hopefully) acceptable work-around by ignoring `getAnnotations()` calls for `AnnotationLayerBuilder` instances that we're destroying (in `PDFPageView.reset()`).
2017-10-06 17:26:54 +02:00
|
|
|
this.annotationLayer.cancel();
|
|
|
|
this.annotationLayer = null;
|
2021-11-06 18:36:49 +01:00
|
|
|
this._annotationCanvasMap = null;
|
Prevent the `annotationLayer` from, in some cases, becoming duplicated on the first page when the document loads
I don't know if this is a regression, but I noticed earlier today that depending on the initial scale *and* sidebar state, the `annotationLayer` of the first rendered page may end up duplicated; please see screen-shot below.
[screen-shot]
I can reproduce this reliable with e.g. https://arxiv.org/pdf/1112.0542v1.pdf#zoom=page-width&pagemode=bookmarks.
When the document loads, rendering of the first page begins immediately. When the sidebar is then opened, that forces re-rendering which thus aborts rendering of the first page.
Note that calling `PDFPageView.draw()` will always, provided an `AnnotationLayerFactory` instance exists, call `AnnotationLayerBuilder.render()`. Hence the events described above will result in *two* such calls, where the actual annotation rendering/updating happens asynchronously.
For reasons that I don't (at all) understand, when multiple `pdfPage.getAnnotations()` promises are handled back-to-back (in `AnnotationLayerBuilder.render()`), the `this.div` property seems to not update in time for the subsequent calls.
This thus, at least in Firefox, result in double rendering of all annotations on the first page.
Obviously it'd be good to find out why it breaks, since it *really* shouldn't, but this patch at least provides a (hopefully) acceptable work-around by ignoring `getAnnotations()` calls for `AnnotationLayerBuilder` instances that we're destroying (in `PDFPageView.reset()`).
2017-10-06 17:26:54 +02:00
|
|
|
}
|
2024-09-04 16:45:09 +02:00
|
|
|
if (this.structTreeLayer && !this.textLayer) {
|
2024-09-03 16:49:22 +02:00
|
|
|
this.structTreeLayer = null;
|
|
|
|
}
|
2022-06-01 10:38:08 +02:00
|
|
|
if (
|
|
|
|
this.annotationEditorLayer &&
|
|
|
|
(!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)
|
|
|
|
) {
|
2023-11-22 19:02:42 +01:00
|
|
|
if (this.drawLayer) {
|
|
|
|
this.drawLayer.cancel();
|
|
|
|
this.drawLayer = null;
|
|
|
|
}
|
2022-06-01 10:38:08 +02:00
|
|
|
this.annotationEditorLayer.cancel();
|
|
|
|
this.annotationEditorLayer = null;
|
|
|
|
}
|
2021-07-23 14:14:42 +02:00
|
|
|
if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
|
2021-07-23 11:37:38 +02:00
|
|
|
this.xfaLayer.cancel();
|
|
|
|
this.xfaLayer = null;
|
2022-12-14 13:19:41 +01:00
|
|
|
this._textHighlighter?.disable();
|
2021-07-23 11:37:38 +02:00
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2016-07-29 20:51:37 +02:00
|
|
|
|
2021-07-23 11:37:38 +02:00
|
|
|
cssTransform({
|
|
|
|
redrawAnnotationLayer = false,
|
2022-06-01 10:38:08 +02:00
|
|
|
redrawAnnotationEditorLayer = false,
|
2021-07-23 11:37:38 +02:00
|
|
|
redrawXfaLayer = false,
|
2022-11-21 17:15:39 +01:00
|
|
|
redrawTextLayer = false,
|
2022-12-12 14:24:27 +01:00
|
|
|
hideTextLayer = false,
|
2021-07-23 11:37:38 +02:00
|
|
|
}) {
|
2024-12-04 19:34:57 +01:00
|
|
|
const { canvas } = this;
|
|
|
|
if (!canvas) {
|
|
|
|
return;
|
2022-12-12 14:24:27 +01:00
|
|
|
}
|
|
|
|
|
2024-12-04 19:34:57 +01:00
|
|
|
const originalViewport = this.#originalViewport;
|
2022-12-12 14:24:27 +01:00
|
|
|
if (this.viewport !== originalViewport) {
|
|
|
|
// The canvas may have been originally rotated; rotate relative to that.
|
|
|
|
const relativeRotation =
|
2024-12-04 19:34:57 +01:00
|
|
|
(360 + this.viewport.rotation - originalViewport.rotation) % 360;
|
|
|
|
if (relativeRotation === 90 || relativeRotation === 270) {
|
2022-12-12 14:24:27 +01:00
|
|
|
const { width, height } = this.viewport;
|
|
|
|
// Scale x and y because of the rotation.
|
2024-12-04 19:34:57 +01:00
|
|
|
const scaleX = height / width;
|
|
|
|
const scaleY = width / height;
|
|
|
|
canvas.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX},${scaleY})`;
|
|
|
|
} else {
|
|
|
|
canvas.style.transform =
|
|
|
|
relativeRotation === 0 ? "" : `rotate(${relativeRotation}deg)`;
|
2022-12-12 14:24:27 +01:00
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
|
|
|
|
2021-07-23 11:37:38 +02:00
|
|
|
if (redrawAnnotationLayer && this.annotationLayer) {
|
2022-12-14 13:12:49 +01:00
|
|
|
this.#renderAnnotationLayer();
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2022-06-01 10:38:08 +02:00
|
|
|
if (redrawAnnotationEditorLayer && this.annotationEditorLayer) {
|
2023-11-22 19:02:42 +01:00
|
|
|
if (this.drawLayer) {
|
|
|
|
this.#renderDrawLayer();
|
|
|
|
}
|
2022-12-14 13:12:49 +01:00
|
|
|
this.#renderAnnotationEditorLayer();
|
2022-06-01 10:38:08 +02:00
|
|
|
}
|
2021-07-23 11:37:38 +02:00
|
|
|
if (redrawXfaLayer && this.xfaLayer) {
|
2022-12-14 13:12:49 +01:00
|
|
|
this.#renderXfaLayer();
|
2021-03-19 10:11:40 +01:00
|
|
|
}
|
2022-12-12 14:24:27 +01:00
|
|
|
|
|
|
|
if (this.textLayer) {
|
|
|
|
if (hideTextLayer) {
|
|
|
|
this.textLayer.hide();
|
2023-02-07 14:38:32 +01:00
|
|
|
this.structTreeLayer?.hide();
|
2022-12-12 14:24:27 +01:00
|
|
|
} else if (redrawTextLayer) {
|
|
|
|
this.#renderTextLayer();
|
|
|
|
}
|
2022-11-21 17:15:39 +01:00
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
get width() {
|
|
|
|
return this.viewport.width;
|
|
|
|
}
|
|
|
|
|
|
|
|
get height() {
|
|
|
|
return this.viewport.height;
|
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
getPagePoint(x, y) {
|
|
|
|
return this.viewport.convertToPdfPoint(x, y);
|
|
|
|
}
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
// Wrap the canvas so that if it has a CSS transform for high DPI the
|
|
|
|
// overflow will be hidden in Firefox.
|
|
|
|
_ensureCanvasWrapper() {
|
|
|
|
let canvasWrapper = this.#canvasWrapper;
|
|
|
|
if (!canvasWrapper) {
|
|
|
|
canvasWrapper = this.#canvasWrapper = document.createElement("div");
|
|
|
|
canvasWrapper.classList.add("canvasWrapper");
|
|
|
|
this.#addLayer(canvasWrapper, "canvasWrapper");
|
|
|
|
}
|
|
|
|
return canvasWrapper;
|
|
|
|
}
|
|
|
|
|
|
|
|
_getRenderingContext(canvasContext, transform) {
|
|
|
|
return {
|
|
|
|
canvasContext,
|
|
|
|
transform,
|
|
|
|
viewport: this.viewport,
|
|
|
|
annotationMode: this.#annotationMode,
|
|
|
|
optionalContentConfigPromise: this._optionalContentConfigPromise,
|
|
|
|
annotationCanvasMap: this._annotationCanvasMap,
|
|
|
|
pageColors: this.pageColors,
|
|
|
|
isEditing: this.#isEditing,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-03-28 21:51:57 +02:00
|
|
|
async draw() {
|
2017-05-28 22:44:00 +02:00
|
|
|
if (this.renderingState !== RenderingStates.INITIAL) {
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
console.error("Must be in new state before drawing");
|
2017-05-28 22:44:00 +02:00
|
|
|
this.reset(); // Ensure that we reset all state to prevent issues.
|
|
|
|
}
|
2024-12-11 13:58:52 +01:00
|
|
|
const { div, l10n, pdfPage, viewport } = this;
|
2017-05-28 22:44:00 +02:00
|
|
|
|
2020-02-08 17:43:53 +01:00
|
|
|
if (!pdfPage) {
|
2017-08-03 17:24:19 -05:00
|
|
|
this.renderingState = RenderingStates.FINISHED;
|
2023-03-28 21:51:57 +02:00
|
|
|
throw new Error("pdfPage is not loaded");
|
2017-08-03 17:24:19 -05:00
|
|
|
}
|
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
this.renderingState = RenderingStates.RUNNING;
|
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
const canvasWrapper = this._ensureCanvasWrapper();
|
2014-09-27 13:03:28 -05:00
|
|
|
|
2022-11-21 17:15:39 +01:00
|
|
|
if (
|
|
|
|
!this.textLayer &&
|
2023-04-22 13:07:07 +02:00
|
|
|
this.#textLayerMode !== TextLayerMode.DISABLE &&
|
[api-minor] Remove the `textLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `textLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-07 00:09:14 +01:00
|
|
|
!pdfPage.isPureXfa
|
2022-11-21 17:15:39 +01:00
|
|
|
) {
|
|
|
|
this._accessibilityManager ||= new TextAccessibilityManager();
|
|
|
|
|
[api-minor] Remove the `textLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `textLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-07 00:09:14 +01:00
|
|
|
this.textLayer = new TextLayerBuilder({
|
2024-05-26 12:11:50 +02:00
|
|
|
pdfPage,
|
2022-12-14 13:19:41 +01:00
|
|
|
highlighter: this._textHighlighter,
|
2022-07-28 17:59:03 +02:00
|
|
|
accessibilityManager: this._accessibilityManager,
|
2023-04-22 13:07:07 +02:00
|
|
|
enablePermissions:
|
|
|
|
this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
|
2024-03-11 17:03:44 +01:00
|
|
|
onAppend: textLayerDiv => {
|
|
|
|
// Pause translation when inserting the textLayer in the DOM.
|
|
|
|
this.l10n.pause();
|
|
|
|
this.#addLayer(textLayerDiv, "textLayer");
|
|
|
|
this.l10n.resume();
|
|
|
|
},
|
2022-07-29 14:47:57 +02:00
|
|
|
});
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
|
|
|
|
2021-11-06 18:36:49 +01:00
|
|
|
if (
|
[api-minor] Remove the `annotationLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:34:55 +01:00
|
|
|
!this.annotationLayer &&
|
|
|
|
this.#annotationMode !== AnnotationMode.DISABLE
|
2021-11-06 18:36:49 +01:00
|
|
|
) {
|
[api-minor] Remove the `annotationLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:34:55 +01:00
|
|
|
const {
|
|
|
|
annotationStorage,
|
2024-04-09 15:25:49 +02:00
|
|
|
annotationEditorUIManager,
|
[api-minor] Remove the `annotationLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:34:55 +01:00
|
|
|
downloadManager,
|
|
|
|
enableScripting,
|
|
|
|
fieldObjectsPromise,
|
|
|
|
hasJSActionsPromise,
|
|
|
|
linkService,
|
2023-09-25 10:56:12 +02:00
|
|
|
} = this.#layerProperties;
|
[api-minor] Remove the `annotationLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:34:55 +01:00
|
|
|
|
2021-11-06 18:36:49 +01:00
|
|
|
this._annotationCanvasMap ||= new Map();
|
[api-minor] Remove the `annotationLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:34:55 +01:00
|
|
|
this.annotationLayer = new AnnotationLayerBuilder({
|
|
|
|
pdfPage,
|
|
|
|
annotationStorage,
|
|
|
|
imageResourcesPath: this.imageResourcesPath,
|
|
|
|
renderForms: this.#annotationMode === AnnotationMode.ENABLE_FORMS,
|
|
|
|
linkService,
|
|
|
|
downloadManager,
|
|
|
|
enableScripting,
|
|
|
|
hasJSActionsPromise,
|
|
|
|
fieldObjectsPromise,
|
|
|
|
annotationCanvasMap: this._annotationCanvasMap,
|
|
|
|
accessibilityManager: this._accessibilityManager,
|
2024-04-09 15:25:49 +02:00
|
|
|
annotationEditorUIManager,
|
2024-03-11 17:03:44 +01:00
|
|
|
onAppend: annotationLayerDiv => {
|
|
|
|
this.#addLayer(annotationLayerDiv, "annotationLayer");
|
|
|
|
},
|
[api-minor] Remove the `annotationLayerFactory` in the viewer
Please note that this functionality has never really mattered for the Firefox PDF Viewer, the GENERIC viewer, or even the "simpleviewer"/"singlepageviewer" component-examples. Hence, in practice this means that only the "pageviewer" component-example[1] have ever really utilized this.
Using factories to initialize various layers in the viewer, rather than simply invoking the relevant code directly, seems (at least to me) like a somewhat roundabout way of doing things.
Not only does this lead to more code, both to write and maintain, but since many of the layers have common parameters (e.g. an `AnnotationStorage`-instance) there's also some duplication.
Hence this patch, which removes the `annotationLayerFactory` and instead uses a lookup-function in the `PDFPageView`-class to access the external viewer-properties as necessary.
Note that this should even be an improvement for the "pageviewer" component-example, since most layers will now work by default rather than require manual configuration.
---
[1] In practice we generally suggest using the "simpleviewer", or "singlepageviewer", since it does *most* things out-of-the-box and given that a lot of functionality really require *a viewer* and not just a single page in order to work.
2022-12-06 23:34:55 +01:00
|
|
|
});
|
2021-11-06 18:36:49 +01:00
|
|
|
}
|
|
|
|
|
2022-12-12 14:24:27 +01:00
|
|
|
const { width, height } = viewport;
|
2024-12-04 19:34:57 +01:00
|
|
|
this.#originalViewport = viewport;
|
2023-03-28 21:52:07 +02:00
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
const { canvas, prevCanvas, ctx } = this._createCanvas(newCanvas => {
|
|
|
|
// Always inject the canvas as the first element in the wrapper.
|
|
|
|
canvasWrapper.prepend(newCanvas);
|
2024-06-12 12:51:51 +02:00
|
|
|
});
|
2024-12-11 13:54:50 +01:00
|
|
|
canvas.setAttribute("role", "presentation");
|
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
if (!this.outputScale) {
|
|
|
|
this.#computeScale();
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2024-12-11 13:58:52 +01:00
|
|
|
const { outputScale } = this;
|
|
|
|
this.#hasRestrictedScaling = this.#needsRestrictedScaling;
|
|
|
|
|
2019-12-27 00:22:32 +01:00
|
|
|
const sfx = approximateFraction(outputScale.sx);
|
|
|
|
const sfy = approximateFraction(outputScale.sy);
|
2022-11-21 17:15:39 +01:00
|
|
|
|
2024-09-05 17:05:22 +02:00
|
|
|
const canvasWidth = (canvas.width = floorToDivide(
|
|
|
|
calcRound(width * outputScale.sx),
|
|
|
|
sfx[0]
|
|
|
|
));
|
|
|
|
const canvasHeight = (canvas.height = floorToDivide(
|
|
|
|
calcRound(height * outputScale.sy),
|
|
|
|
sfy[0]
|
|
|
|
));
|
|
|
|
const pageWidth = floorToDivide(calcRound(width), sfx[1]);
|
|
|
|
const pageHeight = floorToDivide(calcRound(height), sfy[1]);
|
|
|
|
outputScale.sx = canvasWidth / pageWidth;
|
|
|
|
outputScale.sy = canvasHeight / pageHeight;
|
|
|
|
|
|
|
|
if (this.#scaleRoundX !== sfx[1]) {
|
|
|
|
div.style.setProperty("--scale-round-x", `${sfx[1]}px`);
|
|
|
|
this.#scaleRoundX = sfx[1];
|
|
|
|
}
|
|
|
|
if (this.#scaleRoundY !== sfy[1]) {
|
|
|
|
div.style.setProperty("--scale-round-y", `${sfy[1]}px`);
|
|
|
|
this.#scaleRoundY = sfy[1];
|
|
|
|
}
|
2021-11-06 18:36:49 +01:00
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
// Rendering area
|
2022-02-17 22:21:59 +01:00
|
|
|
const transform = outputScale.scaled
|
|
|
|
? [outputScale.sx, 0, 0, outputScale.sy, 0, 0]
|
|
|
|
: null;
|
2024-12-11 13:54:50 +01:00
|
|
|
const resultPromise = this._drawCanvas(
|
2024-12-11 13:58:52 +01:00
|
|
|
this._getRenderingContext(ctx, transform),
|
|
|
|
() => {
|
|
|
|
prevCanvas?.remove();
|
|
|
|
this._resetCanvas();
|
|
|
|
},
|
2024-12-11 13:54:50 +01:00
|
|
|
renderTask => {
|
|
|
|
// Ensure that the thumbnails won't become partially (or fully) blank,
|
|
|
|
// for documents that contain interactive form elements.
|
|
|
|
this.#useThumbnailCanvas.regularAnnotations =
|
|
|
|
!renderTask.separateAnnots;
|
|
|
|
|
2024-12-11 13:58:52 +01:00
|
|
|
this.dispatchPageRendered(
|
|
|
|
/* cssTransform */ false,
|
|
|
|
/* isDetailView */ false
|
|
|
|
);
|
2024-12-11 13:54:50 +01:00
|
|
|
}
|
|
|
|
).then(async () => {
|
|
|
|
this.structTreeLayer ||= new StructTreeLayerBuilder(
|
|
|
|
pdfPage,
|
|
|
|
viewport.rawDims
|
|
|
|
);
|
2024-09-03 16:49:22 +02:00
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
const textLayerPromise = this.#renderTextLayer();
|
2023-03-28 21:52:07 +02:00
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
if (this.annotationLayer) {
|
|
|
|
await this.#renderAnnotationLayer();
|
2024-11-12 11:26:32 +05:30
|
|
|
|
2025-02-28 12:41:47 +01:00
|
|
|
if (this.#enableAutoLinking && this.annotationLayer && this.textLayer) {
|
2024-12-11 13:54:50 +01:00
|
|
|
await this.#injectLinkAnnotations(textLayerPromise);
|
2023-03-28 21:52:07 +02:00
|
|
|
}
|
2024-12-11 13:54:50 +01:00
|
|
|
}
|
2023-03-28 21:52:07 +02:00
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
const { annotationEditorUIManager } = this.#layerProperties;
|
2023-03-28 21:52:07 +02:00
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
if (!annotationEditorUIManager) {
|
|
|
|
return;
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
}
|
2024-12-11 13:54:50 +01:00
|
|
|
this.drawLayer ||= new DrawLayerBuilder({
|
|
|
|
pageIndex: this.id,
|
|
|
|
});
|
|
|
|
await this.#renderDrawLayer();
|
|
|
|
this.drawLayer.setParent(canvasWrapper);
|
|
|
|
|
|
|
|
this.annotationEditorLayer ||= new AnnotationEditorLayerBuilder({
|
|
|
|
uiManager: annotationEditorUIManager,
|
|
|
|
pdfPage,
|
|
|
|
l10n,
|
|
|
|
structTreeLayer: this.structTreeLayer,
|
|
|
|
accessibilityManager: this._accessibilityManager,
|
|
|
|
annotationLayer: this.annotationLayer?.annotationLayer,
|
|
|
|
textLayer: this.textLayer,
|
|
|
|
drawLayer: this.drawLayer.getDrawLayer(),
|
|
|
|
onAppend: annotationEditorLayerDiv => {
|
|
|
|
this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer");
|
|
|
|
},
|
|
|
|
});
|
|
|
|
this.#renderAnnotationEditorLayer();
|
|
|
|
});
|
2023-03-28 21:52:07 +02:00
|
|
|
|
|
|
|
if (pdfPage.isPureXfa) {
|
|
|
|
if (!this.xfaLayer) {
|
2023-09-25 10:56:12 +02:00
|
|
|
const { annotationStorage, linkService } = this.#layerProperties;
|
2023-03-28 21:52:07 +02:00
|
|
|
|
|
|
|
this.xfaLayer = new XfaLayerBuilder({
|
|
|
|
pdfPage,
|
|
|
|
annotationStorage,
|
|
|
|
linkService,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
this.#renderXfaLayer();
|
|
|
|
}
|
|
|
|
|
|
|
|
div.setAttribute("data-loaded", true);
|
|
|
|
|
2024-12-11 13:54:50 +01:00
|
|
|
this.dispatchPageRender();
|
|
|
|
|
2023-03-28 21:52:07 +02:00
|
|
|
return resultPromise;
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2016-10-19 09:16:57 -05:00
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
/**
|
|
|
|
* @param {string|null} label
|
|
|
|
*/
|
|
|
|
setPageLabel(label) {
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
this.pageLabel = typeof label === "string" ? label : null;
|
2017-05-28 22:44:00 +02:00
|
|
|
|
2023-10-23 13:42:06 +02:00
|
|
|
this.div.setAttribute(
|
|
|
|
"data-l10n-args",
|
|
|
|
JSON.stringify({ page: this.pageLabel ?? this.id })
|
|
|
|
);
|
|
|
|
|
2017-05-28 22:44:00 +02:00
|
|
|
if (this.pageLabel !== null) {
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
this.div.setAttribute("data-page-label", this.pageLabel);
|
2017-05-28 22:44:00 +02:00
|
|
|
} else {
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
this.div.removeAttribute("data-page-label");
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
|
|
|
}
|
2022-07-24 13:14:58 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* For use by the `PDFThumbnailView.setImage`-method.
|
|
|
|
* @ignore
|
|
|
|
*/
|
|
|
|
get thumbnailCanvas() {
|
2023-06-01 18:46:50 +02:00
|
|
|
const { directDrawing, initialOptionalContent, regularAnnotations } =
|
2022-06-27 11:41:37 +02:00
|
|
|
this.#useThumbnailCanvas;
|
2023-06-01 18:46:50 +02:00
|
|
|
return directDrawing && initialOptionalContent && regularAnnotations
|
|
|
|
? this.canvas
|
|
|
|
: null;
|
2022-07-24 13:14:58 +02:00
|
|
|
}
|
2017-05-28 22:44:00 +02:00
|
|
|
}
|
2016-04-08 12:34:27 -05:00
|
|
|
|
Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes).
Prettier is being used for a couple of reasons:
- To be consistent with `mozilla-central`, where Prettier is already in use across the tree.
- To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters.
Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some).
Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long.
*Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit.
(On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
2019-12-25 15:59:37 +01:00
|
|
|
export { PDFPageView };
|