diff --git a/README.md b/README.md index 23a543599..b7b89c316 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,6 @@ all dependencies for PDF.js: $ npm install -> [!NOTE] -> On MacOS M1/M2 you may see some `node-gyp`-related errors when running `npm install`. This is because one of our dependencies, `"canvas"`, does not provide pre-built binaries for this platform and instead `npm` will try to build it from source. Please make sure to first install the necessary native dependencies using `brew`: https://github.com/Automattic/node-canvas#compiling. - Finally, you need to start a local web server as some browsers do not allow opening PDF files using a `file://` URL. Run: diff --git a/examples/node/pdf2png/README.md b/examples/node/pdf2png/README.md index 00b388b9f..8b114061b 100644 --- a/examples/node/pdf2png/README.md +++ b/examples/node/pdf2png/README.md @@ -9,9 +9,7 @@ Install the dependencies and build the PDF.js library: $ npm install $ gulp dist-install -Install the Node canvas library and run the example to convert the first page of a -PDF file to a PNG image: +Run the example to convert the first page of a PDF file to a PNG image: - $ npm install canvas $ cd examples/node/pdf2png - $ node pdf2png.js + $ node pdf2png.mjs diff --git a/examples/node/pdf2png/pdf2png.mjs b/examples/node/pdf2png/pdf2png.mjs index 359fc807b..ed01834b0 100644 --- a/examples/node/pdf2png/pdf2png.mjs +++ b/examples/node/pdf2png/pdf2png.mjs @@ -57,7 +57,7 @@ try { const renderTask = page.render(renderContext); await renderTask.promise; // Convert the canvas to an image buffer. - const image = canvasAndContext.canvas.toBuffer(); + const image = canvasAndContext.canvas.toBuffer("image/png"); fs.writeFile("output.png", image, function (error) { if (error) { console.error("Error: " + error); diff --git a/gulpfile.mjs b/gulpfile.mjs index 1f8a29dae..ff4802cc1 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -2256,8 +2256,7 @@ function packageJson() { bugs: DIST_BUGS_URL, license: DIST_LICENSE, optionalDependencies: { - canvas: "^3.0.0-rc2", - path2d: "^0.2.1", + "@napi-rs/canvas": "^0.1.60", }, browser: { canvas: false, diff --git a/package-lock.json b/package-lock.json index 0f96a62a6..dc1270cb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,11 @@ "@jazzer.js/core": "^2.1.0", "@metalsmith/layouts": "^2.7.0", "@metalsmith/markdown": "^1.10.0", + "@napi-rs/canvas": "^0.1.60", "@types/node": "^22.8.7", "autoprefixer": "^10.4.20", "babel-loader": "^9.2.1", "caniuse-lite": "^1.0.30001677", - "canvas": "^3.0.0-rc2", "core-js": "^3.39.0", "eslint": "^8.57.1", "eslint-plugin-import": "^2.31.0", @@ -42,7 +42,6 @@ "metalsmith": "^2.6.3", "metalsmith-html-relative": "^2.0.5", "ordered-read-streams": "^2.0.0", - "path2d": "^0.2.1", "pngjs": "^7.0.0", "postcss": "^8.4.47", "postcss-dark-theme-class": "^1.3.0", @@ -2286,6 +2285,180 @@ "metalsmith": "^2.5.0" } }, + "node_modules/@napi-rs/canvas": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.60.tgz", + "integrity": "sha512-2a/8ynCHVXu9JVTeT/RLrZy6kro3VHnxDqy7SyHIdzCUUwJoKuKNmDzXjD6bqE0W/07j1lFW7OVIAYSr1GiWuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.60", + "@napi-rs/canvas-darwin-arm64": "0.1.60", + "@napi-rs/canvas-darwin-x64": "0.1.60", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.60", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.60", + "@napi-rs/canvas-linux-arm64-musl": "0.1.60", + "@napi-rs/canvas-linux-x64-gnu": "0.1.60", + "@napi-rs/canvas-linux-x64-musl": "0.1.60", + "@napi-rs/canvas-win32-x64-msvc": "0.1.60" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.60.tgz", + "integrity": "sha512-KNOBYH3BUfUl5mo5wvrA2C+tJk0RnF4InkbsCoHdsxjhLjbriJKmu5DCFLaiG/c6WPfTcLRz73bGcP7boVeb6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.60.tgz", + "integrity": "sha512-j6PA7RwRcx0409Jk3zz6beq3EtvwEgvN46FyKgFnSnzoV0ey2kM+KI2XTpG3tE/v4+fTnQenR+ysUBEgtWuUuA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.60.tgz", + "integrity": "sha512-k0uBuShNK7QnOJlLhzxSsnSdJMkiU8VexqvuTEi0qABqKkHrYzD0ezUgtyvaVLOOoqxwGy1Hh5ZoEze5s9H/6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.60.tgz", + "integrity": "sha512-X2cQ6MIDZn5dMsy9jakASM6tvo2PGd3dq25gqrUzJeQIngQhLIWZtaYWza3md3M6HoQ4b/6W81OVQhgL/8uTkA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.60.tgz", + "integrity": "sha512-Ch02kQsetlXA4tfHfSJ63oyq9EbYB00yy/6hZ0/VYh60pLnopvsMt682+cM+rGBbgm14G+Heh3rDzJ6zBiiocw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.60.tgz", + "integrity": "sha512-7TpSJM4RnhHnAMrA/bDXitNVx9TV8ZLQ/47QHsNhdZ77yCgcEyLBRgUGvjsmnUpWIHhTOWTHDlGY47zHcQDfhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.60.tgz", + "integrity": "sha512-46yi+fIUQ5SRg0Qs3L04zh67kk0uFJa2elWt/cS/7kEydu06uhjbJwW3123J9KShu2PKLlaZEqxJPksYpowoeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.60.tgz", + "integrity": "sha512-lTKiv5VnccFyZAd27AL6t69djDXQlfUgVE03PTM5HZUUy0h7sQKnrGh2mSMq58E3/vA0k65IFDqVqxyLjCpvlw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.60.tgz", + "integrity": "sha512-b7VjNQ3V/7G6VQqB8KvG9A06ENFZhxFMe4areUduipFwuJ0w35PGgOmYZHd0+iY9Nh7niECjgPRNDcrzpDlWXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3739,22 +3912,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/canvas": { - "version": "3.0.0-rc2", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-3.0.0-rc2.tgz", - "integrity": "sha512-esx4bYDznnqgRX4G8kaEaf0W3q8xIc51WpmrIitDzmcoEgwnv9wSKdzT6UxWZ4wkVu5+ileofppX0TpyviJRdQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^7.0.0", - "prebuild-install": "^7.1.1", - "simple-get": "^3.0.3" - }, - "engines": { - "node": "^18.12.0 || >= 20.9.0" - } - }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -4525,18 +4682,6 @@ "node": ">=0.10.0" } }, - "node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -9381,18 +9526,6 @@ "node": ">=6" } }, - "node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -10143,16 +10276,6 @@ "node": ">=8" } }, - "node_modules/path2d": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/path2d/-/path2d-0.2.1.tgz", - "integrity": "sha512-Fl2z/BHvkTNvkuBzYTpTuirHZg6wW9z8+4SND/3mDTEcYbbNKWAy21dz9D3ePNNwrrK8pqZO5vLPZ1hLF6T7XA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -11671,17 +11794,6 @@ } ] }, - "node_modules/simple-get": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", - "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "dev": true, - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", diff --git a/package.json b/package.json index a8d26f3bf..de2ae98c7 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,11 @@ "@jazzer.js/core": "^2.1.0", "@metalsmith/layouts": "^2.7.0", "@metalsmith/markdown": "^1.10.0", + "@napi-rs/canvas": "^0.1.60", "@types/node": "^22.8.7", "autoprefixer": "^10.4.20", "babel-loader": "^9.2.1", "caniuse-lite": "^1.0.30001677", - "canvas": "^3.0.0-rc2", "core-js": "^3.39.0", "eslint": "^8.57.1", "eslint-plugin-import": "^2.31.0", @@ -37,7 +37,6 @@ "metalsmith": "^2.6.3", "metalsmith-html-relative": "^2.0.5", "ordered-read-streams": "^2.0.0", - "path2d": "^0.2.1", "pngjs": "^7.0.0", "postcss": "^8.4.47", "postcss-dark-theme-class": "^1.3.0", diff --git a/src/display/canvas.js b/src/display/canvas.js index 098741ce9..a7b16572f 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -586,7 +586,7 @@ class CanvasExtraState { } function putBinaryImageData(ctx, imgData) { - if (typeof ImageData !== "undefined" && imgData instanceof ImageData) { + if (imgData instanceof ImageData) { ctx.putImageData(imgData, 0, 0); return; } diff --git a/src/display/node_utils.js b/src/display/node_utils.js index 81ed9375b..4edd7bb3a 100644 --- a/src/display/node_utils.js +++ b/src/display/node_utils.js @@ -31,50 +31,36 @@ if ( !PDFJSDev.test("SKIP_BABEL") && isNodeJS ) { - let canvas, path2d; + let canvas; try { const require = process .getBuiltinModule("module") .createRequire(import.meta.url); try { - canvas = require("canvas"); + canvas = require("@napi-rs/canvas"); } catch (ex) { - warn(`Cannot load "canvas" package: "${ex}".`); - } - try { - path2d = require("path2d"); - } catch (ex) { - warn(`Cannot load "path2d" package: "${ex}".`); + warn(`Cannot load "@napi-rs/canvas" package: "${ex}".`); } } catch {} if (!globalThis.DOMMatrix) { - const DOMMatrix = canvas?.DOMMatrix; - - if (DOMMatrix) { - globalThis.DOMMatrix = DOMMatrix; + if (canvas?.DOMMatrix) { + globalThis.DOMMatrix = canvas.DOMMatrix; } else { warn("Cannot polyfill `DOMMatrix`, rendering may be broken."); } } + if (!globalThis.ImageData) { + if (canvas?.ImageData) { + globalThis.ImageData = canvas.ImageData; + } else { + warn("Cannot polyfill `ImageData`, rendering may be broken."); + } + } if (!globalThis.Path2D) { - const CanvasRenderingContext2D = canvas?.CanvasRenderingContext2D; - const applyPath2DToCanvasRenderingContext = - path2d?.applyPath2DToCanvasRenderingContext; - const Path2D = path2d?.Path2D; - - if ( - CanvasRenderingContext2D && - applyPath2DToCanvasRenderingContext && - Path2D - ) { - try { - applyPath2DToCanvasRenderingContext(CanvasRenderingContext2D); - } catch (ex) { - warn(`applyPath2DToCanvasRenderingContext: "${ex}".`); - } - globalThis.Path2D = Path2D; + if (canvas?.Path2D) { + globalThis.Path2D = canvas.Path2D; } else { warn("Cannot polyfill `Path2D`, rendering may be broken."); } @@ -97,7 +83,7 @@ class NodeCanvasFactory extends BaseCanvasFactory { const require = process .getBuiltinModule("module") .createRequire(import.meta.url); - const canvas = require("canvas"); + const canvas = require("@napi-rs/canvas"); return canvas.createCanvas(width, height); } }