mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-29 08:36:10 +03:00
Fix tests: always fetch up-to-date pixel values, prevent adding loaded tile to the 'bestTiles' array. Enforce _needsDraw check to be based on lastDrawn - we are async now.
This commit is contained in:
parent
fcf20be8ea
commit
9ef2d46e75
@ -352,7 +352,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
* @returns {Boolean} whether the item still needs to be drawn due to blending
|
* @returns {Boolean} whether the item still needs to be drawn due to blending
|
||||||
*/
|
*/
|
||||||
setDrawn: function(){
|
setDrawn: function(){
|
||||||
this._needsDraw = this._isBlending || this._wasBlending;
|
this._needsDraw = this._isBlending || this._wasBlending ||
|
||||||
|
(this.opacity > 0 && this._lastDrawn.length < 1);
|
||||||
return this._needsDraw;
|
return this._needsDraw;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1825,7 +1826,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
if ( tile.loading ) {
|
if ( tile.loading ) {
|
||||||
// the tile is already in the download queue
|
// the tile is already in the download queue
|
||||||
this._tilesLoading++;
|
this._tilesLoading++;
|
||||||
} else if (!loadingCoverage) {
|
} else if (!tile.loaded && !loadingCoverage) {
|
||||||
|
// add tile to best tiles to load only when not loaded already
|
||||||
best = this._compareTiles( best, tile, this.maxTilesPerFrame );
|
best = this._compareTiles( best, tile, this.maxTilesPerFrame );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,10 +87,6 @@
|
|||||||
this._clippingContext = null;
|
this._clippingContext = null;
|
||||||
this._renderingCanvas = null;
|
this._renderingCanvas = null;
|
||||||
|
|
||||||
// Unique type per drawer: uploads texture to unique webgl context.
|
|
||||||
this._dataType = `${Date.now()}_TEX_2D`;
|
|
||||||
this._setupTextureHandlers(this._dataType);
|
|
||||||
|
|
||||||
// Reject listening for the tile-drawing and tile-drawn events, which this drawer does not fire
|
// Reject listening for the tile-drawing and tile-drawn events, which this drawer does not fire
|
||||||
this.viewer.rejectEventHandler("tile-drawn", "The WebGLDrawer does not raise the tile-drawn event");
|
this.viewer.rejectEventHandler("tile-drawn", "The WebGLDrawer does not raise the tile-drawn event");
|
||||||
this.viewer.rejectEventHandler("tile-drawing", "The WebGLDrawer does not raise the tile-drawing event");
|
this.viewer.rejectEventHandler("tile-drawing", "The WebGLDrawer does not raise the tile-drawing event");
|
||||||
@ -101,6 +97,10 @@
|
|||||||
this._setupCanvases();
|
this._setupCanvases();
|
||||||
this._setupRenderer();
|
this._setupRenderer();
|
||||||
|
|
||||||
|
// Unique type per drawer: uploads texture to unique webgl context.
|
||||||
|
this._dataType = `${Date.now()}_TEX_2D`;
|
||||||
|
this._setupTextureHandlers(this._dataType);
|
||||||
|
|
||||||
this.context = this._outputContext; // API required by tests
|
this.context = this._outputContext; // API required by tests
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -757,7 +757,6 @@
|
|||||||
this._renderingCanvas.height = this._clippingCanvas.height = this._outputCanvas.height;
|
this._renderingCanvas.height = this._clippingCanvas.height = this._outputCanvas.height;
|
||||||
|
|
||||||
this._gl = this._renderingCanvas.getContext('webgl');
|
this._gl = this._renderingCanvas.getContext('webgl');
|
||||||
|
|
||||||
//make the additional canvas elements mirror size changes to the output canvas
|
//make the additional canvas elements mirror size changes to the output canvas
|
||||||
this.viewer.addHandler("resize", function(){
|
this.viewer.addHandler("resize", function(){
|
||||||
|
|
||||||
@ -784,12 +783,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_setupTextureHandlers(thisType) {
|
_setupTextureHandlers(thisType) {
|
||||||
|
const _this = this;
|
||||||
const tex2DCompatibleLoader = (tile, data) => {
|
const tex2DCompatibleLoader = (tile, data) => {
|
||||||
let tiledImage = tile.tiledImage;
|
let tiledImage = tile.tiledImage;
|
||||||
//todo verify we are calling conversion just right amount of time!
|
//todo verify we are calling conversion just right amount of time!
|
||||||
// e.g. no upload of cpu-existing texture
|
// e.g. no upload of cpu-existing texture
|
||||||
|
// also check textures are really getting destroyed (it is tested, but also do this with demos)
|
||||||
|
|
||||||
let gl = this._gl;
|
let gl = _this._gl;
|
||||||
|
|
||||||
// create a gl Texture for this tile and bind the canvas with the image data
|
// create a gl Texture for this tile and bind the canvas with the image data
|
||||||
let texture = gl.createTexture();
|
let texture = gl.createTexture();
|
||||||
@ -798,16 +799,16 @@
|
|||||||
if( overlap > 0){
|
if( overlap > 0){
|
||||||
// calculate the normalized position of the rect to actually draw
|
// calculate the normalized position of the rect to actually draw
|
||||||
// discarding overlap.
|
// discarding overlap.
|
||||||
let overlapFraction = this._calculateOverlapFraction(tile, tiledImage);
|
let overlapFraction = _this._calculateOverlapFraction(tile, tiledImage);
|
||||||
|
|
||||||
let left = tile.x === 0 ? 0 : overlapFraction.x;
|
let left = tile.x === 0 ? 0 : overlapFraction.x;
|
||||||
let top = tile.y === 0 ? 0 : overlapFraction.y;
|
let top = tile.y === 0 ? 0 : overlapFraction.y;
|
||||||
let right = tile.isRightMost ? 1 : 1 - overlapFraction.x;
|
let right = tile.isRightMost ? 1 : 1 - overlapFraction.x;
|
||||||
let bottom = tile.isBottomMost ? 1 : 1 - overlapFraction.y;
|
let bottom = tile.isBottomMost ? 1 : 1 - overlapFraction.y;
|
||||||
position = this._makeQuadVertexBuffer(left, right, top, bottom);
|
position = _this._makeQuadVertexBuffer(left, right, top, bottom);
|
||||||
} else {
|
} else {
|
||||||
// no overlap: this texture can use the unit quad as its position data
|
// no overlap: this texture can use the unit quad as its position data
|
||||||
position = this._unitQuad;
|
position = _this._unitQuad;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.activeTexture(gl.TEXTURE0);
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
@ -848,11 +849,12 @@
|
|||||||
|
|
||||||
this.declareSupportedDataFormats(imageTexType, c2dTexType);
|
this.declareSupportedDataFormats(imageTexType, c2dTexType);
|
||||||
|
|
||||||
// We should be OK uploading any of these types.
|
// We should be OK uploading any of these types. The complexity is selected to be O(3n), should be
|
||||||
$.convertor.learn("context2d", c2dTexType, tex2DCompatibleLoader, 1, 2);
|
// more than linear pass over pixels
|
||||||
$.convertor.learn("image", imageTexType, tex2DCompatibleLoader, 1, 2);
|
$.convertor.learn("context2d", c2dTexType, tex2DCompatibleLoader, 1, 3);
|
||||||
$.convertor.learn(c2dTexType, "context2d", dataRetrieval, 1, 2);
|
$.convertor.learn("image", imageTexType, tex2DCompatibleLoader, 1, 3);
|
||||||
$.convertor.learn(imageTexType, "image", dataRetrieval, 1, 2);
|
$.convertor.learn(c2dTexType, "context2d", dataRetrieval, 1, 3);
|
||||||
|
$.convertor.learn(imageTexType, "image", dataRetrieval, 1, 3);
|
||||||
|
|
||||||
$.convertor.learnDestroy(c2dTexType, tex2DCompatibleDestructor);
|
$.convertor.learnDestroy(c2dTexType, tex2DCompatibleDestructor);
|
||||||
$.convertor.learnDestroy(imageTexType, tex2DCompatibleDestructor);
|
$.convertor.learnDestroy(imageTexType, tex2DCompatibleDestructor);
|
||||||
|
@ -284,9 +284,9 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|||||||
draw: function() {
|
draw: function() {
|
||||||
this.viewer.drawer.draw(this._items);
|
this.viewer.drawer.draw(this._items);
|
||||||
this._needsDraw = false;
|
this._needsDraw = false;
|
||||||
this._items.forEach(function(item){
|
for (let item of this._items) {
|
||||||
this._needsDraw = item.setDrawn() || this._needsDraw;
|
this._needsDraw = item.setDrawn() || this._needsDraw;
|
||||||
});
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -220,17 +220,23 @@
|
|||||||
var done = assert.async();
|
var done = assert.async();
|
||||||
viewer.open('/test/data/testpattern.dzi');
|
viewer.open('/test/data/testpattern.dzi');
|
||||||
|
|
||||||
var density = OpenSeadragon.pixelDensityRatio;
|
function getPixelFromViewerScreenCoords(x, y) {
|
||||||
|
const density = OpenSeadragon.pixelDensityRatio;
|
||||||
|
const imageData = viewer.drawer.context.getImageData(x * density, y * density, 1, 1);
|
||||||
|
return {
|
||||||
|
r: imageData.data[0],
|
||||||
|
g: imageData.data[1],
|
||||||
|
b: imageData.data[2],
|
||||||
|
a: imageData.data[3]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
viewer.addHandler('open', function() {
|
viewer.addHandler('open', function() {
|
||||||
var firstImage = viewer.world.getItemAt(0);
|
var firstImage = viewer.world.getItemAt(0);
|
||||||
firstImage.addHandler('fully-loaded-change', function() {
|
firstImage.addHandler('fully-loaded-change', function() {
|
||||||
viewer.addOnceHandler('update-viewport', function(){
|
viewer.addOnceHandler('update-viewport', function(){
|
||||||
var imageData = viewer.drawer.context.getImageData(0, 0,
|
|
||||||
500 * density, 500 * density);
|
|
||||||
|
|
||||||
// Pixel 250,250 will be in the hole of the A
|
// Pixel 250,250 will be in the hole of the A
|
||||||
var expectedVal = getPixelValue(imageData, 250 * density, 250 * density);
|
var expectedVal = getPixelFromViewerScreenCoords(250, 250);
|
||||||
|
|
||||||
assert.notEqual(expectedVal.r, 0, 'Red channel should not be 0');
|
assert.notEqual(expectedVal.r, 0, 'Red channel should not be 0');
|
||||||
assert.notEqual(expectedVal.g, 0, 'Green channel should not be 0');
|
assert.notEqual(expectedVal.g, 0, 'Green channel should not be 0');
|
||||||
@ -243,8 +249,7 @@
|
|||||||
var secondImage = viewer.world.getItemAt(1);
|
var secondImage = viewer.world.getItemAt(1);
|
||||||
secondImage.addHandler('fully-loaded-change', function() {
|
secondImage.addHandler('fully-loaded-change', function() {
|
||||||
viewer.addOnceHandler('update-viewport', function(){
|
viewer.addOnceHandler('update-viewport', function(){
|
||||||
var imageData = viewer.drawer.context.getImageData(0, 0, 500 * density, 500 * density);
|
var actualVal = getPixelFromViewerScreenCoords(250, 250);
|
||||||
var actualVal = getPixelValue(imageData, 250 * density, 250 * density);
|
|
||||||
|
|
||||||
assert.equal(actualVal.r, expectedVal.r,
|
assert.equal(actualVal.r, expectedVal.r,
|
||||||
'Red channel should not change in transparent part of the A');
|
'Red channel should not change in transparent part of the A');
|
||||||
@ -255,10 +260,10 @@
|
|||||||
assert.equal(actualVal.a, expectedVal.a,
|
assert.equal(actualVal.a, expectedVal.a,
|
||||||
'Alpha channel should not change in transparent part of the A');
|
'Alpha channel should not change in transparent part of the A');
|
||||||
|
|
||||||
var onAVal = getPixelValue(imageData, 333 * density, 250 * density);
|
var onAVal = getPixelFromViewerScreenCoords(333 , 250);
|
||||||
assert.equal(onAVal.r, 0, 'Red channel should be null on the A');
|
assert.equal(onAVal.r, 0, 'Red channel should be 0 on the A');
|
||||||
assert.equal(onAVal.g, 0, 'Green channel should be null on the A');
|
assert.equal(onAVal.g, 0, 'Green channel should be 0 on the A');
|
||||||
assert.equal(onAVal.b, 0, 'Blue channel should be null on the A');
|
assert.equal(onAVal.b, 0, 'Blue channel should be 0 on the A');
|
||||||
assert.equal(onAVal.a, 255, 'Alpha channel should be 255 on the A');
|
assert.equal(onAVal.a, 255, 'Alpha channel should be 255 on the A');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
@ -271,17 +276,6 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getPixelValue(imageData, x, y) {
|
|
||||||
var offset = 4 * (y * imageData.width + x);
|
|
||||||
return {
|
|
||||||
r: imageData.data[offset],
|
|
||||||
g: imageData.data[offset + 1],
|
|
||||||
b: imageData.data[offset + 2],
|
|
||||||
a: imageData.data[offset + 3]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -123,7 +123,13 @@
|
|||||||
QUnit.test('basics', function(assert) {
|
QUnit.test('basics', function(assert) {
|
||||||
const done = assert.async();
|
const done = assert.async();
|
||||||
const fakeViewer = {
|
const fakeViewer = {
|
||||||
raiseEvent: function() {}
|
raiseEvent: function() {},
|
||||||
|
drawer: {
|
||||||
|
// tile in safe mode inspects the supported formats upon cache set
|
||||||
|
getSupportedDataFormats() {
|
||||||
|
return [T_A, T_B, T_C, T_D, T_E];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const fakeTiledImage0 = {
|
const fakeTiledImage0 = {
|
||||||
viewer: fakeViewer,
|
viewer: fakeViewer,
|
||||||
@ -170,7 +176,13 @@
|
|||||||
QUnit.test('maxImageCacheCount', function(assert) {
|
QUnit.test('maxImageCacheCount', function(assert) {
|
||||||
const done = assert.async();
|
const done = assert.async();
|
||||||
const fakeViewer = {
|
const fakeViewer = {
|
||||||
raiseEvent: function() {}
|
raiseEvent: function() {},
|
||||||
|
drawer: {
|
||||||
|
// tile in safe mode inspects the supported formats upon cache set
|
||||||
|
getSupportedDataFormats() {
|
||||||
|
return [T_A, T_B, T_C, T_D, T_E];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const fakeTiledImage0 = {
|
const fakeTiledImage0 = {
|
||||||
viewer: fakeViewer,
|
viewer: fakeViewer,
|
||||||
@ -218,7 +230,13 @@
|
|||||||
QUnit.test('Tile API: basic conversion', function(test) {
|
QUnit.test('Tile API: basic conversion', function(test) {
|
||||||
const done = test.async();
|
const done = test.async();
|
||||||
const fakeViewer = {
|
const fakeViewer = {
|
||||||
raiseEvent: function() {}
|
raiseEvent: function() {},
|
||||||
|
drawer: {
|
||||||
|
// tile in safe mode inspects the supported formats upon cache set
|
||||||
|
getSupportedDataFormats() {
|
||||||
|
return [T_A, T_B, T_C, T_D, T_E];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const tileCache = new OpenSeadragon.TileCache();
|
const tileCache = new OpenSeadragon.TileCache();
|
||||||
const fakeTiledImage0 = {
|
const fakeTiledImage0 = {
|
||||||
@ -406,7 +424,13 @@
|
|||||||
QUnit.test('Tile API Cache Interaction', function(test) {
|
QUnit.test('Tile API Cache Interaction', function(test) {
|
||||||
const done = test.async();
|
const done = test.async();
|
||||||
const fakeViewer = {
|
const fakeViewer = {
|
||||||
raiseEvent: function() {}
|
raiseEvent: function() {},
|
||||||
|
drawer: {
|
||||||
|
// tile in safe mode inspects the supported formats upon cache set
|
||||||
|
getSupportedDataFormats() {
|
||||||
|
return [T_A, T_B, T_C, T_D, T_E];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const tileCache = new OpenSeadragon.TileCache();
|
const tileCache = new OpenSeadragon.TileCache();
|
||||||
const fakeTiledImage0 = {
|
const fakeTiledImage0 = {
|
||||||
|
Loading…
Reference in New Issue
Block a user