]> git.proxmox.com Git - mirror_novnc.git/blob - core/decoders/hextile.js
feat: add French localization strings
[mirror_novnc.git] / core / decoders / hextile.js
1 /*
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2019 The noVNC Authors
4 * Licensed under MPL 2.0 (see LICENSE.txt)
5 *
6 * See README.md for usage and integration instructions.
7 *
8 */
9
10 import * as Log from '../util/logging.js';
11
12 export default class HextileDecoder {
13 constructor() {
14 this._tiles = 0;
15 this._lastsubencoding = 0;
16 this._tileBuffer = new Uint8Array(16 * 16 * 4);
17 }
18
19 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 }
26
27 while (this._tiles > 0) {
28 let bytes = 1;
29
30 if (sock.rQwait("HEXTILE", bytes)) {
31 return false;
32 }
33
34 let rQ = sock.rQ;
35 let rQi = sock.rQi;
36
37 let subencoding = rQ[rQi]; // Peek
38 if (subencoding > 30) { // Raw
39 throw new Error("Illegal hextile subencoding (subencoding: " +
40 subencoding + ")");
41 }
42
43 const currTile = this._totalTiles - this._tiles;
44 const tileX = currTile % this._tilesX;
45 const tileY = Math.floor(currTile / this._tilesX);
46 const tx = x + tileX * 16;
47 const ty = y + tileY * 16;
48 const tw = Math.min(16, (x + width) - tx);
49 const th = Math.min(16, (y + height) - ty);
50
51 // Figure out how much we are expecting
52 if (subencoding & 0x01) { // Raw
53 bytes += tw * th * 4;
54 } else {
55 if (subencoding & 0x02) { // Background
56 bytes += 4;
57 }
58 if (subencoding & 0x04) { // Foreground
59 bytes += 4;
60 }
61 if (subencoding & 0x08) { // AnySubrects
62 bytes++; // Since we aren't shifting it off
63
64 if (sock.rQwait("HEXTILE", bytes)) {
65 return false;
66 }
67
68 let subrects = rQ[rQi + bytes - 1]; // Peek
69 if (subencoding & 0x10) { // SubrectsColoured
70 bytes += subrects * (4 + 2);
71 } else {
72 bytes += subrects * 2;
73 }
74 }
75 }
76
77 if (sock.rQwait("HEXTILE", bytes)) {
78 return false;
79 }
80
81 // We know the encoding and have a whole tile
82 rQi++;
83 if (subencoding === 0) {
84 if (this._lastsubencoding & 0x01) {
85 // Weird: ignore blanks are RAW
86 Log.Debug(" Ignoring blank after RAW");
87 } else {
88 display.fillRect(tx, ty, tw, th, this._background);
89 }
90 } else if (subencoding & 0x01) { // Raw
91 let pixels = tw * th;
92 // Max sure the image is fully opaque
93 for (let i = 0;i < pixels;i++) {
94 rQ[rQi + i * 4 + 3] = 255;
95 }
96 display.blitImage(tx, ty, tw, th, rQ, rQi);
97 rQi += bytes - 1;
98 } else {
99 if (subencoding & 0x02) { // Background
100 this._background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
101 rQi += 4;
102 }
103 if (subencoding & 0x04) { // Foreground
104 this._foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
105 rQi += 4;
106 }
107
108 this._startTile(tx, ty, tw, th, this._background);
109 if (subencoding & 0x08) { // AnySubrects
110 let subrects = rQ[rQi];
111 rQi++;
112
113 for (let s = 0; s < subrects; s++) {
114 let color;
115 if (subencoding & 0x10) { // SubrectsColoured
116 color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
117 rQi += 4;
118 } else {
119 color = this._foreground;
120 }
121 const xy = rQ[rQi];
122 rQi++;
123 const sx = (xy >> 4);
124 const sy = (xy & 0x0f);
125
126 const wh = rQ[rQi];
127 rQi++;
128 const sw = (wh >> 4) + 1;
129 const sh = (wh & 0x0f) + 1;
130
131 this._subTile(sx, sy, sw, sh, color);
132 }
133 }
134 this._finishTile(display);
135 }
136 sock.rQi = rQi;
137 this._lastsubencoding = subencoding;
138 this._tiles--;
139 }
140
141 return true;
142 }
143
144 // start updating a tile
145 _startTile(x, y, width, height, color) {
146 this._tileX = x;
147 this._tileY = y;
148 this._tileW = width;
149 this._tileH = height;
150
151 const red = color[0];
152 const green = color[1];
153 const blue = color[2];
154
155 const data = this._tileBuffer;
156 for (let i = 0; i < width * height * 4; i += 4) {
157 data[i] = red;
158 data[i + 1] = green;
159 data[i + 2] = blue;
160 data[i + 3] = 255;
161 }
162 }
163
164 // update sub-rectangle of the current tile
165 _subTile(x, y, w, h, color) {
166 const red = color[0];
167 const green = color[1];
168 const blue = color[2];
169 const xend = x + w;
170 const yend = y + h;
171
172 const data = this._tileBuffer;
173 const width = this._tileW;
174 for (let j = y; j < yend; j++) {
175 for (let i = x; i < xend; i++) {
176 const p = (i + (j * width)) * 4;
177 data[p] = red;
178 data[p + 1] = green;
179 data[p + 2] = blue;
180 data[p + 3] = 255;
181 }
182 }
183 }
184
185 // draw the current tile to the screen
186 _finishTile(display) {
187 display.blitImage(this._tileX, this._tileY,
188 this._tileW, this._tileH,
189 this._tileBuffer, 0);
190 }
191 }