From e9e9fee833dbcec423c500b1e796f86ec4dfaaa0 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 12 Aug 2022 12:26:52 +0200 Subject: [PATCH] Only compile Type3 glyphs when `Path2D` is supported According to MDN `Path2D` is available in all browsers that we currently support, see https://developer.mozilla.org/en-US/docs/Web/API/Path2D#browser_compatibility Hence only Node.js is currently lagging behind here, and requires that we keep the old code as a fallback in the `compileType3Glyph` function. However, there's an open PR in the `node-canvas` repository for adding `Path2D` support. As far as I'm concerned, there's two possible solutions here: - We land this patch now, since it removes unnecessary code in e.g. the Firefox PDF Viewer, which means that compilation of Type3 glyphs will be disabled in Node.js until that PR is landed.[1] If users report bugs about Type3 glyphs looking "inconsistent" in Node.js and/or being slow to render, we could perhaps encourage them to upvote and otherwise help out getting that PR landed? - We wait for the mentioned PR to land *first*, before moving forward with this patch. Given that there's been no updates on that PR for almost two months, this alternative may possibly take a while. --- [1] Note that Type3 fonts are first of all not very common in PDF documents, and secondly that compilation only applies specifically to Type3 glyphs that contain /ImageMask-data (i.e. not all Type3 fonts are affected). --- src/display/canvas.js | 54 +++++++++++-------------------------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/src/display/canvas.js b/src/display/canvas.js index bc13f24aa..53faae50b 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -54,8 +54,14 @@ const EXECUTION_TIME = 15; // ms // Defines the number of steps before checking the execution time. const EXECUTION_STEPS = 10; -const COMPILE_TYPE3_GLYPHS = true; -const MAX_SIZE_TO_COMPILE = 1000; +// To disable Type3 compilation, set the value to `-1`. +const MAX_SIZE_TO_COMPILE = + typeof PDFJSDev !== "undefined" && + PDFJSDev.test("GENERIC") && + isNodeJS && + typeof Path2D === "undefined" + ? -1 + : 1000; const FULL_CHUNK_HEIGHT = 16; @@ -294,11 +300,7 @@ function drawImageAtIntegerCoords( function compileType3Glyph(imgData) { const { width, height } = imgData; - if ( - !COMPILE_TYPE3_GLYPHS || - width > MAX_SIZE_TO_COMPILE || - height > MAX_SIZE_TO_COMPILE - ) { + if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) { return null; } @@ -404,12 +406,7 @@ function compileType3Glyph(imgData) { // building outlines const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); - let path, outlines, coords; - if (!isNodeJS) { - path = new Path2D(); - } else { - outlines = []; - } + const path = new Path2D(); for (i = 0; count && i <= height; i++) { let p = i * width1; @@ -420,12 +417,7 @@ function compileType3Glyph(imgData) { if (p === end) { continue; } - - if (path) { - path.moveTo(p % width1, i); - } else { - coords = [p % width1, i]; - } + path.moveTo(p % width1, i); const p0 = p; let type = points[p]; @@ -448,21 +440,12 @@ function compileType3Glyph(imgData) { // set new type for "future hit" points[p] &= (type >> 2) | (type << 2); } - - if (path) { - path.lineTo(p % width1, (p / width1) | 0); - } else { - coords.push(p % width1, (p / width1) | 0); - } + path.lineTo(p % width1, (p / width1) | 0); if (!points[p]) { --count; } } while (p0 !== p); - - if (!path) { - outlines.push(coords); - } --i; } @@ -475,18 +458,7 @@ function compileType3Glyph(imgData) { // the path shall be painted in [0..1]x[0..1] space c.scale(1 / width, -1 / height); c.translate(0, -height); - if (path) { - c.fill(path); - } else { - c.beginPath(); - for (const o of outlines) { - c.moveTo(o[0], o[1]); - for (let l = 2, ll = o.length; l < ll; l += 2) { - c.lineTo(o[l], o[l + 1]); - } - } - c.fill(); - } + c.fill(path); c.beginPath(); c.restore(); };