Moved the "pixels + mask -> RGBA" logic to rfb.js

As requested by Pierre Ossman - he needs this for supporting other
cursor extensions.
This commit is contained in:
Alexander E. Patrakov 2018-08-12 01:43:38 +08:00
parent e15950a8ef
commit d1314d4b3a
2 changed files with 51 additions and 23 deletions

View File

@ -166,7 +166,15 @@ export default class RFB extends EventTargetMixin {
this._canvas.tabIndex = -1; this._canvas.tabIndex = -1;
this._screen.appendChild(this._canvas); 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 // populate encHandlers with bound versions
this._encHandlers[encodings.encodingRaw] = RFB.encodingHandlers.RAW.bind(this); 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); 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) { static genDES(password, challenge) {
const passwd = []; const passwd = [];
for (let i = 0; i < password.length; i++) { for (let i = 0; i < password.length; i++) {
@ -2521,20 +2546,36 @@ RFB.encodingHandlers = {
Cursor() { Cursor() {
Log.Debug(">> set_cursor"); Log.Debug(">> set_cursor");
const x = this._FBU.x; // hotspot-x const hotx = this._FBU.x; // hotspot-x
const y = this._FBU.y; // hotspot-y const hoty = this._FBU.y; // hotspot-y
const w = this._FBU.width; const w = this._FBU.width;
const h = this._FBU.height; const h = this._FBU.height;
const pixelslength = w * h * 4; 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; this._FBU.bytes = pixelslength + masklength;
if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; } if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; }
this._cursor.change(this._sock.rQshiftBytes(pixelslength), // Decode from BGRX pixels + bit mask to RGBA
this._sock.rQshiftBytes(masklength), const pixels = this._sock.rQshiftBytes(pixelslength);
x, y, w, h); 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.bytes = 0;
this._FBU.rects--; this._FBU.rects--;

View File

@ -79,25 +79,12 @@ export default class Cursor {
this._target = null; this._target = null;
} }
change(pixels, mask, hotx, hoty, w, h) { change(rgba, hotx, hoty, w, h) {
if ((w === 0) || (h === 0)) { if ((w === 0) || (h === 0)) {
this.clear(); this.clear();
return; 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.x = this._position.x + this._hotSpot.x - hotx;
this._position.y = this._position.y + this._hotSpot.y - hoty; this._position.y = this._position.y + this._hotSpot.y - hoty;
this._hotSpot.x = hotx; this._hotSpot.x = hotx;
@ -111,10 +98,10 @@ export default class Cursor {
let img; let img;
try { try {
// IE doesn't support this // IE doesn't support this
img = new ImageData(new Uint8ClampedArray(cur), w, h); img = new ImageData(new Uint8ClampedArray(rgba), w, h);
} catch (ex) { } catch (ex) {
img = ctx.createImageData(w, h); img = ctx.createImageData(w, h);
img.data.set(new Uint8ClampedArray(cur)); img.data.set(new Uint8ClampedArray(rgba));
} }
ctx.clearRect(0, 0, w, h); ctx.clearRect(0, 0, w, h);
ctx.putImageData(img, 0, 0); ctx.putImageData(img, 0, 0);