[api-minor] Use a SVG filter when rendering pages in HCM
The idea is to apply an overall filter on each page: the main advantage is to have some filtered images which could help to make them visible for some users.
This commit is contained in:
parent
85166c60fd
commit
da080cc26e
@ -3082,7 +3082,7 @@ class WorkerTransport {
|
|||||||
this.fontLoader.clear();
|
this.fontLoader.clear();
|
||||||
}
|
}
|
||||||
this.#methodPromises.clear();
|
this.#methodPromises.clear();
|
||||||
this.filterFactory.destroy();
|
this.filterFactory.destroy(/* keepHCM = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
get loadingParams() {
|
get loadingParams() {
|
||||||
@ -3337,7 +3337,7 @@ class InternalRenderTask {
|
|||||||
cancel(error = null, extraDelay = 0) {
|
cancel(error = null, extraDelay = 0) {
|
||||||
this.running = false;
|
this.running = false;
|
||||||
this.cancelled = true;
|
this.cancelled = true;
|
||||||
this.gfx?.endDrawing();
|
this.gfx?.endDrawing(this.pageColors);
|
||||||
|
|
||||||
if (this._canvas) {
|
if (this._canvas) {
|
||||||
InternalRenderTask.#canvasInUse.delete(this._canvas);
|
InternalRenderTask.#canvasInUse.delete(this._canvas);
|
||||||
@ -3402,7 +3402,7 @@ class InternalRenderTask {
|
|||||||
if (this.operatorListIdx === this.operatorList.argsArray.length) {
|
if (this.operatorListIdx === this.operatorList.argsArray.length) {
|
||||||
this.running = false;
|
this.running = false;
|
||||||
if (this.operatorList.lastChunk) {
|
if (this.operatorList.lastChunk) {
|
||||||
this.gfx.endDrawing();
|
this.gfx.endDrawing(this.pageColors);
|
||||||
if (this._canvas) {
|
if (this._canvas) {
|
||||||
InternalRenderTask.#canvasInUse.delete(this._canvas);
|
InternalRenderTask.#canvasInUse.delete(this._canvas);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,11 @@ class BaseFilterFactory {
|
|||||||
return "none";
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {}
|
addHCMFilter(fgColor, bgColor) {
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(keepHCM = false) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BaseCanvasFactory {
|
class BaseCanvasFactory {
|
||||||
|
@ -29,7 +29,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
getCurrentTransform,
|
getCurrentTransform,
|
||||||
getCurrentTransformInverse,
|
getCurrentTransformInverse,
|
||||||
getRGB,
|
|
||||||
PixelsPerInch,
|
PixelsPerInch,
|
||||||
} from "./display_utils.js";
|
} from "./display_utils.js";
|
||||||
import {
|
import {
|
||||||
@ -773,8 +772,8 @@ function copyCtxState(sourceCtx, destCtx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetCtxToDefault(ctx, foregroundColor) {
|
function resetCtxToDefault(ctx) {
|
||||||
ctx.strokeStyle = ctx.fillStyle = foregroundColor || "#000000";
|
ctx.strokeStyle = ctx.fillStyle = "#000000";
|
||||||
ctx.fillRule = "nonzero";
|
ctx.fillRule = "nonzero";
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = 1;
|
||||||
@ -948,8 +947,7 @@ class CanvasGraphics {
|
|||||||
canvasFactory,
|
canvasFactory,
|
||||||
filterFactory,
|
filterFactory,
|
||||||
{ optionalContentConfig, markedContentStack = null },
|
{ optionalContentConfig, markedContentStack = null },
|
||||||
annotationCanvasMap,
|
annotationCanvasMap
|
||||||
pageColors
|
|
||||||
) {
|
) {
|
||||||
this.ctx = canvasCtx;
|
this.ctx = canvasCtx;
|
||||||
this.current = new CanvasExtraState(
|
this.current = new CanvasExtraState(
|
||||||
@ -985,8 +983,6 @@ class CanvasGraphics {
|
|||||||
this.viewportScale = 1;
|
this.viewportScale = 1;
|
||||||
this.outputScaleX = 1;
|
this.outputScaleX = 1;
|
||||||
this.outputScaleY = 1;
|
this.outputScaleY = 1;
|
||||||
this.backgroundColor = pageColors?.background || null;
|
|
||||||
this.foregroundColor = pageColors?.foreground || null;
|
|
||||||
|
|
||||||
this._cachedScaleForStroking = null;
|
this._cachedScaleForStroking = null;
|
||||||
this._cachedGetSinglePixelWidth = null;
|
this._cachedGetSinglePixelWidth = null;
|
||||||
@ -1015,69 +1011,11 @@ class CanvasGraphics {
|
|||||||
// transparent canvas when we have blend modes.
|
// transparent canvas when we have blend modes.
|
||||||
const width = this.ctx.canvas.width;
|
const width = this.ctx.canvas.width;
|
||||||
const height = this.ctx.canvas.height;
|
const height = this.ctx.canvas.height;
|
||||||
const defaultBackgroundColor = background || "#ffffff";
|
|
||||||
this.ctx.save();
|
|
||||||
|
|
||||||
if (this.foregroundColor && this.backgroundColor) {
|
const savedFillStyle = this.ctx.fillStyle;
|
||||||
// Get the #RRGGBB value of the color. If it's a name (e.g. CanvasText)
|
this.ctx.fillStyle = background || "#ffffff";
|
||||||
// then it'll be converted to its rgb value.
|
|
||||||
this.ctx.fillStyle = this.foregroundColor;
|
|
||||||
const fg = (this.foregroundColor = this.ctx.fillStyle);
|
|
||||||
this.ctx.fillStyle = this.backgroundColor;
|
|
||||||
const bg = (this.backgroundColor = this.ctx.fillStyle);
|
|
||||||
let isValidDefaultBg = true;
|
|
||||||
let defaultBg = defaultBackgroundColor;
|
|
||||||
|
|
||||||
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
|
|
||||||
this.ctx.fillStyle = defaultBackgroundColor;
|
|
||||||
defaultBg = this.ctx.fillStyle;
|
|
||||||
isValidDefaultBg =
|
|
||||||
typeof defaultBg === "string" && /^#[0-9A-Fa-f]{6}$/.test(defaultBg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
(fg === "#000000" && bg === "#ffffff") ||
|
|
||||||
fg === bg ||
|
|
||||||
!isValidDefaultBg
|
|
||||||
) {
|
|
||||||
// Ignore the `pageColors`-option when:
|
|
||||||
// - The computed background/foreground colors have their default
|
|
||||||
// values, i.e. white/black.
|
|
||||||
// - The computed background/foreground colors are identical,
|
|
||||||
// since that'd render the `canvas` mostly blank.
|
|
||||||
// - The `background`-option has a value that's incompatible with
|
|
||||||
// the `pageColors`-values.
|
|
||||||
//
|
|
||||||
this.foregroundColor = this.backgroundColor = null;
|
|
||||||
} else {
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_Colors_and_Luminance
|
|
||||||
//
|
|
||||||
// Relative luminance:
|
|
||||||
// https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
|
||||||
//
|
|
||||||
// We compute the rounded luminance of the default background color.
|
|
||||||
// Then for every color in the pdf, if its rounded luminance is the
|
|
||||||
// same as the background one then it's replaced by the new
|
|
||||||
// background color else by the foreground one.
|
|
||||||
const [rB, gB, bB] = getRGB(defaultBg);
|
|
||||||
const newComp = x => {
|
|
||||||
x /= 255;
|
|
||||||
return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
|
|
||||||
};
|
|
||||||
const lumB = Math.round(
|
|
||||||
0.2126 * newComp(rB) + 0.7152 * newComp(gB) + 0.0722 * newComp(bB)
|
|
||||||
);
|
|
||||||
this.selectColor = (r, g, b) => {
|
|
||||||
const lumC =
|
|
||||||
0.2126 * newComp(r) + 0.7152 * newComp(g) + 0.0722 * newComp(b);
|
|
||||||
return Math.round(lumC) === lumB ? bg : fg;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ctx.fillStyle = this.backgroundColor || defaultBackgroundColor;
|
|
||||||
this.ctx.fillRect(0, 0, width, height);
|
this.ctx.fillRect(0, 0, width, height);
|
||||||
this.ctx.restore();
|
this.ctx.fillStyle = savedFillStyle;
|
||||||
|
|
||||||
if (transparency) {
|
if (transparency) {
|
||||||
const transparentCanvas = this.cachedCanvases.getCanvas(
|
const transparentCanvas = this.cachedCanvases.getCanvas(
|
||||||
@ -1095,7 +1033,7 @@ class CanvasGraphics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.ctx.save();
|
this.ctx.save();
|
||||||
resetCtxToDefault(this.ctx, this.foregroundColor);
|
resetCtxToDefault(this.ctx);
|
||||||
if (transform) {
|
if (transform) {
|
||||||
this.ctx.transform(...transform);
|
this.ctx.transform(...transform);
|
||||||
this.outputScaleX = transform[0];
|
this.outputScaleX = transform[0];
|
||||||
@ -1197,7 +1135,7 @@ class CanvasGraphics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endDrawing() {
|
endDrawing(pageColors = null) {
|
||||||
this.#restoreInitialState();
|
this.#restoreInitialState();
|
||||||
|
|
||||||
this.cachedCanvases.clear();
|
this.cachedCanvases.clear();
|
||||||
@ -1215,6 +1153,19 @@ class CanvasGraphics {
|
|||||||
cache.clear();
|
cache.clear();
|
||||||
}
|
}
|
||||||
this._cachedBitmapsMap.clear();
|
this._cachedBitmapsMap.clear();
|
||||||
|
|
||||||
|
if (pageColors) {
|
||||||
|
const hcmFilterId = this.filterFactory.addHCMFilter(
|
||||||
|
pageColors.foreground,
|
||||||
|
pageColors.background
|
||||||
|
);
|
||||||
|
if (hcmFilterId !== "none") {
|
||||||
|
const savedFilter = this.ctx.filter;
|
||||||
|
this.ctx.filter = hcmFilterId;
|
||||||
|
this.ctx.drawImage(this.ctx.canvas, 0, 0);
|
||||||
|
this.ctx.filter = savedFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_scaleImage(img, inverseTransform) {
|
_scaleImage(img, inverseTransform) {
|
||||||
@ -2439,13 +2390,13 @@ class CanvasGraphics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setStrokeRGBColor(r, g, b) {
|
setStrokeRGBColor(r, g, b) {
|
||||||
const color = this.selectColor?.(r, g, b) || Util.makeHexColor(r, g, b);
|
const color = Util.makeHexColor(r, g, b);
|
||||||
this.ctx.strokeStyle = color;
|
this.ctx.strokeStyle = color;
|
||||||
this.current.strokeColor = color;
|
this.current.strokeColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
setFillRGBColor(r, g, b) {
|
setFillRGBColor(r, g, b) {
|
||||||
const color = this.selectColor?.(r, g, b) || Util.makeHexColor(r, g, b);
|
const color = Util.makeHexColor(r, g, b);
|
||||||
this.ctx.fillStyle = color;
|
this.ctx.fillStyle = color;
|
||||||
this.current.fillColor = color;
|
this.current.fillColor = color;
|
||||||
this.current.patternFill = false;
|
this.current.patternFill = false;
|
||||||
@ -2719,7 +2670,7 @@ class CanvasGraphics {
|
|||||||
// a clipping path, whatever...
|
// a clipping path, whatever...
|
||||||
// So in order to have something clean, we restore the initial state.
|
// So in order to have something clean, we restore the initial state.
|
||||||
this.#restoreInitialState();
|
this.#restoreInitialState();
|
||||||
resetCtxToDefault(this.ctx, this.foregroundColor);
|
resetCtxToDefault(this.ctx);
|
||||||
|
|
||||||
this.ctx.save();
|
this.ctx.save();
|
||||||
this.save();
|
this.save();
|
||||||
@ -2763,9 +2714,9 @@ class CanvasGraphics {
|
|||||||
this.ctx = context;
|
this.ctx = context;
|
||||||
this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY);
|
this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY);
|
||||||
|
|
||||||
resetCtxToDefault(this.ctx, this.foregroundColor);
|
resetCtxToDefault(this.ctx);
|
||||||
} else {
|
} else {
|
||||||
resetCtxToDefault(this.ctx, this.foregroundColor);
|
resetCtxToDefault(this.ctx);
|
||||||
|
|
||||||
this.ctx.rect(rect[0], rect[1], width, height);
|
this.ctx.rect(rect[0], rect[1], width, height);
|
||||||
this.ctx.clip();
|
this.ctx.clip();
|
||||||
|
@ -58,6 +58,12 @@ class DOMFilterFactory extends BaseFilterFactory {
|
|||||||
|
|
||||||
#document;
|
#document;
|
||||||
|
|
||||||
|
#hcmFilter;
|
||||||
|
|
||||||
|
#hcmKey;
|
||||||
|
|
||||||
|
#hcmUrl;
|
||||||
|
|
||||||
#id = 0;
|
#id = 0;
|
||||||
|
|
||||||
constructor({ docId, ownerDocument = globalThis.document } = {}) {
|
constructor({ docId, ownerDocument = globalThis.document } = {}) {
|
||||||
@ -172,7 +178,136 @@ class DOMFilterFactory extends BaseFilterFactory {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
addHCMFilter(fgColor, bgColor) {
|
||||||
|
const key = `${fgColor}-${bgColor}`;
|
||||||
|
if (this.#hcmKey === key) {
|
||||||
|
return this.#hcmUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#hcmKey = key;
|
||||||
|
this.#hcmUrl = "none";
|
||||||
|
this.#hcmFilter?.remove();
|
||||||
|
|
||||||
|
if (!fgColor || !bgColor) {
|
||||||
|
return this.#hcmUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#defs.style.color = fgColor;
|
||||||
|
fgColor = getComputedStyle(this.#defs).getPropertyValue("color");
|
||||||
|
const fgRGB = getRGB(fgColor);
|
||||||
|
fgColor = Util.makeHexColor(...fgRGB);
|
||||||
|
this.#defs.style.color = bgColor;
|
||||||
|
bgColor = getComputedStyle(this.#defs).getPropertyValue("color");
|
||||||
|
const bgRGB = getRGB(bgColor);
|
||||||
|
bgColor = Util.makeHexColor(...bgRGB);
|
||||||
|
this.#defs.style.color = "";
|
||||||
|
|
||||||
|
if (
|
||||||
|
(fgColor === "#000000" && bgColor === "#ffffff") ||
|
||||||
|
fgColor === bgColor
|
||||||
|
) {
|
||||||
|
return this.#hcmUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_Colors_and_Luminance
|
||||||
|
//
|
||||||
|
// Relative luminance:
|
||||||
|
// https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
||||||
|
//
|
||||||
|
// We compute the rounded luminance of the default background color.
|
||||||
|
// Then for every color in the pdf, if its rounded luminance is the
|
||||||
|
// same as the background one then it's replaced by the new
|
||||||
|
// background color else by the foreground one.
|
||||||
|
const map = new Array(256);
|
||||||
|
for (let i = 0; i <= 255; i++) {
|
||||||
|
const x = i / 255;
|
||||||
|
map[i] = x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
|
||||||
|
}
|
||||||
|
const table = map.join(",");
|
||||||
|
|
||||||
|
const id = `g_${this.#docId}_hcm_filter`;
|
||||||
|
const filter = (this.#hcmFilter = this.#document.createElementNS(
|
||||||
|
SVG_NS,
|
||||||
|
"filter",
|
||||||
|
SVG_NS
|
||||||
|
));
|
||||||
|
filter.setAttribute("id", id);
|
||||||
|
filter.setAttribute("color-interpolation-filters", "sRGB");
|
||||||
|
let feComponentTransfer = this.#document.createElementNS(
|
||||||
|
SVG_NS,
|
||||||
|
"feComponentTransfer"
|
||||||
|
);
|
||||||
|
filter.append(feComponentTransfer);
|
||||||
|
|
||||||
|
let type = "discrete";
|
||||||
|
let feFuncR = this.#document.createElementNS(SVG_NS, "feFuncR");
|
||||||
|
feFuncR.setAttribute("type", type);
|
||||||
|
feFuncR.setAttribute("tableValues", table);
|
||||||
|
feComponentTransfer.append(feFuncR);
|
||||||
|
|
||||||
|
let feFuncG = this.#document.createElementNS(SVG_NS, "feFuncG");
|
||||||
|
feFuncG.setAttribute("type", type);
|
||||||
|
feFuncG.setAttribute("tableValues", table);
|
||||||
|
feComponentTransfer.append(feFuncG);
|
||||||
|
|
||||||
|
let feFuncB = this.#document.createElementNS(SVG_NS, "feFuncB");
|
||||||
|
feFuncB.setAttribute("type", type);
|
||||||
|
feFuncB.setAttribute("tableValues", table);
|
||||||
|
feComponentTransfer.append(feFuncB);
|
||||||
|
|
||||||
|
const feColorMatrix = this.#document.createElementNS(
|
||||||
|
SVG_NS,
|
||||||
|
"feColorMatrix"
|
||||||
|
);
|
||||||
|
feColorMatrix.setAttribute("type", "matrix");
|
||||||
|
feColorMatrix.setAttribute(
|
||||||
|
"values",
|
||||||
|
"0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"
|
||||||
|
);
|
||||||
|
filter.append(feColorMatrix);
|
||||||
|
|
||||||
|
feComponentTransfer = this.#document.createElementNS(
|
||||||
|
SVG_NS,
|
||||||
|
"feComponentTransfer"
|
||||||
|
);
|
||||||
|
filter.append(feComponentTransfer);
|
||||||
|
|
||||||
|
const getSteps = (c, n) => {
|
||||||
|
const start = fgRGB[c] / 255;
|
||||||
|
const end = bgRGB[c] / 255;
|
||||||
|
const arr = new Array(n + 1);
|
||||||
|
for (let i = 0; i <= n; i++) {
|
||||||
|
arr[i] = start + (i / n) * (end - start);
|
||||||
|
}
|
||||||
|
return arr.join(",");
|
||||||
|
};
|
||||||
|
|
||||||
|
type = "discrete";
|
||||||
|
feFuncR = this.#document.createElementNS(SVG_NS, "feFuncR");
|
||||||
|
feFuncR.setAttribute("type", type);
|
||||||
|
feFuncR.setAttribute("tableValues", `${getSteps(0, 5)}`);
|
||||||
|
feComponentTransfer.append(feFuncR);
|
||||||
|
|
||||||
|
feFuncG = this.#document.createElementNS(SVG_NS, "feFuncG");
|
||||||
|
feFuncG.setAttribute("type", type);
|
||||||
|
feFuncG.setAttribute("tableValues", `${getSteps(1, 5)}`);
|
||||||
|
feComponentTransfer.append(feFuncG);
|
||||||
|
|
||||||
|
feFuncB = this.#document.createElementNS(SVG_NS, "feFuncB");
|
||||||
|
feFuncB.setAttribute("type", type);
|
||||||
|
feFuncB.setAttribute("tableValues", `${getSteps(2, 5)}`);
|
||||||
|
feComponentTransfer.append(feFuncB);
|
||||||
|
|
||||||
|
this.#defs.append(filter);
|
||||||
|
|
||||||
|
this.#hcmUrl = `url(#${id})`;
|
||||||
|
return this.#hcmUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(keepHCM = false) {
|
||||||
|
if (keepHCM && this.#hcmUrl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.#_defs) {
|
if (this.#_defs) {
|
||||||
this.#_defs.parentNode.parentNode.remove();
|
this.#_defs.parentNode.parentNode.remove();
|
||||||
this.#_defs = null;
|
this.#_defs = null;
|
||||||
|
@ -1002,8 +1002,14 @@ class PDFPageView {
|
|||||||
// is complete when `!this.renderingQueue`, to prevent black flickering.
|
// is complete when `!this.renderingQueue`, to prevent black flickering.
|
||||||
canvas.hidden = true;
|
canvas.hidden = true;
|
||||||
let isCanvasHidden = true;
|
let isCanvasHidden = true;
|
||||||
const showCanvas = function () {
|
const hasHCM = !!(
|
||||||
if (isCanvasHidden) {
|
this.pageColors?.background && this.pageColors?.foreground
|
||||||
|
);
|
||||||
|
const showCanvas = function (isLastShow) {
|
||||||
|
// In HCM, a final filter is applied on the canvas which means that
|
||||||
|
// before it's applied we've normal colors. Consequently, to avoid to have
|
||||||
|
// a final flash we just display it once all the drawing is done.
|
||||||
|
if (isCanvasHidden && (!hasHCM || isLastShow)) {
|
||||||
canvas.hidden = false;
|
canvas.hidden = false;
|
||||||
isCanvasHidden = false;
|
isCanvasHidden = false;
|
||||||
}
|
}
|
||||||
@ -1064,7 +1070,7 @@ class PDFPageView {
|
|||||||
};
|
};
|
||||||
const renderTask = this.pdfPage.render(renderContext);
|
const renderTask = this.pdfPage.render(renderContext);
|
||||||
renderTask.onContinue = function (cont) {
|
renderTask.onContinue = function (cont) {
|
||||||
showCanvas();
|
showCanvas(false);
|
||||||
if (result.onRenderContinue) {
|
if (result.onRenderContinue) {
|
||||||
result.onRenderContinue(cont);
|
result.onRenderContinue(cont);
|
||||||
} else {
|
} else {
|
||||||
@ -1074,7 +1080,7 @@ class PDFPageView {
|
|||||||
|
|
||||||
renderTask.promise.then(
|
renderTask.promise.then(
|
||||||
function () {
|
function () {
|
||||||
showCanvas();
|
showCanvas(true);
|
||||||
renderCapability.resolve();
|
renderCapability.resolve();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@ -1082,7 +1088,7 @@ class PDFPageView {
|
|||||||
// a black canvas if rendering was cancelled before the `onContinue`-
|
// a black canvas if rendering was cancelled before the `onContinue`-
|
||||||
// callback had been invoked at least once.
|
// callback had been invoked at least once.
|
||||||
if (!(error instanceof RenderingCancelledException)) {
|
if (!(error instanceof RenderingCancelledException)) {
|
||||||
showCanvas();
|
showCanvas(true);
|
||||||
}
|
}
|
||||||
renderCapability.reject(error);
|
renderCapability.reject(error);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user