mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-22 21:26:10 +03:00
Add auto recognition of the need for tiledImage draw call. Fix ajax-headers test: did not finish because we don't call tile-loaded on cached tiles by default.
This commit is contained in:
parent
2c67860c61
commit
90ce0669c5
@ -194,7 +194,7 @@ $.DataTypeConvertor = class {
|
||||
const canvas = document.createElement( 'canvas' );
|
||||
canvas.width = imageData.width;
|
||||
canvas.height = imageData.height;
|
||||
const context = canvas.getContext('2d');
|
||||
const context = canvas.getContext('2d', { willReadFrequently: true });
|
||||
context.drawImage( imageData, 0, 0 );
|
||||
return context;
|
||||
};
|
||||
|
67
src/tile.js
67
src/tile.js
@ -469,7 +469,7 @@ $.Tile.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the default data for this tile
|
||||
* Get the data to render 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
|
||||
@ -484,6 +484,22 @@ $.Tile.prototype = {
|
||||
return cache.getDataAs(type, copy);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
//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);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set cache data
|
||||
* @param {*} value
|
||||
@ -539,7 +555,8 @@ $.Tile.prototype = {
|
||||
type = $.convertor.guessType(data);
|
||||
}
|
||||
|
||||
if (_safely && key === this.cacheKey) {
|
||||
const writesToRenderingCache = key === this.cacheKey;
|
||||
if (writesToRenderingCache && _safely) {
|
||||
//todo later, we could have drawers register their supported rendering type
|
||||
// and OpenSeadragon would check compatibility automatically, now we render
|
||||
// using two main types so we check their ability
|
||||
@ -609,25 +626,53 @@ $.Tile.prototype = {
|
||||
drawCanvas: function( context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source) {
|
||||
|
||||
var position = this.position.times($.pixelDensityRatio),
|
||||
size = this.size.times($.pixelDensityRatio),
|
||||
rendered = this.getCanvasContext();
|
||||
size = this.size.times($.pixelDensityRatio);
|
||||
|
||||
if (!rendered) {
|
||||
const _this = this;
|
||||
// This gives the application a chance to make image manipulation
|
||||
// changes as we are rendering the image
|
||||
drawingHandler({context: context, tile: this, get rendered() {
|
||||
$.console.warn("[tile-drawing rendered] property is deprecated. Use Tile data API.");
|
||||
const context = _this.getCanvasContext();
|
||||
if (!context) {
|
||||
$.console.warn(
|
||||
'[Tile.drawCanvas] attempting to draw tile %s when it\'s not cached',
|
||||
this.toString());
|
||||
return;
|
||||
_this.toString());
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if ( !this.loaded || !rendered ){
|
||||
if ( !_this.loaded || !context ){
|
||||
$.console.warn(
|
||||
"Attempting to draw tile %s when it's not yet loaded.",
|
||||
_this.toString()
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
return _this.getCanvasContext();
|
||||
}});
|
||||
|
||||
//Now really get the tile data
|
||||
const cache = this.getCache(this.cacheKey);
|
||||
if (!cache) {
|
||||
$.console.error(
|
||||
"Attempting to draw tile %s when it's main cache key has no associated cache record!",
|
||||
this.toString()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (cache.type !== "context2d") {
|
||||
//cache not ready to render, wait
|
||||
cache.transformTo("context2d");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !cache.loaded ){
|
||||
//cache not ready to render, wait
|
||||
return;
|
||||
}
|
||||
const rendered = cache.data;
|
||||
|
||||
context.save();
|
||||
context.globalAlpha = this.opacity;
|
||||
|
||||
@ -665,10 +710,6 @@ $.Tile.prototype = {
|
||||
);
|
||||
}
|
||||
|
||||
// This gives the application a chance to make image manipulation
|
||||
// changes as we are rendering the image
|
||||
drawingHandler({context: context, tile: this, rendered: rendered});
|
||||
|
||||
var sourceWidth, sourceHeight;
|
||||
if (this.sourceBounds) {
|
||||
sourceWidth = Math.min(this.sourceBounds.width, rendered.canvas.width);
|
||||
|
@ -65,7 +65,7 @@ $.CacheRecord = class {
|
||||
* Might be undefined if this.loaded = false.
|
||||
* You can access the data in synchronous way, but the data might not be available.
|
||||
* If you want to access the data indirectly (await), use this.transformTo or this.getDataAs
|
||||
* @return {any}
|
||||
* @returns {any}
|
||||
*/
|
||||
get data() {
|
||||
return this._data;
|
||||
@ -74,7 +74,7 @@ $.CacheRecord = class {
|
||||
/**
|
||||
* Read the cache type. The type can dynamically change, but should be consistent at
|
||||
* one point in the time. For available types see the OpenSeadragon.Convertor, or the tutorials.
|
||||
* @return {string}
|
||||
* @returns {string}
|
||||
*/
|
||||
get type() {
|
||||
return this._type;
|
||||
@ -315,6 +315,12 @@ $.CacheRecord = class {
|
||||
});
|
||||
}
|
||||
|
||||
_triggerNeedsDraw() {
|
||||
for (let tile of this._tiles) {
|
||||
tile.tiledImage._needsDraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely overwrite the cache data and return the old data
|
||||
* @private
|
||||
@ -330,6 +336,7 @@ $.CacheRecord = class {
|
||||
this._type = type;
|
||||
this._data = data;
|
||||
this._promise = $.Promise.resolve(data);
|
||||
this._triggerNeedsDraw();
|
||||
return this._promise;
|
||||
}
|
||||
return this._promise.then(x => {
|
||||
@ -337,6 +344,7 @@ $.CacheRecord = class {
|
||||
this._type = type;
|
||||
this._data = data;
|
||||
this._promise = $.Promise.resolve(data);
|
||||
this._triggerNeedsDraw();
|
||||
return x;
|
||||
});
|
||||
}
|
||||
@ -481,6 +489,9 @@ $.TileCache = class {
|
||||
}
|
||||
|
||||
cacheRecord.addTile(theTile, options.data, options.dataType);
|
||||
if (cacheKey === theTile.cacheKey) {
|
||||
theTile.tiledImage._needsDraw = true;
|
||||
}
|
||||
|
||||
// Note that just because we're unloading a tile doesn't necessarily mean
|
||||
// we're unloading its cache records. With repeated calls it should sort itself out, though.
|
||||
|
@ -49,7 +49,15 @@
|
||||
loadTilesWithAjax: true,
|
||||
ajaxHeaders: {
|
||||
'X-Viewer-Header': 'ViewerHeaderValue'
|
||||
}
|
||||
},
|
||||
// TODO: this test proves that tile cacheKey does not change
|
||||
// with headers change, which by default are part of the key,
|
||||
// but we cannot automatically update them since users might
|
||||
// manually change it long before... or can we? The tile gets
|
||||
// reloaded, so user code should get re-executed. IMHO,
|
||||
// with tile propagation the best would be throw away old tile
|
||||
// and start anew
|
||||
callTileLoadedWithCachedData: true
|
||||
});
|
||||
},
|
||||
afterEach: function() {
|
||||
|
@ -213,7 +213,7 @@
|
||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||
undefined, true, null, dummyRect, "", "key");
|
||||
|
||||
dummyTile.tiledImage = {};
|
||||
const cache = new OpenSeadragon.CacheRecord();
|
||||
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
||||
|
||||
@ -262,7 +262,7 @@
|
||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||
undefined, true, null, dummyRect, "", "key");
|
||||
|
||||
dummyTile.tiledImage = {};
|
||||
const cache = new OpenSeadragon.CacheRecord();
|
||||
cache.testGetSet = async function(type) {
|
||||
const value = await cache.getDataAs(type, false);
|
||||
@ -330,7 +330,7 @@
|
||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||
undefined, true, null, dummyRect, "", "key");
|
||||
|
||||
dummyTile.tiledImage = {};
|
||||
const cache = new OpenSeadragon.CacheRecord();
|
||||
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
||||
cache.getDataAs("__TEST__longConversionProcessForTesting").then(convertedData => {
|
||||
@ -374,7 +374,7 @@
|
||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||
undefined, true, null, dummyRect, "", "key");
|
||||
|
||||
dummyTile.tiledImage = {};
|
||||
const cache = new OpenSeadragon.CacheRecord();
|
||||
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
||||
cache.transformTo("__TEST__longConversionProcessForTesting").then(_ => {
|
||||
|
Loading…
Reference in New Issue
Block a user