Merge pull request #19889 from Snuffleupagus/loadXfaResources

Slightly re-factor how we pre-load fonts and images in XFA documents
This commit is contained in:
Tim van der Meij 2025-05-04 14:28:11 +02:00 committed by GitHub
commit 06f44916c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 44 additions and 61 deletions

View File

@ -1237,7 +1237,7 @@ class PDFDocument {
return this.xfaFactory ? this.xfaFactory.getPages() : null;
}
async loadXfaImages() {
async #loadXfaImages() {
const xfaImages = await this.pdfManager.ensureCatalog("xfaImages");
if (!xfaImages) {
return;
@ -1245,7 +1245,7 @@ class PDFDocument {
this.xfaFactory.setImages(xfaImages);
}
async loadXfaFonts(handler, task) {
async #loadXfaFonts(handler, task) {
const acroForm = await this.pdfManager.ensureCatalog("acroForm");
if (!acroForm) {
return;
@ -1264,18 +1264,19 @@ class PDFDocument {
const options = Object.assign(
Object.create(null),
this.pdfManager.evaluatorOptions
this.pdfManager.evaluatorOptions,
{ useSystemFonts: false }
);
options.useSystemFonts = false;
const { builtInCMapCache, fontCache, standardFontDataCache } = this.catalog;
const partialEvaluator = new PartialEvaluator({
xref: this.xref,
handler,
pageIndex: -1,
idFactory: this._globalIdFactory,
fontCache: this.catalog.fontCache,
builtInCMapCache: this.catalog.builtInCMapCache,
standardFontDataCache: this.catalog.standardFontDataCache,
fontCache,
builtInCMapCache,
standardFontDataCache,
options,
});
const operatorList = new OperatorList();
@ -1292,6 +1293,23 @@ class PDFDocument {
},
};
const parseFont = (fontName, fallbackFontDict, cssFontInfo) =>
partialEvaluator
.handleSetFont(
resources,
[Name.get(fontName), 1],
/* fontRef = */ null,
operatorList,
task,
initialState,
fallbackFontDict,
cssFontInfo
)
.catch(reason => {
warn(`loadXfaFonts: "${reason}".`);
return null;
});
const promises = [];
for (const [fontName, font] of fontRes) {
const descriptor = font.get("FontDescriptor");
@ -1313,21 +1331,7 @@ class PDFDocument {
continue;
}
promises.push(
partialEvaluator
.handleSetFont(
resources,
[Name.get(fontName), 1],
/* fontRef = */ null,
operatorList,
task,
initialState,
/* fallbackFontDict = */ null,
/* cssFontInfo = */ cssFontInfo
)
.catch(function (reason) {
warn(`loadXfaFonts: "${reason}".`);
return null;
})
parseFont(fontName, /* fallbackFontDict = */ null, cssFontInfo)
);
}
@ -1365,28 +1369,13 @@ class PDFDocument {
{ name: "BoldItalic", fontWeight: 700, italicAngle: 12 },
]) {
const name = `${missing}-${fontInfo.name}`;
const dict = getXfaFontDict(name);
promises.push(
partialEvaluator
.handleSetFont(
resources,
[Name.get(name), 1],
/* fontRef = */ null,
operatorList,
task,
initialState,
/* fallbackFontDict = */ dict,
/* cssFontInfo = */ {
fontFamily: missing,
fontWeight: fontInfo.fontWeight,
italicAngle: fontInfo.italicAngle,
}
)
.catch(function (reason) {
warn(`loadXfaFonts: "${reason}".`);
return null;
})
parseFont(name, getXfaFontDict(name), {
fontFamily: missing,
fontWeight: fontInfo.fontWeight,
italicAngle: fontInfo.italicAngle,
})
);
}
}
@ -1395,6 +1384,15 @@ class PDFDocument {
this.xfaFactory.appendFonts(pdfFonts, reallyMissingFonts);
}
loadXfaResources(handler, task) {
return Promise.all([
this.#loadXfaFonts(handler, task).catch(() => {
// Ignore errors, to allow the document to load.
}),
this.#loadXfaImages(),
]);
}
serializeXfaData(annotationStorage) {
return this.xfaFactory
? this.xfaFactory.serializeData(annotationStorage)

View File

@ -115,14 +115,6 @@ class BasePdfManager {
return this.pdfDocument.fontFallback(id, handler);
}
loadXfaFonts(handler, task) {
return this.pdfDocument.loadXfaFonts(handler, task);
}
loadXfaImages() {
return this.pdfDocument.loadXfaImages();
}
cleanup(manuallyTriggered = false) {
return this.pdfDocument.cleanup(manuallyTriggered);
}

View File

@ -170,18 +170,11 @@ class WorkerMessageHandler {
const isPureXfa = await pdfManager.ensureDoc("isPureXfa");
if (isPureXfa) {
const task = new WorkerTask("loadXfaFonts");
const task = new WorkerTask("loadXfaResources");
startWorkerTask(task);
await Promise.all([
pdfManager
.loadXfaFonts(handler, task)
.catch(reason => {
// Ignore errors, to allow the document to load.
})
.then(() => finishWorkerTask(task)),
pdfManager.loadXfaImages(),
]);
await pdfManager.ensureDoc("loadXfaResources", [handler, task]);
finishWorkerTask(task);
}
const [numPages, fingerprints] = await Promise.all([

View File

@ -43,7 +43,7 @@ class XFAFactory {
}
isValid() {
return this.root && this.form;
return !!(this.root && this.form);
}
/**