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' );
|
const canvas = document.createElement( 'canvas' );
|
||||||
canvas.width = imageData.width;
|
canvas.width = imageData.width;
|
||||||
canvas.height = imageData.height;
|
canvas.height = imageData.height;
|
||||||
const context = canvas.getContext('2d');
|
const context = canvas.getContext('2d', { willReadFrequently: true });
|
||||||
context.drawImage( imageData, 0, 0 );
|
context.drawImage( imageData, 0, 0 );
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
77
src/tile.js
77
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 {string} type data type to require
|
||||||
* @param {boolean?} [copy=this.loaded] whether to force copy retrieval
|
* @param {boolean?} [copy=this.loaded] whether to force copy retrieval
|
||||||
* @return {*|undefined} data in the desired type, or undefined if a conversion is ongoing
|
* @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);
|
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
|
* Set cache data
|
||||||
* @param {*} value
|
* @param {*} value
|
||||||
@ -539,7 +555,8 @@ $.Tile.prototype = {
|
|||||||
type = $.convertor.guessType(data);
|
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
|
//todo later, we could have drawers register their supported rendering type
|
||||||
// and OpenSeadragon would check compatibility automatically, now we render
|
// and OpenSeadragon would check compatibility automatically, now we render
|
||||||
// using two main types so we check their ability
|
// using two main types so we check their ability
|
||||||
@ -609,25 +626,53 @@ $.Tile.prototype = {
|
|||||||
drawCanvas: function( context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source) {
|
drawCanvas: function( context, drawingHandler, scale, translate, shouldRoundPositionAndSize, source) {
|
||||||
|
|
||||||
var position = this.position.times($.pixelDensityRatio),
|
var position = this.position.times($.pixelDensityRatio),
|
||||||
size = this.size.times($.pixelDensityRatio),
|
size = this.size.times($.pixelDensityRatio);
|
||||||
rendered = this.getCanvasContext();
|
|
||||||
|
|
||||||
if (!rendered) {
|
const _this = this;
|
||||||
$.console.warn(
|
// This gives the application a chance to make image manipulation
|
||||||
'[Tile.drawCanvas] attempting to draw tile %s when it\'s not cached',
|
// changes as we are rendering the image
|
||||||
this.toString());
|
drawingHandler({context: context, tile: this, get rendered() {
|
||||||
return;
|
$.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 undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !this.loaded || !rendered ){
|
if ( !_this.loaded || !context ){
|
||||||
$.console.warn(
|
$.console.warn(
|
||||||
"Attempting to draw tile %s when it's not yet loaded.",
|
"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()
|
this.toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
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.save();
|
||||||
context.globalAlpha = this.opacity;
|
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;
|
var sourceWidth, sourceHeight;
|
||||||
if (this.sourceBounds) {
|
if (this.sourceBounds) {
|
||||||
sourceWidth = Math.min(this.sourceBounds.width, rendered.canvas.width);
|
sourceWidth = Math.min(this.sourceBounds.width, rendered.canvas.width);
|
||||||
|
@ -65,7 +65,7 @@ $.CacheRecord = class {
|
|||||||
* Might be undefined if this.loaded = false.
|
* Might be undefined if this.loaded = false.
|
||||||
* You can access the data in synchronous way, but the data might not be available.
|
* 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
|
* If you want to access the data indirectly (await), use this.transformTo or this.getDataAs
|
||||||
* @return {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
get data() {
|
get data() {
|
||||||
return this._data;
|
return this._data;
|
||||||
@ -74,7 +74,7 @@ $.CacheRecord = class {
|
|||||||
/**
|
/**
|
||||||
* Read the cache type. The type can dynamically change, but should be consistent at
|
* 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.
|
* one point in the time. For available types see the OpenSeadragon.Convertor, or the tutorials.
|
||||||
* @return {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
get type() {
|
get type() {
|
||||||
return this._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
|
* Safely overwrite the cache data and return the old data
|
||||||
* @private
|
* @private
|
||||||
@ -330,6 +336,7 @@ $.CacheRecord = class {
|
|||||||
this._type = type;
|
this._type = type;
|
||||||
this._data = data;
|
this._data = data;
|
||||||
this._promise = $.Promise.resolve(data);
|
this._promise = $.Promise.resolve(data);
|
||||||
|
this._triggerNeedsDraw();
|
||||||
return this._promise;
|
return this._promise;
|
||||||
}
|
}
|
||||||
return this._promise.then(x => {
|
return this._promise.then(x => {
|
||||||
@ -337,6 +344,7 @@ $.CacheRecord = class {
|
|||||||
this._type = type;
|
this._type = type;
|
||||||
this._data = data;
|
this._data = data;
|
||||||
this._promise = $.Promise.resolve(data);
|
this._promise = $.Promise.resolve(data);
|
||||||
|
this._triggerNeedsDraw();
|
||||||
return x;
|
return x;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -481,6 +489,9 @@ $.TileCache = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cacheRecord.addTile(theTile, options.data, options.dataType);
|
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
|
// 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.
|
// we're unloading its cache records. With repeated calls it should sort itself out, though.
|
||||||
|
@ -49,7 +49,15 @@
|
|||||||
loadTilesWithAjax: true,
|
loadTilesWithAjax: true,
|
||||||
ajaxHeaders: {
|
ajaxHeaders: {
|
||||||
'X-Viewer-Header': 'ViewerHeaderValue'
|
'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() {
|
afterEach: function() {
|
||||||
|
@ -213,7 +213,7 @@
|
|||||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||||
undefined, true, null, dummyRect, "", "key");
|
undefined, true, null, dummyRect, "", "key");
|
||||||
|
dummyTile.tiledImage = {};
|
||||||
const cache = new OpenSeadragon.CacheRecord();
|
const cache = new OpenSeadragon.CacheRecord();
|
||||||
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
||||||
|
|
||||||
@ -262,7 +262,7 @@
|
|||||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||||
undefined, true, null, dummyRect, "", "key");
|
undefined, true, null, dummyRect, "", "key");
|
||||||
|
dummyTile.tiledImage = {};
|
||||||
const cache = new OpenSeadragon.CacheRecord();
|
const cache = new OpenSeadragon.CacheRecord();
|
||||||
cache.testGetSet = async function(type) {
|
cache.testGetSet = async function(type) {
|
||||||
const value = await cache.getDataAs(type, false);
|
const value = await cache.getDataAs(type, false);
|
||||||
@ -330,7 +330,7 @@
|
|||||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||||
undefined, true, null, dummyRect, "", "key");
|
undefined, true, null, dummyRect, "", "key");
|
||||||
|
dummyTile.tiledImage = {};
|
||||||
const cache = new OpenSeadragon.CacheRecord();
|
const cache = new OpenSeadragon.CacheRecord();
|
||||||
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
||||||
cache.getDataAs("__TEST__longConversionProcessForTesting").then(convertedData => {
|
cache.getDataAs("__TEST__longConversionProcessForTesting").then(convertedData => {
|
||||||
@ -374,7 +374,7 @@
|
|||||||
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
const dummyRect = new OpenSeadragon.Rect(0, 0, 0, 0, 0);
|
||||||
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
const dummyTile = new OpenSeadragon.Tile(0, 0, 0, dummyRect, true, "",
|
||||||
undefined, true, null, dummyRect, "", "key");
|
undefined, true, null, dummyRect, "", "key");
|
||||||
|
dummyTile.tiledImage = {};
|
||||||
const cache = new OpenSeadragon.CacheRecord();
|
const cache = new OpenSeadragon.CacheRecord();
|
||||||
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
cache.addTile(dummyTile, "/test/data/A.png", "__TEST__url");
|
||||||
cache.transformTo("__TEST__longConversionProcessForTesting").then(_ => {
|
cache.transformTo("__TEST__longConversionProcessForTesting").then(_ => {
|
||||||
|
Loading…
Reference in New Issue
Block a user