mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-02 20:37:21 +02:00
Compare commits
16 Commits
ea18e73de2
...
e6cb600896
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6cb600896 | ||
|
|
adcde1175e | ||
|
|
143a7244a3 | ||
|
|
13a61b1f72 | ||
|
|
941e17296e | ||
|
|
1f8eed020f | ||
|
|
bbfbe5159c | ||
|
|
4daca805d6 | ||
|
|
d37e0b40a5 | ||
|
|
46b16bd42e | ||
|
|
59086fa582 | ||
|
|
057507f6ce | ||
|
|
31c6561b91 | ||
|
|
05de3c8a88 | ||
|
|
bd14524536 | ||
|
|
fb9758303b |
@ -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]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -787,6 +787,12 @@ class CFFParser {
|
|||||||
this.emptyPrivateDictionary(parentDict);
|
this.emptyPrivateDictionary(parentDict);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// The Private DICT extends past the end of the font data, which means
|
||||||
|
// the embedded font is truncated; abort so the caller can substitute a
|
||||||
|
// system font instead of rendering blank glyphs (issue 7625).
|
||||||
|
if (offset + size > this.bytes.length) {
|
||||||
|
throw new FormatError("CFF Private DICT extends past end of font");
|
||||||
|
}
|
||||||
|
|
||||||
const privateDictEnd = offset + size;
|
const privateDictEnd = offset + size;
|
||||||
const dictData = this.bytes.subarray(offset, privateDictEnd);
|
const dictData = this.bytes.subarray(offset, privateDictEnd);
|
||||||
|
|||||||
@ -87,25 +87,28 @@ class XRefWrapper {
|
|||||||
this._getNewRef = getNewRef;
|
this._getNewRef = getNewRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(ref) {
|
|
||||||
return ref instanceof Ref ? this.entries[ref.num] : ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchIfRefAsync(ref) {
|
|
||||||
return Promise.resolve(this.fetch(ref));
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchIfRef(ref) {
|
|
||||||
return this.fetch(ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchAsync(ref) {
|
|
||||||
return Promise.resolve(this.fetch(ref));
|
|
||||||
}
|
|
||||||
|
|
||||||
getNewTemporaryRef() {
|
getNewTemporaryRef() {
|
||||||
return this._getNewRef();
|
return this._getNewRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchIfRef(obj) {
|
||||||
|
return obj instanceof Ref ? this.fetch(obj) : obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(ref) {
|
||||||
|
if (!(ref instanceof Ref)) {
|
||||||
|
throw new Error("ref object is not a reference");
|
||||||
|
}
|
||||||
|
return this.entries[ref.num];
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchIfRefAsync(obj) {
|
||||||
|
return obj instanceof Ref ? this.fetchAsync(obj) : obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchAsync(ref) {
|
||||||
|
return this.fetch(ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PDFEditor {
|
class PDFEditor {
|
||||||
@ -193,8 +196,7 @@ class PDFEditor {
|
|||||||
* @returns {Ref}
|
* @returns {Ref}
|
||||||
*/
|
*/
|
||||||
get newRef() {
|
get newRef() {
|
||||||
const ref = Ref.get(this.newRefCount++, 0);
|
return Ref.get(this.newRefCount++, 0);
|
||||||
return ref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -518,9 +520,9 @@ class PDFEditor {
|
|||||||
attributes = [attributes];
|
attributes = [attributes];
|
||||||
}
|
}
|
||||||
for (let attr of attributes) {
|
for (let attr of attributes) {
|
||||||
attr = this.xrefWrapper.fetch(attr);
|
attr = this.xrefWrapper.fetchIfRef(attr);
|
||||||
if (isName(attr.get("O"), "Table") && attr.has("Headers")) {
|
if (isName(attr.get("O"), "Table") && attr.has("Headers")) {
|
||||||
const headers = this.xrefWrapper.fetch(attr.getRaw("Headers"));
|
const headers = this.xrefWrapper.fetchIfRef(attr.getRaw("Headers"));
|
||||||
if (Array.isArray(headers)) {
|
if (Array.isArray(headers)) {
|
||||||
for (let i = 0, ii = headers.length; i < ii; i++) {
|
for (let i = 0, ii = headers.length; i < ii; i++) {
|
||||||
const newId = dedupIDs.get(
|
const newId = dedupIDs.get(
|
||||||
|
|||||||
@ -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({
|
||||||
@ -4666,18 +4570,11 @@ class PartialEvaluator {
|
|||||||
|
|
||||||
let fontFile, fontFileN, subtype, length1, length2, length3;
|
let fontFile, fontFileN, subtype, length1, length2, length3;
|
||||||
try {
|
try {
|
||||||
fontFile = descriptor.get("FontFile");
|
for (const n of ["FontFile", "FontFile2", "FontFile3"]) {
|
||||||
|
fontFile = descriptor.get(n);
|
||||||
if (fontFile) {
|
if (fontFile) {
|
||||||
fontFileN = 1;
|
fontFileN = n;
|
||||||
} else {
|
break;
|
||||||
fontFile = descriptor.get("FontFile2");
|
|
||||||
if (fontFile) {
|
|
||||||
fontFileN = 2;
|
|
||||||
} else {
|
|
||||||
fontFile = descriptor.get("FontFile3");
|
|
||||||
if (fontFile) {
|
|
||||||
fontFileN = 3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4831,7 +4728,35 @@ class PartialEvaluator {
|
|||||||
const newProperties = await this.extractDataStructures(dict, properties);
|
const newProperties = await this.extractDataStructures(dict, properties);
|
||||||
this.extractWidths(dict, descriptor, newProperties);
|
this.extractWidths(dict, descriptor, newProperties);
|
||||||
|
|
||||||
return new Font(fontName.name, fontFile, newProperties, this.options);
|
const font = new Font(fontName.name, fontFile, newProperties, this.options);
|
||||||
|
// The embedded font may have been too corrupt to parse, in which case
|
||||||
|
// we ended up in the fallback path without a substitution selected.
|
||||||
|
// Try the substitution map now so text renders in a font close to what
|
||||||
|
// the document asked for (issue 7625).
|
||||||
|
if (
|
||||||
|
font.missingFile &&
|
||||||
|
!font.systemFontInfo &&
|
||||||
|
!isType3Font &&
|
||||||
|
this.options.useSystemFonts
|
||||||
|
) {
|
||||||
|
const standardFontName = getStandardFontName(fontName.name);
|
||||||
|
const substitution = getFontSubstitution(
|
||||||
|
this.systemFontCache,
|
||||||
|
this.idFactory,
|
||||||
|
this.options.standardFontDataUrl,
|
||||||
|
fontName.name,
|
||||||
|
standardFontName,
|
||||||
|
type
|
||||||
|
);
|
||||||
|
if (substitution) {
|
||||||
|
if (substitution.guessFallback) {
|
||||||
|
substitution.guessFallback = false;
|
||||||
|
substitution.css += `,${font.fallbackName}`;
|
||||||
|
}
|
||||||
|
font.systemFontInfo = substitution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
static buildFontPaths(font, glyphs, handler, evaluatorOptions) {
|
static buildFontPaths(font, glyphs, handler, evaluatorOptions) {
|
||||||
|
|||||||
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 };
|
||||||
@ -2698,7 +2698,7 @@ class Font {
|
|||||||
if (
|
if (
|
||||||
(header.version === "OTTO" &&
|
(header.version === "OTTO" &&
|
||||||
(!properties.composite ||
|
(!properties.composite ||
|
||||||
(properties.fontFileN === 3 && parsedCff?.isCIDFont))) ||
|
(properties.fontFileN === "FontFile3" && parsedCff?.isCIDFont))) ||
|
||||||
!tables.head ||
|
!tables.head ||
|
||||||
!tables.hhea ||
|
!tables.hhea ||
|
||||||
!tables.maxp ||
|
!tables.maxp ||
|
||||||
|
|||||||
@ -566,6 +566,13 @@ class Type1Parser {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let token, length, data, lenIV;
|
let token, length, data, lenIV;
|
||||||
|
// Some fonts (e.g. those embedded in issue18548.pdf) define a second
|
||||||
|
// `/Subrs` and `/CharStrings` block that the PostScript runtime selects
|
||||||
|
// conditionally (e.g. high-resolution variants). Testing with other
|
||||||
|
// viewers shows that none of them actually use these conditional blocks,
|
||||||
|
// so we can "safely" ignore them.
|
||||||
|
let subrsParsed = false;
|
||||||
|
let charStringsParsed = false;
|
||||||
while ((token = this.getToken()) !== null) {
|
while ((token = this.getToken()) !== null) {
|
||||||
if (token !== "/") {
|
if (token !== "/") {
|
||||||
continue;
|
continue;
|
||||||
@ -573,6 +580,10 @@ class Type1Parser {
|
|||||||
token = this.getToken();
|
token = this.getToken();
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case "CharStrings":
|
case "CharStrings":
|
||||||
|
if (charStringsParsed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
charStringsParsed = true;
|
||||||
// The number immediately following CharStrings must be greater or
|
// The number immediately following CharStrings must be greater or
|
||||||
// equal to the number of CharStrings.
|
// equal to the number of CharStrings.
|
||||||
this.getToken();
|
this.getToken();
|
||||||
@ -610,6 +621,10 @@ class Type1Parser {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Subrs":
|
case "Subrs":
|
||||||
|
if (subrsParsed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
subrsParsed = true;
|
||||||
this.readInt(); // num
|
this.readInt(); // num
|
||||||
this.getToken(); // read in 'array'
|
this.getToken(); // read in 'array'
|
||||||
while (this.getToken() === "dup") {
|
while (this.getToken() === "dup") {
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,54 +28,32 @@ function expandBBox(array, index, minX, minY, maxX, maxY) {
|
|||||||
array[index * 4 + 3] = Math.max(array[index * 4 + 3], maxY);
|
array[index * 4 + 3] = Math.max(array[index * 4 + 3], maxY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply a scaling matrix to some min/max values.
|
|
||||||
// If a scaling factor is negative then min and max must be swapped.
|
// If a scaling factor is negative then min and max must be swapped.
|
||||||
function scaleMinMax(transform, minMax) {
|
function scaleCharBBox(scaleX, scaleY, x, y, bbox) {
|
||||||
let temp;
|
let temp;
|
||||||
if (transform[0]) {
|
if (scaleX) {
|
||||||
if (transform[0] < 0) {
|
if (scaleX < 0) {
|
||||||
temp = minMax[0];
|
temp = bbox[0];
|
||||||
minMax[0] = minMax[2];
|
bbox[0] = bbox[2];
|
||||||
minMax[2] = temp;
|
bbox[2] = temp;
|
||||||
}
|
}
|
||||||
minMax[0] *= transform[0];
|
bbox[0] *= scaleX;
|
||||||
minMax[2] *= transform[0];
|
bbox[2] *= scaleX;
|
||||||
|
|
||||||
if (transform[3] < 0) {
|
if (scaleY < 0) {
|
||||||
temp = minMax[1];
|
temp = bbox[1];
|
||||||
minMax[1] = minMax[3];
|
bbox[1] = bbox[3];
|
||||||
minMax[3] = temp;
|
bbox[3] = temp;
|
||||||
}
|
}
|
||||||
minMax[1] *= transform[3];
|
bbox[1] *= scaleY;
|
||||||
minMax[3] *= transform[3];
|
bbox[3] *= scaleY;
|
||||||
} else {
|
} else {
|
||||||
temp = minMax[0];
|
bbox.fill(0);
|
||||||
minMax[0] = minMax[1];
|
|
||||||
minMax[1] = temp;
|
|
||||||
temp = minMax[2];
|
|
||||||
minMax[2] = minMax[3];
|
|
||||||
minMax[3] = temp;
|
|
||||||
|
|
||||||
if (transform[1] < 0) {
|
|
||||||
temp = minMax[1];
|
|
||||||
minMax[1] = minMax[3];
|
|
||||||
minMax[3] = temp;
|
|
||||||
}
|
}
|
||||||
minMax[1] *= transform[1];
|
bbox[0] += x;
|
||||||
minMax[3] *= transform[1];
|
bbox[1] += y;
|
||||||
|
bbox[2] += x;
|
||||||
if (transform[2] < 0) {
|
bbox[3] += y;
|
||||||
temp = minMax[0];
|
|
||||||
minMax[0] = minMax[2];
|
|
||||||
minMax[2] = temp;
|
|
||||||
}
|
|
||||||
minMax[0] *= transform[2];
|
|
||||||
minMax[2] *= transform[2];
|
|
||||||
}
|
|
||||||
minMax[0] += transform[4];
|
|
||||||
minMax[1] += transform[5];
|
|
||||||
minMax[2] += transform[4];
|
|
||||||
minMax[3] += transform[5];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is computed rathter than hard-coded to keep into
|
// This is computed rathter than hard-coded to keep into
|
||||||
@ -663,7 +641,7 @@ class CanvasDependencyTracker {
|
|||||||
computedBBox = [0, 0, 0, 0];
|
computedBBox = [0, 0, 0, 0];
|
||||||
Util.axialAlignedBoundingBox(fontBBox, font.fontMatrix, computedBBox);
|
Util.axialAlignedBoundingBox(fontBBox, font.fontMatrix, computedBBox);
|
||||||
if (scale !== 1 || x !== 0 || y !== 0) {
|
if (scale !== 1 || x !== 0 || y !== 0) {
|
||||||
scaleMinMax([scale, 0, 0, -scale, x, y], computedBBox);
|
scaleCharBBox(scale, -scale, x, y, computedBBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBBoxTrustworthy) {
|
if (isBBoxTrustworthy) {
|
||||||
|
|||||||
@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2271,9 +2271,7 @@ describe("Highlight Editor", () => {
|
|||||||
const pdfData = fs.readFileSync(pdfPath).toString("base64");
|
const pdfData = fs.readFileSync(pdfPath).toString("base64");
|
||||||
const dataTransfer = await page.evaluateHandle(data => {
|
const dataTransfer = await page.evaluateHandle(data => {
|
||||||
const transfer = new DataTransfer();
|
const transfer = new DataTransfer();
|
||||||
const view = Uint8Array.from(atob(data), code =>
|
const view = Uint8Array.fromBase64(data);
|
||||||
code.charCodeAt(0)
|
|
||||||
);
|
|
||||||
const file = new File([view], "basicapi.pdf", {
|
const file = new File([view], "basicapi.pdf", {
|
||||||
type: "application/pdf",
|
type: "application/pdf",
|
||||||
});
|
});
|
||||||
|
|||||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -922,3 +922,4 @@
|
|||||||
!knockout_groups_test.pdf
|
!knockout_groups_test.pdf
|
||||||
!issue18032.pdf
|
!issue18032.pdf
|
||||||
!Embedded_font.pdf
|
!Embedded_font.pdf
|
||||||
|
!issue18548_reduced.pdf
|
||||||
|
|||||||
BIN
test/pdfs/issue18548_reduced.pdf
Normal file
BIN
test/pdfs/issue18548_reduced.pdf
Normal file
Binary file not shown.
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
|
||||||
1
test/pdfs/issue7625.pdf.link
Normal file
1
test/pdfs/issue7625.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://github.com/mozilla/pdf.js/files/467169/Er.aestetik.en.loftestang.for.laering.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",
|
||||||
@ -14267,5 +14303,22 @@
|
|||||||
"md5": "b68dd5a3e6833d1af94e295fe1d60285",
|
"md5": "b68dd5a3e6833d1af94e295fe1d60285",
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "issue18548_reduced",
|
||||||
|
"file": "pdfs/issue18548_reduced.pdf",
|
||||||
|
"md5": "39d15f7f810bd89a4e5858df9c75ca4e",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "issue7625",
|
||||||
|
"file": "pdfs/issue7625.pdf",
|
||||||
|
"md5": "77ca0a41da767dca31ca45219e2ae202",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"firstPage": 1,
|
||||||
|
"lastPage": 1,
|
||||||
|
"type": "eq"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -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,14 +142,17 @@ 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] =
|
||||||
|
await Promise.all([
|
||||||
this.pdfPage.getAnnotations({ intent }),
|
this.pdfPage.getAnnotations({ intent }),
|
||||||
this._hasJSActionsPromise,
|
this._hasJSActionsPromise,
|
||||||
this._fieldObjectsPromise,
|
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);
|
||||||
|
|||||||
@ -37,6 +37,10 @@ import { XfaLayer } from "pdfjs-lib";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class XfaLayerBuilder {
|
class XfaLayerBuilder {
|
||||||
|
#cancelled = false;
|
||||||
|
|
||||||
|
div = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {XfaLayerBuilderOptions} options
|
* @param {XfaLayerBuilderOptions} options
|
||||||
*/
|
*/
|
||||||
@ -50,9 +54,6 @@ class XfaLayerBuilder {
|
|||||||
this.annotationStorage = annotationStorage;
|
this.annotationStorage = annotationStorage;
|
||||||
this.linkService = linkService;
|
this.linkService = linkService;
|
||||||
this.xfaHtml = xfaHtml;
|
this.xfaHtml = xfaHtml;
|
||||||
|
|
||||||
this.div = null;
|
|
||||||
this._cancelled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,50 +63,33 @@ class XfaLayerBuilder {
|
|||||||
* with a `textDivs` property that can be used with the TextHighlighter.
|
* with a `textDivs` property that can be used with the TextHighlighter.
|
||||||
*/
|
*/
|
||||||
async render({ viewport, intent = "display" }) {
|
async render({ viewport, intent = "display" }) {
|
||||||
|
let xfaHtml;
|
||||||
if (intent === "print") {
|
if (intent === "print") {
|
||||||
const parameters = {
|
xfaHtml = this.xfaHtml;
|
||||||
viewport: viewport.clone({ dontFlip: true }),
|
} else {
|
||||||
div: this.div,
|
xfaHtml = await this.pdfPage.getXfa();
|
||||||
xfaHtml: this.xfaHtml,
|
|
||||||
annotationStorage: this.annotationStorage,
|
|
||||||
linkService: this.linkService,
|
|
||||||
intent,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create an xfa layer div and render the form
|
if (this.#cancelled || !xfaHtml) {
|
||||||
this.div = document.createElement("div");
|
|
||||||
parameters.div = this.div;
|
|
||||||
|
|
||||||
return XfaLayer.render(parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
// intent === "display"
|
|
||||||
const xfaHtml = await this.pdfPage.getXfa();
|
|
||||||
if (this._cancelled || !xfaHtml) {
|
|
||||||
return { textDivs: [] };
|
return { textDivs: [] };
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const parameters = {
|
// Create an xfa layer div and render the form
|
||||||
|
const hasDiv = !!this.div;
|
||||||
|
const params = {
|
||||||
viewport: viewport.clone({ dontFlip: true }),
|
viewport: viewport.clone({ dontFlip: true }),
|
||||||
div: this.div,
|
div: (this.div ??= document.createElement("div")),
|
||||||
xfaHtml,
|
xfaHtml,
|
||||||
annotationStorage: this.annotationStorage,
|
annotationStorage: this.annotationStorage,
|
||||||
linkService: this.linkService,
|
linkService: this.linkService,
|
||||||
intent,
|
intent,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.div) {
|
return hasDiv ? XfaLayer.update(params) : XfaLayer.render(params);
|
||||||
return XfaLayer.update(parameters);
|
|
||||||
}
|
|
||||||
// Create an xfa layer div and render the form
|
|
||||||
this.div = document.createElement("div");
|
|
||||||
parameters.div = this.div;
|
|
||||||
|
|
||||||
return XfaLayer.render(parameters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
this._cancelled = true;
|
this.#cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user