summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2019-12-23 15:40:17 +0100
committerPierre Ossman <ossman@cendio.se>2019-12-23 15:52:54 +0100
commitc4eb4ddcfe284a84fe147544cddfce2962fd4a87 (patch)
tree4af64da98c6b7a714aa667eb9684cf03569e81be
parent4babdf33bd6441343ce33802d72ef69e74d6f69d (diff)
downloadnovnc-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.js9
-rw-r--r--tests/test.display.js27
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]);