From 1578fa68ac754ed1ca29431a87586b2463d354db Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 22 Sep 2016 10:19:26 +0200 Subject: [PATCH] Hide image handling in display object The callers don't need to concern themselves with how images are rendered, so hide the details behind the API. This also avoids exposing the render queue. --- core/display.js | 41 ++++++++++++++++++++++++++--------------- core/rfb.js | 16 ++-------------- tests/test.display.js | 14 +++++++------- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/core/display.js b/core/display.js index e6239f48..938bb895 100644 --- a/core/display.js +++ b/core/display.js @@ -365,7 +365,7 @@ fillRect: function (x, y, width, height, color, from_queue) { if (this._renderQ.length !== 0 && !from_queue) { - this.renderQ_push({ + this._renderQ_push({ 'type': 'fill', 'x': x, 'y': y, @@ -381,7 +381,7 @@ copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) { if (this._renderQ.length !== 0 && !from_queue) { - this.renderQ_push({ + this._renderQ_push({ 'type': 'copy', 'old_x': old_x, 'old_y': old_y, @@ -400,6 +400,17 @@ } }, + imageRect: function(x, y, mime, arr) { + var img = new Image(); + img.src = "data: " + mime + ";base64," + Base64.encode(arr); + this._renderQ_push({ + 'type': 'img', + 'img': img, + 'x': x, + 'y': y + }); + }, + // start updating a tile startTile: function (x, y, width, height, color) { this._tile_x = x; @@ -480,7 +491,7 @@ // this probably isn't getting called *nearly* as much var new_arr = new Uint8Array(width * height * 4); new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); - this.renderQ_push({ + this._renderQ_push({ 'type': 'blit', 'data': new_arr, 'x': x, @@ -502,7 +513,7 @@ // this probably isn't getting called *nearly* as much var new_arr = new Uint8Array(width * height * 3); new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); - this.renderQ_push({ + this._renderQ_push({ 'type': 'blitRgb', 'data': new_arr, 'x': x, @@ -525,7 +536,7 @@ // this probably isn't getting called *nearly* as much var new_arr = new Uint8Array(width * height * 4); new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); - this.renderQ_push({ + this._renderQ_push({ 'type': 'blitRgbx', 'data': new_arr, 'x': x, @@ -552,16 +563,6 @@ this._drawCtx.drawImage(img, x - this._viewportLoc.x, y - this._viewportLoc.y); }, - renderQ_push: function (action) { - this._renderQ.push(action); - if (this._renderQ.length === 1) { - // If this can be rendered immediately it will be, otherwise - // the scanner will start polling the queue (every - // requestAnimationFrame interval) - this._scan_renderQ(); - } - }, - changeCursor: function (pixels, mask, hotx, hoty, w, h) { if (this._cursor_uri === false) { Util.Warn("changeCursor called but no cursor data URI support"); @@ -741,6 +742,16 @@ this._drawCtx.putImageData(img, x - vx, y - vy); }, + _renderQ_push: function (action) { + this._renderQ.push(action); + if (this._renderQ.length === 1) { + // If this can be rendered immediately it will be, otherwise + // the scanner will start polling the queue (every + // requestAnimationFrame interval) + this._scan_renderQ(); + } + }, + _scan_renderQ: function () { var ready = true; while (ready && this._renderQ.length > 0) { diff --git a/core/rfb.js b/core/rfb.js index a0136f35..7567519c 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -1692,10 +1692,6 @@ return (new DES(passwd)).encrypt(challenge); }; - RFB.extract_data_uri = function (arr) { - return ";base64," + Base64.encode(arr); - }; - RFB.encodingHandlers = { RAW: function () { if (this._FBU.lines === 0) { @@ -2198,16 +2194,8 @@ // We have everything, render it this._sock.rQskipBytes(1 + cl_header); // shift off clt + compact length - var img = new Image(); - img.src = "data: image/" + cmode + - RFB.extract_data_uri(this._sock.rQshiftBytes(cl_data)); - this._display.renderQ_push({ - 'type': 'img', - 'img': img, - 'x': this._FBU.x, - 'y': this._FBU.y - }); - img = null; + data = this._sock.rQshiftBytes(cl_data); + this._display.imageRect(this._FBU.x, this._FBU.y, "image/" + cmode, data); break; case "filter": var filterId = rQ[rQi + 1]; diff --git a/tests/test.display.js b/tests/test.display.js index 7c7c693b..64932b10 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -396,13 +396,13 @@ describe('Display/Canvas Helper', function () { }); it('should try to process an item when it is pushed on, if nothing else is on the queue', function () { - display.renderQ_push({ type: 'noop' }); // does nothing + display._renderQ_push({ type: 'noop' }); // does nothing expect(display._scan_renderQ).to.have.been.calledOnce; }); it('should not try to process an item when it is pushed on if we are waiting for other items', function () { display._renderQ.length = 2; - display.renderQ_push({ type: 'noop' }); + display._renderQ_push({ type: 'noop' }); expect(display._scan_renderQ).to.not.have.been.called; }); @@ -425,35 +425,35 @@ describe('Display/Canvas Helper', function () { it('should draw a blit image on type "blit"', function () { display.blitImage = sinon.spy(); - display.renderQ_push({ type: 'blit', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] }); + display._renderQ_push({ type: 'blit', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] }); expect(display.blitImage).to.have.been.calledOnce; expect(display.blitImage).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9], 0); }); it('should draw a blit RGB image on type "blitRgb"', function () { display.blitRgbImage = sinon.spy(); - display.renderQ_push({ type: 'blitRgb', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] }); + display._renderQ_push({ type: 'blitRgb', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] }); expect(display.blitRgbImage).to.have.been.calledOnce; expect(display.blitRgbImage).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9], 0); }); it('should copy a region on type "copy"', function () { display.copyImage = sinon.spy(); - display.renderQ_push({ type: 'copy', x: 3, y: 4, width: 5, height: 6, old_x: 7, old_y: 8 }); + display._renderQ_push({ type: 'copy', x: 3, y: 4, width: 5, height: 6, old_x: 7, old_y: 8 }); expect(display.copyImage).to.have.been.calledOnce; expect(display.copyImage).to.have.been.calledWith(7, 8, 3, 4, 5, 6); }); it('should fill a rect with a given color on type "fill"', function () { display.fillRect = sinon.spy(); - display.renderQ_push({ type: 'fill', x: 3, y: 4, width: 5, height: 6, color: [7, 8, 9]}); + display._renderQ_push({ type: 'fill', x: 3, y: 4, width: 5, height: 6, color: [7, 8, 9]}); expect(display.fillRect).to.have.been.calledOnce; expect(display.fillRect).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9]); }); 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: { complete: true } }); expect(display.drawImage).to.have.been.calledOnce; expect(display.drawImage).to.have.been.calledWith({ complete: true }, 3, 4); });