diff --git a/src/mousetracker.js b/src/mousetracker.js index 7a381b7e..2a0b6a3c 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -357,7 +357,7 @@ getActivePointersListByType: function ( type ) { var delegate = THIS[ this.hash ], i, - len = delegate.activePointersLists.length, + len = delegate ? delegate.activePointersLists.length : 0, list; for ( i = 0; i < len; i++ ) { @@ -367,7 +367,9 @@ } list = new $.MouseTracker.GesturePointList( type ); - delegate.activePointersLists.push( list ); + if(delegate){ + delegate.activePointersLists.push( list ); + } return list; }, diff --git a/src/webgldrawer.js b/src/webgldrawer.js index 276cfc97..8fbd3bed 100644 --- a/src/webgldrawer.js +++ b/src/webgldrawer.js @@ -44,7 +44,7 @@ * For the first pass, tile composition for a given TiledImage is always done using a canvas with a WebGL context. * This allows tiles to be stitched together without seams or artifacts, without requiring a tile source with overlap. If overlap is present, * overlapping pixels are discarded. The second pass copies all pixel data from the WebGL context onto an output canvas - * with a Context2d context. This allows appliations to have access to pixel data and other functionality provided by + * with a Context2d context. This allows applications to have access to pixel data and other functionality provided by * Context2d, regardless of whether the CanvasDrawer or the WebGLDrawer is used. Certain options, including compositeOperation, * clip, croppingPolygons, and debugMode are implemented using Context2d operations; in these scenarios, each TiledImage is * drawn onto the output canvas immediately after the tile composition step (pass 1). Otherwise, for efficiency, all TiledImages @@ -83,7 +83,7 @@ this.viewer.addHandler("image-unloaded", ev => this._imageUnloadedHandler(ev)); // this.viewer and this.canvas are part of the public DrawerBase API - // and are set by the parent constructor. Additional setup is done by + // and are defined by the parent DrawerBase class. Additional setup is done by // the private _setupCanvases and _setupRenderer functions. this._setupCanvases(); this._setupRenderer(); @@ -273,6 +273,10 @@ } let maxTextures = this._gl.getParameter(this._gl.MAX_TEXTURE_IMAGE_UNITS); + if(maxTextures <= 0){ + $.console.error(`There was a WebGL problem: bad value for MAX_TEXTURE_IMAGE_UNITS (${maxTextures})`); + return; + } let texturePositionArray = new Float32Array(maxTextures * 12); // 6 vertices (2 triangles) x 2 coordinates per vertex let textureDataArray = new Array(maxTextures); let matrixArray = new Array(maxTextures); @@ -362,7 +366,10 @@ gl.clear(gl.COLOR_BUFFER_BIT); // clear the back buffer } - this._raiseTiledImageDrawnEvent(tiledImage, tilesToDraw.map(info=>info.tile)); + // after drawing the first TiledImage, fire the tiled-image-drawn event (for testing) + if(tiledImageIndex === 0){ + this._raiseTiledImageDrawnEvent(tiledImage, tilesToDraw.map(info=>info.tile)); + } }); diff --git a/test/modules/tiledimage.js b/test/modules/tiledimage.js index bc950c49..6c33b752 100644 --- a/test/modules/tiledimage.js +++ b/test/modules/tiledimage.js @@ -1,7 +1,9 @@ /* global QUnit, $, Util, testLog */ (function() { - var viewer; + let viewer; + + let precision = 0.000000001; QUnit.module('TiledImage', { beforeEach: function() { @@ -120,8 +122,8 @@ viewer.addHandler('animation-finish', function animationHandler() { viewer.removeHandler('animation-finish', animationHandler); - assert.propEqual(image.getBounds(), new OpenSeadragon.Rect(1, 2, 3, 3), 'target bounds after animation'); - assert.propEqual(image.getBounds(true), new OpenSeadragon.Rect(1, 2, 3, 3), 'current bounds after animation'); + Util.assertRectangleEquals(assert, new OpenSeadragon.Rect(1, 2, 3, 3), image.getBounds(), precision, 'target bounds after animation'); + Util.assertRectangleEquals(assert, new OpenSeadragon.Rect(1, 2, 3, 3), image.getBounds(true), precision, 'target bounds after animation'); done(); }); }); diff --git a/test/modules/tilesource-dynamic-url.js b/test/modules/tilesource-dynamic-url.js index c6c7fe94..099530af 100644 --- a/test/modules/tilesource-dynamic-url.js +++ b/test/modules/tilesource-dynamic-url.js @@ -4,6 +4,7 @@ (function() { var ASSERT = null; + var done = null; var DYNAMIC_URL = ""; var viewer = null; var OriginalAjax = OpenSeadragon.makeAjaxRequest; @@ -16,9 +17,10 @@ /** * Set up shared variables for test */ - var configure = function(assert, url) { + var configure = function(assert, url, assertAsyncDone) { ASSERT = assert; DYNAMIC_URL = url; + done = assertAsyncDone; firstUrlPromise = new Promise(resolve => { firstUrlPromiseResolver = () => { isFirstUrlPromiseResolved = true; @@ -94,6 +96,7 @@ // Otherwise close viewer if (isFirstUrlPromiseResolved) { viewer.close(); + done(); } else { firstUrlPromiseResolver(); } @@ -119,8 +122,11 @@ OpenSeadragon.extend( Tile.prototype, OpenSeadragon.Tile.prototype, { getUrl: function() { - // TODO: it seems sometimes this can be called after ASSERT is destroyed; should this be fixed differently? - ASSERT && ASSERT.ok(true, 'Tile.getUrl called'); + // if ASSERT is still truthy, call ASSERT.ok. If the viewer + // has already been destroyed and ASSERT has set to null, ignore this + if(ASSERT){ + ASSERT.ok(true, 'Tile.getUrl called'); + } return OriginalTile.prototype.getUrl.apply(this); } }); @@ -190,11 +196,12 @@ // ---------- QUnit.test('TileSource.getTileUrl supports returning a function', function(assert) { - configure(assert, 'dynamicUrl'); + const done = assert.async(); + configure(assert, 'dynamicUrl', done); const viewer = testUrlCall('dynamicUrl'); firstUrlPromise.then(() => { // after querying with first dynamic url, update the url and trigger new request - DYNAMIC_URL = 'dyanmicUrl2'; + DYNAMIC_URL = 'dynamicUrl2'; delete viewer.world.getItemAt(0).tilesMatrix[1][0][0]; }) });