mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-29 08:36:10 +03:00
Fix issues with tile reference in cache: keep the 'most fresh' ref.
This commit is contained in:
parent
d91df0126b
commit
63f0adbc15
@ -513,12 +513,14 @@ $.Tile.prototype = {
|
|||||||
* @return {OpenSeadragon.CacheRecord}
|
* @return {OpenSeadragon.CacheRecord}
|
||||||
*/
|
*/
|
||||||
getCache: function(key = this.cacheKey) {
|
getCache: function(key = this.cacheKey) {
|
||||||
return this._caches[key];
|
const cache = this._caches[key];
|
||||||
|
if (cache) {
|
||||||
|
cache.withTileReference(this);
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: set cache might be misleading name since we do not update data,
|
|
||||||
* this should be either changed or method renamed...
|
|
||||||
* Set tile cache, possibly multiple with custom key
|
* Set tile cache, possibly multiple with custom key
|
||||||
* @param {string} key cache key, must be unique (we recommend re-using this.cacheTile
|
* @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
|
* value and extend it with some another unique content, by default overrides the existing
|
||||||
@ -600,6 +602,7 @@ $.Tile.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Get the ratio between current and original size.
|
* Get the ratio between current and original size.
|
||||||
* @function
|
* @function
|
||||||
|
* @deprecated
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
getScaleForEdgeSmoothing: function() {
|
getScaleForEdgeSmoothing: function() {
|
||||||
|
@ -128,14 +128,13 @@
|
|||||||
* @returns {OpenSeadragon.Promise<?>} desired data type in promise, undefined if the cache was destroyed
|
* @returns {OpenSeadragon.Promise<?>} desired data type in promise, undefined if the cache was destroyed
|
||||||
*/
|
*/
|
||||||
getDataAs(type = this._type, copy = true) {
|
getDataAs(type = this._type, copy = true) {
|
||||||
const referenceTile = this._tiles[0];
|
|
||||||
if (this.loaded) {
|
if (this.loaded) {
|
||||||
if (type === this._type) {
|
if (type === this._type) {
|
||||||
return copy ? $.convertor.copy(referenceTile, this._data, type) : this._promise;
|
return copy ? $.convertor.copy(this._tRef, this._data, type) : this._promise;
|
||||||
}
|
}
|
||||||
return this._getDataAsUnsafe(referenceTile, this._data, type, copy);
|
return this._getDataAsUnsafe(this._tRef, this._data, type, copy);
|
||||||
}
|
}
|
||||||
return this._promise.then(data => this._getDataAsUnsafe(referenceTile, data, type, copy));
|
return this._promise.then(data => this._getDataAsUnsafe(this._tRef, data, type, copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
_getDataAsUnsafe(referenceTile, data, type, copy) {
|
_getDataAsUnsafe(referenceTile, data, type, copy) {
|
||||||
@ -161,7 +160,6 @@
|
|||||||
* @param {Array<string>} supportedTypes required data (or one of) type(s)
|
* @param {Array<string>} supportedTypes required data (or one of) type(s)
|
||||||
* @param {boolean} keepInternalCopy if true, the cache keeps internally the drawer data
|
* @param {boolean} keepInternalCopy if true, the cache keeps internally the drawer data
|
||||||
* until 'setData' is called
|
* until 'setData' is called
|
||||||
* todo: keep internal copy is not configurable and always enforced -> set as option for osd?
|
|
||||||
* @returns {any|undefined} desired data if available, undefined if conversion must be done
|
* @returns {any|undefined} desired data if available, undefined if conversion must be done
|
||||||
*/
|
*/
|
||||||
getDataForRendering(supportedTypes, keepInternalCopy = true) {
|
getDataForRendering(supportedTypes, keepInternalCopy = true) {
|
||||||
@ -176,7 +174,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (internalCache) {
|
if (internalCache) {
|
||||||
internalCache.withTemporaryTileRef(this._tiles[0]);
|
internalCache.withTileReference(this._tRef);
|
||||||
} else {
|
} else {
|
||||||
internalCache = this;
|
internalCache = this;
|
||||||
}
|
}
|
||||||
@ -201,7 +199,6 @@
|
|||||||
* @return {OpenSeadragon.Promise<OpenSeadragon.SimpleCacheRecord|OpenSeadragon.CacheRecord>}
|
* @return {OpenSeadragon.Promise<OpenSeadragon.SimpleCacheRecord|OpenSeadragon.CacheRecord>}
|
||||||
*/
|
*/
|
||||||
prepareForRendering(supportedTypes, keepInternalCopy = true) {
|
prepareForRendering(supportedTypes, keepInternalCopy = true) {
|
||||||
const referenceTile = this._tiles[0];
|
|
||||||
// if not internal copy and we have no data, bypass rendering
|
// if not internal copy and we have no data, bypass rendering
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
return $.Promise.resolve(this);
|
return $.Promise.resolve(this);
|
||||||
@ -214,9 +211,9 @@
|
|||||||
$.console.error(`[getDataForRendering] Conversion conversion ${this.type} ---> ${supportedTypes} cannot be done!`);
|
$.console.error(`[getDataForRendering] Conversion conversion ${this.type} ---> ${supportedTypes} cannot be done!`);
|
||||||
return $.Promise.resolve(this);
|
return $.Promise.resolve(this);
|
||||||
}
|
}
|
||||||
internalCache.withTemporaryTileRef(referenceTile);
|
internalCache.withTileReference(this._tRef);
|
||||||
const selectedFormat = conversionPath[conversionPath.length - 1].target.value;
|
const selectedFormat = conversionPath[conversionPath.length - 1].target.value;
|
||||||
return $.convertor.convert(referenceTile, this.data, this.type, selectedFormat).then(data => {
|
return $.convertor.convert(this._tRef, this.data, this.type, selectedFormat).then(data => {
|
||||||
internalCache.setDataAs(data, selectedFormat);
|
internalCache.setDataAs(data, selectedFormat);
|
||||||
return internalCache;
|
return internalCache;
|
||||||
});
|
});
|
||||||
@ -276,6 +273,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conversion requires tile references:
|
||||||
|
* keep the most 'up to date' ref here. It is called and managed automatically.
|
||||||
|
* @param {OpenSeadragon.Tile} ref
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
withTileReference(ref) {
|
||||||
|
this._tRef = ref;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set initial state, prepare for usage.
|
* Set initial state, prepare for usage.
|
||||||
* Must not be called on active cache, e.g. first call destroy().
|
* Must not be called on active cache, e.g. first call destroy().
|
||||||
@ -318,6 +325,7 @@
|
|||||||
this._tiles = null;
|
this._tiles = null;
|
||||||
this._data = null;
|
this._data = null;
|
||||||
this._type = null;
|
this._type = null;
|
||||||
|
this._tRef = null;
|
||||||
this._promise = null;
|
this._promise = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,6 +367,10 @@
|
|||||||
for (let i = 0; i < this._tiles.length; i++) {
|
for (let i = 0; i < this._tiles.length; i++) {
|
||||||
if (this._tiles[i] === tile) {
|
if (this._tiles[i] === tile) {
|
||||||
this._tiles.splice(i, 1);
|
this._tiles.splice(i, 1);
|
||||||
|
if (this._tRef === tile) {
|
||||||
|
// keep fresh ref
|
||||||
|
this._tRef = this._tiles[i - 1];
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,7 +434,7 @@
|
|||||||
const internal = this[DRAWER_INTERNAL_CACHE];
|
const internal = this[DRAWER_INTERNAL_CACHE];
|
||||||
if (internal) {
|
if (internal) {
|
||||||
// TODO: if update will be greedy uncomment (see below)
|
// TODO: if update will be greedy uncomment (see below)
|
||||||
//internal.withTemporaryTileRef(this._tiles[0]);
|
//internal.withTileReference(this._tRef);
|
||||||
internal.setDataAs(data, type);
|
internal.setDataAs(data, type);
|
||||||
}
|
}
|
||||||
this._triggerNeedsDraw();
|
this._triggerNeedsDraw();
|
||||||
@ -436,7 +448,7 @@
|
|||||||
const internal = this[DRAWER_INTERNAL_CACHE];
|
const internal = this[DRAWER_INTERNAL_CACHE];
|
||||||
if (internal) {
|
if (internal) {
|
||||||
// TODO: if update will be greedy uncomment (see below)
|
// TODO: if update will be greedy uncomment (see below)
|
||||||
//internal.withTemporaryTileRef(this._tiles[0]);
|
//internal.withTileReference(this._tRef);
|
||||||
internal.setDataAs(data, type);
|
internal.setDataAs(data, type);
|
||||||
}
|
}
|
||||||
this._triggerNeedsDraw();
|
this._triggerNeedsDraw();
|
||||||
@ -452,7 +464,6 @@
|
|||||||
*/
|
*/
|
||||||
_convert(from, to) {
|
_convert(from, to) {
|
||||||
const convertor = $.convertor,
|
const convertor = $.convertor,
|
||||||
referenceTile = this._tiles[0],
|
|
||||||
conversionPath = convertor.getConversionPath(from, to);
|
conversionPath = convertor.getConversionPath(from, to);
|
||||||
if (!conversionPath) {
|
if (!conversionPath) {
|
||||||
$.console.error(`[CacheRecord._convert] Conversion conversion ${from} ---> ${to} cannot be done!`);
|
$.console.error(`[CacheRecord._convert] Conversion conversion ${from} ---> ${to} cannot be done!`);
|
||||||
@ -470,7 +481,7 @@
|
|||||||
return $.Promise.resolve(x);
|
return $.Promise.resolve(x);
|
||||||
}
|
}
|
||||||
let edge = conversionPath[i];
|
let edge = conversionPath[i];
|
||||||
let y = edge.transform(referenceTile, x);
|
let y = edge.transform(_this._tRef, x);
|
||||||
if (y === undefined) {
|
if (y === undefined) {
|
||||||
_this.loaded = false;
|
_this.loaded = false;
|
||||||
throw `[CacheRecord._convert] data mid result undefined value (while converting using ${edge}})`;
|
throw `[CacheRecord._convert] data mid result undefined value (while converting using ${edge}})`;
|
||||||
@ -530,7 +541,7 @@
|
|||||||
* compatible api with CacheRecord where tile refs are known.
|
* compatible api with CacheRecord where tile refs are known.
|
||||||
* @param {OpenSeadragon.Tile} referenceTile reference tile for conversion
|
* @param {OpenSeadragon.Tile} referenceTile reference tile for conversion
|
||||||
*/
|
*/
|
||||||
withTemporaryTileRef(referenceTile) {
|
withTileReference(referenceTile) {
|
||||||
this._temporaryTileRef = referenceTile;
|
this._temporaryTileRef = referenceTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -727,9 +738,12 @@
|
|||||||
for ( let i = this._tilesLoaded.length - 1; i >= 0; i-- ) {
|
for ( let i = this._tilesLoaded.length - 1; i >= 0; i-- ) {
|
||||||
prevTile = this._tilesLoaded[ i ];
|
prevTile = this._tilesLoaded[ i ];
|
||||||
|
|
||||||
if ( prevTile.level <= cutoff || prevTile.beingDrawn ) {
|
if ( prevTile.level <= cutoff ||
|
||||||
|
prevTile.beingDrawn ||
|
||||||
|
prevTile.loading ) {
|
||||||
continue;
|
continue;
|
||||||
} else if ( !worstTile ) {
|
}
|
||||||
|
if ( !worstTile ) {
|
||||||
worstTile = prevTile;
|
worstTile = prevTile;
|
||||||
worstTileIndex = i;
|
worstTileIndex = i;
|
||||||
continue;
|
continue;
|
||||||
|
@ -2045,7 +2045,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
*/
|
*/
|
||||||
_onTileLoad: function( tile, time, data, errorMsg, tileRequest, dataType ) {
|
_onTileLoad: function( tile, time, data, errorMsg, tileRequest, dataType ) {
|
||||||
//data is set to null on error by image loader, allow custom falsey values (e.g. 0)
|
//data is set to null on error by image loader, allow custom falsey values (e.g. 0)
|
||||||
if ( data === null ) {
|
if ( data === null || data === undefined ) {
|
||||||
$.console.error( "Tile %s failed to load: %s - error: %s", tile, tile.getUrl(), errorMsg );
|
$.console.error( "Tile %s failed to load: %s - error: %s", tile, tile.getUrl(), errorMsg );
|
||||||
/**
|
/**
|
||||||
* Triggered when a tile fails to load.
|
* Triggered when a tile fails to load.
|
||||||
@ -2095,6 +2095,11 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
* @param {?Boolean} [withEvent=true] do not trigger event if true
|
* @param {?Boolean} [withEvent=true] do not trigger event if true
|
||||||
*/
|
*/
|
||||||
_setTileLoaded: function(tile, data, cutoff, tileRequest, dataType, withEvent = true) {
|
_setTileLoaded: function(tile, data, cutoff, tileRequest, dataType, withEvent = true) {
|
||||||
|
const originalDelete = tile.unload;
|
||||||
|
tile.unload = (function () {
|
||||||
|
throw `Cannot unload tile while being loaded!`;
|
||||||
|
});
|
||||||
|
|
||||||
tile.tiledImage = this; //unloaded with tile.unload(), so we need to set it back
|
tile.tiledImage = this; //unloaded with tile.unload(), so we need to set it back
|
||||||
// does nothing if tile.cacheKey already present
|
// does nothing if tile.cacheKey already present
|
||||||
tile.addCache(tile.cacheKey, data, dataType, false);
|
tile.addCache(tile.cacheKey, data, dataType, false);
|
||||||
@ -2124,17 +2129,19 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
resolver(tile);
|
resolver(tile);
|
||||||
} else if (!requiredTypes.includes(cache.type)) {
|
} else if (!requiredTypes.includes(cache.type)) {
|
||||||
//initiate conversion as soon as possible if incompatible with the drawer
|
//initiate conversion as soon as possible if incompatible with the drawer
|
||||||
cache.prepareForRendering(requiredTypes).then(cacheRef => {
|
cache.prepareForRendering(requiredTypes, _this.viewer.drawer.options.detachedCache).then(cacheRef => {
|
||||||
if (!cacheRef) {
|
if (!cacheRef) {
|
||||||
return cache.transformTo(requiredTypes);
|
return cache.transformTo(requiredTypes);
|
||||||
}
|
}
|
||||||
return cacheRef;
|
return cacheRef;
|
||||||
}).then(_ => {
|
}).then(_ => {
|
||||||
|
tile.unload = originalDelete;
|
||||||
tile.loading = false;
|
tile.loading = false;
|
||||||
tile.loaded = true;
|
tile.loaded = true;
|
||||||
resolver(tile);
|
resolver(tile);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
tile.unload = originalDelete;
|
||||||
tile.loading = false;
|
tile.loading = false;
|
||||||
tile.loaded = true;
|
tile.loaded = true;
|
||||||
resolver(tile);
|
resolver(tile);
|
||||||
|
Loading…
Reference in New Issue
Block a user