From d1314d4b3a2dba261ba293ec90c0e3204042734b Mon Sep 17 00:00:00 2001 From: "Alexander E. Patrakov" Date: Sun, 12 Aug 2018 01:43:38 +0800 Subject: Moved the "pixels + mask -> RGBA" logic to rfb.js As requested by Pierre Ossman - he needs this for supporting other cursor extensions. --- core/rfb.js | 55 ++++++++++++++++++++++++++++++++++++++++++++++------- core/util/cursor.js | 19 +++--------------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/core/rfb.js b/core/rfb.js index a52c00d..5d40cdd 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -166,7 +166,15 @@ export default class RFB extends EventTargetMixin { this._canvas.tabIndex = -1; this._screen.appendChild(this._canvas); - this._cursor = new Cursor(); + // Cursor + this._cursor = new Cursor(); + this._cursorImage = { + rgbaPixels: [], + hotx: 0, + hoty: 0, + w: 0, + h: 0, + }; // populate encHandlers with bound versions this._encHandlers[encodings.encodingRaw] = RFB.encodingHandlers.RAW.bind(this); @@ -1601,6 +1609,23 @@ export default class RFB extends EventTargetMixin { RFB.messages.xvpOp(this._sock, ver, op); } + _updateCursor(rgba, hotx, hoty, w, h) { + this._cursorImage = { + rgbaPixels: rgba, + hotx: hotx, hoty: hoty, w: w, h: h, + }; + this._refreshCursor(); + } + + _refreshCursor() { + this._cursor.change(this._cursorImage.rgbaPixels, + this._cursorImage.hotx, + this._cursorImage.hoty, + this._cursorImage.w, + this._cursorImage.h + ); + } + static genDES(password, challenge) { const passwd = []; for (let i = 0; i < password.length; i++) { @@ -2521,20 +2546,36 @@ RFB.encodingHandlers = { Cursor() { Log.Debug(">> set_cursor"); - const x = this._FBU.x; // hotspot-x - const y = this._FBU.y; // hotspot-y + const hotx = this._FBU.x; // hotspot-x + const hoty = this._FBU.y; // hotspot-y const w = this._FBU.width; const h = this._FBU.height; const pixelslength = w * h * 4; - const masklength = Math.floor((w + 7) / 8) * h; + const masklength = Math.ceil(w / 8) * h; this._FBU.bytes = pixelslength + masklength; if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; } - this._cursor.change(this._sock.rQshiftBytes(pixelslength), - this._sock.rQshiftBytes(masklength), - x, y, w, h); + // Decode from BGRX pixels + bit mask to RGBA + const pixels = this._sock.rQshiftBytes(pixelslength); + const mask = this._sock.rQshiftBytes(masklength); + let rgba = new Uint8Array(w * h * 4); + + let pix_idx = 0; + for (let y = 0; y < h; y++) { + for (let x = 0; x < w; x++) { + let mask_idx = y * Math.ceil(w / 8) + Math.floor(x / 8); + let alpha = (mask[mask_idx] << (x % 8)) & 0x80 ? 255 : 0; + rgba[pix_idx ] = pixels[pix_idx + 2]; + rgba[pix_idx + 1] = pixels[pix_idx + 1]; + rgba[pix_idx + 2] = pixels[pix_idx]; + rgba[pix_idx + 3] = alpha; + pix_idx += 4; + } + } + + this._updateCursor(rgba, hotx, hoty, w, h); this._FBU.bytes = 0; this._FBU.rects--; diff --git a/core/util/cursor.js b/core/util/cursor.js index 18aa7be..7997194 100644 --- a/core/util/cursor.js +++ b/core/util/cursor.js @@ -79,25 +79,12 @@ export default class Cursor { this._target = null; } - change(pixels, mask, hotx, hoty, w, h) { + change(rgba, hotx, hoty, w, h) { if ((w === 0) || (h === 0)) { this.clear(); return; } - let cur = [] - for (let y = 0; y < h; y++) { - for (let x = 0; x < w; x++) { - let idx = y * Math.ceil(w / 8) + Math.floor(x / 8); - let alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0; - idx = ((w * y) + x) * 4; - cur.push(pixels[idx + 2]); // red - cur.push(pixels[idx + 1]); // green - cur.push(pixels[idx]); // blue - cur.push(alpha); // alpha - } - } - this._position.x = this._position.x + this._hotSpot.x - hotx; this._position.y = this._position.y + this._hotSpot.y - hoty; this._hotSpot.x = hotx; @@ -111,10 +98,10 @@ export default class Cursor { let img; try { // IE doesn't support this - img = new ImageData(new Uint8ClampedArray(cur), w, h); + img = new ImageData(new Uint8ClampedArray(rgba), w, h); } catch (ex) { img = ctx.createImageData(w, h); - img.data.set(new Uint8ClampedArray(cur)); + img.data.set(new Uint8ClampedArray(rgba)); } ctx.clearRect(0, 0, w, h); ctx.putImageData(img, 0, 0); -- cgit v1.2.1