1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 14:48:08 +02:00

[api-minor] Use a Path2D when doing a path operation in the canvas (bug 1946953)

With this patch, all the paths components are collected in the worker until a path
operation is met (i.e., stroke, fill, ...).
Then in the canvas a Path2D is created and will replace the path data transfered from the worker,
this way when rescaling, the Path2D can be reused.
In term of performances, using Path2D is very slightly improving speed when scaling the canvas.
This commit is contained in:
Calixte Denizet 2025-03-19 20:39:02 +01:00
parent a229914b46
commit be1f5671bb
10 changed files with 367 additions and 374 deletions

View file

@ -0,0 +1 @@
https://bugzilla.mozilla.org/attachment.cgi?id=9464841

View file

@ -11995,5 +11995,15 @@
"md5": "9993aa298c0214a3d3ff5f90ce0d40bb",
"rounds": 1,
"type": "eq"
},
{
"id": "bug1946953",
"file": "pdfs/bug1946953.pdf",
"md5": "a71fb64e348b9c7161945e48e75c6681",
"rounds": 1,
"link": true,
"firstPage": 1,
"lastPage": 1,
"type": "eq"
}
]

View file

@ -26,6 +26,7 @@ import {
AnnotationFieldFlag,
AnnotationFlag,
AnnotationType,
DrawOPS,
OPS,
RenderingIntentFlag,
stringToBytes,
@ -4285,14 +4286,13 @@ describe("annotation", function () {
null
);
expect(opList.fnArray.length).toEqual(16);
expect(opList.fnArray.length).toEqual(15);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.save,
OPS.transform,
OPS.constructPath,
OPS.clip,
OPS.endPath,
OPS.constructPath,
OPS.beginText,
OPS.setFillRGBColor,
OPS.setCharSpacing,
@ -4659,7 +4659,7 @@ describe("annotation", function () {
null
);
expect(opList.argsArray.length).toEqual(8);
expect(opList.argsArray.length).toEqual(7);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setLineWidth,
@ -4667,7 +4667,6 @@ describe("annotation", function () {
OPS.setLineJoin,
OPS.setStrokeRGBColor,
OPS.constructPath,
OPS.stroke,
OPS.endAnnotation,
]);
@ -4680,10 +4679,23 @@ describe("annotation", function () {
// Color.
expect(opList.argsArray[4]).toEqual(new Uint8ClampedArray([0, 255, 0]));
// Path.
expect(opList.argsArray[5][0]).toEqual([OPS.moveTo, OPS.curveTo]);
expect(opList.argsArray[5][1]).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
expect(opList.argsArray[5][0]).toEqual(OPS.stroke);
expect(opList.argsArray[5][1]).toEqual([
new Float32Array([
DrawOPS.moveTo,
1,
2,
DrawOPS.curveTo,
3,
4,
5,
6,
7,
8,
]),
]);
// Min-max.
expect(opList.argsArray[5][2]).toEqual([1, 2, 1, 2]);
expect(opList.argsArray[5][2]).toEqual(new Float32Array([1, 2, 7, 8]));
});
});
@ -4831,13 +4843,12 @@ describe("annotation", function () {
null
);
expect(opList.argsArray.length).toEqual(6);
expect(opList.argsArray.length).toEqual(5);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.setGState,
OPS.constructPath,
OPS.eoFill,
OPS.endAnnotation,
]);
});
@ -4953,13 +4964,12 @@ describe("annotation", function () {
null
);
expect(opList.argsArray.length).toEqual(6);
expect(opList.argsArray.length).toEqual(5);
expect(opList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.setFillRGBColor,
OPS.setGState,
OPS.constructPath,
OPS.fill,
OPS.endAnnotation,
]);
});

View file

@ -17,6 +17,7 @@ import {
AnnotationEditorType,
AnnotationMode,
AnnotationType,
DrawOPS,
ImageKind,
InvalidPDFException,
isNodeJS,
@ -794,17 +795,25 @@ describe("api", function () {
OPS.setLineWidth,
OPS.setStrokeRGBColor,
OPS.constructPath,
OPS.closeStroke,
]);
expect(opList.argsArray).toEqual([
[0.5],
new Uint8ClampedArray([255, 0, 0]),
[
[OPS.moveTo, OPS.lineTo],
[0, 9.75, 0.5, 9.75],
[0, 9.75, 0.5, 9.75],
OPS.closeStroke,
[
new Float32Array([
DrawOPS.moveTo,
0,
9.75,
DrawOPS.lineTo,
0.5,
9.75,
DrawOPS.closePath,
]),
],
new Float32Array([0, 9.75, 0.5, 9.75]),
],
null,
]);
expect(opList.lastChunk).toEqual(true);
@ -4236,8 +4245,8 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
const opListAnnotEnable = await pdfPage.getOperatorList({
annotationMode: AnnotationMode.ENABLE,
});
expect(opListAnnotEnable.fnArray.length).toBeGreaterThan(140);
expect(opListAnnotEnable.argsArray.length).toBeGreaterThan(140);
expect(opListAnnotEnable.fnArray.length).toBeGreaterThan(130);
expect(opListAnnotEnable.argsArray.length).toBeGreaterThan(130);
expect(opListAnnotEnable.lastChunk).toEqual(true);
expect(opListAnnotEnable.separateAnnots).toEqual({
form: false,
@ -4270,8 +4279,8 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
const opListAnnotEnableStorage = await pdfPage.getOperatorList({
annotationMode: AnnotationMode.ENABLE_STORAGE,
});
expect(opListAnnotEnableStorage.fnArray.length).toBeGreaterThan(170);
expect(opListAnnotEnableStorage.argsArray.length).toBeGreaterThan(170);
expect(opListAnnotEnableStorage.fnArray.length).toBeGreaterThan(150);
expect(opListAnnotEnableStorage.argsArray.length).toBeGreaterThan(150);
expect(opListAnnotEnableStorage.lastChunk).toEqual(true);
expect(opListAnnotEnableStorage.separateAnnots).toEqual({
form: false,

View file

@ -74,8 +74,8 @@ describe("evaluator", function () {
);
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
expect(result.fnArray.length).toEqual(1);
expect(result.fnArray[0]).toEqual(OPS.fill);
expect(result.argsArray[0]).toEqual(null);
expect(result.fnArray[0]).toEqual(OPS.constructPath);
expect(result.argsArray[0]).toEqual([OPS.fill, [null], null]);
});
it("should handle one operation", async function () {
@ -130,9 +130,14 @@ describe("evaluator", function () {
);
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
expect(result.fnArray.length).toEqual(3);
expect(result.fnArray[0]).toEqual(OPS.fill);
expect(result.fnArray[1]).toEqual(OPS.fill);
expect(result.fnArray[2]).toEqual(OPS.fill);
expect(result.fnArray).toEqual([
OPS.constructPath,
OPS.constructPath,
OPS.constructPath,
]);
expect(result.argsArray[0][0]).toEqual(OPS.fill);
expect(result.argsArray[1][0]).toEqual(OPS.fill);
expect(result.argsArray[2][0]).toEqual(OPS.fill);
});
it("should handle three glued operations #2", async function () {
@ -145,10 +150,14 @@ describe("evaluator", function () {
resources
);
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
expect(result.fnArray.length).toEqual(3);
expect(result.fnArray[0]).toEqual(OPS.eoFillStroke);
expect(result.fnArray[1]).toEqual(OPS.fillStroke);
expect(result.fnArray[2]).toEqual(OPS.eoFill);
expect(result.fnArray).toEqual([
OPS.constructPath,
OPS.constructPath,
OPS.constructPath,
]);
expect(result.argsArray[0][0]).toEqual(OPS.eoFillStroke);
expect(result.argsArray[1][0]).toEqual(OPS.fillStroke);
expect(result.argsArray[2][0]).toEqual(OPS.eoFill);
});
it("should handle glued operations and operands", async function () {
@ -160,7 +169,7 @@ describe("evaluator", function () {
);
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
expect(result.fnArray.length).toEqual(2);
expect(result.fnArray[0]).toEqual(OPS.fill);
expect(result.fnArray[0]).toEqual(OPS.constructPath);
expect(result.fnArray[1]).toEqual(OPS.setTextRise);
expect(result.argsArray.length).toEqual(2);
expect(result.argsArray[1].length).toEqual(1);
@ -178,13 +187,13 @@ describe("evaluator", function () {
expect(result.fnArray.length).toEqual(3);
expect(result.fnArray[0]).toEqual(OPS.setFlatness);
expect(result.fnArray[1]).toEqual(OPS.setRenderingIntent);
expect(result.fnArray[2]).toEqual(OPS.endPath);
expect(result.fnArray[2]).toEqual(OPS.constructPath);
expect(result.argsArray.length).toEqual(3);
expect(result.argsArray[0].length).toEqual(1);
expect(result.argsArray[0][0]).toEqual(true);
expect(result.argsArray[1].length).toEqual(1);
expect(result.argsArray[1][0]).toEqual(false);
expect(result.argsArray[2]).toEqual(null);
expect(result.argsArray[2]).toEqual([OPS.endPath, [null], null]);
});
});