From b5d205d58e2633119c3aa850f7aa1136107e70dd Mon Sep 17 00:00:00 2001 From: Jesper Dam Date: Fri, 11 Jul 2014 15:18:22 +0200 Subject: [PATCH] Don't process images until their 'load' event has been emitted In IE11, the 'complete' property on an image is set before the image is fully initialized (so it still has 0x0 dimensions). So rather than relying on this property, always just wait for the 'load' event. --- core/display.js | 8 +++++--- tests/test.display.js | 15 ++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/core/display.js b/core/display.js index 1528384d..44b01246 100644 --- a/core/display.js +++ b/core/display.js @@ -375,13 +375,16 @@ export default class Display { imageRect(x, y, mime, arr) { const img = new Image(); + img._noVNC_display = this; img.src = "data: " + mime + ";base64," + Base64.encode(arr); + img.addEventListener('load', this._resume_renderQ); this._renderQ_push({ 'type': 'img', 'img': img, 'x': x, 'y': y }); + return img; } // start updating a tile @@ -602,6 +605,7 @@ export default class Display { // "this" is the object that is ready, not the // display object this.removeEventListener('load', this._noVNC_display._resume_renderQ); + this.completeAndLoaded = true; this._noVNC_display._scan_renderQ(); } @@ -629,11 +633,9 @@ export default class Display { this.blitRgbxImage(a.x, a.y, a.width, a.height, a.data, 0, true); break; case 'img': - if (a.img.complete) { + if (a.img.completeAndLoaded) { this.drawImage(a.img, a.x, a.y); } else { - a.img._noVNC_display = this; - a.img.addEventListener('load', this._resume_renderQ); // We need to wait for this image to 'load' // to keep things in-order ready = false; diff --git a/tests/test.display.js b/tests/test.display.js index b3595503..9ab514c7 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -321,12 +321,15 @@ describe('Display/Canvas Helper', function () { }); it('should support drawing images via #imageRect', function (done) { - display.imageRect(0, 0, "image/png", make_image_png(checked_data)); + const img = display.imageRect(0, 0, "image/png", make_image_png(checked_data)); + img.dispatchEvent(new CustomEvent('load', {})); display.flip(); display.onflush = () => { expect(display).to.have.displayed(checked_data); + expect(img.completeAndLoaded).to.equal(true); done(); }; + display.flush(); }); @@ -422,7 +425,7 @@ describe('Display/Canvas Helper', function () { }); it('should wait until an image is loaded to attempt to draw it and the rest of the queue', function () { - const img = { complete: false, addEventListener: sinon.spy() }; + const img = { completeAndLoaded: false }; display._renderQ = [{ type: 'img', x: 3, y: 4, img: img }, { type: 'fill', x: 1, y: 2, width: 3, height: 4, color: 5 }]; display.drawImage = sinon.spy(); @@ -431,13 +434,11 @@ describe('Display/Canvas Helper', function () { display._scan_renderQ(); expect(display.drawImage).to.not.have.been.called; expect(display.fillRect).to.not.have.been.called; - expect(img.addEventListener).to.have.been.calledOnce; - display._renderQ[0].img.complete = true; + display._renderQ[0].img.completeAndLoaded = true; display._scan_renderQ(); expect(display.drawImage).to.have.been.calledOnce; expect(display.fillRect).to.have.been.calledOnce; - expect(img.addEventListener).to.have.been.calledOnce; }); it('should call callback when queue is flushed', function () { @@ -478,9 +479,9 @@ describe('Display/Canvas Helper', function () { it('should draw an image from an image object on type "img" (if complete)', function () { display.drawImage = sinon.spy(); - display._renderQ_push({ type: 'img', x: 3, y: 4, img: { complete: true } }); + display._renderQ_push({ type: 'img', x: 3, y: 4, img: { completeAndLoaded: true } }); expect(display.drawImage).to.have.been.calledOnce; - expect(display.drawImage).to.have.been.calledWith({ complete: true }, 3, 4); + expect(display.drawImage).to.have.been.calledWith({ completeAndLoaded: true }, 3, 4); }); }); });