Merge pull request #16920 from Snuffleupagus/annotationGlobals
Slightly reduce asynchronicity when parsing Annotations
This commit is contained in:
commit
18a661b6a0
@ -67,6 +67,35 @@ import { writeObject } from "./writer.js";
|
|||||||
import { XFAFactory } from "./xfa/factory.js";
|
import { XFAFactory } from "./xfa/factory.js";
|
||||||
|
|
||||||
class AnnotationFactory {
|
class AnnotationFactory {
|
||||||
|
static createGlobals(pdfManager) {
|
||||||
|
return Promise.all([
|
||||||
|
pdfManager.ensureCatalog("acroForm"),
|
||||||
|
pdfManager.ensureDoc("xfaDatasets"),
|
||||||
|
pdfManager.ensureCatalog("structTreeRoot"),
|
||||||
|
// Only necessary to prevent the `Catalog.baseUrl`-getter, used
|
||||||
|
// with some Annotations, from throwing and thus breaking parsing:
|
||||||
|
pdfManager.ensureCatalog("baseUrl"),
|
||||||
|
// Only necessary to prevent the `Catalog.attachments`-getter, used
|
||||||
|
// with "GoToE" actions, from throwing and thus breaking parsing:
|
||||||
|
pdfManager.ensureCatalog("attachments"),
|
||||||
|
]).then(
|
||||||
|
([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments]) => {
|
||||||
|
return {
|
||||||
|
pdfManager,
|
||||||
|
acroForm: acroForm instanceof Dict ? acroForm : Dict.empty,
|
||||||
|
xfaDatasets,
|
||||||
|
structTreeRoot,
|
||||||
|
baseUrl,
|
||||||
|
attachments,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
reason => {
|
||||||
|
warn(`createGlobals: "${reason}".`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an `Annotation` object of the correct type for the given reference
|
* Create an `Annotation` object of the correct type for the given reference
|
||||||
* to an annotation dictionary. This yields a promise that is resolved when
|
* to an annotation dictionary. This yields a promise that is resolved when
|
||||||
@ -74,48 +103,33 @@ class AnnotationFactory {
|
|||||||
*
|
*
|
||||||
* @param {XRef} xref
|
* @param {XRef} xref
|
||||||
* @param {Object} ref
|
* @param {Object} ref
|
||||||
* @param {PDFManager} pdfManager
|
* @params {Object} annotationGlobals
|
||||||
* @param {Object} idFactory
|
* @param {Object} idFactory
|
||||||
* @param {boolean} collectFields
|
* @param {boolean} [collectFields]
|
||||||
* @param {Object} [pageRef]
|
* @param {Object} [pageRef]
|
||||||
* @returns {Promise} A promise that is resolved with an {Annotation}
|
* @returns {Promise} A promise that is resolved with an {Annotation}
|
||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
static create(xref, ref, pdfManager, idFactory, collectFields, pageRef) {
|
static async create(
|
||||||
return Promise.all([
|
xref,
|
||||||
pdfManager.ensureCatalog("acroForm"),
|
ref,
|
||||||
// Only necessary to prevent the `pdfManager.docBaseUrl`-getter, used
|
annotationGlobals,
|
||||||
// with certain Annotations, from throwing and thus breaking parsing:
|
idFactory,
|
||||||
pdfManager.ensureCatalog("baseUrl"),
|
collectFields,
|
||||||
// Only necessary in the `Catalog.parseDestDictionary`-method,
|
pageRef
|
||||||
// when parsing "GoToE" actions:
|
) {
|
||||||
pdfManager.ensureCatalog("attachments"),
|
const pageIndex = collectFields
|
||||||
pdfManager.ensureDoc("xfaDatasets"),
|
? await this._getPageIndex(xref, ref, annotationGlobals.pdfManager)
|
||||||
collectFields ? this._getPageIndex(xref, ref, pdfManager) : -1,
|
: null;
|
||||||
pageRef ? pdfManager.ensureCatalog("structTreeRoot") : null,
|
|
||||||
]).then(
|
return annotationGlobals.pdfManager.ensure(this, "_create", [
|
||||||
([
|
xref,
|
||||||
acroForm,
|
ref,
|
||||||
baseUrl,
|
annotationGlobals,
|
||||||
attachments,
|
idFactory,
|
||||||
xfaDatasets,
|
pageIndex,
|
||||||
pageIndex,
|
pageRef,
|
||||||
structTreeRoot,
|
]);
|
||||||
]) =>
|
|
||||||
pdfManager.ensure(this, "_create", [
|
|
||||||
xref,
|
|
||||||
ref,
|
|
||||||
pdfManager,
|
|
||||||
idFactory,
|
|
||||||
acroForm,
|
|
||||||
attachments,
|
|
||||||
xfaDatasets,
|
|
||||||
collectFields,
|
|
||||||
pageIndex,
|
|
||||||
structTreeRoot,
|
|
||||||
pageRef,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,14 +138,9 @@ class AnnotationFactory {
|
|||||||
static _create(
|
static _create(
|
||||||
xref,
|
xref,
|
||||||
ref,
|
ref,
|
||||||
pdfManager,
|
annotationGlobals,
|
||||||
idFactory,
|
idFactory,
|
||||||
acroForm,
|
pageIndex = null,
|
||||||
attachments = null,
|
|
||||||
xfaDatasets,
|
|
||||||
collectFields,
|
|
||||||
pageIndex = -1,
|
|
||||||
structTreeRoot = null,
|
|
||||||
pageRef = null
|
pageRef = null
|
||||||
) {
|
) {
|
||||||
const dict = xref.fetchIfRef(ref);
|
const dict = xref.fetchIfRef(ref);
|
||||||
@ -139,6 +148,7 @@ class AnnotationFactory {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { acroForm, pdfManager } = annotationGlobals;
|
||||||
const id =
|
const id =
|
||||||
ref instanceof Ref ? ref.toString() : `annot_${idFactory.createObjId()}`;
|
ref instanceof Ref ? ref.toString() : `annot_${idFactory.createObjId()}`;
|
||||||
|
|
||||||
@ -146,8 +156,6 @@ class AnnotationFactory {
|
|||||||
let subtype = dict.get("Subtype");
|
let subtype = dict.get("Subtype");
|
||||||
subtype = subtype instanceof Name ? subtype.name : null;
|
subtype = subtype instanceof Name ? subtype.name : null;
|
||||||
|
|
||||||
const acroFormDict = acroForm instanceof Dict ? acroForm : Dict.empty;
|
|
||||||
|
|
||||||
// Return the right annotation object based on the subtype and field type.
|
// Return the right annotation object based on the subtype and field type.
|
||||||
const parameters = {
|
const parameters = {
|
||||||
xref,
|
xref,
|
||||||
@ -155,16 +163,11 @@ class AnnotationFactory {
|
|||||||
dict,
|
dict,
|
||||||
subtype,
|
subtype,
|
||||||
id,
|
id,
|
||||||
pdfManager,
|
annotationGlobals,
|
||||||
acroForm: acroFormDict,
|
|
||||||
attachments,
|
|
||||||
xfaDatasets,
|
|
||||||
collectFields,
|
|
||||||
needAppearances:
|
needAppearances:
|
||||||
!collectFields && acroFormDict.get("NeedAppearances") === true,
|
pageIndex === null && acroForm.get("NeedAppearances") === true,
|
||||||
pageIndex,
|
pageIndex,
|
||||||
evaluatorOptions: pdfManager.evaluatorOptions,
|
evaluatorOptions: pdfManager.evaluatorOptions,
|
||||||
structTreeRoot,
|
|
||||||
pageRef,
|
pageRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -241,7 +244,7 @@ class AnnotationFactory {
|
|||||||
return new FileAttachmentAnnotation(parameters);
|
return new FileAttachmentAnnotation(parameters);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!collectFields) {
|
if (pageIndex === null) {
|
||||||
if (!subtype) {
|
if (!subtype) {
|
||||||
warn("Annotation is missing the required /Subtype.");
|
warn("Annotation is missing the required /Subtype.");
|
||||||
} else {
|
} else {
|
||||||
@ -392,6 +395,7 @@ class AnnotationFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async printNewAnnotations(
|
static async printNewAnnotations(
|
||||||
|
annotationGlobals,
|
||||||
evaluator,
|
evaluator,
|
||||||
task,
|
task,
|
||||||
annotations,
|
annotations,
|
||||||
@ -410,18 +414,28 @@ class AnnotationFactory {
|
|||||||
switch (annotation.annotationType) {
|
switch (annotation.annotationType) {
|
||||||
case AnnotationEditorType.FREETEXT:
|
case AnnotationEditorType.FREETEXT:
|
||||||
promises.push(
|
promises.push(
|
||||||
FreeTextAnnotation.createNewPrintAnnotation(xref, annotation, {
|
FreeTextAnnotation.createNewPrintAnnotation(
|
||||||
evaluator,
|
annotationGlobals,
|
||||||
task,
|
xref,
|
||||||
evaluatorOptions: options,
|
annotation,
|
||||||
})
|
{
|
||||||
|
evaluator,
|
||||||
|
task,
|
||||||
|
evaluatorOptions: options,
|
||||||
|
}
|
||||||
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case AnnotationEditorType.INK:
|
case AnnotationEditorType.INK:
|
||||||
promises.push(
|
promises.push(
|
||||||
InkAnnotation.createNewPrintAnnotation(xref, annotation, {
|
InkAnnotation.createNewPrintAnnotation(
|
||||||
evaluatorOptions: options,
|
annotationGlobals,
|
||||||
})
|
xref,
|
||||||
|
annotation,
|
||||||
|
{
|
||||||
|
evaluatorOptions: options,
|
||||||
|
}
|
||||||
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case AnnotationEditorType.STAMP:
|
case AnnotationEditorType.STAMP:
|
||||||
@ -438,10 +452,15 @@ class AnnotationFactory {
|
|||||||
image.imageStream = image.smaskStream = null;
|
image.imageStream = image.smaskStream = null;
|
||||||
}
|
}
|
||||||
promises.push(
|
promises.push(
|
||||||
StampAnnotation.createNewPrintAnnotation(xref, annotation, {
|
StampAnnotation.createNewPrintAnnotation(
|
||||||
image,
|
annotationGlobals,
|
||||||
evaluatorOptions: options,
|
xref,
|
||||||
})
|
annotation,
|
||||||
|
{
|
||||||
|
image,
|
||||||
|
evaluatorOptions: options,
|
||||||
|
}
|
||||||
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -570,7 +589,7 @@ function getTransformMatrix(rect, bbox, matrix) {
|
|||||||
|
|
||||||
class Annotation {
|
class Annotation {
|
||||||
constructor(params) {
|
constructor(params) {
|
||||||
const { dict, xref } = params;
|
const { dict, xref, annotationGlobals } = params;
|
||||||
|
|
||||||
this.setTitle(dict.get("T"));
|
this.setTitle(dict.get("T"));
|
||||||
this.setContents(dict.get("Contents"));
|
this.setContents(dict.get("Contents"));
|
||||||
@ -598,11 +617,15 @@ class Annotation {
|
|||||||
const isLocked = !!(this.flags & AnnotationFlag.LOCKED);
|
const isLocked = !!(this.flags & AnnotationFlag.LOCKED);
|
||||||
const isContentLocked = !!(this.flags & AnnotationFlag.LOCKEDCONTENTS);
|
const isContentLocked = !!(this.flags & AnnotationFlag.LOCKEDCONTENTS);
|
||||||
|
|
||||||
if (params.structTreeRoot) {
|
if (annotationGlobals.structTreeRoot) {
|
||||||
let structParent = dict.get("StructParent");
|
let structParent = dict.get("StructParent");
|
||||||
structParent =
|
structParent =
|
||||||
Number.isInteger(structParent) && structParent >= 0 ? structParent : -1;
|
Number.isInteger(structParent) && structParent >= 0 ? structParent : -1;
|
||||||
params.structTreeRoot.addAnnotationIdToPage(params.pageRef, structParent);
|
|
||||||
|
annotationGlobals.structTreeRoot.addAnnotationIdToPage(
|
||||||
|
params.pageRef,
|
||||||
|
structParent
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose public properties using a data object.
|
// Expose public properties using a data object.
|
||||||
@ -624,7 +647,7 @@ class Annotation {
|
|||||||
noHTML: isLocked && isContentLocked,
|
noHTML: isLocked && isContentLocked,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (params.collectFields) {
|
if (params.pageIndex !== null) {
|
||||||
// Fields can act as container for other fields and have
|
// Fields can act as container for other fields and have
|
||||||
// some actions even if no Annotation inherit from them.
|
// some actions even if no Annotation inherit from them.
|
||||||
// Those fields can be referenced by CO (calculation order).
|
// Those fields can be referenced by CO (calculation order).
|
||||||
@ -755,9 +778,11 @@ class Annotation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setDefaultAppearance(params) {
|
setDefaultAppearance(params) {
|
||||||
|
const { dict, annotationGlobals } = params;
|
||||||
|
|
||||||
const defaultAppearance =
|
const defaultAppearance =
|
||||||
getInheritableProperty({ dict: params.dict, key: "DA" }) ||
|
getInheritableProperty({ dict, key: "DA" }) ||
|
||||||
params.acroForm.get("DA");
|
annotationGlobals.acroForm.get("DA");
|
||||||
this._defaultAppearance =
|
this._defaultAppearance =
|
||||||
typeof defaultAppearance === "string" ? defaultAppearance : "";
|
typeof defaultAppearance === "string" ? defaultAppearance : "";
|
||||||
this.data.defaultAppearanceData = parseDefaultAppearance(
|
this.data.defaultAppearanceData = parseDefaultAppearance(
|
||||||
@ -1634,13 +1659,19 @@ class MarkupAnnotation extends Annotation {
|
|||||||
return { ref: annotationRef, data: buffer.join("") };
|
return { ref: annotationRef, data: buffer.join("") };
|
||||||
}
|
}
|
||||||
|
|
||||||
static async createNewPrintAnnotation(xref, annotation, params) {
|
static async createNewPrintAnnotation(
|
||||||
|
annotationGlobals,
|
||||||
|
xref,
|
||||||
|
annotation,
|
||||||
|
params
|
||||||
|
) {
|
||||||
const ap = await this.createNewAppearanceStream(annotation, xref, params);
|
const ap = await this.createNewAppearanceStream(annotation, xref, params);
|
||||||
const annotationDict = this.createNewDict(annotation, xref, { ap });
|
const annotationDict = this.createNewDict(annotation, xref, { ap });
|
||||||
|
|
||||||
const newAnnotation = new this.prototype.constructor({
|
const newAnnotation = new this.prototype.constructor({
|
||||||
dict: annotationDict,
|
dict: annotationDict,
|
||||||
xref,
|
xref,
|
||||||
|
annotationGlobals,
|
||||||
evaluatorOptions: params.evaluatorOptions,
|
evaluatorOptions: params.evaluatorOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1656,7 +1687,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
constructor(params) {
|
constructor(params) {
|
||||||
super(params);
|
super(params);
|
||||||
|
|
||||||
const { dict, xref } = params;
|
const { dict, xref, annotationGlobals } = params;
|
||||||
const data = this.data;
|
const data = this.data;
|
||||||
this._needAppearances = params.needAppearances;
|
this._needAppearances = params.needAppearances;
|
||||||
|
|
||||||
@ -1683,12 +1714,13 @@ class WidgetAnnotation extends Annotation {
|
|||||||
});
|
});
|
||||||
data.defaultFieldValue = this._decodeFormValue(defaultFieldValue);
|
data.defaultFieldValue = this._decodeFormValue(defaultFieldValue);
|
||||||
|
|
||||||
if (fieldValue === undefined && params.xfaDatasets) {
|
if (fieldValue === undefined && annotationGlobals.xfaDatasets) {
|
||||||
// Try to figure out if we have something in the xfa dataset.
|
// Try to figure out if we have something in the xfa dataset.
|
||||||
const path = this._title.str;
|
const path = this._title.str;
|
||||||
if (path) {
|
if (path) {
|
||||||
this._hasValueFromXFA = true;
|
this._hasValueFromXFA = true;
|
||||||
data.fieldValue = fieldValue = params.xfaDatasets.getValue(path);
|
data.fieldValue = fieldValue =
|
||||||
|
annotationGlobals.xfaDatasets.getValue(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1711,7 +1743,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
data.fieldType = fieldType instanceof Name ? fieldType.name : null;
|
data.fieldType = fieldType instanceof Name ? fieldType.name : null;
|
||||||
|
|
||||||
const localResources = getInheritableProperty({ dict, key: "DR" });
|
const localResources = getInheritableProperty({ dict, key: "DR" });
|
||||||
const acroFormResources = params.acroForm.get("DR");
|
const acroFormResources = annotationGlobals.acroForm.get("DR");
|
||||||
const appearanceResources = this.appearance?.dict.get("Resources");
|
const appearanceResources = this.appearance?.dict.get("Resources");
|
||||||
|
|
||||||
this._fieldResources = {
|
this._fieldResources = {
|
||||||
@ -3208,22 +3240,20 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_processPushButton(params) {
|
_processPushButton(params) {
|
||||||
if (
|
const { dict, annotationGlobals } = params;
|
||||||
!params.dict.has("A") &&
|
|
||||||
!params.dict.has("AA") &&
|
if (!dict.has("A") && !dict.has("AA") && !this.data.alternativeText) {
|
||||||
!this.data.alternativeText
|
|
||||||
) {
|
|
||||||
warn("Push buttons without action dictionaries are not supported");
|
warn("Push buttons without action dictionaries are not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data.isTooltipOnly = !params.dict.has("A") && !params.dict.has("AA");
|
this.data.isTooltipOnly = !dict.has("A") && !dict.has("AA");
|
||||||
|
|
||||||
Catalog.parseDestDictionary({
|
Catalog.parseDestDictionary({
|
||||||
destDict: params.dict,
|
destDict: dict,
|
||||||
resultObj: this.data,
|
resultObj: this.data,
|
||||||
docBaseUrl: params.pdfManager.docBaseUrl,
|
docBaseUrl: annotationGlobals.baseUrl,
|
||||||
docAttachments: params.attachments,
|
docAttachments: annotationGlobals.attachments,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3581,9 +3611,10 @@ class LinkAnnotation extends Annotation {
|
|||||||
constructor(params) {
|
constructor(params) {
|
||||||
super(params);
|
super(params);
|
||||||
|
|
||||||
|
const { dict, annotationGlobals } = params;
|
||||||
this.data.annotationType = AnnotationType.LINK;
|
this.data.annotationType = AnnotationType.LINK;
|
||||||
|
|
||||||
const quadPoints = getQuadPoints(params.dict, this.rectangle);
|
const quadPoints = getQuadPoints(dict, this.rectangle);
|
||||||
if (quadPoints) {
|
if (quadPoints) {
|
||||||
this.data.quadPoints = quadPoints;
|
this.data.quadPoints = quadPoints;
|
||||||
}
|
}
|
||||||
@ -3592,10 +3623,10 @@ class LinkAnnotation extends Annotation {
|
|||||||
this.data.borderColor ||= this.data.color;
|
this.data.borderColor ||= this.data.color;
|
||||||
|
|
||||||
Catalog.parseDestDictionary({
|
Catalog.parseDestDictionary({
|
||||||
destDict: params.dict,
|
destDict: dict,
|
||||||
resultObj: this.data,
|
resultObj: this.data,
|
||||||
docBaseUrl: params.pdfManager.docBaseUrl,
|
docBaseUrl: annotationGlobals.baseUrl,
|
||||||
docAttachments: params.attachments,
|
docAttachments: annotationGlobals.attachments,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ class Catalog {
|
|||||||
Catalog.parseDestDictionary({
|
Catalog.parseDestDictionary({
|
||||||
destDict: outlineDict,
|
destDict: outlineDict,
|
||||||
resultObj: data,
|
resultObj: data,
|
||||||
docBaseUrl: this.pdfManager.docBaseUrl,
|
docBaseUrl: this.baseUrl,
|
||||||
docAttachments: this.attachments,
|
docAttachments: this.attachments,
|
||||||
});
|
});
|
||||||
const title = outlineDict.get("Title");
|
const title = outlineDict.get("Title");
|
||||||
@ -1405,7 +1405,7 @@ class Catalog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, "baseUrl", null);
|
return shadow(this, "baseUrl", this.pdfManager.docBaseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1423,19 +1423,16 @@ class Catalog {
|
|||||||
* Helper function used to parse the contents of destination dictionaries.
|
* Helper function used to parse the contents of destination dictionaries.
|
||||||
* @param {ParseDestDictionaryParameters} params
|
* @param {ParseDestDictionaryParameters} params
|
||||||
*/
|
*/
|
||||||
static parseDestDictionary(params) {
|
static parseDestDictionary({
|
||||||
const destDict = params.destDict;
|
destDict,
|
||||||
|
resultObj,
|
||||||
|
docBaseUrl = null,
|
||||||
|
docAttachments = null,
|
||||||
|
}) {
|
||||||
if (!(destDict instanceof Dict)) {
|
if (!(destDict instanceof Dict)) {
|
||||||
warn("parseDestDictionary: `destDict` must be a dictionary.");
|
warn("parseDestDictionary: `destDict` must be a dictionary.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resultObj = params.resultObj;
|
|
||||||
if (typeof resultObj !== "object") {
|
|
||||||
warn("parseDestDictionary: `resultObj` must be an object.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const docBaseUrl = params.docBaseUrl || null;
|
|
||||||
const docAttachments = params.docAttachments || null;
|
|
||||||
|
|
||||||
let action = destDict.get("A"),
|
let action = destDict.get("A"),
|
||||||
url,
|
url,
|
||||||
|
@ -426,9 +426,12 @@ class Page {
|
|||||||
|
|
||||||
let newAnnotationsPromise = Promise.resolve(null);
|
let newAnnotationsPromise = Promise.resolve(null);
|
||||||
if (newAnnotationsByPage) {
|
if (newAnnotationsByPage) {
|
||||||
let imagePromises;
|
|
||||||
const newAnnotations = newAnnotationsByPage.get(this.pageIndex);
|
const newAnnotations = newAnnotationsByPage.get(this.pageIndex);
|
||||||
if (newAnnotations) {
|
if (newAnnotations) {
|
||||||
|
const annotationGlobalsPromise =
|
||||||
|
this.pdfManager.ensureDoc("annotationGlobals");
|
||||||
|
let imagePromises;
|
||||||
|
|
||||||
// An annotation can contain a reference to a bitmap, but this bitmap
|
// An annotation can contain a reference to a bitmap, but this bitmap
|
||||||
// is defined in another annotation. So we need to find this annotation
|
// is defined in another annotation. So we need to find this annotation
|
||||||
// and generate the bitmap.
|
// and generate the bitmap.
|
||||||
@ -467,11 +470,21 @@ class Page {
|
|||||||
|
|
||||||
deletedAnnotations = new RefSet();
|
deletedAnnotations = new RefSet();
|
||||||
this.#replaceIdByRef(newAnnotations, deletedAnnotations, null);
|
this.#replaceIdByRef(newAnnotations, deletedAnnotations, null);
|
||||||
newAnnotationsPromise = AnnotationFactory.printNewAnnotations(
|
|
||||||
partialEvaluator,
|
newAnnotationsPromise = annotationGlobalsPromise.then(
|
||||||
task,
|
annotationGlobals => {
|
||||||
newAnnotations,
|
if (!annotationGlobals) {
|
||||||
imagePromises
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AnnotationFactory.printNewAnnotations(
|
||||||
|
annotationGlobals,
|
||||||
|
partialEvaluator,
|
||||||
|
task,
|
||||||
|
newAnnotations,
|
||||||
|
imagePromises
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -663,7 +676,7 @@ class Page {
|
|||||||
async getAnnotationsData(handler, task, intent) {
|
async getAnnotationsData(handler, task, intent) {
|
||||||
const annotations = await this._parsedAnnotations;
|
const annotations = await this._parsedAnnotations;
|
||||||
if (annotations.length === 0) {
|
if (annotations.length === 0) {
|
||||||
return [];
|
return annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
const annotationsData = [],
|
const annotationsData = [],
|
||||||
@ -723,16 +736,25 @@ class Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get _parsedAnnotations() {
|
get _parsedAnnotations() {
|
||||||
const parsedAnnotations = this.pdfManager
|
const promise = this.pdfManager
|
||||||
.ensure(this, "annotations")
|
.ensure(this, "annotations")
|
||||||
.then(() => {
|
.then(async annots => {
|
||||||
|
if (annots.length === 0) {
|
||||||
|
return annots;
|
||||||
|
}
|
||||||
|
const annotationGlobals =
|
||||||
|
await this.pdfManager.ensureDoc("annotationGlobals");
|
||||||
|
if (!annotationGlobals) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const annotationPromises = [];
|
const annotationPromises = [];
|
||||||
for (const annotationRef of this.annotations) {
|
for (const annotationRef of annots) {
|
||||||
annotationPromises.push(
|
annotationPromises.push(
|
||||||
AnnotationFactory.create(
|
AnnotationFactory.create(
|
||||||
this.xref,
|
this.xref,
|
||||||
annotationRef,
|
annotationRef,
|
||||||
this.pdfManager,
|
annotationGlobals,
|
||||||
this._localIdFactory,
|
this._localIdFactory,
|
||||||
/* collectFields */ false,
|
/* collectFields */ false,
|
||||||
this.ref
|
this.ref
|
||||||
@ -743,34 +765,28 @@ class Page {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(annotationPromises).then(function (annotations) {
|
const sortedAnnotations = [];
|
||||||
if (annotations.length === 0) {
|
let popupAnnotations;
|
||||||
return annotations;
|
// Ensure that PopupAnnotations are handled last, since they depend on
|
||||||
|
// their parent Annotation in the display layer; fixes issue 11362.
|
||||||
|
for (const annotation of await Promise.all(annotationPromises)) {
|
||||||
|
if (!annotation) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (annotation instanceof PopupAnnotation) {
|
||||||
|
(popupAnnotations ||= []).push(annotation);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sortedAnnotations.push(annotation);
|
||||||
|
}
|
||||||
|
if (popupAnnotations) {
|
||||||
|
sortedAnnotations.push(...popupAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
const sortedAnnotations = [];
|
return sortedAnnotations;
|
||||||
let popupAnnotations;
|
|
||||||
// Ensure that PopupAnnotations are handled last, since they depend on
|
|
||||||
// their parent Annotation in the display layer; fixes issue 11362.
|
|
||||||
for (const annotation of annotations) {
|
|
||||||
if (!annotation) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (annotation instanceof PopupAnnotation) {
|
|
||||||
(popupAnnotations ||= []).push(annotation);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sortedAnnotations.push(annotation);
|
|
||||||
}
|
|
||||||
if (popupAnnotations) {
|
|
||||||
sortedAnnotations.push(...popupAnnotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sortedAnnotations;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return shadow(this, "_parsedAnnotations", parsedAnnotations);
|
return shadow(this, "_parsedAnnotations", promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
get jsActions() {
|
get jsActions() {
|
||||||
@ -1695,10 +1711,7 @@ class PDFDocument {
|
|||||||
: clearGlobalCaches();
|
: clearGlobalCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#collectFieldObjects(name, fieldRef, promises, annotationGlobals) {
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_collectFieldObjects(name, fieldRef, promises) {
|
|
||||||
const field = this.xref.fetchIfRef(fieldRef);
|
const field = this.xref.fetchIfRef(fieldRef);
|
||||||
if (field.has("T")) {
|
if (field.has("T")) {
|
||||||
const partName = stringToPDFString(field.get("T"));
|
const partName = stringToPDFString(field.get("T"));
|
||||||
@ -1712,22 +1725,21 @@ class PDFDocument {
|
|||||||
AnnotationFactory.create(
|
AnnotationFactory.create(
|
||||||
this.xref,
|
this.xref,
|
||||||
fieldRef,
|
fieldRef,
|
||||||
this.pdfManager,
|
annotationGlobals,
|
||||||
this._localIdFactory,
|
this._localIdFactory,
|
||||||
/* collectFields */ true,
|
/* collectFields */ true,
|
||||||
/* pageRef */ null
|
/* pageRef */ null
|
||||||
)
|
)
|
||||||
.then(annotation => annotation?.getFieldObject())
|
.then(annotation => annotation?.getFieldObject())
|
||||||
.catch(function (reason) {
|
.catch(function (reason) {
|
||||||
warn(`_collectFieldObjects: "${reason}".`);
|
warn(`#collectFieldObjects: "${reason}".`);
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (field.has("Kids")) {
|
if (field.has("Kids")) {
|
||||||
const kids = field.get("Kids");
|
for (const kid of field.get("Kids")) {
|
||||||
for (const kid of kids) {
|
this.#collectFieldObjects(name, kid, promises, annotationGlobals);
|
||||||
this._collectFieldObjects(name, kid, promises);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1737,29 +1749,41 @@ class PDFDocument {
|
|||||||
return shadow(this, "fieldObjects", Promise.resolve(null));
|
return shadow(this, "fieldObjects", Promise.resolve(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
const allFields = Object.create(null);
|
const promise = this.pdfManager
|
||||||
const fieldPromises = new Map();
|
.ensureDoc("annotationGlobals")
|
||||||
for (const fieldRef of this.catalog.acroForm.get("Fields")) {
|
.then(async annotationGlobals => {
|
||||||
this._collectFieldObjects("", fieldRef, fieldPromises);
|
if (!annotationGlobals) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const allPromises = [];
|
const allFields = Object.create(null);
|
||||||
for (const [name, promises] of fieldPromises) {
|
const fieldPromises = new Map();
|
||||||
allPromises.push(
|
for (const fieldRef of this.catalog.acroForm.get("Fields")) {
|
||||||
Promise.all(promises).then(fields => {
|
this.#collectFieldObjects(
|
||||||
fields = fields.filter(field => !!field);
|
"",
|
||||||
if (fields.length > 0) {
|
fieldRef,
|
||||||
allFields[name] = fields;
|
fieldPromises,
|
||||||
}
|
annotationGlobals
|
||||||
})
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return shadow(
|
const allPromises = [];
|
||||||
this,
|
for (const [name, promises] of fieldPromises) {
|
||||||
"fieldObjects",
|
allPromises.push(
|
||||||
Promise.all(allPromises).then(() => allFields)
|
Promise.all(promises).then(fields => {
|
||||||
);
|
fields = fields.filter(field => !!field);
|
||||||
|
if (fields.length > 0) {
|
||||||
|
allFields[name] = fields;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(allPromises);
|
||||||
|
return allFields;
|
||||||
|
});
|
||||||
|
|
||||||
|
return shadow(this, "fieldObjects", promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasJSActions() {
|
get hasJSActions() {
|
||||||
@ -1809,6 +1833,14 @@ class PDFDocument {
|
|||||||
}
|
}
|
||||||
return shadow(this, "calculationOrderIds", ids);
|
return shadow(this, "calculationOrderIds", ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get annotationGlobals() {
|
||||||
|
return shadow(
|
||||||
|
this,
|
||||||
|
"annotationGlobals",
|
||||||
|
AnnotationFactory.createGlobals(this.pdfManager)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Page, PDFDocument };
|
export { Page, PDFDocument };
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
import {
|
import {
|
||||||
createValidAbsoluteUrl,
|
createValidAbsoluteUrl,
|
||||||
FeatureTest,
|
FeatureTest,
|
||||||
shadow,
|
|
||||||
unreachable,
|
unreachable,
|
||||||
warn,
|
warn,
|
||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
@ -62,8 +61,7 @@ class BasePdfManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get docBaseUrl() {
|
get docBaseUrl() {
|
||||||
const catalog = this.pdfDocument.catalog;
|
return this._docBaseUrl;
|
||||||
return shadow(this, "docBaseUrl", catalog.baseUrl || this._docBaseUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureDoc(prop, args) {
|
ensureDoc(prop, args) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user