Skip to content

Commit 0fec688

Browse files
committed
Move getContext call to InternalRenderTask
This is a precursor to moving the call into a worker thread to let us use `OffscreenCanvas`. The current position wouldn't work since we make transformations to the canvas object after the getContext call, which isn't allowed for OffscreenCanvas. Also it isn't allowed to clone or `transferControlToOffscreen` the canvas after the `getContext` call.
1 parent 802808c commit 0fec688

File tree

10 files changed

+93
-54
lines changed

10 files changed

+93
-54
lines changed

src/display/api.js

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,8 @@ function getDocument(src = {}) {
501501
task,
502502
networkStream,
503503
transportParams,
504-
transportFactory
504+
transportFactory,
505+
enableHWA
505506
);
506507
task._transport = transport;
507508
messageHandler.send("Ready", null);
@@ -1181,8 +1182,12 @@ class PDFDocumentProxy {
11811182
* Page render parameters.
11821183
*
11831184
* @typedef {Object} RenderParameters
1184-
* @property {CanvasRenderingContext2D} canvasContext - A 2D context of a DOM
1185-
* Canvas object.
1185+
* @property {CanvasRenderingContext2D} canvasContext - Deprecated 2D context of
1186+
* a DOM Canvas object for backwards compatibility; it is recommended to use
1187+
* the `canvas` parameter instead.
1188+
* @property {HTMLCanvasElement} canvas - A DOM Canvas object. The default value
1189+
* is the canvas associated with the `canvasContext` parameter if no value is
1190+
* provided explicitly.
11861191
* @property {PageViewport} viewport - Rendering viewport obtained by calling
11871192
* the `PDFPageProxy.getViewport` method.
11881193
* @property {string} [intent] - Rendering intent, can be 'display', 'print',
@@ -1405,6 +1410,7 @@ class PDFPageProxy {
14051410
*/
14061411
render({
14071412
canvasContext,
1413+
canvas = canvasContext.canvas,
14081414
viewport,
14091415
intent = "display",
14101416
annotationMode = AnnotationMode.ENABLE,
@@ -1497,6 +1503,7 @@ class PDFPageProxy {
14971503
// Only include the required properties, and *not* the entire object.
14981504
params: {
14991505
canvasContext,
1506+
canvas,
15001507
viewport,
15011508
transform,
15021509
background,
@@ -1511,6 +1518,7 @@ class PDFPageProxy {
15111518
useRequestAnimationFrame: !intentPrint,
15121519
pdfBug: this._pdfBug,
15131520
pageColors,
1521+
enableHWA: this._transport.enableHWA,
15141522
});
15151523

15161524
(intentState.renderTasks ||= new Set()).add(internalRenderTask);
@@ -2305,7 +2313,14 @@ class WorkerTransport {
23052313

23062314
#passwordCapability = null;
23072315

2308-
constructor(messageHandler, loadingTask, networkStream, params, factory) {
2316+
constructor(
2317+
messageHandler,
2318+
loadingTask,
2319+
networkStream,
2320+
params,
2321+
factory,
2322+
enableHWA
2323+
) {
23092324
this.messageHandler = messageHandler;
23102325
this.loadingTask = loadingTask;
23112326
this.commonObjs = new PDFObjects();
@@ -2329,6 +2344,7 @@ class WorkerTransport {
23292344
this._fullReader = null;
23302345
this._lastProgress = null;
23312346
this.downloadInfoCapability = Promise.withResolvers();
2347+
this.enableHWA = enableHWA;
23322348

23332349
this.setupMessageHandler();
23342350

@@ -3104,6 +3120,7 @@ class InternalRenderTask {
31043120
useRequestAnimationFrame = false,
31053121
pdfBug = false,
31063122
pageColors = null,
3123+
enableHWA = false,
31073124
}) {
31083125
this.callback = callback;
31093126
this.params = params;
@@ -3131,7 +3148,8 @@ class InternalRenderTask {
31313148
this._continueBound = this._continue.bind(this);
31323149
this._scheduleNextBound = this._scheduleNext.bind(this);
31333150
this._nextBound = this._next.bind(this);
3134-
this._canvas = params.canvasContext.canvas;
3151+
this._canvas = params.canvas;
3152+
this._enableHWA = enableHWA;
31353153
}
31363154

31373155
get completed() {
@@ -3161,7 +3179,12 @@ class InternalRenderTask {
31613179
this.stepper.init(this.operatorList);
31623180
this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
31633181
}
3164-
const { canvasContext, viewport, transform, background } = this.params;
3182+
const { viewport, transform, background } = this.params;
3183+
3184+
const canvasContext = this._canvas.getContext("2d", {
3185+
alpha: false,
3186+
willReadFrequently: !this._enableHWA,
3187+
});
31653188

31663189
this.gfx = new CanvasGraphics(
31673190
canvasContext,

test/driver.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ class Driver {
10161016
}
10171017
}
10181018
const renderContext = {
1019-
canvasContext: ctx,
1019+
canvas: this.canvas,
10201020
viewport,
10211021
optionalContentConfigPromise: task.optionalContentConfigPromise,
10221022
annotationCanvasMap,

test/unit/api_spec.js

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4410,7 +4410,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
44104410
viewport.height
44114411
);
44124412
const renderTask = pdfPage.render({
4413-
canvasContext: canvasAndCtx.context,
4413+
canvas: canvasAndCtx.canvas,
44144414
viewport,
44154415
});
44164416
expect(renderTask instanceof RenderTask).toEqual(true);
@@ -4446,7 +4446,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
44464446
viewport.height
44474447
);
44484448
const renderTask = page.render({
4449-
canvasContext: canvasAndCtx.context,
4449+
canvas: canvasAndCtx.canvas,
44504450
viewport,
44514451
});
44524452
expect(renderTask instanceof RenderTask).toEqual(true);
@@ -4477,7 +4477,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
44774477
viewport.height
44784478
);
44794479
const renderTask = page.render({
4480-
canvasContext: canvasAndCtx.context,
4480+
canvas: canvasAndCtx.canvas,
44814481
viewport,
44824482
});
44834483
expect(renderTask instanceof RenderTask).toEqual(true);
@@ -4494,7 +4494,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
44944494
}
44954495

44964496
const reRenderTask = page.render({
4497-
canvasContext: canvasAndCtx.context,
4497+
canvas: canvasAndCtx.canvas,
44984498
viewport,
44994499
});
45004500
expect(reRenderTask instanceof RenderTask).toEqual(true);
@@ -4518,14 +4518,14 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
45184518
viewport.height
45194519
);
45204520
const renderTask1 = page.render({
4521-
canvasContext: canvasAndCtx.context,
4521+
canvas: canvasAndCtx.canvas,
45224522
viewport,
45234523
optionalContentConfigPromise,
45244524
});
45254525
expect(renderTask1 instanceof RenderTask).toEqual(true);
45264526

45274527
const renderTask2 = page.render({
4528-
canvasContext: canvasAndCtx.context,
4528+
canvas: canvasAndCtx.canvas,
45294529
viewport,
45304530
optionalContentConfigPromise,
45314531
});
@@ -4562,7 +4562,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
45624562
viewport.height
45634563
);
45644564
const renderTask = pdfPage.render({
4565-
canvasContext: canvasAndCtx.context,
4565+
canvas: canvasAndCtx.canvas,
45664566
viewport,
45674567
});
45684568
expect(renderTask instanceof RenderTask).toEqual(true);
@@ -4591,7 +4591,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
45914591
viewport.height
45924592
);
45934593
const renderTask = pdfPage.render({
4594-
canvasContext: canvasAndCtx.context,
4594+
canvas: canvasAndCtx.canvas,
45954595
viewport,
45964596
background: "#FF0000", // See comment below.
45974597
});
@@ -4651,7 +4651,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
46514651
viewport.height
46524652
);
46534653
const renderTask = pdfPage.render({
4654-
canvasContext: canvasAndCtx.context,
4654+
canvas: canvasAndCtx.canvas,
46554655
viewport,
46564656
});
46574657

@@ -4755,7 +4755,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
47554755
viewport.height
47564756
);
47574757
const renderTask = pdfPage.render({
4758-
canvasContext: canvasAndCtx.context,
4758+
canvas: canvasAndCtx.canvas,
47594759
viewport,
47604760
});
47614761

@@ -4802,7 +4802,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
48024802
viewport.height
48034803
);
48044804
const renderTask = pdfPage.render({
4805-
canvasContext: canvasAndCtx.context,
4805+
canvas: canvasAndCtx.canvas,
48064806
viewport,
48074807
});
48084808

@@ -4852,7 +4852,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
48524852
viewport.height
48534853
);
48544854
const renderTask = pdfPage.render({
4855-
canvasContext: canvasAndCtx.context,
4855+
canvas: canvasAndCtx.canvas,
48564856
viewport,
48574857
intent: "print",
48584858
annotationMode: AnnotationMode.ENABLE_STORAGE,
@@ -4911,6 +4911,34 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
49114911

49124912
await loadingTask.destroy();
49134913
});
4914+
4915+
it("should work with the legacy canvasContext parameter", async function () {
4916+
const loadingTask = getDocument(tracemonkeyGetDocumentParams);
4917+
const pdfDoc = await loadingTask.promise;
4918+
const pdfPage = await pdfDoc.getPage(1);
4919+
const viewport = pdfPage.getViewport({ scale: 1 });
4920+
4921+
const { canvasFactory } = pdfDoc;
4922+
const canvasAndCtx = canvasFactory.create(
4923+
viewport.width,
4924+
viewport.height
4925+
);
4926+
const renderTask = pdfPage.render({
4927+
canvasContext: canvasAndCtx.context,
4928+
viewport,
4929+
});
4930+
expect(renderTask instanceof RenderTask).toEqual(true);
4931+
4932+
await renderTask.promise;
4933+
expect(
4934+
canvasAndCtx.context
4935+
.getImageData(0, 0, viewport.width, viewport.height)
4936+
.data.some(channel => channel !== 0)
4937+
).toEqual(true);
4938+
4939+
canvasFactory.destroy(canvasAndCtx);
4940+
await loadingTask.destroy();
4941+
});
49144942
});
49154943

49164944
describe("Multiple `getDocument` instances", function () {
@@ -4939,7 +4967,7 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
49394967
viewport.height
49404968
);
49414969
const renderTask = page.render({
4942-
canvasContext: canvasAndCtx.context,
4970+
canvas: canvasAndCtx.canvas,
49434971
viewport,
49444972
});
49454973
await renderTask.promise;

test/unit/custom_spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ describe("custom canvas rendering", function () {
5050
const canvasAndCtx = canvasFactory.create(viewport.width, viewport.height);
5151

5252
const renderTask = page.render({
53-
canvasContext: canvasAndCtx.context,
53+
canvas: canvasAndCtx.canvas,
5454
viewport,
5555
});
5656
await renderTask.promise;
@@ -70,7 +70,7 @@ describe("custom canvas rendering", function () {
7070
const canvasAndCtx = canvasFactory.create(viewport.width, viewport.height);
7171

7272
const renderTask = page.render({
73-
canvasContext: canvasAndCtx.context,
73+
canvas: canvasAndCtx.canvas,
7474
viewport,
7575
background: "rgba(255,0,0,1.0)",
7676
});
@@ -160,7 +160,7 @@ describe("custom ownerDocument", function () {
160160
const canvasAndCtx = canvasFactory.create(viewport.width, viewport.height);
161161

162162
await page.render({
163-
canvasContext: canvasAndCtx.context,
163+
canvas: canvasAndCtx.canvas,
164164
viewport,
165165
}).promise;
166166

@@ -194,7 +194,7 @@ describe("custom ownerDocument", function () {
194194
const canvasAndCtx = canvasFactory.create(viewport.width, viewport.height);
195195

196196
await page.render({
197-
canvasContext: canvasAndCtx.context,
197+
canvas: canvasAndCtx.canvas,
198198
viewport,
199199
}).promise;
200200

web/base_pdf_page_view.js

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ import { RenderingCancelledException } from "pdfjs-lib";
1717
import { RenderingStates } from "./ui_utils.js";
1818

1919
class BasePDFPageView {
20-
#enableHWA = false;
21-
2220
#loadingId = null;
2321

2422
#minDurationToUpdateCanvas = 0;
@@ -51,8 +49,6 @@ class BasePDFPageView {
5149
resume = null;
5250

5351
constructor(options) {
54-
this.#enableHWA =
55-
#enableHWA in options ? options.#enableHWA : options.enableHWA || false;
5652
this.eventBus = options.eventBus;
5753
this.id = options.id;
5854
this.pageColors = options.pageColors || null;
@@ -166,12 +162,7 @@ class BasePDFPageView {
166162
}
167163
};
168164

169-
const ctx = canvas.getContext("2d", {
170-
alpha: false,
171-
willReadFrequently: !this.#enableHWA,
172-
});
173-
174-
return { canvas, prevCanvas, ctx };
165+
return { canvas, prevCanvas };
175166
}
176167

177168
#renderContinueCallback = cont => {

web/firefox_print_service.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function composePage(
7272
currentRenderTask = null;
7373
}
7474
const renderContext = {
75-
canvasContext: ctx,
75+
canvas: ctx.canvas,
7676
transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
7777
viewport: pdfPage.getViewport({ scale: 1, rotation: size.rotation }),
7878
intent: "print",

web/pdf_page_detail_view.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ class PDFPageDetailView extends BasePDFPageView {
214214

215215
const canvasWrapper = this.pageView._ensureCanvasWrapper();
216216

217-
const { canvas, prevCanvas, ctx } = this._createCanvas(newCanvas => {
217+
const { canvas, prevCanvas } = this._createCanvas(newCanvas => {
218218
// If there is already the background canvas, inject this new canvas
219219
// after it. We cannot simply use .append because all canvases must
220220
// be before the SVG elements used for drawings.
@@ -249,7 +249,7 @@ class PDFPageDetailView extends BasePDFPageView {
249249
style.left = `${(area.minX * 100) / width}%`;
250250

251251
const renderingPromise = this._drawCanvas(
252-
this.pageView._getRenderingContext(ctx, transform),
252+
this.pageView._getRenderingContext(canvas, transform),
253253
() => {
254254
// If the rendering is cancelled, keep the old canvas visible.
255255
this.canvas?.remove();

web/pdf_page_view.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ import { XfaLayerBuilder } from "./xfa_layer_builder.js";
9595
* @property {IL10n} [l10n] - Localization service.
9696
* @property {Object} [layerProperties] - The object that is used to lookup
9797
* the necessary layer-properties.
98-
* @property {boolean} [enableHWA] - Enables hardware acceleration for
99-
* rendering. The default value is `false`.
10098
* @property {boolean} [enableAutoLinking] - Enable creation of hyperlinks from
10199
* text that look like URLs. The default value is `true`.
102100
*/
@@ -912,9 +910,9 @@ class PDFPageView extends BasePDFPageView {
912910
return canvasWrapper;
913911
}
914912

915-
_getRenderingContext(canvasContext, transform) {
913+
_getRenderingContext(canvas, transform) {
916914
return {
917-
canvasContext,
915+
canvas,
918916
transform,
919917
viewport: this.viewport,
920918
annotationMode: this.#annotationMode,
@@ -1000,7 +998,7 @@ class PDFPageView extends BasePDFPageView {
1000998
const { width, height } = viewport;
1001999
this.#originalViewport = viewport;
10021000

1003-
const { canvas, prevCanvas, ctx } = this._createCanvas(newCanvas => {
1001+
const { canvas, prevCanvas } = this._createCanvas(newCanvas => {
10041002
// Always inject the canvas as the first element in the wrapper.
10051003
canvasWrapper.prepend(newCanvas);
10061004
});
@@ -1042,7 +1040,7 @@ class PDFPageView extends BasePDFPageView {
10421040
? [outputScale.sx, 0, 0, outputScale.sy, 0, 0]
10431041
: null;
10441042
const resultPromise = this._drawCanvas(
1045-
this._getRenderingContext(ctx, transform),
1043+
this._getRenderingContext(canvas, transform),
10461044
() => {
10471045
prevCanvas?.remove();
10481046
this._resetCanvas();

0 commit comments

Comments
 (0)