From 3402d33088b067eea6cc9ddc379df2fadf855a53 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Jan 2015 11:19:49 -0500 Subject: [PATCH 1/6] WIP basic high pixel density support re: openseadragon/openseadragon#541 --- src/drawer.js | 21 +++++++++++++++++++-- src/openseadragon.js | 26 ++++++++++++++++++++++++++ src/tiledimage.js | 4 ++-- src/viewport.js | 10 +++++++++- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/drawer.js b/src/drawer.js index cfd2c71d..3ae136de 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -108,6 +108,13 @@ $.Drawer = function( options ) { // Note that this means overlays you want to be rtl need to be explicitly set to rtl. this.container.dir = 'ltr'; + // check canvas available width and height, set canvas width and height such that the canvas backing store is set to the proper pixel density + if (this.useCanvas) { + var viewportSize = this._calculateCanvasSize(); + this.canvas.width = viewportSize.x; + this.canvas.height = viewportSize.y; + } + this.canvas.style.width = "100%"; this.canvas.style.height = "100%"; this.canvas.style.position = "absolute"; @@ -215,7 +222,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ clear: function() { this.canvas.innerHTML = ""; if ( this.useCanvas ) { - var viewportSize = this.viewport.getContainerSize(); + var viewportSize = this._calculateCanvasSize(); if( this.canvas.width != viewportSize.x || this.canvas.height != viewportSize.y ) { this.canvas.width = viewportSize.x; @@ -256,7 +263,7 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ if ( this.useCanvas ) { this.context.save(); this.context.lineWidth = 2; - this.context.font = 'small-caps bold 13px ariel'; + this.context.font = 'small-caps bold 13px arial'; this.context.strokeStyle = this.debugGridColor; this.context.fillStyle = this.debugGridColor; @@ -369,6 +376,16 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ tile.position.y = py; this.context.restore(); + }, + + // private + _calculateCanvasSize: function() { + var pixelDensityRatio = $.pixelDensityRatio; + var viewportSize = this.viewport.getContainerSize(); + return { + x: viewportSize.x * pixelDensityRatio, + y: viewportSize.y * pixelDensityRatio + }; } }; diff --git a/src/openseadragon.js b/src/openseadragon.js index 1db57c67..44a02ef6 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -816,6 +816,32 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ canvasElement.getContext( '2d' ) ); }()); + /** + * @private + * @inner + * @function + * @returns {Number} The device's pixel density ratio, or null if canvas isn't supported by the browser. + */ + $.pixelDensityRatio = (function () { + if ( $.supportsCanvas ) { + var context = document.createElement('canvas').getContext('2d'); + var devicePixelRatio = window.devicePixelRatio || 1; + var backingStoreRatio = context.webkitBackingStorePixelRatio || + context.mozBackingStorePixelRatio || + context.msBackingStorePixelRatio || + context.oBackingStorePixelRatio || + context.backingStorePixelRatio || 1; + return devicePixelRatio / backingStoreRatio; + // var viewportSize = this.viewport.getContainerSize(); + // return { + // x: viewportSize.x * canvasDensityRatio, + // y: viewportSize.y * canvasDensityRatio, + // ratio: canvasDensityRatio + // }; + } else { + return 1; + } + }()); }( OpenSeadragon )); diff --git a/src/tiledimage.js b/src/tiledimage.js index fc444b83..34c8cd3b 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -262,7 +262,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag // private _viewportToImageDelta: function( viewerX, viewerY, current ) { - var scale = current ? this._scaleSpring.current.value : this._scaleSpring.target.value; + var scale = (current ? this._scaleSpring.current.value : this._scaleSpring.target.value) / $.pixelDensityRatio; return new $.Point(viewerX * (this.source.dimensions.x / scale), viewerY * ((this.source.dimensions.y * this.contentAspectX) / scale)); }, @@ -294,7 +294,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag // private _imageToViewportDelta: function( imageX, imageY, current ) { - var scale = current ? this._scaleSpring.current.value : this._scaleSpring.target.value; + var scale = (current ? this._scaleSpring.current.value : this._scaleSpring.target.value) / $.pixelDensityRatio; return new $.Point((imageX / this.source.dimensions.x) * scale, (imageY / this.source.dimensions.y / this.contentAspectX) * scale); }, diff --git a/src/viewport.js b/src/viewport.js index 44654f7e..d1f52223 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -897,6 +897,8 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ deltaPixelsFromPoints: function( deltaPoints, current ) { return deltaPoints.times( this._containerInnerSize.x * this.getZoom( current ) + ).times( + $.pixelDensityRatio ); }, @@ -908,6 +910,8 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ deltaPointsFromPixels: function( deltaPixels, current ) { return deltaPixels.divide( this._containerInnerSize.x * this.getZoom( current ) + ).divide( + $.pixelDensityRatio ); }, @@ -928,6 +932,8 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ this._containerInnerSize.x / bounds.width ).plus( new $.Point(this._margins.left, this._margins.top) + ).times( + $.pixelDensityRatio ); }, @@ -938,7 +944,9 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ */ pointFromPixel: function( pixel, current ) { var bounds = this.getBounds( current ); - return pixel.minus( + return pixel.divide( + $.pixelDensityRatio + ).minus( new $.Point(this._margins.left, this._margins.top) ).divide( this._containerInnerSize.x / bounds.width From a23da44b8f8682cfdbfe33a02266fd4392e34517 Mon Sep 17 00:00:00 2001 From: Wesley Fok Date: Thu, 29 Jan 2015 15:14:41 -0500 Subject: [PATCH 2/6] Clean up $.pixelDensityRatio comments --- src/openseadragon.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 44a02ef6..f029a7c8 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -817,10 +817,9 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ }()); /** - * @private - * @inner - * @function - * @returns {Number} The device's pixel density ratio, or null if canvas isn't supported by the browser. + * A ratio comparing the device screen's pixel density to the canvas's backing store pixel density. Defaults to 1 if canvas isn't supported by the browser. + * @member {Number} pixelDensityRatio + * @memberof OpenSeadragon */ $.pixelDensityRatio = (function () { if ( $.supportsCanvas ) { @@ -832,12 +831,6 @@ window.OpenSeadragon = window.OpenSeadragon || function( options ){ context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; return devicePixelRatio / backingStoreRatio; - // var viewportSize = this.viewport.getContainerSize(); - // return { - // x: viewportSize.x * canvasDensityRatio, - // y: viewportSize.y * canvasDensityRatio, - // ratio: canvasDensityRatio - // }; } else { return 1; } From 28ddf5a8091dae4875688fbed019d52822846c40 Mon Sep 17 00:00:00 2001 From: Wesley Fok Date: Fri, 30 Jan 2015 15:46:52 -0500 Subject: [PATCH 3/6] Backed out old coordinate translation modifications, moving pixel density check to rendering code --- src/tile.js | 20 ++++++++++---------- src/tiledimage.js | 5 +++-- src/viewport.js | 10 +--------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/tile.js b/src/tile.js index 30082315..e2f34941 100644 --- a/src/tile.js +++ b/src/tile.js @@ -268,18 +268,18 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ //clearing only the inside of the rectangle occupied //by the png prevents edge flikering context.clearRect( - position.x+1, - position.y+1, - size.x-2, - size.y-2 + (position.x * $.pixelDensityRatio)+1, + (position.y * $.pixelDensityRatio)+1, + (size.x * $.pixelDensityRatio)-2, + (size.y * $.pixelDensityRatio)-2 ); } if(!rendered){ canvas = document.createElement( 'canvas' ); - canvas.width = this.image.width; - canvas.height = this.image.height; + canvas.width = this.image.width * $.pixelDensityRatio; + canvas.height = this.image.height * $.pixelDensityRatio; rendered = canvas.getContext('2d'); rendered.drawImage( this.image, 0, 0 ); this.cacheImageRecord.setRenderedContext(rendered); @@ -297,10 +297,10 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ 0, rendered.canvas.width, rendered.canvas.height, - position.x, - position.y, - size.x, - size.y + position.x * $.pixelDensityRatio, + position.y * $.pixelDensityRatio, + size.x * $.pixelDensityRatio, + size.y * $.pixelDensityRatio ); }, diff --git a/src/tiledimage.js b/src/tiledimage.js index 34c8cd3b..2f3378d2 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -262,7 +262,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag // private _viewportToImageDelta: function( viewerX, viewerY, current ) { - var scale = (current ? this._scaleSpring.current.value : this._scaleSpring.target.value) / $.pixelDensityRatio; + var scale = (current ? this._scaleSpring.current.value : this._scaleSpring.target.value); return new $.Point(viewerX * (this.source.dimensions.x / scale), viewerY * ((this.source.dimensions.y * this.contentAspectX) / scale)); }, @@ -294,7 +294,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag // private _imageToViewportDelta: function( imageX, imageY, current ) { - var scale = (current ? this._scaleSpring.current.value : this._scaleSpring.target.value) / $.pixelDensityRatio; + var scale = (current ? this._scaleSpring.current.value : this._scaleSpring.target.value); return new $.Point((imageX / this.source.dimensions.x) * scale, (imageY / this.source.dimensions.y / this.contentAspectX) * scale); }, @@ -562,6 +562,7 @@ function updateViewport( tiledImage ) { var viewportBR = viewportBounds.getBottomRight(); //Don't draw if completely outside of the viewport + $.console.log(viewportTL.x); if ( !tiledImage.wrapHorizontal && (viewportBR.x < 0 || viewportTL.x > tiledImage._worldWidthCurrent ) ) { return; } diff --git a/src/viewport.js b/src/viewport.js index d1f52223..44654f7e 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -897,8 +897,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ deltaPixelsFromPoints: function( deltaPoints, current ) { return deltaPoints.times( this._containerInnerSize.x * this.getZoom( current ) - ).times( - $.pixelDensityRatio ); }, @@ -910,8 +908,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ deltaPointsFromPixels: function( deltaPixels, current ) { return deltaPixels.divide( this._containerInnerSize.x * this.getZoom( current ) - ).divide( - $.pixelDensityRatio ); }, @@ -932,8 +928,6 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ this._containerInnerSize.x / bounds.width ).plus( new $.Point(this._margins.left, this._margins.top) - ).times( - $.pixelDensityRatio ); }, @@ -944,9 +938,7 @@ $.Viewport.prototype = /** @lends OpenSeadragon.Viewport.prototype */{ */ pointFromPixel: function( pixel, current ) { var bounds = this.getBounds( current ); - return pixel.divide( - $.pixelDensityRatio - ).minus( + return pixel.minus( new $.Point(this._margins.left, this._margins.top) ).divide( this._containerInnerSize.x / bounds.width From 832ba62df0a857d0e3087ae1f4a652b4d395a92e Mon Sep 17 00:00:00 2001 From: Wesley Fok Date: Fri, 30 Jan 2015 16:03:45 -0500 Subject: [PATCH 4/6] Remove unneeded $.console.log calls --- src/tiledimage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tiledimage.js b/src/tiledimage.js index 2f3378d2..c75bdc1c 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -562,7 +562,6 @@ function updateViewport( tiledImage ) { var viewportBR = viewportBounds.getBottomRight(); //Don't draw if completely outside of the viewport - $.console.log(viewportTL.x); if ( !tiledImage.wrapHorizontal && (viewportBR.x < 0 || viewportTL.x > tiledImage._worldWidthCurrent ) ) { return; } From b67cf2aa087b507e8652c4e2e5d23a8625c1968a Mon Sep 17 00:00:00 2001 From: Wesley Fok Date: Fri, 30 Jan 2015 16:40:34 -0500 Subject: [PATCH 5/6] Fixed tile image canvas being too large --- src/tile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tile.js b/src/tile.js index e2f34941..756d9d4a 100644 --- a/src/tile.js +++ b/src/tile.js @@ -278,8 +278,8 @@ $.Tile.prototype = /** @lends OpenSeadragon.Tile.prototype */{ if(!rendered){ canvas = document.createElement( 'canvas' ); - canvas.width = this.image.width * $.pixelDensityRatio; - canvas.height = this.image.height * $.pixelDensityRatio; + canvas.width = this.image.width; + canvas.height = this.image.height; rendered = canvas.getContext('2d'); rendered.drawImage( this.image, 0, 0 ); this.cacheImageRecord.setRenderedContext(rendered); From 65c8ed6f36ccb30c8e60b8fc1f9e8f5e4b530885 Mon Sep 17 00:00:00 2001 From: Wesley Fok Date: Tue, 3 Feb 2015 14:45:39 -0500 Subject: [PATCH 6/6] drawDebugInfo is now high-dpi aware --- src/drawer.js | 67 +++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/drawer.js b/src/drawer.js index 3ae136de..77f078ad 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -262,22 +262,24 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ drawDebugInfo: function( tile, count, i ){ if ( this.useCanvas ) { this.context.save(); - this.context.lineWidth = 2; - this.context.font = 'small-caps bold 13px arial'; + this.context.lineWidth = 2 * $.pixelDensityRatio; + this.context.font = 'small-caps bold ' + (13 * $.pixelDensityRatio) + 'px arial'; this.context.strokeStyle = this.debugGridColor; this.context.fillStyle = this.debugGridColor; - this._offsetForRotation( tile, this.canvas, this.context, this.viewport.degrees ); + if ( this.viewport.degrees !== 0 ) { + this._offsetForRotation( tile, this.canvas, this.context, this.viewport.degrees ); + } this.context.strokeRect( - tile.position.x, - tile.position.y, - tile.size.x, - tile.size.y + tile.position.x * $.pixelDensityRatio, + tile.position.y * $.pixelDensityRatio, + tile.size.x * $.pixelDensityRatio, + tile.size.y * $.pixelDensityRatio ); - var tileCenterX = tile.position.x + (tile.size.x / 2); - var tileCenterY = tile.position.y + (tile.size.y / 2); + var tileCenterX = (tile.position.x + (tile.size.x / 2)) * $.pixelDensityRatio; + var tileCenterY = (tile.position.y + (tile.size.y / 2)) * $.pixelDensityRatio; // Rotate the text the right way around. this.context.translate( tileCenterX, tileCenterY ); @@ -287,46 +289,49 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ if( tile.x === 0 && tile.y === 0 ){ this.context.fillText( "Zoom: " + this.viewport.getZoom(), - tile.position.x, - tile.position.y - 30 + tile.position.x * $.pixelDensityRatio, + (tile.position.y - 30) * $.pixelDensityRatio ); this.context.fillText( "Pan: " + this.viewport.getBounds().toString(), - tile.position.x, - tile.position.y - 20 + tile.position.x * $.pixelDensityRatio, + (tile.position.y - 20) * $.pixelDensityRatio ); } this.context.fillText( "Level: " + tile.level, - tile.position.x + 10, - tile.position.y + 20 + (tile.position.x + 10) * $.pixelDensityRatio, + (tile.position.y + 20) * $.pixelDensityRatio ); this.context.fillText( "Column: " + tile.x, - tile.position.x + 10, - tile.position.y + 30 + (tile.position.x + 10) * $.pixelDensityRatio, + (tile.position.y + 30) * $.pixelDensityRatio ); this.context.fillText( "Row: " + tile.y, - tile.position.x + 10, - tile.position.y + 40 + (tile.position.x + 10) * $.pixelDensityRatio, + (tile.position.y + 40) * $.pixelDensityRatio ); this.context.fillText( "Order: " + i + " of " + count, - tile.position.x + 10, - tile.position.y + 50 + (tile.position.x + 10) * $.pixelDensityRatio, + (tile.position.y + 50) * $.pixelDensityRatio ); this.context.fillText( "Size: " + tile.size.toString(), - tile.position.x + 10, - tile.position.y + 60 + (tile.position.x + 10) * $.pixelDensityRatio, + (tile.position.y + 60) * $.pixelDensityRatio ); this.context.fillText( "Position: " + tile.position.toString(), - tile.position.x + 10, - tile.position.y + 70 + (tile.position.x + 10) * $.pixelDensityRatio, + (tile.position.y + 70) * $.pixelDensityRatio ); - this._restoreRotationChanges( tile, this.canvas, this.context ); + + if ( this.viewport.degrees !== 0 ) { + this._restoreRotationChanges( tile, this.canvas, this.context ); + } this.context.restore(); } }, @@ -335,15 +340,15 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ debugRect: function(rect) { if ( this.useCanvas ) { this.context.save(); - this.context.lineWidth = 2; + this.context.lineWidth = 2 * $.pixelDensityRatio; this.context.strokeStyle = this.debugGridColor; this.context.fillStyle = this.debugGridColor; this.context.strokeRect( - rect.x, - rect.y, - rect.width, - rect.height + rect.x * $.pixelDensityRatio, + rect.y * $.pixelDensityRatio, + rect.width * $.pixelDensityRatio, + rect.height * $.pixelDensityRatio ); this.context.restore();