diff --git a/src/drawerbase.js b/src/drawerbase.js index d84531f7..c3138655 100644 --- a/src/drawerbase.js +++ b/src/drawerbase.js @@ -97,7 +97,8 @@ OpenSeadragon.DrawerBase = class DrawerBase{ */ get defaultOptions() { return { - usePrivateCache: false + usePrivateCache: false, + preloadCache: true, }; } @@ -161,7 +162,7 @@ OpenSeadragon.DrawerBase = class DrawerBase{ $.console.warn("Attempt to draw tile %s when not cached!", tile); return undefined; } - const dataCache = cache.getCacheForRendering(this, tile); + const dataCache = cache.getDataForRendering(this, tile); return dataCache && dataCache.data; } @@ -240,6 +241,31 @@ OpenSeadragon.DrawerBase = class DrawerBase{ $.console.warn('[drawer].clear() is deprecated. The drawer is responsible for clearing itself as needed before drawing tiles.'); } + /** + * If options.usePrivateCache is true, this method MUST RETURN the private cache content + * @param {OpenSeadragon.CacheRecord} cache + * @param {OpenSeadragon.Tile} tile + * @return any + */ + dataCreate(cache, tile) {} + + /** + * It is possible to perform any necessary cleanup on internal cache, necessary if you + * need to clean up some memory (e.g. destroy canvas by setting with & height to 0). + * @param {*} data object returned by dataCreate(...) + */ + dataFree(data) {} + + /** + * Call to invalidate internal cache. It will be rebuilt. With synchronous converions, + * it will be rebuilt immediatelly. With asynchronous, it will be rebuilt once invalidation + * routine happens, e.g. you should call also requestInvalidate() if you need to happen + * it as soon as possible. + */ + setDataNeedsRefresh() { + this._dataNeedsRefresh = $.now(); + } + // Private functions /** diff --git a/src/tilecache.js b/src/tilecache.js index a66a32f5..105a24b0 100644 --- a/src/tilecache.js +++ b/src/tilecache.js @@ -79,7 +79,7 @@ */ await() { if (!this._promise) { //if not cache loaded, do not fail - return $.Promise.resolve(); + return $.Promise.resolve(this._data); } return this._promise; } @@ -171,83 +171,133 @@ * @param {OpenSeadragon.Tile} tileToDraw reference to the tile that is in the process of drawing and * for which we request the data; if we attempt to draw such tile while main cache target is destroyed, * attempt to reset the tile state to force system to re-download it again - * @returns {OpenSeadragon.CacheRecord|OpenSeadragon.SimpleCacheRecord|undefined} desired data if available, + * @returns {OpenSeadragon.CacheRecord|OpenSeadragon.InternalCacheRecord|undefined} desired data if available, * wrapped in the cache container. This data is guaranteed to be loaded & in the type supported by the drawer. * Returns undefined if the data is not ready for rendering. * @private */ - getCacheForRendering(drawer, tileToDraw) { - const supportedTypes = drawer.getSupportedDataFormats(), - keepInternalCopy = drawer.options.usePrivateCache; - if (this.loaded && supportedTypes.includes(this.type)) { - return this; - } + getDataForRendering(drawer, tileToDraw) { + const keepInternalCopy = drawer.options.usePrivateCache; + if (!this.loaded) { + $.console.error("Attempt to draw tile when not loaded main cache!"); + return undefined; + } if (this._destroyed) { $.console.error("Attempt to draw tile with destroyed main cache!"); tileToDraw._unload(); // try to restore the state so that the tile is later on fetched again return undefined; } - let internalCache = this[DRAWER_INTERNAL_CACHE]; - internalCache = internalCache && internalCache[drawer.getId()]; - if (keepInternalCopy && !internalCache) { - $.console.warn("Attempt to render cache that is not prepared for current drawer " + - "supported format: the preparation should've happened after tile processing has finished.", - this, tileToDraw); - - this.prepareForRendering(drawer.getId(), supportedTypes, keepInternalCopy) - .then(() => this._triggerNeedsDraw()); + const supportedTypes = drawer.getSupportedDataFormats(); + if (!supportedTypes.includes(this.type)) { + $.console.error("Attempt to draw tile with unsupported target drawer type!"); + this.prepareForRendering(drawer); return undefined; } - if (internalCache) { - internalCache.withTileReference(this._tRef); - } else { - internalCache = this; + // If we support internal cache + if (keepInternalCopy && !drawer.options.preloadCache) { + // let sync preparation handle data + if (!drawer.options.preloadCache) { + return this.prepareInternalCacheSync(drawer); + } + // or check that it was properly initiated before returning + const internalCache = this._getInternalCacheRef(drawer); + if (!internalCache || !internalCache.loaded) { + $.console.error("Attempt to draw tile with internal cache non-ready state!"); + return undefined; + } + return internalCache; } - // Cache in the process of loading, no-op - if (!internalCache.loaded) { - $.console.warn("Attempt to render cache that is not prepared for current drawer: " + - "internal cache still loading: this should be awaited.", - this, tileToDraw); - this._triggerNeedsDraw(); - return undefined; - } - - if (!supportedTypes.includes(internalCache.type)) { - let logReference = this[DRAWER_INTERNAL_CACHE]; - logReference = logReference ? Object.entries(logReference) : this; - $.console.warn("Attempt to render cache that is not prepared for current drawer " + - "supported format: the preparation should've happened after tile processing has finished.", - logReference, tileToDraw); - - internalCache.transformTo(supportedTypes.length > 1 ? supportedTypes : supportedTypes[0]) - .then(() => this._triggerNeedsDraw()); - return undefined; // type is NOT compatible - } - return internalCache; + // If no internal cache support, we are ready - just return self reference + return this; } /** * Should not be called if cache type is already among supported types * @private - * @param drawerId - * @param supportedTypes - * @param keepInternalCopy if a drawer requests internal copy, it means it can only use - * given cache for itself, cannot be shared -> initialize privately - * @return {OpenSeadragon.Promise | null} - * reference to the cache processed for drawer rendering requirements, or null on error + * @param {OpenSeadragon.DrawerBase} drawer + * @return {OpenSeadragon.Promise<*>} reference to the data, + * or null if not data yet loaded/ready (usually due to error) */ - prepareForRendering(drawerId, supportedTypes, keepInternalCopy = true) { - // if not internal copy and we have no data, or we are ready to render, exit - if (!this.loaded || supportedTypes.includes(this.type)) { - return $.Promise.resolve(this); + prepareForRendering(drawer) { + const supportedTypes = drawer.getRequiredDataFormats(); + + if (drawer.options.usePrivateCache && drawer.options.preloadCache) { + return this.prepareInternalCacheAsync(drawer).then(_ => { + // if not internal copy and we have no data, or we are ready to render, exit + if (!this.loaded || supportedTypes.includes(this.type)) { + return this.await(); + } + + return this.transformTo(supportedTypes); + }); } - if (!keepInternalCopy) { - return this.transformTo(supportedTypes); + if (!this.loaded || supportedTypes.includes(this.type)) { + return this.await(); + } + return this.transformTo(supportedTypes); + } + + /** + * Must not be called if drawer.options.usePrivateCache == false. Called inside prepareForRenderine + * by cache itself if preloadCache == true (supports async behavior). + * + * @private + * @param {OpenSeadragon.DrawerBase} drawer + * @return {OpenSeadragon.Promise<*>} reference to the data wrapped in a promise, + * or null if not data yet loaded/ready (usually due to error) + */ + prepareInternalCacheAsync(drawer) { + let internalCache = this._getInternalCacheRef(drawer); + if (this._checkInternalCacheUpToDate(internalCache, drawer)) { + return internalCache.await(); + } + + // Force reset + if (internalCache && !internalCache.loaded) { + internalCache.await().then(() => internalCache.destroy()); + } + + $.console.assert(this._tRef, "Data Create called from invalidation routine needs tile reference!"); + const transformedData = drawer.dataCreate(this, this._tRef); + $.console.assert(transformedData !== undefined, "[DrawerBase.dataCreate] must return a value if usePrivateCache is enabled!"); + internalCache = this[DRAWER_INTERNAL_CACHE][drawer.getId()] = new $.InternalCacheRecord(transformedData, (data) => drawer.dataFree(data)); + return internalCache.await(); + } + + /** + * Must not be called if drawer.options.usePrivateCache == false. Called inside getDataForRendering + * by cache itself if preloadCache == false (without support for async behavior). + * @private + * @param {OpenSeadragon.DrawerBase} drawer + * @return {OpenSeadragon.InternalCacheRecord} reference to the cache + */ + prepareInternalCacheSync(drawer) { + let internalCache = this._getInternalCacheRef(drawer); + if (this._checkInternalCacheUpToDate(internalCache, drawer)) { + return internalCache; + } + + // Force reset + if (internalCache) { + internalCache.destroy(); + } + + $.console.assert(this._tRef, "Data Create called from drawing loop needs tile reference!"); + const transformedData = drawer.dataCreate(this, this._tRef); + $.console.assert(transformedData !== undefined, "[DrawerBase.dataCreate] must return a value if usePrivateCache is enabled!"); + internalCache = this[DRAWER_INTERNAL_CACHE][drawer.getId()] = new $.InternalCacheRecord(transformedData, (data) => drawer.dataFree(data)); + return internalCache; + } + + _getInternalCacheRef(drawer) { + const options = drawer.options; + if (!options.usePrivateCache) { + return $.Promise.reject("[CacheRecord.prepareInternalCacheSync] must not be called when usePrivateCache is false."); } // we can get here only if we want to render incompatible type @@ -255,32 +305,13 @@ if (!internalCache) { internalCache = this[DRAWER_INTERNAL_CACHE] = {}; } + return internalCache[drawer.getId()]; + } - internalCache = internalCache[drawerId]; - if (internalCache && supportedTypes.includes(internalCache.type)) { - // already done - return $.Promise.resolve(this); - } - - const conversionPath = $.convertor.getConversionPath(this.type, supportedTypes); - if (!conversionPath) { - $.console.error(`[getCacheForRendering] Conversion ${this.type} ---> ${supportedTypes} cannot be done!`); - return $.Promise.resolve(this); - } - const newInternalCache = new $.SimpleCacheRecord(); - - newInternalCache.withTileReference(this._tRef); - const selectedFormat = conversionPath[conversionPath.length - 1].target.value; - return $.convertor.convert(this._tRef, this.data, this.type, selectedFormat).then(data => { - newInternalCache.setDataAs(data, selectedFormat); // synchronous, SimpleCacheRecord call - - // if existed, delete - if (internalCache) { - internalCache.destroy(); - } - this[DRAWER_INTERNAL_CACHE][drawerId] = newInternalCache; - return newInternalCache; - }); + _checkInternalCacheUpToDate(internalCache, drawer) { + // We respect existing records, unless they are outdated. Invalidation routine by its nature + // destroys internal cache, therefore we do not need to check if internal cache is consistent with its parent. + return internalCache && internalCache.loaded && internalCache.tstamp >= drawer._dataNeedsRefresh; } /** @@ -623,7 +654,7 @@ }; /** - * @class SimpleCacheRecord + * @class InternalCacheRecord * @memberof OpenSeadragon * @classdesc Simple cache record without robust support for async access. Meant for internal use only. * @@ -635,12 +666,22 @@ * It also does not record tiles nor allows cache/tile sharing. * @private */ - $.SimpleCacheRecord = class { - constructor(preferredTypes) { - this._data = null; - this._type = null; - this.loaded = false; - this.format = Array.isArray(preferredTypes) ? preferredTypes : null; + $.InternalCacheRecord = class { + constructor(data, onDestroy) { + this.tstamp = $.now(); + this._ondestroy = onDestroy; + + if (data instanceof $.Promise) { + this._promise = data; + data.then(data => { + this.loaded = true; + this._data = data; + }); + } else { + this._promise = null; + this.loaded = true; + this._data = data; + } } /** @@ -656,86 +697,42 @@ * @returns {string} */ get type() { - return this._type; + return "__internal_cache__"; + } + + /** + * Await ongoing process so that we get cache ready on callback. + * @returns {OpenSeadragon.Promise} + */ + await() { + if (!this._promise) { //if not cache loaded, do not fail + return $.Promise.resolve(this._data); + } + return this._promise; } /** * Must be called before transformTo or setDataAs. To keep * compatible api with CacheRecord where tile refs are known. * @param {OpenSeadragon.Tile} referenceTile reference tile for conversion - * @return {OpenSeadragon.SimpleCacheRecord} self reference for builder pattern + * @return {OpenSeadragon.InternalCacheRecord} self reference for builder pattern */ withTileReference(referenceTile) { this._temporaryTileRef = referenceTile; return this; } - /** - * Transform cache to desired type and get the data after conversion. - * Does nothing if the type equals to the current type. Asynchronous. - * @param {string|string[]} type if array provided, the system will - * try to optimize for the best type to convert to. - * @returns {OpenSeadragon.Promise} - */ - transformTo(type) { - $.console.assert(this._temporaryTileRef, "SimpleCacheRecord needs tile reference set before update operation!"); - const convertor = $.convertor, - conversionPath = convertor.getConversionPath(this._type, type); - if (!conversionPath) { - $.console.error(`[SimpleCacheRecord.transformTo] Conversion ${this._type} ---> ${type} cannot be done!`); - return $.Promise.resolve(); //no-op - } - - const stepCount = conversionPath.length, - _this = this, - convert = (x, i) => { - if (i >= stepCount) { - _this._data = x; - _this.loaded = true; - _this._temporaryTileRef = null; - return $.Promise.resolve(x); - } - let edge = conversionPath[i]; - try { - // no test for y - less robust approach - let y = edge.transform(this._temporaryTileRef, x); - convertor.destroy(x, edge.origin.value); - const result = $.type(y) === "promise" ? y : $.Promise.resolve(y); - return result.then(res => convert(res, i + 1)); - } catch (e) { - _this.loaded = false; - _this._temporaryTileRef = null; - throw e; - } - }; - - this.loaded = false; - // Read target type from the conversion path: [edge.target] = Vertex, its value=type - this._type = conversionPath[stepCount - 1].target.value; - const promise = convert(this._data, 0); - this._data = undefined; - return promise; - } - /** * Free all the data and call data destructors if defined. */ destroy() { - $.convertor.destroy(this._data, this._type); - this._data = null; - this._type = null; - } - - /** - * Safely overwrite the cache data and return the old data - * @private - */ - setDataAs(data, type) { - // no check for state, users must ensure compatibility manually - $.convertor.destroy(this._data, this._type); - this._type = type; - this._data = data; - this.loaded = true; + if (this.loaded) { + if (this._ondestroy) { + this._ondestroy(this._data); + } + this._data = null; + this.loaded = false; + } } }; diff --git a/src/webgldrawer.js b/src/webgldrawer.js index 1ae21e80..7e3a5fd1 100644 --- a/src/webgldrawer.js +++ b/src/webgldrawer.js @@ -100,10 +100,7 @@ this._setupCanvases(); this._setupRenderer(); - this._setupCallCount = 1; - this._supportedFormats = this._setupTextureHandlers(); - this._requiredFormats = this._supportedFormats; - + this._supportedFormats = ["context2d", "image"]; this.context = this._outputContext; // API required by tests } @@ -247,9 +244,9 @@ $.console.warn("Attempt to draw tile %s when not cached!", tile); return undefined; } - const dataCache = cache.getCacheForRendering(this, tile); + const dataCache = cache.getDataForRendering(this, tile); // Use CPU Data for the drawer instead - return dataCache && dataCache.data.cpuData.getContext("2d"); + return dataCache && dataCache.cpuData; }; } @@ -480,10 +477,6 @@ } - getRequiredDataFormats() { - return this._requiredFormats; - } - // Public API required by all Drawer implementations /** * Sets whether image smoothing is enabled or disabled @@ -492,15 +485,9 @@ setImageSmoothingEnabled(enabled){ if( this._imageSmoothingEnabled !== enabled ){ this._imageSmoothingEnabled = enabled; - - // Todo consider removing old type handlers if _supportedFormats had already types defined, - // and remove support for rendering old types... - const newFormats = this._setupTextureHandlers(); // re-sets the type to enforce re-initialization - this._supportedFormats.push(...newFormats); - this._requiredFormats = newFormats; - return this.viewer.requestInvalidate(); + this.setDataNeedsRefresh(); + this.viewer.forceRedraw(); } - return $.Promise.resolve(); } /** @@ -883,97 +870,83 @@ this.viewer.addHandler("resize", this._resizeHandler); } - _setupTextureHandlers() { - const tex2DCompatibleLoader = (tile, data) => { - let tiledImage = tile.tiledImage; - let gl = this._gl; - let texture; - let position; + dataCreate(cache, tile) { + let tiledImage = tile.tiledImage; + let gl = this._gl; + let texture; + let position; - if (!tiledImage.isTainted()) { - if((data instanceof CanvasRenderingContext2D) && $.isCanvasTainted(data.canvas)){ - tiledImage.setTainted(true); - $.console.warn('WebGL cannot be used to draw this TiledImage because it has tainted data. Does crossOriginPolicy need to be set?'); - this._raiseDrawerErrorEvent(tiledImage, 'Tainted data cannot be used by the WebGLDrawer. Falling back to CanvasDrawer for this TiledImage.'); + const data = cache.data; + + if (!tiledImage.isTainted()) { + if((data instanceof CanvasRenderingContext2D) && $.isCanvasTainted(data.canvas)){ + tiledImage.setTainted(true); + $.console.warn('WebGL cannot be used to draw this TiledImage because it has tainted data. Does crossOriginPolicy need to be set?'); + this._raiseDrawerErrorEvent(tiledImage, 'Tainted data cannot be used by the WebGLDrawer. Falling back to CanvasDrawer for this TiledImage.'); + } else { + let sourceWidthFraction, sourceHeightFraction; + if (tile.sourceBounds) { + sourceWidthFraction = Math.min(tile.sourceBounds.width, data.width) / data.width; + sourceHeightFraction = Math.min(tile.sourceBounds.height, data.height) / data.height; } else { - let sourceWidthFraction, sourceHeightFraction; - if (tile.sourceBounds) { - sourceWidthFraction = Math.min(tile.sourceBounds.width, data.width) / data.width; - sourceHeightFraction = Math.min(tile.sourceBounds.height, data.height) / data.height; - } else { - sourceWidthFraction = 1; - sourceHeightFraction = 1; - } + sourceWidthFraction = 1; + sourceHeightFraction = 1; + } - // create a gl Texture for this tile and bind the canvas with the image data - texture = gl.createTexture(); - let overlap = tiledImage.source.tileOverlap; - if( overlap > 0){ - // calculate the normalized position of the rect to actually draw - // discarding overlap. - let overlapFraction = this._calculateOverlapFraction(tile, tiledImage); + // create a gl Texture for this tile and bind the canvas with the image data + texture = gl.createTexture(); + let overlap = tiledImage.source.tileOverlap; + if( overlap > 0){ + // calculate the normalized position of the rect to actually draw + // discarding overlap. + let overlapFraction = this._calculateOverlapFraction(tile, tiledImage); - let left = (tile.x === 0 ? 0 : overlapFraction.x) * sourceWidthFraction; - let top = (tile.y === 0 ? 0 : overlapFraction.y) * sourceHeightFraction; - let right = (tile.isRightMost ? 1 : 1 - overlapFraction.x) * sourceWidthFraction; - let bottom = (tile.isBottomMost ? 1 : 1 - overlapFraction.y) * sourceHeightFraction; - position = this._makeQuadVertexBuffer(left, right, top, bottom); - } else if (sourceWidthFraction === 1 && sourceHeightFraction === 1) { - // no overlap and no padding: this texture can use the unit quad as its position data - position = this._unitQuad; - } else { - position = this._makeQuadVertexBuffer(0, sourceWidthFraction, 0, sourceHeightFraction); - } + let left = (tile.x === 0 ? 0 : overlapFraction.x) * sourceWidthFraction; + let top = (tile.y === 0 ? 0 : overlapFraction.y) * sourceHeightFraction; + let right = (tile.isRightMost ? 1 : 1 - overlapFraction.x) * sourceWidthFraction; + let bottom = (tile.isBottomMost ? 1 : 1 - overlapFraction.y) * sourceHeightFraction; + position = this._makeQuadVertexBuffer(left, right, top, bottom); + } else if (sourceWidthFraction === 1 && sourceHeightFraction === 1) { + // no overlap and no padding: this texture can use the unit quad as its position data + position = this._unitQuad; + } else { + position = this._makeQuadVertexBuffer(0, sourceWidthFraction, 0, sourceHeightFraction); + } - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture); - // Set the parameters so we can render any size image. - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this._textureFilter()); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, texture); + // Set the parameters so we can render any size image. + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this._textureFilter()); - try { - // This depends on gl.TEXTURE_2D being bound to the texture - // associated with this canvas before calling this function - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data); - } catch (e){ - // Todo a bit dirty re-use of the tainted flag, but makes the code more stable - tiledImage.setTainted(true); - $.console.error('Error uploading image data to WebGL. Falling back to canvas renderer.', e); - this._raiseDrawerErrorEvent(tiledImage, 'Unknown error when uploading texture. Falling back to CanvasDrawer for this TiledImage.'); - } + try { + // This depends on gl.TEXTURE_2D being bound to the texture + // associated with this canvas before calling this function + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data); + } catch (e){ + // Todo a bit dirty re-use of the tainted flag, but makes the code more stable + tiledImage.setTainted(true); + $.console.error('Error uploading image data to WebGL. Falling back to canvas renderer.', e); + this._raiseDrawerErrorEvent(tiledImage, 'Unknown error when uploading texture. Falling back to CanvasDrawer for this TiledImage.'); } } + } - // TextureInfo stored in the cache - return { - texture: texture, - position: position, - cpuData: data - }; - }; - const tex2DCompatibleDestructor = textureInfo => { - if (textureInfo) { - this._gl.deleteTexture(textureInfo.texture); - } + // TextureInfo stored in the cache + return { + texture: texture, + position: position, + cpuData: data // Reference to the outer cache data, used to draw if webgl cannot be used }; + } - const thisType = `${this.getId()}_${this._setupCallCount++}_TEX_2D`; - // Differentiate type also based on type used to upload data: we can support bidirectional conversion. - const c2dTexType = thisType + ":context2d", - imageTexType = thisType + ":image"; - - // We should be OK uploading any of these types. The complexity is selected to be O(3n), should be - // more than linear pass over pixels - $.convertor.learn("context2d", c2dTexType, (t, d) => tex2DCompatibleLoader(t, d.canvas), 1, 3); - // TODO: lost support for image - // $.convertor.learn("image", imageTexType, tex2DCompatibleLoader, 1, 3); - - $.convertor.learnDestroy(c2dTexType, tex2DCompatibleDestructor); - // TODO - // $.convertor.learnDestroy(imageTexType, tex2DCompatibleDestructor); - return [c2dTexType, imageTexType]; + dataFree(data) { + if (data && data.texture) { + this._gl.deleteTexture(data.texture); + data.texture = null; + } } // private diff --git a/src/world.js b/src/world.js index 3530cf05..6ab55742 100644 --- a/src/world.js +++ b/src/world.js @@ -310,9 +310,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W // We call the event on the parent viewer window no matter what const eventTarget = this.viewer.viewer || this.viewer; // However, we must pick the correct drawer reference (navigator VS viewer) - const supportedFormats = this.viewer.drawer.getRequiredDataFormats(); - const keepInternalCacheCopy = this.viewer.drawer.options.usePrivateCache; - const drawerId = this.viewer.drawer.getId(); + const drawer = this.viewer.drawer; const jobList = tileList.map(tile => { const tiledImage = tile.tiledImage; @@ -360,7 +358,6 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W tiledImage._tileCache.restoreTilesThatShareOriginalCache(tile, tile.getCache(tile.originalCacheKey), true); } }; - /** * @event tile-invalidated * @memberof OpenSeadragon.Viewer @@ -391,7 +388,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W }).then(_ => { if (originalCache.__invStamp === tStamp && (tile.loaded || tile.loading)) { if (workingCache) { - return workingCache.prepareForRendering(drawerId, supportedFormats, keepInternalCacheCopy).then(c => { + return workingCache.prepareForRendering(drawer).then(c => { if (c && originalCache.__invStamp === tStamp) { atomicCacheSwap(); originalCache.__invStamp = null; @@ -402,7 +399,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W // If we requested restore, perform now if (restoreTiles) { const freshOriginalCacheRef = tile.getCache(tile.originalCacheKey); - return freshOriginalCacheRef.prepareForRendering(drawerId, supportedFormats, keepInternalCacheCopy).then((c) => { + return freshOriginalCacheRef.prepareForRendering(drawer).then((c) => { if (c && originalCache.__invStamp === tStamp) { atomicCacheSwap(); originalCache.__invStamp = null; @@ -412,7 +409,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W // Preventive call to ensure we stay compatible const freshMainCacheRef = tile.getCache(); - return freshMainCacheRef.prepareForRendering(drawerId, supportedFormats, keepInternalCacheCopy).then(() => { + return freshMainCacheRef.prepareForRendering(drawer).then(() => { atomicCacheSwap(); originalCache.__invStamp = null; });