From 99c35aa3cb5ef825e2661e4fbfe860e023c512e0 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 21 Feb 2024 16:01:18 -0500 Subject: [PATCH] consolidate drawer creation into viewer api. add drawer-error event --- src/drawerbase.js | 31 +++++++++++++++++++++++++++++++ src/viewer.js | 29 +++++++++++++++++------------ src/webgldrawer.js | 7 ++----- test/demo/drawercomparison.js | 2 +- 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/drawerbase.js b/src/drawerbase.js index 29d7a3b4..0a0d04ce 100644 --- a/src/drawerbase.js +++ b/src/drawerbase.js @@ -280,6 +280,37 @@ OpenSeadragon.DrawerBase = class DrawerBase{ }); } + /** + * Called by implementations to fire the drawer-error event + * @private + */ + _raiseDrawerErrorEvent(tiledImage, errorMessage){ + if(!this.viewer) { + return; + } + + /** + * Raised when a tiled image is drawn to the canvas. Used internally for testing. + * The update-viewport event is preferred if you want to know when a frame has been drawn. + * + * @event drawer-error + * @memberof OpenSeadragon.Viewer + * @type {object} + * @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event. + * @property {OpenSeadragon.TiledImage} tiledImage - Which TiledImage is being drawn. + * @property {OpenSeadragon.DrawerBase} drawer - The drawer that raised the error. + * @property {String} error - A message describing the error. + * @property {?Object} userData - Arbitrary subscriber-defined object. + * @private + */ + this.viewer.raiseEvent( 'drawer-error', { + tiledImage: tiledImage, + drawer: this, + error: errorMessage, + }); + } + + }; }( OpenSeadragon )); diff --git a/src/viewer.js b/src/viewer.js index c3c10938..c2168c1b 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -456,7 +456,7 @@ $.Viewer = function( options ) { this.drawer = null; for (const drawerCandidate of drawerCandidates){ - let success = this.setDrawer(drawerCandidate, false); + let success = this.requestDrawer(drawerCandidate, true, false); if(success){ break; } @@ -929,19 +929,20 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, }, /** - * Set the drawer for this viewer, as a supported string or drawer constructor. - * @param {String | OpenSeadragon.DrawerBase} drawerCandidate The type of drawer to try to construct - * @param { Boolean } [redrawImmediately] Whether to immediately draw a new frame. Default = true. + * Request a drawer for this viewer, as a supported string or drawer constructor. + * @param {String | OpenSeadragon.DrawerBase} drawerCandidate The type of drawer to try to construct. + * @param { Boolean } [mainDrawer] Whether to use this as the viewer's main drawer. Default = true. + * @param { Boolean } [redrawImmediately] Whether to immediately draw a new frame. Only used if mainDrawer = true. Default = true. * @param { Object } [drawerOptions] Options for this drawer. If falsey, defaults to viewer.drawerOptions * for this viewer type. See {@link OpenSeadragon.Options}. - * @returns {Boolean} whether the drawer was created successfully + * @returns {Object | Boolean} The drawer that was created, or false if the requestd drawer is not supported */ - setDrawer(drawerCandidate, redrawImmediately = true, drawerOptions = null){ + requestDrawer(drawerCandidate, mainDrawer = true, redrawImmediately = true, drawerOptions = null){ const oldDrawer = this.drawer; let Drawer = null; - //if inherits from a drawer base, use it + //if the candidate inherits from a drawer base, use it if (drawerCandidate && drawerCandidate.prototype instanceof $.DrawerBase) { Drawer = drawerCandidate; drawerCandidate = 'custom'; @@ -957,12 +958,12 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, if (Drawer && Drawer.isSupported()) { // first destroy the previous drawer - if(oldDrawer){ + if(oldDrawer && mainDrawer){ oldDrawer.destroy(); } // create the new drawer - this.drawer = new Drawer({ + const newDrawer = new Drawer({ viewer: this, viewport: this.viewport, element: this.canvas, @@ -970,10 +971,14 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, options: drawerOptions || this.drawerOptions[drawerCandidate], }); - if(redrawImmediately){ - this.forceRedraw(); + if(mainDrawer){ + this.drawer = newDrawer; + if(redrawImmediately){ + this.forceRedraw(); + } } - return true; + + return newDrawer; } return false; diff --git a/src/webgldrawer.js b/src/webgldrawer.js index b747779e..af3ff198 100644 --- a/src/webgldrawer.js +++ b/src/webgldrawer.js @@ -231,11 +231,7 @@ */ _getBackupCanvasDrawer(){ if(!this._backupCanvasDrawer){ - this._backupCanvasDrawer = new $.CanvasDrawer({ - viewer: this.viewer, - viewport: this.viewport, - element: this.container, - }); + this._backupCanvasDrawer = this.viewer.requestDrawer('canvas', false); this._backupCanvasDrawer.canvas.style.setProperty('visibility', 'hidden'); } @@ -882,6 +878,7 @@ if(!wasTainted){ 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.'); } return; } diff --git a/test/demo/drawercomparison.js b/test/demo/drawercomparison.js index 96793915..76c780a4 100644 --- a/test/demo/drawercomparison.js +++ b/test/demo/drawercomparison.js @@ -49,7 +49,7 @@ let viewer2 = window.viewer2 = OpenSeadragon({ minZoomImageRatio:0.01, maxZoomPixelRatio:100, smoothTileEdgesMinZoom:1.1, - crossOriginPolicy: 'Anonymous', + // crossOriginPolicy: 'Anonymous', ajaxWithCredentials: false, // maxImageCacheCount: 30, drawer:drawer2,