From b6c6a0cb7cefc81de857cfa4419051d014ad05e1 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 13 Jul 2021 17:05:07 +0200 Subject: [PATCH] Avoid all rendering breaking completely when `CanvasPattern.setTransform()` is unsupported *Please note:* This patch doesn't fix rendering of (various) patterns in browsers/environments without full `CanvasPattern.setTransform()` support, but it at least prevents outright failures and thus allows the rest of the page to render. This patch provides a temporary work-around for Firefox 78 ESR[1], and for Node.js environments (see issue 13724), where rendering is currently completely broken. --- [1] Please note that the `createMatrix` helper function doesn't actually work as intended. The reason is that it's not `DOMMatrix` itself which is unsupported in older Firefox versions, but rather calling `CanvasPattern.setTransform(...)` with a `DOMMatrix`-argument. Furthermore, the `createSVGMatrix` fallback won't actually help either since that method doesn't accept any parameters and would thus require *manually* specifying the matrix-state; see e.g. https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern/setTransform#examples Finally, given that it's less than a month to the [Firefox 91 ESR release](https://wiki.mozilla.org/RapidRelease/Calendar) and that as-is all patterns are completely broken e.g. when using the latest viewer in Firefox 78 ESR, I'm just not convinced that it's worth the "hassle" of providing a more proper work-around. --- src/display/pattern_helper.js | 39 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/display/pattern_helper.js b/src/display/pattern_helper.js index 6311e0e6f..d4321cb02 100644 --- a/src/display/pattern_helper.js +++ b/src/display/pattern_helper.js @@ -19,22 +19,8 @@ import { shadow, unreachable, Util, + warn, } from "../shared/util.js"; -import { DOMSVGFactory } from "./display_utils.js"; - -let svgElement; - -// TODO: remove this when Firefox ESR supports DOMMatrix. -function createMatrix(matrix) { - if (typeof DOMMatrix !== "undefined") { - return new DOMMatrix(matrix); - } - if (!svgElement) { - const svgFactory = new DOMSVGFactory(); - svgElement = svgFactory.createElement("svg"); - } - return svgElement.createSVGMatrix(matrix); -} function applyBoundingBox(ctx, bbox) { if (!bbox || typeof Path2D === "undefined") { @@ -120,8 +106,16 @@ class RadialAxialShadingPattern extends BaseShadingPattern { tmpCtx.fillStyle = grad; tmpCtx.fill(); + const domMatrix = new DOMMatrix(inverse); + const pattern = ctx.createPattern(tmpCanvas.canvas, "repeat"); - pattern.setTransform(createMatrix(inverse)); + try { + pattern.setTransform(domMatrix); + } catch (ex) { + // Avoid rendering breaking completely in Firefox 78 ESR, + // and in Node.js (see issue 13724). + warn(`RadialAxialShadingPattern.getPattern: "${ex?.message}".`); + } return pattern; } } @@ -627,7 +621,7 @@ class TilingPattern { const temporaryPatternCanvas = this.createPatternCanvas(owner); - let domMatrix = createMatrix(matrix); + let domMatrix = new DOMMatrix(matrix); // Rescale and so that the ctx.createPattern call generates a pattern with // the desired size. domMatrix = domMatrix.translate( @@ -640,10 +634,15 @@ class TilingPattern { ); const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat"); - pattern.setTransform(domMatrix); - + try { + pattern.setTransform(domMatrix); + } catch (ex) { + // Avoid rendering breaking completely in Firefox 78 ESR, + // and in Node.js (see issue 13724). + warn(`TilingPattern.getPattern: "${ex?.message}".`); + } return pattern; } } -export { createMatrix, getShadingPattern, TilingPattern }; +export { getShadingPattern, TilingPattern };