Skip to content

Commit 673f19b

Browse files
authored
Merge pull request #19043 from nicolo-ribaudo/compute-bounding-boxes
Add logic to track rendering area of various PDF ops
2 parents e20ee99 + 6a22da9 commit 673f19b

17 files changed

Lines changed: 2558 additions & 212 deletions

extensions/chromium/preferences_schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@
238238
"description": "Enable creation of comment annotations.",
239239
"type": "boolean",
240240
"default": false
241+
},
242+
"enableOptimizedPartialRendering": {
243+
"description": "Enable tracking of PDF operations to optimize partial rendering.",
244+
"type": "boolean",
245+
"default": false
241246
}
242247
}
243248
}

src/display/api.js

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import {
6060
NodeStandardFontDataFactory,
6161
NodeWasmFactory,
6262
} from "display-node_utils";
63+
import { CanvasDependencyTracker } from "./canvas_dependency_tracker.js";
6364
import { CanvasGraphics } from "./canvas.js";
6465
import { DOMCanvasFactory } from "./canvas_factory.js";
6566
import { DOMCMapReaderFactory } from "display-cmap_reader_factory";
@@ -1239,6 +1240,10 @@ class PDFDocumentProxy {
12391240
* annotation ids with canvases used to render them.
12401241
* @property {PrintAnnotationStorage} [printAnnotationStorage]
12411242
* @property {boolean} [isEditing] - Render the page in editing mode.
1243+
* @property {boolean} [recordOperations] - Record the dependencies and bounding
1244+
* boxes of all PDF operations that render onto the canvas.
1245+
* @property {Set<number>} [filteredOperationIndexes] - If provided, only run
1246+
* the PDF operations that are included in this set.
12421247
*/
12431248

12441249
/**
@@ -1309,6 +1314,7 @@ class PDFPageProxy {
13091314

13101315
this._intentStates = new Map();
13111316
this.destroyed = false;
1317+
this.recordedGroups = null;
13121318
}
13131319

13141320
/**
@@ -1433,6 +1439,8 @@ class PDFPageProxy {
14331439
pageColors = null,
14341440
printAnnotationStorage = null,
14351441
isEditing = false,
1442+
recordOperations = false,
1443+
filteredOperationIndexes = null,
14361444
}) {
14371445
this._stats?.time("Overall");
14381446

@@ -1479,9 +1487,26 @@ class PDFPageProxy {
14791487
this._pumpOperatorList(intentArgs);
14801488
}
14811489

1490+
const shouldRecordOperations =
1491+
!this.recordedGroups &&
1492+
(recordOperations ||
1493+
(this._pdfBug && globalThis.StepperManager?.enabled));
1494+
14821495
const complete = error => {
14831496
intentState.renderTasks.delete(internalRenderTask);
14841497

1498+
if (shouldRecordOperations) {
1499+
const recordedGroups = internalRenderTask.gfx?.dependencyTracker.take();
1500+
if (recordedGroups) {
1501+
internalRenderTask.stepper?.setOperatorGroups(recordedGroups);
1502+
if (recordOperations) {
1503+
this.recordedGroups = recordedGroups;
1504+
}
1505+
} else if (recordOperations) {
1506+
this.recordedGroups = [];
1507+
}
1508+
}
1509+
14851510
// Attempt to reduce memory usage during *printing*, by always running
14861511
// cleanup immediately once rendering has finished.
14871512
if (intentPrint) {
@@ -1516,6 +1541,9 @@ class PDFPageProxy {
15161541
params: {
15171542
canvas,
15181543
canvasContext,
1544+
dependencyTracker: shouldRecordOperations
1545+
? new CanvasDependencyTracker(canvas)
1546+
: null,
15191547
viewport,
15201548
transform,
15211549
background,
@@ -1531,6 +1559,7 @@ class PDFPageProxy {
15311559
pdfBug: this._pdfBug,
15321560
pageColors,
15331561
enableHWA: this._transport.enableHWA,
1562+
filteredOperationIndexes,
15341563
});
15351564

15361565
(intentState.renderTasks ||= new Set()).add(internalRenderTask);
@@ -3140,6 +3169,7 @@ class InternalRenderTask {
31403169
pdfBug = false,
31413170
pageColors = null,
31423171
enableHWA = false,
3172+
filteredOperationIndexes = null,
31433173
}) {
31443174
this.callback = callback;
31453175
this.params = params;
@@ -3170,6 +3200,8 @@ class InternalRenderTask {
31703200
this._canvas = params.canvas;
31713201
this._canvasContext = params.canvas ? null : params.canvasContext;
31723202
this._enableHWA = enableHWA;
3203+
this._dependencyTracker = params.dependencyTracker;
3204+
this._filteredOperationIndexes = filteredOperationIndexes;
31733205
}
31743206

31753207
get completed() {
@@ -3199,7 +3231,7 @@ class InternalRenderTask {
31993231
this.stepper.init(this.operatorList);
32003232
this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
32013233
}
3202-
const { viewport, transform, background } = this.params;
3234+
const { viewport, transform, background, dependencyTracker } = this.params;
32033235

32043236
// When printing in Firefox, we get a specific context in mozPrintCallback
32053237
// which cannot be created from the canvas itself.
@@ -3218,7 +3250,8 @@ class InternalRenderTask {
32183250
this.filterFactory,
32193251
{ optionalContentConfig },
32203252
this.annotationCanvasMap,
3221-
this.pageColors
3253+
this.pageColors,
3254+
dependencyTracker
32223255
);
32233256
this.gfx.beginDrawing({
32243257
transform,
@@ -3294,7 +3327,8 @@ class InternalRenderTask {
32943327
this.operatorList,
32953328
this.operatorListIdx,
32963329
this._continueBound,
3297-
this.stepper
3330+
this.stepper,
3331+
this._filteredOperationIndexes
32983332
);
32993333
if (this.operatorListIdx === this.operatorList.argsArray.length) {
33003334
this.running = false;

0 commit comments

Comments
 (0)