mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-07-24 16:07:22 +02:00
Merge pull request #21313 from Snuffleupagus/Annotation-OC
Add support for Optional Content in the AnnotationLayer (issue 20433)
This commit is contained in:
commit
941e17296e
@ -76,6 +76,7 @@ import { FileSpec } from "./file_spec.js";
|
|||||||
import { JpegStream } from "./jpeg_stream.js";
|
import { JpegStream } from "./jpeg_stream.js";
|
||||||
import { ObjectLoader } from "./object_loader.js";
|
import { ObjectLoader } from "./object_loader.js";
|
||||||
import { OperatorList } from "./operator_list.js";
|
import { OperatorList } from "./operator_list.js";
|
||||||
|
import { parseMarkedContentProps } from "./evaluator_utils.js";
|
||||||
import { XFAFactory } from "./xfa/factory.js";
|
import { XFAFactory } from "./xfa/factory.js";
|
||||||
|
|
||||||
class AnnotationFactory {
|
class AnnotationFactory {
|
||||||
@ -663,6 +664,8 @@ function getTransformMatrix(rect, bbox, matrix) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Annotation {
|
class Annotation {
|
||||||
|
_oc = undefined;
|
||||||
|
|
||||||
constructor(params) {
|
constructor(params) {
|
||||||
const { annotationGlobals, dict, orphanFields, ref, subtype, xref } =
|
const { annotationGlobals, dict, orphanFields, ref, subtype, xref } =
|
||||||
params;
|
params;
|
||||||
@ -679,7 +682,7 @@ class Annotation {
|
|||||||
this.setColor(dict.getArray("C"));
|
this.setColor(dict.getArray("C"));
|
||||||
this.setBorderStyle(dict);
|
this.setBorderStyle(dict);
|
||||||
this.setAppearance(dict);
|
this.setAppearance(dict);
|
||||||
this.setOptionalContent(dict);
|
this.#setOptionalContent(xref, dict);
|
||||||
|
|
||||||
const MK = dict.get("MK");
|
const MK = dict.get("MK");
|
||||||
this.setBorderAndBackgroundColors(MK);
|
this.setBorderAndBackgroundColors(MK);
|
||||||
@ -710,6 +713,7 @@ class Annotation {
|
|||||||
hasAppearance: !!this.appearance,
|
hasAppearance: !!this.appearance,
|
||||||
id: params.id,
|
id: params.id,
|
||||||
modificationDate: this.modificationDate,
|
modificationDate: this.modificationDate,
|
||||||
|
oc: this._oc,
|
||||||
rect: this.rectangle,
|
rect: this.rectangle,
|
||||||
subtype,
|
subtype,
|
||||||
hasOwnCanvas: false,
|
hasOwnCanvas: false,
|
||||||
@ -1169,14 +1173,17 @@ class Annotation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setOptionalContent(dict) {
|
#setOptionalContent(xref, dict) {
|
||||||
this.oc = null;
|
if (dict.has("OC")) {
|
||||||
|
try {
|
||||||
const oc = dict.get("OC");
|
this._oc = parseMarkedContentProps(
|
||||||
if (oc instanceof Name) {
|
xref,
|
||||||
warn("setOptionalContent: Support for /Name-entry is not implemented.");
|
dict.get("OC"),
|
||||||
} else if (oc instanceof Dict) {
|
/* resources = */ null
|
||||||
this.oc = oc;
|
);
|
||||||
|
} catch (ex) {
|
||||||
|
warn(`#setOptionalContent: ${ex}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1229,13 +1236,7 @@ class Annotation {
|
|||||||
|
|
||||||
const opList = new OperatorList();
|
const opList = new OperatorList();
|
||||||
|
|
||||||
let optionalContent;
|
const optionalContent = this._oc;
|
||||||
if (this.oc) {
|
|
||||||
optionalContent = await evaluator.parseMarkedContentProps(
|
|
||||||
this.oc,
|
|
||||||
/* resources = */ null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (optionalContent !== undefined) {
|
if (optionalContent !== undefined) {
|
||||||
opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
|
opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
|
||||||
}
|
}
|
||||||
@ -2110,13 +2111,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
const bbox = [0, 0, this.width, this.height];
|
const bbox = [0, 0, this.width, this.height];
|
||||||
const transform = getTransformMatrix(this.data.rect, bbox, matrix);
|
const transform = getTransformMatrix(this.data.rect, bbox, matrix);
|
||||||
|
|
||||||
let optionalContent;
|
const optionalContent = this._oc;
|
||||||
if (this.oc) {
|
|
||||||
optionalContent = await evaluator.parseMarkedContentProps(
|
|
||||||
this.oc,
|
|
||||||
/* resources = */ null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (optionalContent !== undefined) {
|
if (optionalContent !== undefined) {
|
||||||
opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
|
opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,7 @@ import { getGlyphsUnicode } from "./glyphlist.js";
|
|||||||
import { getMetrics } from "./metrics.js";
|
import { getMetrics } from "./metrics.js";
|
||||||
import { getUnicodeForGlyph } from "./unicode.js";
|
import { getUnicodeForGlyph } from "./unicode.js";
|
||||||
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
|
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
|
||||||
|
import { parseMarkedContentProps } from "./evaluator_utils.js";
|
||||||
import { PDFImage } from "./image.js";
|
import { PDFImage } from "./image.js";
|
||||||
import { Stream } from "./stream.js";
|
import { Stream } from "./stream.js";
|
||||||
import { stringToPDFString } from "./string_utils.js";
|
import { stringToPDFString } from "./string_utils.js";
|
||||||
@ -1651,105 +1652,8 @@ class PartialEvaluator {
|
|||||||
throw new FormatError(`Unknown PatternName: ${patternName}`);
|
throw new FormatError(`Unknown PatternName: ${patternName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
_parseVisibilityExpression(array, nestingCounter, currentResult) {
|
|
||||||
const MAX_NESTING = 10;
|
|
||||||
if (++nestingCounter > MAX_NESTING) {
|
|
||||||
warn("Visibility expression is too deeply nested");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const length = array.length;
|
|
||||||
const operator = this.xref.fetchIfRef(array[0]);
|
|
||||||
if (length < 2 || !(operator instanceof Name)) {
|
|
||||||
warn("Invalid visibility expression");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (operator.name) {
|
|
||||||
case "And":
|
|
||||||
case "Or":
|
|
||||||
case "Not":
|
|
||||||
currentResult.push(operator.name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warn(`Invalid operator ${operator.name} in visibility expression`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (let i = 1; i < length; i++) {
|
|
||||||
const raw = array[i];
|
|
||||||
const object = this.xref.fetchIfRef(raw);
|
|
||||||
if (Array.isArray(object)) {
|
|
||||||
const nestedResult = [];
|
|
||||||
currentResult.push(nestedResult);
|
|
||||||
// Recursively parse a subarray.
|
|
||||||
this._parseVisibilityExpression(object, nestingCounter, nestedResult);
|
|
||||||
} else if (raw instanceof Ref) {
|
|
||||||
// Reference to an OCG dictionary.
|
|
||||||
currentResult.push(raw.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async parseMarkedContentProps(contentProperties, resources) {
|
async parseMarkedContentProps(contentProperties, resources) {
|
||||||
let optionalContent;
|
return parseMarkedContentProps(this.xref, contentProperties, resources);
|
||||||
if (contentProperties instanceof Name) {
|
|
||||||
const properties = resources.get("Properties");
|
|
||||||
optionalContent = properties.get(contentProperties.name);
|
|
||||||
} else if (contentProperties instanceof Dict) {
|
|
||||||
optionalContent = contentProperties;
|
|
||||||
} else {
|
|
||||||
throw new FormatError("Optional content properties malformed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionalContentType = optionalContent.get("Type")?.name;
|
|
||||||
if (optionalContentType === "OCG") {
|
|
||||||
return {
|
|
||||||
type: optionalContentType,
|
|
||||||
id: optionalContent.objId,
|
|
||||||
};
|
|
||||||
} else if (optionalContentType === "OCMD") {
|
|
||||||
const expression = optionalContent.get("VE");
|
|
||||||
if (Array.isArray(expression)) {
|
|
||||||
const result = [];
|
|
||||||
this._parseVisibilityExpression(expression, 0, result);
|
|
||||||
if (result.length > 0) {
|
|
||||||
return {
|
|
||||||
type: "OCMD",
|
|
||||||
expression: result,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionalContentGroups = optionalContent.get("OCGs");
|
|
||||||
if (
|
|
||||||
Array.isArray(optionalContentGroups) ||
|
|
||||||
optionalContentGroups instanceof Dict
|
|
||||||
) {
|
|
||||||
const groupIds = [];
|
|
||||||
if (Array.isArray(optionalContentGroups)) {
|
|
||||||
for (const ocg of optionalContentGroups) {
|
|
||||||
groupIds.push(ocg.toString());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Dictionary, just use the obj id.
|
|
||||||
groupIds.push(optionalContentGroups.objId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: optionalContentType,
|
|
||||||
ids: groupIds,
|
|
||||||
policy:
|
|
||||||
optionalContent.get("P") instanceof Name
|
|
||||||
? optionalContent.get("P").name
|
|
||||||
: null,
|
|
||||||
expression: null,
|
|
||||||
};
|
|
||||||
} else if (optionalContentGroups instanceof Ref) {
|
|
||||||
return {
|
|
||||||
type: optionalContentType,
|
|
||||||
id: optionalContentGroups.toString(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOperatorList({
|
async getOperatorList({
|
||||||
|
|||||||
123
src/core/evaluator_utils.js
Normal file
123
src/core/evaluator_utils.js
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Dict, Name, Ref } from "./primitives.js";
|
||||||
|
import { FormatError, warn } from "../shared/util.js";
|
||||||
|
|
||||||
|
function _parseVisibilityExpression(
|
||||||
|
xref,
|
||||||
|
array,
|
||||||
|
nestingCounter,
|
||||||
|
currentResult
|
||||||
|
) {
|
||||||
|
const MAX_NESTING = 10;
|
||||||
|
if (++nestingCounter > MAX_NESTING) {
|
||||||
|
warn("Visibility expression is too deeply nested");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const length = array.length;
|
||||||
|
const operator = xref.fetchIfRef(array[0]);
|
||||||
|
if (length < 2 || !(operator instanceof Name)) {
|
||||||
|
warn("Invalid visibility expression");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (operator.name) {
|
||||||
|
case "And":
|
||||||
|
case "Or":
|
||||||
|
case "Not":
|
||||||
|
currentResult.push(operator.name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warn(`Invalid operator ${operator.name} in visibility expression`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 1; i < length; i++) {
|
||||||
|
const raw = array[i];
|
||||||
|
const object = xref.fetchIfRef(raw);
|
||||||
|
if (Array.isArray(object)) {
|
||||||
|
const nestedResult = [];
|
||||||
|
currentResult.push(nestedResult);
|
||||||
|
// Recursively parse a subarray.
|
||||||
|
_parseVisibilityExpression(xref, object, nestingCounter, nestedResult);
|
||||||
|
} else if (raw instanceof Ref) {
|
||||||
|
// Reference to an OCG dictionary.
|
||||||
|
currentResult.push(raw.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseMarkedContentProps(xref, contentProperties, resources) {
|
||||||
|
let optionalContent;
|
||||||
|
if (contentProperties instanceof Name) {
|
||||||
|
const properties = resources.get("Properties");
|
||||||
|
optionalContent = properties.get(contentProperties.name);
|
||||||
|
} else if (contentProperties instanceof Dict) {
|
||||||
|
optionalContent = contentProperties;
|
||||||
|
} else {
|
||||||
|
throw new FormatError("Optional content properties malformed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionalContentType = optionalContent.get("Type")?.name;
|
||||||
|
if (optionalContentType === "OCG") {
|
||||||
|
return {
|
||||||
|
type: optionalContentType,
|
||||||
|
id: optionalContent.objId,
|
||||||
|
};
|
||||||
|
} else if (optionalContentType === "OCMD") {
|
||||||
|
const expression = optionalContent.get("VE");
|
||||||
|
if (Array.isArray(expression)) {
|
||||||
|
const result = [];
|
||||||
|
_parseVisibilityExpression(xref, expression, 0, result);
|
||||||
|
if (result.length > 0) {
|
||||||
|
return {
|
||||||
|
type: "OCMD",
|
||||||
|
expression: result,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionalContentGroups = optionalContent.get("OCGs");
|
||||||
|
if (
|
||||||
|
Array.isArray(optionalContentGroups) ||
|
||||||
|
optionalContentGroups instanceof Dict
|
||||||
|
) {
|
||||||
|
const groupIds = [];
|
||||||
|
if (Array.isArray(optionalContentGroups)) {
|
||||||
|
for (const ocg of optionalContentGroups) {
|
||||||
|
groupIds.push(ocg.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Dictionary, just use the obj id.
|
||||||
|
groupIds.push(optionalContentGroups.objId);
|
||||||
|
}
|
||||||
|
const p = optionalContent.get("P");
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: optionalContentType,
|
||||||
|
ids: groupIds,
|
||||||
|
policy: p instanceof Name ? p.name : null,
|
||||||
|
expression: null,
|
||||||
|
};
|
||||||
|
} else if (optionalContentGroups instanceof Ref) {
|
||||||
|
return {
|
||||||
|
type: optionalContentType,
|
||||||
|
id: optionalContentGroups.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { parseMarkedContentProps };
|
||||||
@ -16,6 +16,8 @@
|
|||||||
/** @typedef {import("./api").PDFPageProxy} PDFPageProxy */
|
/** @typedef {import("./api").PDFPageProxy} PDFPageProxy */
|
||||||
/** @typedef {import("./page_viewport").PageViewport} PageViewport */
|
/** @typedef {import("./page_viewport").PageViewport} PageViewport */
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
|
/** @typedef {import("../src/display/optional_content_config").OptionalContentConfig} OptionalContentConfig */
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
/** @typedef {import("../../web/text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
|
/** @typedef {import("../../web/text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
|
||||||
@ -886,6 +888,18 @@ class AnnotationElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateOC(optionalContentConfig) {
|
||||||
|
if (!this.data.oc || !optionalContentConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isVisible = optionalContentConfig.isVisible(this.data.oc);
|
||||||
|
if (isVisible) {
|
||||||
|
this.show();
|
||||||
|
} else {
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get width() {
|
get width() {
|
||||||
return this.data.rect[2] - this.data.rect[0];
|
return this.data.rect[2] - this.data.rect[0];
|
||||||
}
|
}
|
||||||
@ -3755,7 +3769,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
|||||||
* @property {TextAccessibilityManager} [accessibilityManager]
|
* @property {TextAccessibilityManager} [accessibilityManager]
|
||||||
* @property {AnnotationEditorUIManager} [annotationEditorUIManager]
|
* @property {AnnotationEditorUIManager} [annotationEditorUIManager]
|
||||||
* @property {StructTreeLayerBuilder} [structTreeLayer]
|
* @property {StructTreeLayerBuilder} [structTreeLayer]
|
||||||
* @property {CommentManager} [commentManager] - The comment manager instance.
|
* @property {OptionalContentConfig} [optionalContentConfig]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3827,7 +3841,7 @@ class AnnotationLayer {
|
|||||||
* @memberof AnnotationLayer
|
* @memberof AnnotationLayer
|
||||||
*/
|
*/
|
||||||
async render(params) {
|
async render(params) {
|
||||||
const { annotations } = params;
|
const { annotations, optionalContentConfig } = params;
|
||||||
const layer = this.div;
|
const layer = this.div;
|
||||||
setLayerDimensions(layer, this.viewport);
|
setLayerDimensions(layer, this.viewport);
|
||||||
|
|
||||||
@ -3892,6 +3906,7 @@ class AnnotationLayer {
|
|||||||
if (data.hidden) {
|
if (data.hidden) {
|
||||||
rendered.style.visibility = "hidden";
|
rendered.style.visibility = "hidden";
|
||||||
}
|
}
|
||||||
|
element.updateOC(optionalContentConfig);
|
||||||
|
|
||||||
if (element._isEditable) {
|
if (element._isEditable) {
|
||||||
this.#editableAnnotations.set(element.data.id, element);
|
this.#editableAnnotations.set(element.data.id, element);
|
||||||
@ -4052,11 +4067,14 @@ class AnnotationLayer {
|
|||||||
* @param {AnnotationLayerParameters} viewport
|
* @param {AnnotationLayerParameters} viewport
|
||||||
* @memberof AnnotationLayer
|
* @memberof AnnotationLayer
|
||||||
*/
|
*/
|
||||||
update({ viewport }) {
|
update({ viewport, optionalContentConfig }) {
|
||||||
const layer = this.div;
|
const layer = this.div;
|
||||||
this.viewport = viewport;
|
this.viewport = viewport;
|
||||||
setLayerDimensions(layer, { rotation: viewport.rotation });
|
setLayerDimensions(layer, { rotation: viewport.rotation });
|
||||||
|
|
||||||
|
for (const element of this.#elements) {
|
||||||
|
element.updateOC(optionalContentConfig);
|
||||||
|
}
|
||||||
this.#setAnnotationCanvasMap();
|
this.#setAnnotationCanvasMap();
|
||||||
layer.hidden = false;
|
layer.hidden = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -242,7 +242,8 @@ class Rasterize {
|
|||||||
fieldObjects,
|
fieldObjects,
|
||||||
page,
|
page,
|
||||||
imageResourcesPath,
|
imageResourcesPath,
|
||||||
renderForms = false
|
renderForms = false,
|
||||||
|
optionalContentConfigPromise = null
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const { svg, foreignObject, style, div } = this.createContainer(viewport);
|
const { svg, foreignObject, style, div } = this.createContainer(viewport);
|
||||||
@ -263,6 +264,7 @@ class Rasterize {
|
|||||||
imageResourcesPath,
|
imageResourcesPath,
|
||||||
renderForms,
|
renderForms,
|
||||||
fieldObjects,
|
fieldObjects,
|
||||||
|
optionalContentConfig: await optionalContentConfigPromise,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure that the annotationLayer gets translated.
|
// Ensure that the annotationLayer gets translated.
|
||||||
@ -1355,7 +1357,8 @@ class Driver {
|
|||||||
task.fieldObjects,
|
task.fieldObjects,
|
||||||
page,
|
page,
|
||||||
IMAGE_RESOURCES_PATH,
|
IMAGE_RESOURCES_PATH,
|
||||||
renderForms
|
renderForms,
|
||||||
|
task.optionalContentConfigPromise
|
||||||
).then(() => {
|
).then(() => {
|
||||||
completeRender(false);
|
completeRender(false);
|
||||||
});
|
});
|
||||||
|
|||||||
1
test/pdfs/issue20433.pdf.link
Normal file
1
test/pdfs/issue20433.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://web.archive.org/web/20251107005559/https://octopdf.com/octopdf-sample.pdf
|
||||||
@ -1956,6 +1956,42 @@
|
|||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "issue20433-initial",
|
||||||
|
"file": "pdfs/issue20433.pdf",
|
||||||
|
"md5": "3a550da7807540982ed457397667db79",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"firstPage": 2,
|
||||||
|
"type": "eq",
|
||||||
|
"forms": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "issue20433-no-form",
|
||||||
|
"file": "pdfs/issue20433.pdf",
|
||||||
|
"md5": "3a550da7807540982ed457397667db79",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"firstPage": 2,
|
||||||
|
"type": "eq",
|
||||||
|
"forms": true,
|
||||||
|
"optionalContent": {
|
||||||
|
"73R": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "issue20433-no-mathml",
|
||||||
|
"file": "pdfs/issue20433.pdf",
|
||||||
|
"md5": "3a550da7807540982ed457397667db79",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"firstPage": 2,
|
||||||
|
"type": "eq",
|
||||||
|
"forms": true,
|
||||||
|
"optionalContent": {
|
||||||
|
"115R": false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "issue13845",
|
"id": "issue13845",
|
||||||
"file": "pdfs/issue13845.pdf",
|
"file": "pdfs/issue13845.pdf",
|
||||||
|
|||||||
@ -63,6 +63,7 @@ import { PresentationModeState } from "./ui_utils.js";
|
|||||||
* @property {PageViewport} viewport
|
* @property {PageViewport} viewport
|
||||||
* @property {string} [intent] - The default value is "display".
|
* @property {string} [intent] - The default value is "display".
|
||||||
* @property {StructTreeLayerBuilder} [structTreeLayer]
|
* @property {StructTreeLayerBuilder} [structTreeLayer]
|
||||||
|
* @property {Promise} [optionalContentConfigPromise]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class AnnotationLayerBuilder {
|
class AnnotationLayerBuilder {
|
||||||
@ -125,8 +126,15 @@ class AnnotationLayerBuilder {
|
|||||||
* @returns {Promise<void>} A promise that is resolved when rendering of the
|
* @returns {Promise<void>} A promise that is resolved when rendering of the
|
||||||
* annotations is complete.
|
* annotations is complete.
|
||||||
*/
|
*/
|
||||||
async render({ viewport, intent = "display", structTreeLayer = null }) {
|
async render({
|
||||||
|
viewport,
|
||||||
|
intent = "display",
|
||||||
|
structTreeLayer = null,
|
||||||
|
optionalContentConfigPromise = null,
|
||||||
|
}) {
|
||||||
if (this.div) {
|
if (this.div) {
|
||||||
|
const optionalContentConfig = await optionalContentConfigPromise;
|
||||||
|
|
||||||
if (this._cancelled || !this.annotationLayer) {
|
if (this._cancelled || !this.annotationLayer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -134,15 +142,18 @@ class AnnotationLayerBuilder {
|
|||||||
// transformation matrices.
|
// transformation matrices.
|
||||||
this.annotationLayer.update({
|
this.annotationLayer.update({
|
||||||
viewport: viewport.clone({ dontFlip: true }),
|
viewport: viewport.clone({ dontFlip: true }),
|
||||||
|
optionalContentConfig,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [annotations, hasJSActions, fieldObjects] = await Promise.all([
|
const [annotations, hasJSActions, fieldObjects, optionalContentConfig] =
|
||||||
this.pdfPage.getAnnotations({ intent }),
|
await Promise.all([
|
||||||
this._hasJSActionsPromise,
|
this.pdfPage.getAnnotations({ intent }),
|
||||||
this._fieldObjectsPromise,
|
this._hasJSActionsPromise,
|
||||||
]);
|
this._fieldObjectsPromise,
|
||||||
|
optionalContentConfigPromise,
|
||||||
|
]);
|
||||||
if (this._cancelled) {
|
if (this._cancelled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -169,6 +180,7 @@ class AnnotationLayerBuilder {
|
|||||||
enableScripting: this.enableScripting,
|
enableScripting: this.enableScripting,
|
||||||
hasJSActions,
|
hasJSActions,
|
||||||
fieldObjects,
|
fieldObjects,
|
||||||
|
optionalContentConfig,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#annotations = annotations;
|
this.#annotations = annotations;
|
||||||
|
|||||||
@ -464,6 +464,7 @@ class PDFPageView extends BasePDFPageView {
|
|||||||
viewport: this.viewport,
|
viewport: this.viewport,
|
||||||
intent: "display",
|
intent: "display",
|
||||||
structTreeLayer: this.structTreeLayer,
|
structTreeLayer: this.structTreeLayer,
|
||||||
|
optionalContentConfigPromise: this._optionalContentConfigPromise,
|
||||||
});
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.error("#renderAnnotationLayer:", ex);
|
console.error("#renderAnnotationLayer:", ex);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user