2013-05-01 00:46:16 -04:00
|
|
|
/*
|
2013-05-14 00:00:24 -04:00
|
|
|
* OpenSeadragon - Tile
|
2013-05-01 00:46:16 -04:00
|
|
|
*
|
|
|
|
* Copyright (C) 2009 CodePlex Foundation
|
2023-12-14 19:14:05 -05:00
|
|
|
* Copyright (C) 2010-2024 OpenSeadragon contributors
|
2013-05-01 00:46:16 -04:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met:
|
|
|
|
*
|
|
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* - Neither the name of CodePlex Foundation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2011-12-05 22:50:25 -05:00
|
|
|
(function( $ ){
|
2014-11-05 13:48:27 -08:00
|
|
|
|
2012-01-25 14:14:02 -05:00
|
|
|
/**
|
2013-11-15 22:19:53 -08:00
|
|
|
* @class Tile
|
|
|
|
* @memberof OpenSeadragon
|
2012-01-31 15:59:09 -05:00
|
|
|
* @param {Number} level The zoom level this tile belongs to.
|
|
|
|
* @param {Number} x The vector component 'x'.
|
|
|
|
* @param {Number} y The vector component 'y'.
|
2018-03-21 14:07:00 -07:00
|
|
|
* @param {OpenSeadragon.Rect} bounds Where this tile fits, in normalized
|
2012-03-01 08:38:15 -05:00
|
|
|
* coordinates.
|
2013-06-19 13:33:25 -04:00
|
|
|
* @param {Boolean} exists Is this tile a part of a sparse image? ( Also has
|
2012-03-01 08:38:15 -05:00
|
|
|
* this tile failed to load? )
|
2022-12-16 14:14:40 -08:00
|
|
|
* @param {String|Function} url The URL of this tile's image or a function that returns a url.
|
2023-09-08 08:47:43 +02:00
|
|
|
* @param {CanvasRenderingContext2D} [context2D=undefined] The context2D of this tile if it
|
|
|
|
* * is provided directly by the tile source. Deprecated: use Tile::setCache(...) instead.
|
2016-10-21 17:28:12 -04:00
|
|
|
* @param {Boolean} loadWithAjax Whether this tile image should be loaded with an AJAX request .
|
2016-11-08 12:27:30 -05:00
|
|
|
* @param {Object} ajaxHeaders The headers to send with this tile's AJAX request (if applicable).
|
2018-03-21 14:07:00 -07:00
|
|
|
* @param {OpenSeadragon.Rect} sourceBounds The portion of the tile to use as the source of the
|
2022-03-23 10:22:13 +01:00
|
|
|
* drawing operation, in pixels. Note that this only works when drawing with canvas; when drawing
|
|
|
|
* with HTML the entire tile is always used.
|
2022-04-13 10:47:48 +02:00
|
|
|
* @param {String} postData HTTP POST data (usually but not necessarily in k=v&k2=v2... form,
|
2022-05-04 15:16:13 +02:00
|
|
|
* see TileSource::getPostData) or null
|
2022-03-29 09:30:25 +02:00
|
|
|
* @param {String} cacheKey key to act as a tile cache, must be unique for tiles with unique image data
|
2012-01-25 14:14:02 -05:00
|
|
|
*/
|
2022-03-29 09:30:25 +02:00
|
|
|
$.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, ajaxHeaders, sourceBounds, postData, cacheKey) {
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The zoom level this tile belongs to.
|
|
|
|
* @member {Number} level
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-11 18:22:13 -05:00
|
|
|
this.level = level;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The vector component 'x'.
|
|
|
|
* @member {Number} x
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-11 18:22:13 -05:00
|
|
|
this.x = x;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The vector component 'y'.
|
|
|
|
* @member {Number} y
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-11 18:22:13 -05:00
|
|
|
this.y = y;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* Where this tile fits, in normalized coordinates
|
2015-04-19 16:10:37 -04:00
|
|
|
* @member {OpenSeadragon.Rect} bounds
|
2013-11-25 08:48:44 -08:00
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.bounds = bounds;
|
2023-07-26 15:42:18 -04:00
|
|
|
/**
|
|
|
|
* Where this tile fits, in normalized coordinates, after positioning
|
|
|
|
* @member {OpenSeadragon.Rect} positionedBounds
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.positionedBounds = new OpenSeadragon.Rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
2018-03-21 14:07:00 -07:00
|
|
|
/**
|
2022-04-16 21:19:54 +02:00
|
|
|
* The portion of the tile to use as the source of the drawing operation, in pixels. Note that
|
|
|
|
* this only works when drawing with canvas; when drawing with HTML the entire tile is always used.
|
|
|
|
* @member {OpenSeadragon.Rect} sourceBounds
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2018-03-21 14:07:00 -07:00
|
|
|
this.sourceBounds = sourceBounds;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* Is this tile a part of a sparse image? Also has this tile failed to load?
|
|
|
|
* @member {Boolean} exists
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.exists = exists;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
2022-11-29 15:00:24 -05:00
|
|
|
* Private property to hold string url or url retriever function.
|
|
|
|
* Consumers should access via Tile.getUrl()
|
|
|
|
* @private
|
2022-12-16 14:14:40 -08:00
|
|
|
* @member {String|Function} url
|
2013-11-25 08:48:44 -08:00
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2022-11-29 15:00:24 -05:00
|
|
|
this._url = url;
|
2021-12-08 09:54:14 +01:00
|
|
|
/**
|
2022-04-13 10:47:48 +02:00
|
|
|
* Post parameters for this tile. For example, it can be an URL-encoded string
|
|
|
|
* in k1=v1&k2=v2... format, or a JSON, or a FormData instance... or null if no POST request used
|
2022-03-23 10:22:13 +01:00
|
|
|
* @member {String} postData HTTP POST data (usually but not necessarily in k=v&k2=v2... form,
|
2022-05-04 15:16:13 +02:00
|
|
|
* see TileSource::getPostData) or null
|
2021-12-08 09:54:14 +01:00
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.postData = postData;
|
2015-11-02 19:42:14 -05:00
|
|
|
/**
|
|
|
|
* The context2D of this tile if it is provided directly by the tile source.
|
|
|
|
* @member {CanvasRenderingContext2D} context2D
|
|
|
|
* @memberOf OpenSeadragon.Tile#
|
|
|
|
*/
|
2023-09-08 08:47:43 +02:00
|
|
|
if (context2D) {
|
|
|
|
this.context2D = context2D;
|
|
|
|
}
|
2016-10-21 17:28:12 -04:00
|
|
|
/**
|
2016-11-08 12:27:30 -05:00
|
|
|
* Whether to load this tile's image with an AJAX request.
|
2016-10-21 17:28:12 -04:00
|
|
|
* @member {Boolean} loadWithAjax
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.loadWithAjax = loadWithAjax;
|
|
|
|
/**
|
|
|
|
* The headers to be used in requesting this tile's image.
|
|
|
|
* Only used if loadWithAjax is set to true.
|
2016-11-08 12:27:30 -05:00
|
|
|
* @member {Object} ajaxHeaders
|
2016-10-21 17:28:12 -04:00
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2016-11-08 12:27:30 -05:00
|
|
|
this.ajaxHeaders = ajaxHeaders;
|
2022-04-16 21:19:54 +02:00
|
|
|
|
2022-04-07 14:48:26 +02:00
|
|
|
if (cacheKey === undefined) {
|
2022-08-09 10:40:57 +01:00
|
|
|
$.console.warn("Tile constructor needs 'cacheKey' variable: creation tile cache" +
|
2022-04-07 14:48:26 +02:00
|
|
|
" in Tile class is deprecated. TileSource.prototype.getTileHashKey will be used.");
|
|
|
|
cacheKey = $.TileSource.prototype.getTileHashKey(level, x, y, url, ajaxHeaders, postData);
|
|
|
|
}
|
2022-04-16 21:19:54 +02:00
|
|
|
/**
|
2023-09-08 08:47:43 +02:00
|
|
|
* The unique main cache key for this tile. Created automatically
|
|
|
|
* from the given tiledImage.source.getTileHashKey(...) implementation.
|
2022-04-16 21:19:54 +02:00
|
|
|
* @member {String} cacheKey
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2022-03-29 09:30:25 +02:00
|
|
|
this.cacheKey = cacheKey;
|
2023-09-24 22:30:28 +02:00
|
|
|
/**
|
|
|
|
* By default equal to tile.cacheKey, marks a cache associated with this tile
|
|
|
|
* that holds the cache original data (it was loaded with). In case you
|
|
|
|
* change the tile data, the tile original data should be left with the cache
|
|
|
|
* 'originalCacheKey' and the new, modified data should be stored in cache 'cacheKey'.
|
2023-11-18 20:16:35 +01:00
|
|
|
* This key is used in cache resolution: in case new tile data is requested, if
|
|
|
|
* this cache key exists in the cache it is loaded.
|
2023-09-24 22:30:28 +02:00
|
|
|
* @member {String} originalCacheKey
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.originalCacheKey = this.cacheKey;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* Is this tile loaded?
|
|
|
|
* @member {Boolean} loaded
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.loaded = false;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* Is this tile loading?
|
|
|
|
* @member {Boolean} loading
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.loading = false;
|
|
|
|
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The HTML div element for this tile
|
|
|
|
* @member {Element} element
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-02-01 16:56:04 -05:00
|
|
|
this.element = null;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The HTML img element for this tile.
|
|
|
|
* @member {Element} imgElement
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2013-10-28 12:36:29 -07:00
|
|
|
this.imgElement = null;
|
2012-01-31 15:59:09 -05:00
|
|
|
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The alias of this.element.style.
|
|
|
|
* @member {String} style
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.style = null;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* This tile's position on screen, in pixels.
|
|
|
|
* @member {OpenSeadragon.Point} position
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.position = null;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* This tile's size on screen, in pixels.
|
|
|
|
* @member {OpenSeadragon.Point} size
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.size = null;
|
2020-10-29 20:02:35 +00:00
|
|
|
/**
|
|
|
|
* Whether to flip the tile when rendering.
|
|
|
|
* @member {Boolean} flipped
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.flipped = false;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The start time of this tile's blending.
|
|
|
|
* @member {Number} blendStart
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.blendStart = null;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The current opacity this tile should be.
|
|
|
|
* @member {Number} opacity
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.opacity = null;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
2016-09-02 10:31:36 -04:00
|
|
|
* The squared distance of this tile to the viewport center.
|
|
|
|
* Use for comparing tiles.
|
2016-09-22 23:01:32 -04:00
|
|
|
* @private
|
2016-09-02 10:31:36 -04:00
|
|
|
* @member {Number} squaredDistance
|
2013-11-25 08:48:44 -08:00
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2016-09-02 10:31:36 -04:00
|
|
|
this.squaredDistance = null;
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* The visibility score of this tile.
|
|
|
|
* @member {Number} visibility
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.visibility = null;
|
|
|
|
|
2022-04-29 18:41:43 +02:00
|
|
|
/**
|
|
|
|
* The transparency indicator of this tile.
|
2022-05-04 15:16:13 +02:00
|
|
|
* @member {Boolean} hasTransparency true if tile contains transparency for correct rendering
|
2022-04-29 18:41:43 +02:00
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.hasTransparency = false;
|
|
|
|
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* Whether this tile is currently being drawn.
|
|
|
|
* @member {Boolean} beingDrawn
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.beingDrawn = false;
|
2017-09-08 14:03:40 -07:00
|
|
|
|
2013-11-25 08:48:44 -08:00
|
|
|
/**
|
|
|
|
* Timestamp the tile was last touched.
|
|
|
|
* @member {Number} lastTouchTime
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
2012-01-31 15:59:09 -05:00
|
|
|
this.lastTouchTime = 0;
|
2017-09-08 14:03:40 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether this tile is in the right-most column for its level.
|
|
|
|
* @member {Boolean} isRightMost
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.isRightMost = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether this tile is in the bottom-most row for its level.
|
|
|
|
* @member {Boolean} isBottomMost
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.isBottomMost = false;
|
2023-12-10 16:34:42 +01:00
|
|
|
|
2023-09-08 08:47:43 +02:00
|
|
|
/**
|
2023-12-10 16:34:42 +01:00
|
|
|
* Owner of this tile. Do not change this property manually.
|
2023-09-08 08:47:43 +02:00
|
|
|
* @member {OpenSeadragon.TiledImage}
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
*/
|
|
|
|
this.tiledImage = null;
|
|
|
|
/**
|
|
|
|
* Array of cached tile data associated with the tile.
|
|
|
|
* @member {Object} _caches
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._caches = {};
|
2023-11-26 21:32:26 +01:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._cacheSize = 0;
|
2011-12-05 22:50:25 -05:00
|
|
|
};
|
|
|
|
|
2016-01-24 16:09:18 -05:00
|
|
|
/** @lends OpenSeadragon.Tile.prototype */
|
|
|
|
$.Tile.prototype = {
|
2013-06-19 13:33:25 -04:00
|
|
|
|
2012-01-31 15:59:09 -05:00
|
|
|
/**
|
2013-06-19 13:33:25 -04:00
|
|
|
* Provides a string representation of this tiles level and (x,y)
|
2012-01-31 15:59:09 -05:00
|
|
|
* components.
|
|
|
|
* @function
|
|
|
|
* @returns {String}
|
|
|
|
*/
|
2011-12-05 22:50:25 -05:00
|
|
|
toString: function() {
|
|
|
|
return this.level + "/" + this.x + "_" + this.y;
|
|
|
|
},
|
2012-01-11 18:22:13 -05:00
|
|
|
|
2022-04-16 21:19:54 +02:00
|
|
|
/**
|
2022-04-29 18:41:43 +02:00
|
|
|
* The Image object for this tile.
|
|
|
|
* @member {Object} image
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
2022-05-04 15:16:13 +02:00
|
|
|
* @deprecated
|
2022-10-10 01:12:18 +05:30
|
|
|
* @returns {Image}
|
2022-04-16 21:19:54 +02:00
|
|
|
*/
|
2022-04-29 18:41:43 +02:00
|
|
|
get image() {
|
2023-11-26 21:32:26 +01:00
|
|
|
$.console.error("[Tile.image] property has been deprecated. Use [Tile.getData] instead.");
|
2022-05-04 15:16:13 +02:00
|
|
|
return this.getImage();
|
|
|
|
},
|
|
|
|
|
2022-11-29 15:00:24 -05:00
|
|
|
/**
|
|
|
|
* The URL of this tile's image.
|
|
|
|
* @member {String} url
|
|
|
|
* @memberof OpenSeadragon.Tile#
|
|
|
|
* @deprecated
|
|
|
|
* @returns {String}
|
|
|
|
*/
|
|
|
|
get url() {
|
2023-11-26 21:32:26 +01:00
|
|
|
$.console.error("[Tile.url] property has been deprecated. Use [Tile.getUrl] instead.");
|
2022-11-29 15:00:24 -05:00
|
|
|
return this.getUrl();
|
|
|
|
},
|
|
|
|
|
2022-05-04 15:16:13 +02:00
|
|
|
/**
|
|
|
|
* Get the Image object for this tile.
|
2023-09-08 08:47:43 +02:00
|
|
|
* @returns {?Image}
|
2022-05-04 15:16:13 +02:00
|
|
|
*/
|
|
|
|
getImage: function() {
|
2024-02-04 15:41:05 +01:00
|
|
|
$.console.error("[Tile.getImage] property has been deprecated. Use [Tile.getData] instead.");
|
2023-11-26 21:32:26 +01:00
|
|
|
//this method used to ensure the underlying data model conformed to given type - convert instead of getData()
|
|
|
|
const cache = this.getCache(this.cacheKey);
|
|
|
|
if (!cache) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
cache.transformTo("image");
|
|
|
|
return cache.data;
|
2022-04-16 21:19:54 +02:00
|
|
|
},
|
|
|
|
|
2022-11-29 15:00:24 -05:00
|
|
|
/**
|
|
|
|
* Get the url string for this tile.
|
|
|
|
* @returns {String}
|
|
|
|
*/
|
|
|
|
getUrl: function() {
|
|
|
|
if (typeof this._url === 'function') {
|
|
|
|
return this._url();
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._url;
|
|
|
|
},
|
|
|
|
|
2022-04-16 21:19:54 +02:00
|
|
|
/**
|
2022-05-04 15:16:13 +02:00
|
|
|
* Get the CanvasRenderingContext2D instance for tile image data drawn
|
2022-04-29 18:41:43 +02:00
|
|
|
* onto Canvas if enabled and available
|
2023-09-08 08:47:43 +02:00
|
|
|
* @returns {?CanvasRenderingContext2D}
|
2022-04-16 21:19:54 +02:00
|
|
|
*/
|
2022-05-04 15:16:13 +02:00
|
|
|
getCanvasContext: function() {
|
2024-02-04 15:41:05 +01:00
|
|
|
$.console.error("[Tile.getCanvasContext] property has been deprecated. Use [Tile.getData] instead.");
|
2023-11-26 21:32:26 +01:00
|
|
|
//this method used to ensure the underlying data model conformed to given type - convert instead of getData()
|
|
|
|
const cache = this.getCache(this.cacheKey);
|
|
|
|
if (!cache) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
cache.transformTo("context2d");
|
|
|
|
return cache.data;
|
2023-09-08 08:47:43 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The context2D of this tile if it is provided directly by the tile source.
|
|
|
|
* @deprecated
|
|
|
|
* @type {CanvasRenderingContext2D} context2D
|
|
|
|
*/
|
|
|
|
get context2D() {
|
2023-11-26 21:32:26 +01:00
|
|
|
$.console.error("[Tile.context2D] property has been deprecated. Use [Tile.getData] instead.");
|
|
|
|
return this.getCanvasContext();
|
2023-09-08 08:47:43 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The context2D of this tile if it is provided directly by the tile source.
|
|
|
|
* @deprecated
|
|
|
|
*/
|
|
|
|
set context2D(value) {
|
2023-11-26 21:32:26 +01:00
|
|
|
$.console.error("[Tile.context2D] property has been deprecated. Use [Tile.setData] instead.");
|
2023-09-08 08:47:43 +02:00
|
|
|
this.setData(value, "context2d");
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The default cache for this tile.
|
|
|
|
* @deprecated
|
|
|
|
* @type OpenSeadragon.CacheRecord
|
|
|
|
*/
|
|
|
|
get cacheImageRecord() {
|
|
|
|
$.console.error("[Tile.cacheImageRecord] property has been deprecated. Use Tile::getCache.");
|
|
|
|
return this.getCache(this.cacheKey);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The default cache for this tile.
|
|
|
|
* @deprecated
|
|
|
|
*/
|
|
|
|
set cacheImageRecord(value) {
|
|
|
|
$.console.error("[Tile.cacheImageRecord] property has been deprecated. Use Tile::setCache.");
|
2023-11-26 21:32:26 +01:00
|
|
|
const cache = this._caches[this.cacheKey];
|
|
|
|
|
|
|
|
if (!value) {
|
|
|
|
this.unsetCache(this.cacheKey);
|
|
|
|
} else {
|
|
|
|
const _this = this;
|
|
|
|
cache.await().then(x => _this.setCache(this.cacheKey, x, cache.type, false));
|
|
|
|
}
|
2023-09-08 08:47:43 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2023-11-27 12:12:54 +01:00
|
|
|
* Get the data to render for this tile
|
2023-11-26 21:32:26 +01:00
|
|
|
* @param {string} type data type to require
|
2023-12-10 16:34:42 +01:00
|
|
|
* @param {boolean?} [copy=true] whether to force copy retrieval
|
2023-11-18 20:16:35 +01:00
|
|
|
* @return {*|undefined} data in the desired type, or undefined if a conversion is ongoing
|
2023-09-08 08:47:43 +02:00
|
|
|
*/
|
2023-12-10 16:34:42 +01:00
|
|
|
getData: function(type, copy = true) {
|
|
|
|
if (!this.tiledImage) {
|
|
|
|
return null; //async can access outside its lifetime
|
|
|
|
}
|
|
|
|
|
2023-11-26 21:32:26 +01:00
|
|
|
//we return the data synchronously immediatelly (undefined if conversion happens)
|
2023-09-08 08:47:43 +02:00
|
|
|
const cache = this.getCache(this.cacheKey);
|
|
|
|
if (!cache) {
|
2023-11-26 21:32:26 +01:00
|
|
|
$.console.error("[Tile::getData] There is no cache available for tile with key " + this.cacheKey);
|
2023-09-08 08:47:43 +02:00
|
|
|
return undefined;
|
|
|
|
}
|
2023-11-26 21:32:26 +01:00
|
|
|
return cache.getDataAs(type, copy);
|
2023-09-08 08:47:43 +02:00
|
|
|
},
|
|
|
|
|
2023-11-27 12:12:54 +01:00
|
|
|
/**
|
|
|
|
* Get the original data data for this tile
|
|
|
|
* @param {string} type data type to require
|
|
|
|
* @param {boolean?} [copy=this.loaded] whether to force copy retrieval
|
|
|
|
* @return {*|undefined} data in the desired type, or undefined if a conversion is ongoing
|
|
|
|
*/
|
|
|
|
getOriginalData: function(type, copy = true) {
|
2023-12-10 16:34:42 +01:00
|
|
|
if (!this.tiledImage) {
|
|
|
|
return null; //async can access outside its lifetime
|
|
|
|
}
|
|
|
|
|
2023-11-27 12:12:54 +01:00
|
|
|
//we return the data synchronously immediatelly (undefined if conversion happens)
|
|
|
|
const cache = this.getCache(this.originalCacheKey);
|
|
|
|
if (!cache) {
|
|
|
|
$.console.error("[Tile::getData] There is no cache available for tile with key " + this.originalCacheKey);
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
return cache.getDataAs(type, copy);
|
|
|
|
},
|
|
|
|
|
2023-09-08 08:47:43 +02:00
|
|
|
/**
|
|
|
|
* Set cache data
|
|
|
|
* @param {*} value
|
2023-11-26 21:32:26 +01:00
|
|
|
* @param {?string} type data type to require
|
|
|
|
* @param {boolean} [preserveOriginalData=true] if true and cacheKey === originalCacheKey,
|
|
|
|
* then stores the underlying data as 'original' and changes the cacheKey to point
|
|
|
|
* to a new data. This makes the Tile assigned to two cache objects.
|
|
|
|
*/
|
|
|
|
setData: function(value, type, preserveOriginalData = true) {
|
2023-12-10 16:34:42 +01:00
|
|
|
if (!this.tiledImage) {
|
|
|
|
return null; //async can access outside its lifetime
|
|
|
|
}
|
|
|
|
|
2023-11-26 21:32:26 +01:00
|
|
|
if (preserveOriginalData && this.cacheKey === this.originalCacheKey) {
|
|
|
|
//caches equality means we have only one cache:
|
|
|
|
// change current pointer to a new cache and create it: new tiles will
|
|
|
|
// not arrive at this data, but at originalCacheKey state
|
|
|
|
this.cacheKey = "mod://" + this.originalCacheKey;
|
|
|
|
return this.setCache(this.cacheKey, value, type)._promise;
|
|
|
|
}
|
|
|
|
//else overwrite cache
|
|
|
|
const cache = this.getCache(this.cacheKey);
|
|
|
|
if (!cache) {
|
|
|
|
$.console.error("[Tile::setData] There is no cache available for tile with key " + this.cacheKey);
|
|
|
|
return $.Promise.resolve();
|
|
|
|
}
|
|
|
|
return cache.setDataAs(value, type);
|
2023-09-08 08:47:43 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read tile cache data object (CacheRecord)
|
2023-11-26 21:32:26 +01:00
|
|
|
* @param {string?} [key=this.cacheKey] cache key to read that belongs to this tile
|
2023-09-08 08:47:43 +02:00
|
|
|
* @return {OpenSeadragon.CacheRecord}
|
|
|
|
*/
|
2023-11-26 21:32:26 +01:00
|
|
|
getCache: function(key = this.cacheKey) {
|
2023-09-08 08:47:43 +02:00
|
|
|
return this._caches[key];
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set tile cache, possibly multiple with custom key
|
|
|
|
* @param {string} key cache key, must be unique (we recommend re-using this.cacheTile
|
|
|
|
* value and extend it with some another unique content, by default overrides the existing
|
|
|
|
* main cache used for drawing, if not existing.
|
|
|
|
* @param {*} data data to cache - this data will be sent to the TileSource API for refinement.
|
|
|
|
* @param {?string} type data type, will be guessed if not provided
|
|
|
|
* @param [_safely=true] private
|
2023-12-10 16:34:42 +01:00
|
|
|
* @returns {OpenSeadragon.CacheRecord|null} - The cache record the tile was attached to.
|
2023-09-08 08:47:43 +02:00
|
|
|
*/
|
2023-12-10 16:34:42 +01:00
|
|
|
setCache: function(key, data, type = undefined, _safely = true) {
|
|
|
|
if (!this.tiledImage) {
|
|
|
|
return null; //async can access outside its lifetime
|
|
|
|
}
|
|
|
|
|
2023-11-26 21:32:26 +01:00
|
|
|
if (!type) {
|
|
|
|
if (this.tiledImage && !this.tiledImage.__typeWarningReported) {
|
|
|
|
$.console.warn(this, "[Tile.setCache] called without type specification. " +
|
|
|
|
"Automated deduction is potentially unsafe: prefer specification of data type explicitly.");
|
|
|
|
this.tiledImage.__typeWarningReported = true;
|
|
|
|
}
|
2023-11-18 20:16:35 +01:00
|
|
|
type = $.convertor.guessType(data);
|
|
|
|
}
|
2023-09-08 08:47:43 +02:00
|
|
|
|
2023-11-27 12:12:54 +01:00
|
|
|
const writesToRenderingCache = key === this.cacheKey;
|
|
|
|
if (writesToRenderingCache && _safely) {
|
2023-12-10 16:34:42 +01:00
|
|
|
//todo after-merge-aiosa decide dynamically
|
2023-11-26 21:32:26 +01:00
|
|
|
const conversion = $.convertor.getConversionPath(type, "context2d");
|
2023-09-08 08:47:43 +02:00
|
|
|
$.console.assert(conversion, "[Tile.setCache] data was set for the default tile cache we are unable" +
|
|
|
|
"to render. Make sure OpenSeadragon.convertor was taught to convert type: " + type);
|
|
|
|
}
|
|
|
|
|
2023-12-10 16:34:42 +01:00
|
|
|
if (!this.__cutoff) {
|
|
|
|
//todo consider caching this on a tiled image level..
|
|
|
|
this.__cutoff = this.tiledImage.source.getClosestLevel();
|
|
|
|
}
|
2023-11-26 21:32:26 +01:00
|
|
|
const cachedItem = this.tiledImage._tileCache.cacheTile({
|
2023-09-08 08:47:43 +02:00
|
|
|
data: data,
|
|
|
|
dataType: type,
|
|
|
|
tile: this,
|
|
|
|
cacheKey: key,
|
2023-12-10 16:34:42 +01:00
|
|
|
cutoff: this.__cutoff,
|
2023-09-08 08:47:43 +02:00
|
|
|
});
|
2023-11-26 21:32:26 +01:00
|
|
|
const havingRecord = this._caches[key];
|
|
|
|
if (havingRecord !== cachedItem) {
|
|
|
|
if (!havingRecord) {
|
|
|
|
this._cacheSize++;
|
|
|
|
}
|
|
|
|
this._caches[key] = cachedItem;
|
|
|
|
}
|
|
|
|
return cachedItem;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the number of caches available to this tile
|
|
|
|
* @returns {number} number of caches
|
|
|
|
*/
|
|
|
|
getCacheSize: function() {
|
|
|
|
return this._cacheSize;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Free tile cache. Removes by default the cache record if no other tile uses it.
|
|
|
|
* @param {string} key cache key, required
|
|
|
|
* @param {boolean} [freeIfUnused=true] set to false if zombie should be created
|
|
|
|
*/
|
|
|
|
unsetCache: function(key, freeIfUnused = true) {
|
|
|
|
if (this.cacheKey === key) {
|
|
|
|
if (this.cacheKey !== this.originalCacheKey) {
|
|
|
|
this.cacheKey = this.originalCacheKey;
|
|
|
|
} else {
|
|
|
|
$.console.warn("[Tile.unsetCache] trying to remove the only cache that is used to draw the tile!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (this.tiledImage._tileCache.unloadCacheForTile(this, key, freeIfUnused)) {
|
|
|
|
//if we managed to free tile from record, we are sure we decreased cache count
|
|
|
|
this._cacheSize--;
|
|
|
|
delete this._caches[key];
|
|
|
|
}
|
2022-04-16 21:19:54 +02:00
|
|
|
},
|
|
|
|
|
2015-11-05 16:19:56 +02:00
|
|
|
/**
|
|
|
|
* Get the ratio between current and original size.
|
|
|
|
* @function
|
2024-02-04 15:41:05 +01:00
|
|
|
* @returns {number}
|
2015-11-05 16:19:56 +02:00
|
|
|
*/
|
|
|
|
getScaleForEdgeSmoothing: function() {
|
2024-02-04 15:41:05 +01:00
|
|
|
// getCanvasContext is deprecated and so should be this method.
|
|
|
|
$.console.warn("[Tile.getScaleForEdgeSmoothing] is deprecated, the following error is the consequence:");
|
2023-09-08 08:47:43 +02:00
|
|
|
const context = this.getCanvasContext();
|
|
|
|
if (!context) {
|
2015-11-05 16:19:56 +02:00
|
|
|
$.console.warn(
|
|
|
|
'[Tile.drawCanvas] attempting to get tile scale %s when tile\'s not cached',
|
|
|
|
this.toString());
|
|
|
|
return 1;
|
|
|
|
}
|
2016-04-21 10:31:49 -04:00
|
|
|
return context.canvas.width / (this.size.x * $.pixelDensityRatio);
|
2015-11-05 16:19:56 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a translation vector that when applied to the tile position produces integer coordinates.
|
|
|
|
* Needed to avoid swimming and twitching.
|
|
|
|
* @function
|
2015-11-06 08:55:30 +02:00
|
|
|
* @param {Number} [scale=1] - Scale to be applied to position.
|
2022-10-10 01:12:18 +05:30
|
|
|
* @returns {OpenSeadragon.Point}
|
2015-11-05 16:19:56 +02:00
|
|
|
*/
|
2016-01-23 18:40:53 -05:00
|
|
|
getTranslationForEdgeSmoothing: function(scale, canvasSize, sketchCanvasSize) {
|
2015-11-05 16:19:56 +02:00
|
|
|
// The translation vector must have positive values, otherwise the image goes a bit off
|
|
|
|
// the sketch canvas to the top and left and we must use negative coordinates to repaint it
|
2016-01-26 15:59:10 -05:00
|
|
|
// to the main canvas. In that case, some browsers throw:
|
|
|
|
// INDEX_SIZE_ERR: DOM Exception 1: Index or size was negative, or greater than the allowed value.
|
|
|
|
var x = Math.max(1, Math.ceil((sketchCanvasSize.x - canvasSize.x) / 2));
|
|
|
|
var y = Math.max(1, Math.ceil((sketchCanvasSize.y - canvasSize.y) / 2));
|
|
|
|
return new $.Point(x, y).minus(
|
2015-11-05 16:19:56 +02:00
|
|
|
this.position
|
2015-11-19 10:06:43 +02:00
|
|
|
.times($.pixelDensityRatio)
|
2015-11-05 16:19:56 +02:00
|
|
|
.times(scale || 1)
|
|
|
|
.apply(function(x) {
|
|
|
|
return x % 1;
|
|
|
|
})
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2012-01-31 15:59:09 -05:00
|
|
|
/**
|
2013-12-13 15:12:35 -06:00
|
|
|
* Removes tile from its container.
|
2012-01-31 15:59:09 -05:00
|
|
|
* @function
|
|
|
|
*/
|
2011-12-05 22:50:25 -05:00
|
|
|
unload: function() {
|
2024-02-04 15:41:05 +01:00
|
|
|
//TODO AIOSA remove this.element and move it to a data constructor
|
2013-10-28 12:36:29 -07:00
|
|
|
if ( this.imgElement && this.imgElement.parentNode ) {
|
|
|
|
this.imgElement.parentNode.removeChild( this.imgElement );
|
|
|
|
}
|
2012-02-01 16:56:04 -05:00
|
|
|
if ( this.element && this.element.parentNode ) {
|
|
|
|
this.element.parentNode.removeChild( this.element );
|
2013-06-19 13:33:25 -04:00
|
|
|
}
|
2023-09-08 08:47:43 +02:00
|
|
|
this.tiledImage = null;
|
|
|
|
this._caches = [];
|
2023-11-26 21:32:26 +01:00
|
|
|
this._cacheSize = 0;
|
2013-10-28 12:38:17 -07:00
|
|
|
this.element = null;
|
2013-10-28 12:36:29 -07:00
|
|
|
this.imgElement = null;
|
2013-10-28 12:38:17 -07:00
|
|
|
this.loaded = false;
|
|
|
|
this.loading = false;
|
2024-02-04 15:41:05 +01:00
|
|
|
this.cacheKey = this.originalCacheKey;
|
2011-12-05 22:50:25 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}( OpenSeadragon ));
|