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.
This commit is contained in:
Jonas Jenwald 2021-07-13 17:05:07 +02:00
parent a17bd13023
commit b6c6a0cb7c

View File

@ -19,22 +19,8 @@ import {
shadow, shadow,
unreachable, unreachable,
Util, Util,
warn,
} from "../shared/util.js"; } 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) { function applyBoundingBox(ctx, bbox) {
if (!bbox || typeof Path2D === "undefined") { if (!bbox || typeof Path2D === "undefined") {
@ -120,8 +106,16 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
tmpCtx.fillStyle = grad; tmpCtx.fillStyle = grad;
tmpCtx.fill(); tmpCtx.fill();
const domMatrix = new DOMMatrix(inverse);
const pattern = ctx.createPattern(tmpCanvas.canvas, "repeat"); 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; return pattern;
} }
} }
@ -627,7 +621,7 @@ class TilingPattern {
const temporaryPatternCanvas = this.createPatternCanvas(owner); 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 // Rescale and so that the ctx.createPattern call generates a pattern with
// the desired size. // the desired size.
domMatrix = domMatrix.translate( domMatrix = domMatrix.translate(
@ -640,10 +634,15 @@ class TilingPattern {
); );
const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat"); 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; return pattern;
} }
} }
export { createMatrix, getShadingPattern, TilingPattern }; export { getShadingPattern, TilingPattern };