SPB Git forge

spb/admin-ka

Public
41commits 1branches 0releases
172.9 MBsize
maindefault branch
20 days agolast push
JavaScript 65.5% Python 17.8% CSS 13% HTML 3.7%
5.9 KB · 182 lines javascript
Raw Blame History
1/*2 * noVNC: HTML5 VNC client3 * Copyright (C) 2019 The noVNC authors4 * Licensed under MPL 2.0 (see LICENSE.txt)5 *6 * See README.md for usage and integration instructions.7 *8 */910import * as Log from '../util/logging.js';1112export default class HextileDecoder {13    constructor() {14        this._tiles = 0;15        this._lastsubencoding = 0;16        this._tileBuffer = new Uint8Array(16 * 16 * 4);17    }1819    decodeRect(x, y, width, height, sock, display, depth) {20        if (this._tiles === 0) {21            this._tilesX = Math.ceil(width / 16);22            this._tilesY = Math.ceil(height / 16);23            this._totalTiles = this._tilesX * this._tilesY;24            this._tiles = this._totalTiles;25        }2627        while (this._tiles > 0) {28            let bytes = 1;2930            if (sock.rQwait("HEXTILE", bytes)) {31                return false;32            }3334            let subencoding = sock.rQpeek8();35            if (subencoding > 30) {  // Raw36                throw new Error("Illegal hextile subencoding (subencoding: " +37                            subencoding + ")");38            }3940            const currTile = this._totalTiles - this._tiles;41            const tileX = currTile % this._tilesX;42            const tileY = Math.floor(currTile / this._tilesX);43            const tx = x + tileX * 16;44            const ty = y + tileY * 16;45            const tw = Math.min(16, (x + width) - tx);46            const th = Math.min(16, (y + height) - ty);4748            // Figure out how much we are expecting49            if (subencoding & 0x01) {  // Raw50                bytes += tw * th * 4;51            } else {52                if (subencoding & 0x02) {  // Background53                    bytes += 4;54                }55                if (subencoding & 0x04) {  // Foreground56                    bytes += 4;57                }58                if (subencoding & 0x08) {  // AnySubrects59                    bytes++;  // Since we aren't shifting it off6061                    if (sock.rQwait("HEXTILE", bytes)) {62                        return false;63                    }6465                    let subrects = sock.rQpeekBytes(bytes).at(-1);66                    if (subencoding & 0x10) {  // SubrectsColoured67                        bytes += subrects * (4 + 2);68                    } else {69                        bytes += subrects * 2;70                    }71                }72            }7374            if (sock.rQwait("HEXTILE", bytes)) {75                return false;76            }7778            // We know the encoding and have a whole tile79            sock.rQshift8();80            if (subencoding === 0) {81                if (this._lastsubencoding & 0x01) {82                    // Weird: ignore blanks are RAW83                    Log.Debug("     Ignoring blank after RAW");84                } else {85                    display.fillRect(tx, ty, tw, th, this._background);86                }87            } else if (subencoding & 0x01) {  // Raw88                let pixels = tw * th;89                let data = sock.rQshiftBytes(pixels * 4, false);90                // Max sure the image is fully opaque91                for (let i = 0;i <  pixels;i++) {92                    data[i * 4 + 3] = 255;93                }94                display.blitImage(tx, ty, tw, th, data, 0);95            } else {96                if (subencoding & 0x02) {  // Background97                    this._background = new Uint8Array(sock.rQshiftBytes(4));98                }99                if (subencoding & 0x04) {  // Foreground100                    this._foreground = new Uint8Array(sock.rQshiftBytes(4));101                }102103                this._startTile(tx, ty, tw, th, this._background);104                if (subencoding & 0x08) {  // AnySubrects105                    let subrects = sock.rQshift8();106107                    for (let s = 0; s < subrects; s++) {108                        let color;109                        if (subencoding & 0x10) {  // SubrectsColoured110                            color = sock.rQshiftBytes(4);111                        } else {112                            color = this._foreground;113                        }114                        const xy = sock.rQshift8();115                        const sx = (xy >> 4);116                        const sy = (xy & 0x0f);117118                        const wh = sock.rQshift8();119                        const sw = (wh >> 4) + 1;120                        const sh = (wh & 0x0f) + 1;121122                        this._subTile(sx, sy, sw, sh, color);123                    }124                }125                this._finishTile(display);126            }127            this._lastsubencoding = subencoding;128            this._tiles--;129        }130131        return true;132    }133134    // start updating a tile135    _startTile(x, y, width, height, color) {136        this._tileX = x;137        this._tileY = y;138        this._tileW = width;139        this._tileH = height;140141        const red = color[0];142        const green = color[1];143        const blue = color[2];144145        const data = this._tileBuffer;146        for (let i = 0; i < width * height * 4; i += 4) {147            data[i]     = red;148            data[i + 1] = green;149            data[i + 2] = blue;150            data[i + 3] = 255;151        }152    }153154    // update sub-rectangle of the current tile155    _subTile(x, y, w, h, color) {156        const red = color[0];157        const green = color[1];158        const blue = color[2];159        const xend = x + w;160        const yend = y + h;161162        const data = this._tileBuffer;163        const width = this._tileW;164        for (let j = y; j < yend; j++) {165            for (let i = x; i < xend; i++) {166                const p = (i + (j * width)) * 4;167                data[p]     = red;168                data[p + 1] = green;169                data[p + 2] = blue;170                data[p + 3] = 255;171            }172        }173    }174175    // draw the current tile to the screen176    _finishTile(display) {177        display.blitImage(this._tileX, this._tileY,178                          this._tileW, this._tileH,179                          this._tileBuffer, 0);180    }181}182