prefer_js : false,
+true_color : false,
+colourMap : [],
+
c_x : 0,
c_y : 0,
c_wx : 0,
},
-init: function (id, width, height, keyDown, keyUp,
+init: function (id, width, height, true_color, keyDown, keyUp,
mouseDown, mouseUp, mouseMove, mouseWheel) {
console.log(">> Canvas.init");
Canvas.c_y = c.getPosition().y;
Canvas.c_wx = c.getSize().x;
Canvas.c_wy = c.getSize().y;
+ Canvas.true_color = true_color;
+ Canvas.colourMap = [];
if (! c.getContext) { return; }
Canvas.ctx = c.getContext('2d');
* gecko, Javascript array handling is much slower.
*/
getTile: function(x, y, width, height, color) {
- var img, data, p, red, green, blue, j, i;
+ var img, data, p, rgb, red, green, blue, j, i;
img = {'x': x, 'y': y, 'width': width, 'height': height,
'data': []};
if (Canvas.prefer_js) {
data = img.data;
- red = color[0];
- green = color[1];
- blue = color[2];
+ if (Canvas.true_color) {
+ rgb = color;
+ } else {
+ rgb = Canvas.colourMap[color[0]];
+ }
+ red = rgb[0];
+ green = rgb[1];
+ blue = rgb[2];
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
p = (i + (j * width) ) * 4;
- img.data[p + 0] = red;
- img.data[p + 1] = green;
- img.data[p + 2] = blue;
- //img.data[p + 3] = 255; // Set Alpha
+ data[p + 0] = red;
+ data[p + 1] = green;
+ data[p + 2] = blue;
+ //data[p + 3] = 255; // Set Alpha
}
}
} else {
},
setTile: function(img, x, y, w, h, color) {
- var data, p, red, green, blue, width, j, i;
+ var data, p, rgb, red, green, blue, width, j, i;
if (Canvas.prefer_js) {
data = img.data;
width = img.width;
- red = color[0];
- green = color[1];
- blue = color[2];
+ if (Canvas.true_color) {
+ rgb = color;
+ } else {
+ rgb = Canvas.colourMap[color[0]];
+ }
+ red = rgb[0];
+ green = rgb[1];
+ blue = rgb[2];
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
p = (x + i + ((y + j) * width) ) * 4;
/* Old firefox and Opera don't support createImageData */
img = Canvas.ctx.getImageData(0, 0, width, height);
data = img.data;
- for (i=0; i < (width * height * 4); i=i+4) {
- j=i+offset;
+ for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) {
data[i + 0] = arr[j + 0];
data[i + 1] = arr[j + 1];
data[i + 2] = arr[j + 2];
data[i + 3] = 255; // Set Alpha
}
Canvas.ctx.putImageData(img, x, y);
+},
+cmapImage: function(x, y, width, height, arr, offset) {
+ var img, i, j, k, data, rgb, cmap;
+ img = Canvas.ctx.getImageData(0, 0, width, height);
+ data = img.data;
+ cmap = Canvas.colourMap;
+ //console.log("cmapImage x: " + x + ", y: " + y + "arr.slice(0,20): " + arr.slice(0,20));
+ for (i=0, j=offset; i < (width * height * 4); i=i+4, j++) {
+ rgb = cmap[arr[j]];
+ data[i + 0] = rgb[0];
+ data[i + 1] = rgb[1];
+ data[i + 2] = rgb[2];
+ data[i + 3] = 255; // Set Alpha
+ }
+ Canvas.ctx.putImageData(img, x, y);
+},
+
+blitImage: function(x, y, width, height, arr, offset) {
+ if (Canvas.true_color) {
+ Canvas.rgbxImage(x, y, width, height, arr, offset);
+ } else {
+ Canvas.cmapImage(x, y, width, height, arr, offset);
+ }
},
fillRect: function(x, y, width, height, color) {
- var newStyle = "rgb(" + color[0] + "," + color[1] + "," + color[2] + ")";
+ var rgb, newStyle;
+ if (Canvas.true_color) {
+ rgb = color;
+ } else {
+ rgb = Canvas.colourMap[color[0]];
+ }
if (newStyle !== Canvas.prevStyle) {
+ newStyle = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")";
Canvas.ctx.fillStyle = newStyle;
Canvas.prevStyle = newStyle;
}
background : null
},
+true_color : false,
+fb_Bpp : 4,
+fb_depth : 3,
+
// DOM objects
statusLine : null,
connectBtn : null,
fb_width : 0,
fb_height : 0,
fb_name : "",
-fb_Bpp : 4,
rre_chunk : 100,
timing : {
name_length = RQ.shift32();
RFB.fb_name = RQ.shiftStr(name_length);
- Canvas.init('VNC_canvas', RFB.fb_width, RFB.fb_height,
+ Canvas.init('VNC_canvas', RFB.fb_width, RFB.fb_height, RFB.true_color,
RFB.keyDown, RFB.keyUp, RFB.mouseDown, RFB.mouseUp,
RFB.mouseMove, RFB.mouseWheel);
+ if (RFB.true_color) {
+ RFB.fb_Bpp = 4;
+ RFB.fb_depth = 3;
+ } else {
+ RFB.fb_Bpp = 1;
+ RFB.fb_depth = 1;
+ }
+
response = RFB.pixelFormat();
response = response.concat(RFB.encodings());
response = response.concat(RFB.fbUpdateRequest(0));
//console.log(">> normal_msg");
var RQ = RFB.RQ, FBU = RFB.FBU, now, fbu_rt_diff,
- ret = true, msg_type, num_colours, msg;
+ ret = true, msg_type, msg,
+ c, first_colour, num_colours, red, green, blue;
if (FBU.rects > 0) {
msg_type = 0;
break;
case 1: // SetColourMapEntries
- console.log("SetColourMapEntries (unsupported)");
+ console.log("SetColourMapEntries");
RQ.shift8(); // Padding
- RQ.shift16(); // First colour
+ first_colour = RQ.shift16(); // First colour
num_colours = RQ.shift16();
- RQ.shiftBytes(num_colours * 6);
+ for (c=0; c < num_colours; c++) {
+ red = RQ.shift16();
+ //console.log("red before: " + red);
+ red = parseInt(red / 256, 10);
+ //console.log("red after: " + red);
+ green = parseInt(RQ.shift16() / 256, 10);
+ blue = parseInt(RQ.shift16() / 256, 10);
+ Canvas.colourMap[first_colour + c] = [red, green, blue];
+ }
+ console.log("Registered " + num_colours + " colourMap entries");
+ //console.log("colourMap: " + Canvas.colourMap);
break;
case 2: // Bell
console.log("Bell (unsupported)");
cur_y = FBU.y + (FBU.height - FBU.lines);
cur_height = Math.min(FBU.lines,
Math.floor(RQ.length/(FBU.width * RFB.fb_Bpp)));
- Canvas.rgbxImage(FBU.x, cur_y, FBU.width, cur_height, RQ, 0);
+ Canvas.blitImage(FBU.x, cur_y, FBU.width, cur_height, RQ, 0);
RQ.shiftBytes(FBU.width * cur_height * RFB.fb_Bpp);
FBU.lines -= cur_height;
Canvas.fillRect(x, y, w, h, FBU.background);
}
} else if (FBU.subencoding & 0x01) { // Raw
- Canvas.rgbxImage(x, y, w, h, RQ, idx);
+ Canvas.blitImage(x, y, w, h, RQ, idx);
} else {
if (FBU.subencoding & 0x02) { // Background
FBU.background = RQ.slice(idx, idx + RFB.fb_Bpp);
arr.push8(0); // padding
arr.push8(RFB.fb_Bpp * 8); // bits-per-pixel
- arr.push8(24); // depth
+ arr.push8(RFB.fb_depth * 8); // depth
arr.push8(0); // little-endian
- arr.push8(1); // true-color
+ arr.push8(RFB.true_color); // true-color
arr.push16(255); // red-max
arr.push16(255); // green-max
},
-connect: function (host, port, password, encrypt) {
+connect: function (host, port, password, encrypt, true_color) {
console.log(">> connect");
RFB.host = (host !== undefined) ? host :
$('VNC_password').value;
RFB.encrypt = (encrypt !== undefined) ? encrypt :
$('VNC_encrypt').checked;
+ RFB.true_color = (true_color !== undefined) ? true_color:
+ $('VNC_true_color').checked;
if ((!RFB.host) || (!RFB.port)) {
alert("Must set host and port");
return;
html += ' type="password"></li>';
html += ' <li>Encrypt: <input id="VNC_encrypt"';
html += ' type="checkbox"></li>';
+ html += ' <li>True Color: <input id="VNC_true_color"';
+ html += ' type="checkbox" checked></li>';
html += ' <li><input id="VNC_connect_button" type="button"';
html += ' value="Loading" disabled></li>';
html += ' </ul>';