Compare commits

...

5 Commits

Author SHA1 Message Date
calixteman
4b1875c8c0
Merge pull request #19825 from calixteman/bug1961107
Avoid to create any subarrays when optimizing 'save, transform, constructPath, restore' (bug 1961107)
2025-04-17 19:42:28 +02:00
Calixte Denizet
d7cbda6cb5 Avoid to create any subarrays when optimizing 'save, transform, constructPath, restore' (bug 1961107)
Removing those `subarray`calls helps to improve performance by a factor 6 on Linux and by a factor of 3
on Windows 11.
2025-04-17 19:14:01 +02:00
Jonas Jenwald
f1e20cd668
Merge pull request #19824 from Snuffleupagus/getStructTree-catch-errors
Improve error handling when parsing page-structTrees
2025-04-17 15:21:55 +02:00
Jonas Jenwald
bf553f22da Ensure that the /P-entry is actually a dictionary in StructTreePage.prototype.addNode
This may fix issue 19822, but without a test-case it's simply impossible to know for sure.
2025-04-17 14:01:53 +02:00
Jonas Jenwald
76f23ce3b5 Catch, and ignore, errors during Page.prototype.getStructTree
This way any errors thrown during parsing of the page-structTree will not be forwarded to the viewer.
2025-04-17 13:57:30 +02:00
5 changed files with 30 additions and 23 deletions

View File

@ -707,10 +707,18 @@ class Page {
// Ensure that the structTree will contain the page's annotations.
await this._parsedAnnotations;
const structTree = await this.pdfManager.ensure(this, "_parseStructTree", [
structTreeRoot,
]);
return this.pdfManager.ensure(structTree, "serializable");
try {
const structTree = await this.pdfManager.ensure(
this,
"_parseStructTree",
[structTreeRoot]
);
const data = await this.pdfManager.ensure(structTree, "serializable");
return data;
} catch (ex) {
warn(`getStructTree: "${ex}".`);
return null;
}
}
/**

View File

@ -745,12 +745,9 @@ class Commands {
add(cmd, args) {
if (args) {
const [a, b, c, d, e, f] = this.currentTransform;
const { currentTransform } = this;
for (let i = 0, ii = args.length; i < ii; i += 2) {
const x = args[i];
const y = args[i + 1];
args[i] = a * x + c * y + e;
args[i + 1] = b * x + d * y + f;
Util.applyTransform(args, currentTransform, i);
}
this.cmds.push(`${cmd}${args.join(" ")}`);
} else {

View File

@ -524,11 +524,11 @@ addState(
switch (buffer[k++]) {
case DrawOPS.moveTo:
case DrawOPS.lineTo:
Util.applyTransform(buffer.subarray(k), transform);
Util.applyTransform(buffer, transform, k);
k += 2;
break;
case DrawOPS.curveTo:
Util.applyTransformToBezier(buffer.subarray(k), transform);
Util.applyTransformToBezier(buffer, transform, k);
k += 6;
break;
}

View File

@ -757,7 +757,10 @@ class StructTreePage {
const parent = dict.get("P");
if (!parent || isName(parent.get("Type"), "StructTreeRoot")) {
if (
!(parent instanceof Dict) ||
isName(parent.get("Type"), "StructTreeRoot")
) {
if (!this.addTopLevelNode(dict, element)) {
map.delete(dict);
}

View File

@ -730,15 +730,14 @@ class Util {
}
// For 2d affine transforms
static applyTransform(p, m) {
const p0 = p[0];
const p1 = p[1];
p[0] = p0 * m[0] + p1 * m[2] + m[4];
p[1] = p0 * m[1] + p1 * m[3] + m[5];
static applyTransform(p, m, pos = 0) {
const p0 = p[pos];
const p1 = p[pos + 1];
p[pos] = p0 * m[0] + p1 * m[2] + m[4];
p[pos + 1] = p0 * m[1] + p1 * m[3] + m[5];
}
// For 2d affine transforms
static applyTransformToBezier(p, transform) {
static applyTransformToBezier(p, transform, pos = 0) {
const m0 = transform[0];
const m1 = transform[1];
const m2 = transform[2];
@ -746,10 +745,10 @@ class Util {
const m4 = transform[4];
const m5 = transform[5];
for (let i = 0; i < 6; i += 2) {
const pI = p[i];
const pI1 = p[i + 1];
p[i] = pI * m0 + pI1 * m2 + m4;
p[i + 1] = pI * m1 + pI1 * m3 + m5;
const pI = p[pos + i];
const pI1 = p[pos + i + 1];
p[pos + i] = pI * m0 + pI1 * m2 + m4;
p[pos + i + 1] = pI * m1 + pI1 * m3 + m5;
}
}