From 98c0922d63d5bae0d82e47cc850cba1ef59a424d Mon Sep 17 00:00:00 2001 From: wimrijnders Date: Tue, 13 Jun 2017 20:47:22 +0200 Subject: [PATCH] Consolidate code for determining the pixel ratio (#3088) * Consolidate code for determining the pixel ratio * - Removed local param 'pixerRatio' from CanvasRenderer. Now only canvas.pixelRatio is used. - consolidated ctx.transform() calls in Canvas - Added/edited commenting (also TODO's) - Added Canvas.getContext() --- lib/network/CachedImage.js | 4 ++ lib/network/modules/Canvas.js | 58 +++++++++++++++++++++++---- lib/network/modules/CanvasRenderer.js | 30 ++++---------- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/lib/network/CachedImage.js b/lib/network/CachedImage.js index 6e027f08..ad640017 100644 --- a/lib/network/CachedImage.js +++ b/lib/network/CachedImage.js @@ -66,6 +66,10 @@ class CachedImage { * This methods takes the resizing out of the drawing loop, in order to * reduce performance overhead. * + * TODO: The code assumes that a 2D context can always be gotten. This is + * not necessarily true! OTOH, if not true then usage of this class + * is senseless. + * * @private */ _fillMipMap() { diff --git a/lib/network/modules/Canvas.js b/lib/network/modules/Canvas.js index ee2fd387..25ef90d0 100644 --- a/lib/network/modules/Canvas.js +++ b/lib/network/modules/Canvas.js @@ -188,9 +188,8 @@ class Canvas { this.frame.canvas.appendChild(noCanvas); } else { - let ctx = this.frame.canvas.getContext("2d"); - this._setPixelRatio(ctx); - this.frame.canvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + this._setPixelRatio(); + this.setTransform(); } // add the frame to the container element @@ -257,9 +256,19 @@ class Canvas { let oldHeight = this.frame.canvas.height; // update the pixel ratio - let ctx = this.frame.canvas.getContext("2d"); + // + // NOTE: Comment in following is rather inconsistent; this is the ONLY place in the code + // where it is assumed that the pixel ratio could change at runtime. + // The only way I can think of this happening is a rotating screen or tablet; but then + // there should be a mechanism for reloading the data (TODO: check if this is present). + // + // If the assumption is true (i.e. pixel ratio can change at runtime), then *all* usage + // of pixel ratio must be overhauled for this. + // + // For the time being, I will humor the assumption here, and in the rest of the code assume it is + // constant. let previousRatio = this.pixelRatio; // we cache this because the camera state storage needs the old value - this._setPixelRatio(ctx); + this._setPixelRatio(); if (width != this.options.width || height != this.options.height || this.frame.style.width != width || this.frame.style.height != height) { this._getCameraState(previousRatio); @@ -324,11 +333,23 @@ class Canvas { }; + getContext() { + return this.frame.canvas.getContext("2d"); + } + + /** + * Determine the pixel ratio for various browsers. + * * @private */ - _setPixelRatio(ctx) { - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || + _determinePixelRatio() { + let ctx = this.getContext(); + if (ctx === undefined) { + throw "Could not get canvax context"; + } + + return (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || @@ -336,6 +357,29 @@ class Canvas { } + /** + * Lazy determination of pixel ratio. + * + * @private + */ + _setPixelRatio() { + this.pixelRatio = this._determinePixelRatio(); + } + + + /** + * Set the transform in the contained context, based on its pixelRatio + */ + setTransform() { + let ctx = this.getContext(); + if (ctx === undefined) { + throw "Could not get canvax context"; + } + + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + } + + /** * Convert the X coordinate in DOM-space (coordinate point in browser relative to the container div) to * the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) diff --git a/lib/network/modules/CanvasRenderer.js b/lib/network/modules/CanvasRenderer.js index f8d37e93..27ad7194 100644 --- a/lib/network/modules/CanvasRenderer.js +++ b/lib/network/modules/CanvasRenderer.js @@ -16,7 +16,6 @@ class CanvasRenderer { this.requiresTimeout = true; this.renderingActive = false; this.renderRequests = 0; - this.pixelRatio = undefined; this.allowRedraw = true; this.dragging = false; @@ -138,20 +137,15 @@ class CanvasRenderer { this.body.emitter.emit("initRedraw"); this.redrawRequested = false; - let ctx = this.canvas.frame.canvas.getContext('2d'); // when the container div was hidden, this fixes it back up! if (this.canvas.frame.canvas.width === 0 || this.canvas.frame.canvas.height === 0) { this.canvas.setSize(); } - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || - ctx.mozBackingStorePixelRatio || - ctx.msBackingStorePixelRatio || - ctx.oBackingStorePixelRatio || - ctx.backingStorePixelRatio || 1); + this.canvas.setTransform(); - ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + let ctx = this.canvas.getContext(); // clear the canvas let w = this.canvas.frame.canvas.clientWidth; @@ -198,21 +192,14 @@ class CanvasRenderer { /** * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * * @param {CanvasRenderingContext2D} ctx * @param {Boolean} [alwaysShow] * @private */ _resizeNodes() { - let ctx = this.canvas.frame.canvas.getContext('2d'); - if (this.pixelRatio === undefined) { - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || - ctx.mozBackingStorePixelRatio || - ctx.msBackingStorePixelRatio || - ctx.oBackingStorePixelRatio || - ctx.backingStorePixelRatio || 1); - } - ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + this.canvas.setTransform(); + let ctx = this.canvas.getContext(); ctx.save(); ctx.translate(this.body.view.translation.x, this.body.view.translation.y); ctx.scale(this.body.view.scale, this.body.view.scale); @@ -235,8 +222,8 @@ class CanvasRenderer { /** * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx + * + * @param {CanvasRenderingContext2D} ctx 2D context of a HTML canvas * @param {Boolean} [alwaysShow] * @private */ @@ -283,8 +270,7 @@ class CanvasRenderer { /** * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx + * @param {CanvasRenderingContext2D} ctx 2D context of a HTML canvas * @private */ _drawEdges(ctx) {