From 45a7a4aaf38789788c624bd62de058337eb22236 Mon Sep 17 00:00:00 2001 From: Jirka Date: Fri, 29 Apr 2022 18:41:43 +0200 Subject: [PATCH] Fix comments on #2148: hasTransparency as a property. Move '.image' tile property to be a getter instead. Rename 'ImageJob' data property from 'image' to 'data'. Repair comments related to #2148. --- src/imageloader.js | 27 ++++++++++++++------- src/tile.js | 58 +++++++++++++++++++++------------------------- src/tilecache.js | 20 +++++++--------- src/tiledimage.js | 28 ++++++++++++++-------- src/tilesource.js | 10 +++++++- 5 files changed, 81 insertions(+), 62 deletions(-) diff --git a/src/imageloader.js b/src/imageloader.js index 451fd60d..14e34f33 100644 --- a/src/imageloader.js +++ b/src/imageloader.js @@ -58,11 +58,11 @@ function ImageJob (options) { }, options); /** - * Image object which will contain downloaded image. - * @member {Image|*} image element (default) or other form of image data (depends on TileSource) + * Data object which will contain downloaded image data. + * @member {Image|*} image data object, by default an Image object (depends on TileSource) * @memberof OpenSeadragon.ImageJob# */ - this.image = null; + this.data = null; } ImageJob.prototype = { @@ -77,12 +77,11 @@ ImageJob.prototype = { var selfAbort = this.abort; this.jobId = window.setTimeout(function () { - self.errorMsg = "Image load exceeded timeout (" + self.timeout + " ms)"; - self.finish(false); + self.finish(false, "Image load exceeded timeout (" + self.timeout + " ms)"); }, this.timeout); this.abort = function() { - self.request.abort(); + self.source.downloadTileAbort(self); if (typeof selfAbort === "function") { selfAbort(); } @@ -93,8 +92,7 @@ ImageJob.prototype = { finish: function(successful, errorMessage) { this.errorMsg = errorMessage; - //consider deprecation of .image attribute - this.image = this.source.downloadTileFinish(this, successful); + this.data = this.source.downloadTileFinish(this, successful); if (this.jobId) { window.clearTimeout(this.jobId); @@ -145,6 +143,17 @@ $.ImageLoader.prototype = { * @param {Function} [options.abort] - Called when this image job is aborted. */ addJob: function(options) { + if (!options.source) { + $.console.error('ImageLoader.prototype.addJob() requires [options.source]. ' + + 'TileSource since new API defines how images are fetched. Creating a dummy TileSource.'); + let implementation = $.TileSource.prototype; + options.source = { + downloadTileStart: implementation.downloadTileStart, + downloadTileAbort: implementation.downloadTileAbort, + downloadTileFinish: implementation.downloadTileFinish + }; + } + var _this = this, complete = function(job) { completeJob(_this, job, options.callback); @@ -207,7 +216,7 @@ function completeJob(loader, job, callback) { loader.jobsInProgress++; } - callback(job.image, job.errorMsg, job.request); + callback(job.data, job.errorMsg, job.request); //todo job.request might not exist } }(OpenSeadragon)); diff --git a/src/tile.js b/src/tile.js index e09a0b59..0f5aaa60 100644 --- a/src/tile.js +++ b/src/tile.js @@ -164,12 +164,6 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, aja * @memberof OpenSeadragon.Tile# */ this.imgElement = null; - /** - * The Image object for this tile. - * @member {Object} image - * @memberof OpenSeadragon.Tile# - */ - this.image = null; /** * The alias of this.element.style. @@ -222,6 +216,13 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, aja */ this.visibility = null; + /** + * The transparency indicator of this tile. + * @member {Boolean} true if tile contains transparency for correct rendering + * @memberof OpenSeadragon.Tile# + */ + this.hasTransparency = false; + /** * Whether this tile is currently being drawn. * @member {Boolean} beingDrawn @@ -266,8 +267,8 @@ $.Tile.prototype = { // private _hasTransparencyChannel: function() { - console.warn("Tile.prototype._hasTransparencyChannel has been " + - "deprecated and will be removed in the future."); + console.warn("Tile.prototype._hasTransparencyChannel() has been " + + "deprecated and will be removed in the future. Use TileSource.prototype.hasTransparency() instead."); return !!this.context2D || this.url.match('.png'); }, @@ -296,8 +297,11 @@ $.Tile.prototype = { // content during animation of the container size. if ( !this.element ) { + var image = this.image; + if (!this.image) return; + this.element = $.makeNeutralElement( "div" ); - this.imgElement = this.imageData(); + this.imgElement = image.cloneNode(); this.imgElement.style.msInterpolationMode = "nearest-neighbor"; this.imgElement.style.width = "100%"; this.imgElement.style.height = "100%"; @@ -325,22 +329,23 @@ $.Tile.prototype = { }, /** - * Get the tile image data as element if - * supported - * - * @return {Image || undefined} + * The Image object for this tile. + * @member {Object} image + * @memberof OpenSeadragon.Tile# + * @return {Image} */ - imageData: function() { - return this.image || this.cacheImageRecord.getImage(); + get image() { + this.cacheImageRecord.getImage(); }, /** - * Get the CanvasRenderingContext2D instance for tile image data drawn - * onto Canvas if supported - * - * @return {CanvasRenderingContext2D || undefined} + * The CanvasRenderingContext2D instance for tile image data drawn + * onto Canvas if enabled and available + * @member {CanvasRenderingContext2D} canvasContext + * @memberof OpenSeadragon.Tile# + * @return {CanvasRenderingContext2D} */ - canvasContext: function() { + get canvasContext() { return this.context2D || this.cacheImageRecord.getRenderedContext(); }, @@ -372,7 +377,7 @@ $.Tile.prototype = { return; } - rendered = this.canvasContext(); + rendered = this.canvasContext; if ( !this.loaded || !rendered ){ $.console.warn( @@ -384,7 +389,6 @@ $.Tile.prototype = { } context.save(); - context.globalAlpha = this.opacity; if (typeof scale === 'number' && scale !== 1) { @@ -398,19 +402,11 @@ $.Tile.prototype = { position = position.plus(translate); } - if (source === undefined) { - $.console.warn('[Tile.drawCanvas] deprecated call without argument \'hasTransparency\'.'); - hasTransparency = context.globalAlpha === 1 && this._hasTransparencyChannel(); - } else { - hasTransparency = context.globalAlpha === 1 && - source.hasTransparency(this.context2D, this.url, this.ajaxHeaders, this.postData); - } - //if we are supposed to be rendering fully opaque rectangle, //ie its done fading or fading is turned off, and if we are drawing //an image with an alpha channel, then the only way //to avoid seeing the tile underneath is to clear the rectangle - if (hasTransparency) { + if (context.globalAlpha === 1 && this.hasTransparency) { if (shouldRoundPositionAndSize) { // Round to the nearest whole pixel so we don't get seams from overlap. position.x = Math.round(position.x); diff --git a/src/tilecache.js b/src/tilecache.js index 199e1f80..588a8636 100644 --- a/src/tilecache.js +++ b/src/tilecache.js @@ -45,7 +45,6 @@ var TileRecord = function( options ) { // private class var ImageRecord = function(options) { - //private scope: changed image -> data $.console.assert( options, "[ImageRecord] options is required" ); $.console.assert( options.data, "[ImageRecord] options.data is required" ); this._tiles = []; @@ -63,14 +62,6 @@ ImageRecord.prototype = { this._tiles = null; }, - // Removed (left as a comment so that it stands out) - // setRenderedContext: function(renderedContext) { - // $.console.error("ImageRecord.setRenderedContext is deprecated. " + - // "The rendered context should be created by the ImageRecord " + - // "itself when calling ImageRecord.getRenderedContext."); - // this._renderedContext = renderedContext; - // }, - addTile: function(tile) { $.console.assert(tile, '[ImageRecord.addTile] tile is required'); this._tiles.push(tile); @@ -146,9 +137,16 @@ $.TileCache.prototype = { var imageRecord = this._imagesLoaded[options.tile.cacheKey]; if (!imageRecord) { - $.console.assert( options.image, "[TileCache.cacheTile] options.image is required to create an ImageRecord" ); + + if (!options.data) { + $.console.error("[TileCache.cacheTile] options.image was renamed to options.data. '.image' attribute " + + "has been deprecated and will be removed in the future."); + options.data = options.image; + } + + $.console.assert( options.data, "[TileCache.cacheTile] options.data is required to create an ImageRecord" ); imageRecord = this._imagesLoaded[options.tile.cacheKey] = new ImageRecord({ - data: options.image, + data: options.data, ownerTile: options.tile, create: options.tiledImage.source.createTileCache, destroy: options.tiledImage.source.destroyTileCache, diff --git a/src/tiledimage.js b/src/tiledimage.js index 86e53357..0d44f383 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -1576,8 +1576,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag ajaxHeaders: tile.ajaxHeaders, crossOriginPolicy: this.crossOriginPolicy, ajaxWithCredentials: this.ajaxWithCredentials, - callback: function( image, errorMsg, tileRequest ){ - _this._onTileLoad( tile, time, image, errorMsg, tileRequest ); + callback: function( data, errorMsg, tileRequest ){ + _this._onTileLoad( tile, time, data, errorMsg, tileRequest ); }, abort: function() { tile.loading = false; @@ -1591,12 +1591,12 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * Callback fired when a Tile's Image finished downloading. * @param {OpenSeadragon.Tile} tile * @param {Number} time - * @param {Image} image + * @param {*} data image data * @param {String} errorMsg * @param {XMLHttpRequest} tileRequest */ - _onTileLoad: function( tile, time, image, errorMsg, tileRequest ) { - if ( !image ) { + _onTileLoad: function( tile, time, data, errorMsg, tileRequest ) { + if ( !data ) { $.console.error( "Tile %s failed to load: %s - error: %s", tile, tile.url, errorMsg ); /** * Triggered when a tile fails to load. @@ -1632,7 +1632,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag finish = function() { var ccc = _this.source; var cutoff = ccc.getClosestLevel(); - _this._setTileLoaded(tile, image, cutoff, tileRequest); + _this._setTileLoaded(tile, data, cutoff, tileRequest); }; // Check if we're mid-update; this can happen on IE8 because image load events for @@ -1649,11 +1649,11 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * @private * @inner * @param {OpenSeadragon.Tile} tile - * @param {Image|* || undefined} image + * @param {*} data image data * @param {Number || undefined} cutoff * @param {XMLHttpRequest || undefined} tileRequest */ - _setTileLoaded: function(tile, image, cutoff, tileRequest) { + _setTileLoaded: function(tile, data, cutoff, tileRequest) { var increment = 0, _this = this; @@ -1667,9 +1667,12 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag if (increment === 0) { tile.loading = false; tile.loaded = true; + tile.hasTransparency = this.source.hasTransparency( + tile.context2D, tile.url, tile.ajaxHeaders, tile.postData + ); if (!tile.context2D) { _this._tileCache.cacheTile({ - image: image, + data: data, tile: tile, cutoff: cutoff, tiledImage: _this @@ -1687,6 +1690,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag * @memberof OpenSeadragon.Viewer * @type {object} * @property {Image|*} image - The image (data) of the tile. + * @property {*} data - image data * @property {OpenSeadragon.TiledImage} tiledImage - The tiled image of the loaded tile. * @property {OpenSeadragon.Tile} tile - The tile which has been loaded. * @property {XMLHttpRequest} tileRequest - The AJAX request that loaded this tile (if applicable). @@ -1699,7 +1703,11 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag tile: tile, tiledImage: this, tileRequest: tileRequest, - image: image, + get image() { + $.console.error("[tile-loaded] event property 'image' has been deprecated and will be removed in the future"); + return data; + }, + data: data, getCompletionCallback: getCompletionCallback }); // In case the completion callback is never called, we at least force it once. diff --git a/src/tilesource.js b/src/tilesource.js index 4c9688ef..4dd22066 100644 --- a/src/tilesource.js +++ b/src/tilesource.js @@ -712,7 +712,7 @@ $.TileSource.prototype = { }, /** - * Decide whether tiles have transparency: this is crucial for + * Decide whether tiles have transparency: this is crucial for correct images blending. * @return {boolean} true if the image has transparency */ hasTransparency: function(context2D, url, ajaxHeaders, post) { @@ -794,6 +794,14 @@ $.TileSource.prototype = { } }, + /** + * Provide means of aborting the execution. + * @param {object} context job, the same object as with downloadTileStart(..) + */ + downloadTileAbort: function (context) { + context.request.abort(); + }, + /** * @param {object} context job, the same object as with downloadTileStart(..) * @param successful true if successful