diff options
author | Pierre Ossman <ossman@cendio.se> | 2019-12-23 15:40:17 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2019-12-23 15:52:54 +0100 |
commit | c4eb4ddcfe284a84fe147544cddfce2962fd4a87 (patch) | |
tree | 4af64da98c6b7a714aa667eb9684cf03569e81be | |
parent | 4babdf33bd6441343ce33802d72ef69e74d6f69d (diff) | |
download | novnc-c4eb4ddcfe284a84fe147544cddfce2962fd4a87.tar.gz |
Handle slow loading of images
Internet Explorer seems to flag images as loaded prematurely, which
can result in rendering bugs. We can detect this by looking at the
dimensions though.
-rw-r--r-- | core/display.js | 9 | ||||
-rw-r--r-- | tests/test.display.js | 27 |
2 files changed, 32 insertions, 4 deletions
diff --git a/core/display.js b/core/display.js index c895717..3dd5fce 100644 --- a/core/display.js +++ b/core/display.js @@ -360,8 +360,14 @@ export default class Display { } imageRect(x, y, width, height, mime, arr) { + /* The internal logic cannot handle empty images, so bail early */ + if ((width === 0) || (height === 0)) { + return; + } + const img = new Image(); img.src = "data: " + mime + ";base64," + Base64.encode(arr); + this._renderQ_push({ 'type': 'img', 'img': img, @@ -617,7 +623,8 @@ 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) { + /* IE tends to set "complete" prematurely, so check dimensions */ + if (a.img.complete && (a.img.width !== 0) && (a.img.height !== 0)) { if (a.img.width !== a.width || a.img.height !== a.height) { Log.Error("Decoded image has incorrect dimensions. Got " + a.img.width + "x" + a.img.height + ". Expected " + diff --git a/tests/test.display.js b/tests/test.display.js index 05dd8a7..594f951 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -300,7 +300,7 @@ 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)); + display.imageRect(0, 0, 4, 4, "image/png", make_image_png(checked_data)); display.flip(); display.onflush = () => { expect(display).to.have.displayed(checked_data); @@ -401,8 +401,8 @@ 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() }; - display._renderQ = [{ type: 'img', x: 3, y: 4, img: img }, + const img = { complete: false, width: 4, height: 4, addEventListener: sinon.spy() }; + display._renderQ = [{ type: 'img', x: 3, y: 4, width: 4, height: 4, img: img }, { type: 'fill', x: 1, y: 2, width: 3, height: 4, color: 5 }]; display.drawImage = sinon.spy(); display.fillRect = sinon.spy(); @@ -419,6 +419,27 @@ describe('Display/Canvas Helper', function () { expect(img.addEventListener).to.have.been.calledOnce; }); + it('should wait if an image is incorrectly loaded', function () { + const img = { complete: true, width: 0, height: 0, addEventListener: sinon.spy() }; + display._renderQ = [{ type: 'img', x: 3, y: 4, width: 4, height: 4, img: img }, + { type: 'fill', x: 1, y: 2, width: 3, height: 4, color: 5 }]; + display.drawImage = sinon.spy(); + display.fillRect = sinon.spy(); + + 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.width = 4; + display._renderQ[0].img.height = 4; + 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 () { display.onflush = sinon.spy(); display.fillRect(0, 0, 4, 4, [0, 0xff, 0]); |