|
|
@@ -1,178 +1,267 @@
|
|
|
var ws = null;
|
|
|
var vnc_host = '';
|
|
|
var vnc_port = 5900;
|
|
|
-var rfb_state = 'ProtocolVersion';
|
|
|
-var rfb_continue = -1;
|
|
|
-var rfb_shared = 1;
|
|
|
+var fbu = {
|
|
|
+ rects : 0,
|
|
|
+ bytes : 0,
|
|
|
+ x : 0,
|
|
|
+ y : 0,
|
|
|
+ width : 0,
|
|
|
+ height : 0,
|
|
|
+ encoding : 0,
|
|
|
+ arr : null};
|
|
|
var fb_width = 0;
|
|
|
var fb_height = 0;
|
|
|
var fb_name = "";
|
|
|
+var fb_Bpp = 4;
|
|
|
|
|
|
|
|
|
-Array.prototype.card8 = function (pos) {
|
|
|
- return this[pos];
|
|
|
+Array.prototype.shift8 = function () {
|
|
|
+ return this.shift();
|
|
|
}
|
|
|
-Array.prototype.pushCard8 = function (num) {
|
|
|
+Array.prototype.push8 = function (num) {
|
|
|
this.push(num & 0xFF);
|
|
|
}
|
|
|
|
|
|
-Array.prototype.card16 = function (pos) {
|
|
|
- return (this[pos] << 8) +
|
|
|
- (this[pos+1] );
|
|
|
+Array.prototype.shift16 = function () {
|
|
|
+ return (this.shift() << 8) +
|
|
|
+ (this.shift() );
|
|
|
}
|
|
|
-Array.prototype.pushCard16 = function (num) {
|
|
|
+Array.prototype.push16 = function (num) {
|
|
|
this.push((num >> 8) & 0xFF,
|
|
|
(num ) & 0xFF );
|
|
|
}
|
|
|
|
|
|
|
|
|
-Array.prototype.card32 = function (pos) {
|
|
|
- return (this[pos] << 24) +
|
|
|
- (this[pos+1] << 16) +
|
|
|
- (this[pos+2] << 8) +
|
|
|
- (this[pos+3] );
|
|
|
+Array.prototype.shift32 = function () {
|
|
|
+ return (this.shift() << 24) +
|
|
|
+ (this.shift() << 16) +
|
|
|
+ (this.shift() << 8) +
|
|
|
+ (this.shift() );
|
|
|
}
|
|
|
-Array.prototype.pushCard32 = function (num) {
|
|
|
+Array.prototype.push32 = function (num) {
|
|
|
this.push((num >> 24) & 0xFF,
|
|
|
(num >> 16) & 0xFF,
|
|
|
(num >> 8) & 0xFF,
|
|
|
(num ) & 0xFF );
|
|
|
}
|
|
|
|
|
|
-Array.prototype.substr = function (start, len) {
|
|
|
- return this.slice(start, start+len).map(
|
|
|
- function (num) { return String.fromCharCode(num); } ).join('');
|
|
|
+Array.prototype.shiftStr = function (len) {
|
|
|
+ var arr = this.splice(0, len);
|
|
|
+ return arr.map(function (num) {
|
|
|
+ return String.fromCharCode(num); } ).join('');
|
|
|
+}
|
|
|
+
|
|
|
+Array.prototype.shiftBytes = function (len) {
|
|
|
+ return this.splice(0, len);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Server message handlers
|
|
|
*/
|
|
|
|
|
|
+RFB = {
|
|
|
+
|
|
|
+state : 'ProtocolVersion',
|
|
|
+shared : 1,
|
|
|
+poll_rate : 3000,
|
|
|
+
|
|
|
/* RFB/VNC initialisation */
|
|
|
-function rfb_init_msg(data) {
|
|
|
- debug(">> rfb_init_msg");
|
|
|
+init_msg: function (data) {
|
|
|
+ debug(">> init_msg");
|
|
|
|
|
|
- switch (rfb_state) {
|
|
|
+ switch (RFB.state) {
|
|
|
|
|
|
case 'ProtocolVersion' :
|
|
|
- debug("ProtocolVersion: " + data)
|
|
|
+ debug("ProtocolVersion:")
|
|
|
if (data.length != 12) {
|
|
|
debug("Invalid protocol version from server");
|
|
|
- rfb_state = 'reset';
|
|
|
+ RFB.state = 'reset';
|
|
|
return;
|
|
|
}
|
|
|
- send_string("RFB 003.003\n");
|
|
|
- rfb_state = 'Authentication';
|
|
|
+ debug("Server ProtocolVersion: " + data.shiftStr(11))
|
|
|
+ RFB.send_string("RFB 003.003\n");
|
|
|
+ RFB.state = 'Authentication';
|
|
|
break;
|
|
|
|
|
|
case 'Authentication' :
|
|
|
debug("Authentication")
|
|
|
- if (data.length != 4) {
|
|
|
- debug("Invalid auth scheme");
|
|
|
- rfb_state = 'reset';
|
|
|
+ if (data.length < 4) {
|
|
|
+ debug("Invalid auth frame");
|
|
|
+ RFB.state = 'reset';
|
|
|
return;
|
|
|
}
|
|
|
- var scheme = data.card32(0);
|
|
|
+ var scheme = data.shift32();
|
|
|
debug("Auth scheme: " + scheme);
|
|
|
switch (scheme) {
|
|
|
case 0: // connection failed
|
|
|
- var strlen = data.card32(4);
|
|
|
- var reason = data.substr(8, strlen);
|
|
|
+ var strlen = data.shift32();
|
|
|
+ var reason = data.shiftStr(strlen);
|
|
|
debug("auth failed: " + reason);
|
|
|
- rfb_state = "reset";
|
|
|
+ RFB.state = "failed";
|
|
|
return;
|
|
|
case 1: // no authentication
|
|
|
- send_array([rfb_shared]); // ClientInitialisation
|
|
|
- rfb_state = "ServerInitialisation";
|
|
|
+ RFB.send_array([RFB.shared]); // ClientInitialisation
|
|
|
+ RFB.state = "ServerInitialisation";
|
|
|
break;
|
|
|
case 2: // VNC authentication
|
|
|
- var challenge = data.substr(4, 16);
|
|
|
+ var challenge = data.shiftStr(16);
|
|
|
// TODO:
|
|
|
//var crypt = des(challenge, password);
|
|
|
- //send_string(crypt);
|
|
|
- rfb_state = "Authentication-VNC";
|
|
|
+ //RFB.send_string(crypt);
|
|
|
+ RFB.state = "SecurityResult";
|
|
|
+ debug("challenge: " + challenge + "(" + challenge.length + ")");
|
|
|
+ //response = Javacrypt.crypt(challenge, "jdm239").toString();
|
|
|
+ //response = Javacrypt.crypt("jdm239", challenge).toString();
|
|
|
+ //response = des("jdm239", challenge, 1)
|
|
|
+ /* COWCOW bit mirrored */
|
|
|
+ passwd = [194, 242, 234, 194, 242, 234, 0, 0].shiftStr(8);
|
|
|
+ debug("passwd: " + passwd + "(" + passwd.length + ")");
|
|
|
+ response = des(passwd, challenge, 1)
|
|
|
+ debug("reponse: " + response + "(" + response.length + ")");
|
|
|
+ RFB.send_string(response);
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
- case 'Authentication-VNC' :
|
|
|
- debug("Authentication-VNC")
|
|
|
+ case 'SecurityResult' :
|
|
|
+ debug("SecurityResult")
|
|
|
if (data.length != 4) {
|
|
|
debug("Invalid server auth response");
|
|
|
- rfb_state = 'reset';
|
|
|
+ RFB.state = 'reset';
|
|
|
return;
|
|
|
}
|
|
|
- var resp = data.card32(0);
|
|
|
+ var resp = data.shift32();
|
|
|
switch (resp) {
|
|
|
case 0: // OK
|
|
|
debug("Authentication OK");
|
|
|
break;
|
|
|
case 1: // failed
|
|
|
debug("Authentication failed");
|
|
|
- rfb_state = "reset";
|
|
|
+ RFB.state = "reset";
|
|
|
return;
|
|
|
case 2: // too-many
|
|
|
debug("Too many authentication attempts");
|
|
|
- rfb_state = "reset";
|
|
|
+ RFB.state = "failed";
|
|
|
return;
|
|
|
}
|
|
|
- send_array([rfb_shared]); // ClientInitialisation
|
|
|
- rfb_state = "ServerInitialisation";
|
|
|
+ RFB.send_array([RFB.shared]); // ClientInitialisation
|
|
|
+ RFB.state = "ServerInitialisation";
|
|
|
break;
|
|
|
|
|
|
case 'ServerInitialisation' :
|
|
|
debug("ServerInitialisation")
|
|
|
if (data.length < 24) {
|
|
|
debug("Invalid server initialisation");
|
|
|
- rfb_state = 'reset';
|
|
|
+ RFB.state = 'reset';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
/* Screen size */
|
|
|
- debug("data: " + data);
|
|
|
- fb_width = data.card16(0);
|
|
|
- fb_height = data.card16(2);
|
|
|
+ //debug("data: " + data);
|
|
|
+ fb_width = data.shift16();
|
|
|
+ fb_height = data.shift16();
|
|
|
|
|
|
debug("Screen size: " + fb_width + "x" + fb_height);
|
|
|
|
|
|
/* PIXEL_FORMAT */
|
|
|
- var bits_per_pixel = data.card8(4);
|
|
|
- var depth = data.card8(5);
|
|
|
- var big_endian = data.card8(6);
|
|
|
- var true_color = data.card8(7);
|
|
|
+ var bpp = data.shift8();
|
|
|
+ var depth = data.shift8();
|
|
|
+ var big_endian = data.shift8();
|
|
|
+ var true_color = data.shift8();
|
|
|
|
|
|
- debug("bits per pixel: " + bits_per_pixel);
|
|
|
+ debug("bpp: " + bpp);
|
|
|
debug("depth: " + depth);
|
|
|
debug("big_endian: " + big_endian);
|
|
|
debug("true_color: " + true_color);
|
|
|
|
|
|
/* Connection name/title */
|
|
|
- var name_length = data.card32(20);
|
|
|
- fb_name = data.substr(24, name_length);
|
|
|
+ data.shiftStr(12);
|
|
|
+ var name_length = data.shift32();
|
|
|
+ fb_name = data.shiftStr(name_length);
|
|
|
|
|
|
debug("Name: " + fb_name);
|
|
|
|
|
|
- setEncodings();
|
|
|
+ Canvas.init('vnc', fb_width, fb_height, RFB.keyDown, RFB.keyUp);
|
|
|
+
|
|
|
+ RFB.setEncodings();
|
|
|
+ RFB.setPixelFormat();
|
|
|
|
|
|
- fbUpdateRequest(0, 0, 0, 10, 10);
|
|
|
+ RFB.fbUpdateRequest(0, 0, 0, fb_width, fb_height);
|
|
|
|
|
|
- rfb_state = 'normal';
|
|
|
+ RFB.state = 'normal';
|
|
|
break;
|
|
|
}
|
|
|
- debug("<< rfb_init_msg");
|
|
|
-}
|
|
|
+ debug("<< init_msg");
|
|
|
+},
|
|
|
|
|
|
/* Normal RFB/VNC messages */
|
|
|
-function rfb_msg(data) {
|
|
|
- debug(">> rfb_msg");
|
|
|
- if (rfb_continue >= 0) {
|
|
|
- var msg_type = rfb_continue;
|
|
|
+normal_msg: function (data) {
|
|
|
+ //debug(">> normal_msg");
|
|
|
+ if ((fbu.rects > 0) || (fbu.bytes > 0)) {
|
|
|
+ var msg_type = 0;
|
|
|
} else {
|
|
|
- var msg_type = data.card8(0);
|
|
|
+ var msg_type = data.shift8();
|
|
|
}
|
|
|
switch (msg_type) {
|
|
|
case 0: // FramebufferUpdate
|
|
|
- debug("FramebufferUpdate");
|
|
|
+ if (fbu.rects == 0) {
|
|
|
+ data.shift8();
|
|
|
+ fbu.rects = data.shift16();
|
|
|
+ debug("FramebufferUpdate, " + fbu.rects + " rects");
|
|
|
+ fbu.bytes = 0;
|
|
|
+ fbu.arr = [];
|
|
|
+ } else {
|
|
|
+ //debug("FramebufferUpdate continuation");
|
|
|
+ }
|
|
|
+
|
|
|
+ while (data.length > 0) {
|
|
|
+ //debug("data.length: " + data.length);
|
|
|
+ if (fbu.bytes == 0) {
|
|
|
+ fbu.x = data.shift16();
|
|
|
+ fbu.y = data.shift16();
|
|
|
+ fbu.width = data.shift16();
|
|
|
+ fbu.height = data.shift16();
|
|
|
+ fbu.encoding = data.shift32();
|
|
|
+ //debug('New rect: ' + fbu.x + "," + fbu.y + " -> " + (fbu.x + fbu.width) + "," + (fbu.y + fbu.height));
|
|
|
+ switch (fbu.encoding) {
|
|
|
+ case 0: // Raw
|
|
|
+ fbu.bytes = fbu.width * fbu.height * fb_Bpp;
|
|
|
+ break;
|
|
|
+ case 1: // Copy-Rect
|
|
|
+ fbu_bytes = 4;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (data.length >= fbu.bytes) {
|
|
|
+ //debug('Done rect: ' + fbu.x + "," + fbu.y + " -> " + (fbu.x + fbu.width) + "," + (fbu.y + fbu.height));
|
|
|
+ fbu.arr = fbu.arr.concat(data.shiftBytes(fbu.bytes))
|
|
|
+ fbu.bytes = 0;
|
|
|
+
|
|
|
+ switch (fbu.encoding) {
|
|
|
+ case 0: // Raw
|
|
|
+ debug('Raw-Rect: ' + fbu.x + "," + fbu.y + " -> " + (fbu.x + fbu.width) + "," + (fbu.y + fbu.height));
|
|
|
+ Canvas.rfbImage(fbu.x, fbu.y, fbu.width, fbu.height, fbu.arr);
|
|
|
+ break;
|
|
|
+ case 1: // Copy-Rect
|
|
|
+ debug('Copy-Rect: ' + fbu.x + "," + fbu.y + " -> " + (fbu.x + fbu.width) + "," + (fbu.y + fbu.height));
|
|
|
+ var new_x = fbu.arr.shift16();
|
|
|
+ var new_y = fbu.arr.shift16();
|
|
|
+ Canvas.ctx.drawImage(Canvas.c, fbu.x, fbu.y, fbu.width, fbu.height, new_x, new_y, fbu.width, fbu.height);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ fbu.arr = [];
|
|
|
+ fbu.rects --;
|
|
|
+ } else {
|
|
|
+ //debug('Part rect: ' + fbu.x + "," + fbu.y + " -> " + (fbu.x + fbu.width) + "," + (fbu.y + fbu.height));
|
|
|
+ fbu.bytes = fbu.bytes - data.length;
|
|
|
+ fbu.arr = fbu.arr.concat(data.shiftBytes(data.length))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //debug("Bytes remaining: " + fbu.bytes);
|
|
|
+ }
|
|
|
+ //debug("Finished frame buffer update");
|
|
|
break;
|
|
|
case 1: // SetColourMapEntries
|
|
|
debug("SetColourMapEntries");
|
|
|
@@ -187,203 +276,167 @@ function rfb_msg(data) {
|
|
|
debug("Unknown server message type: " + msg_type);
|
|
|
break;
|
|
|
}
|
|
|
- debug("<< rfb_msg");
|
|
|
-}
|
|
|
+ //debug("<< normal_msg");
|
|
|
+},
|
|
|
|
|
|
/*
|
|
|
* Client message routines
|
|
|
*/
|
|
|
|
|
|
-function send_string(str) {
|
|
|
- ws.send(Base64.encode(str));
|
|
|
-}
|
|
|
-
|
|
|
-function send_array(arr) {
|
|
|
- debug("encoded array: " + Base64.encode_array(arr));
|
|
|
- ws.send(Base64.encode_array(arr));
|
|
|
-}
|
|
|
-
|
|
|
-function setPixelFormat() {
|
|
|
-}
|
|
|
-
|
|
|
-function fixColourMapEntries() {
|
|
|
-}
|
|
|
-
|
|
|
-function setEncodings() {
|
|
|
+setPixelFormat: function () {
|
|
|
+ debug(">> setPixelFormat");
|
|
|
+ var arr = [0]; // msg-type
|
|
|
+ arr.push8(0); // padding
|
|
|
+ arr.push8(0); // padding
|
|
|
+ arr.push8(0); // padding
|
|
|
+
|
|
|
+ arr.push8(fb_Bpp * 8); // bits-per-pixel
|
|
|
+ arr.push8(24); // depth
|
|
|
+ arr.push8(0); // little-endian
|
|
|
+ arr.push8(1); // true-color
|
|
|
+
|
|
|
+ arr.push16(255); // red-max
|
|
|
+ arr.push16(255); // green-max
|
|
|
+ arr.push16(255); // blue-max
|
|
|
+ arr.push8(16); // red-shift
|
|
|
+ arr.push8(8); // green-shift
|
|
|
+ arr.push8(0); // blue-shift
|
|
|
+
|
|
|
+ arr.push8(0); // padding
|
|
|
+ arr.push8(0); // padding
|
|
|
+ arr.push8(0); // padding
|
|
|
+ RFB.send_array(arr);
|
|
|
+ debug("<< setPixelFormat");
|
|
|
+},
|
|
|
+
|
|
|
+fixColourMapEntries: function () {
|
|
|
+},
|
|
|
+
|
|
|
+setEncodings: function () {
|
|
|
debug(">> setEncodings");
|
|
|
var arr = [2]; // msg-type
|
|
|
- arr.pushCard8(0); // padding
|
|
|
- arr.pushCard16(1); // encoding count
|
|
|
- arr.pushCard32(0); // raw encoding
|
|
|
- send_array(arr);
|
|
|
+ arr.push8(0); // padding
|
|
|
+ arr.push16(2); // encoding count
|
|
|
+ arr.push32(1); // copy-rect encoding
|
|
|
+ arr.push32(0); // raw encoding
|
|
|
+ RFB.send_array(arr);
|
|
|
debug("<< setEncodings");
|
|
|
-}
|
|
|
+},
|
|
|
|
|
|
-function fbUpdateRequest(incremental, x, y, xw, yw) {
|
|
|
+fbUpdateRequest: function (incremental, x, y, xw, yw) {
|
|
|
debug(">> fbUpdateRequest");
|
|
|
var arr = [3]; // msg-type
|
|
|
- arr.pushCard8(incremental);
|
|
|
- arr.pushCard16(x);
|
|
|
- arr.pushCard16(y);
|
|
|
- arr.pushCard16(xw);
|
|
|
- arr.pushCard16(yw);
|
|
|
- send_array(arr);
|
|
|
+ arr.push8(incremental);
|
|
|
+ arr.push16(x);
|
|
|
+ arr.push16(y);
|
|
|
+ arr.push16(xw);
|
|
|
+ arr.push16(yw);
|
|
|
+ RFB.send_array(arr);
|
|
|
debug("<< fbUpdateRequest");
|
|
|
-}
|
|
|
+},
|
|
|
|
|
|
-function keyEvent() {
|
|
|
-}
|
|
|
+keyEvent: function (key, code, down) {
|
|
|
+ debug(">> keyEvent: " + key + "(" + code + ") " + down);
|
|
|
+ var arr = [4]; // msg-type
|
|
|
+ arr.push8(down);
|
|
|
+ arr.push16(0);
|
|
|
+ arr.push32(code);
|
|
|
+ RFB.send_array(arr);
|
|
|
+ RFB.fbUpdateRequest(1, 0, 0, fb_width, fb_height);
|
|
|
+ debug("<< keyEvent");
|
|
|
+},
|
|
|
|
|
|
-function pointerEvent() {
|
|
|
-}
|
|
|
+pointerEvent: function () {
|
|
|
+},
|
|
|
|
|
|
-function clientCutText() {
|
|
|
-}
|
|
|
+clientCutText: function () {
|
|
|
+},
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * Utility routines
|
|
|
+ */
|
|
|
+
|
|
|
+send_string: function (str) {
|
|
|
+ ws.send(Base64.encode(str));
|
|
|
+},
|
|
|
+
|
|
|
+send_array: function (arr) {
|
|
|
+ debug("encoded array: " + Base64.encode_array(arr));
|
|
|
+ ws.send(Base64.encode_array(arr));
|
|
|
+},
|
|
|
+
|
|
|
+poller: function () {
|
|
|
+ if (RFB.state == 'normal') {
|
|
|
+ RFB.fbUpdateRequest(1, 0, 0, fb_width, fb_height);
|
|
|
+ RFB.poller.delay(RFB.poll_rate);
|
|
|
+ }
|
|
|
+},
|
|
|
+
|
|
|
+keyDown: function (e) {
|
|
|
+ e.stop();
|
|
|
+ RFB.keyEvent(e.key, e.code, 1);
|
|
|
+},
|
|
|
+
|
|
|
+keyUp: function (e) {
|
|
|
+ e.stop();
|
|
|
+ RFB.keyEvent(e.key, e.code, 0);
|
|
|
+},
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Setup routines
|
|
|
*/
|
|
|
|
|
|
-function _init_ws() {
|
|
|
+_init_ws: function () {
|
|
|
debug(">> _init_ws");
|
|
|
var uri = "ws://" + vnc_host + ":" + vnc_port;
|
|
|
debug("connecting to " + uri);
|
|
|
ws = new WebSocket(uri);
|
|
|
ws.onmessage = function(e) {
|
|
|
- debug(">> onmessage");
|
|
|
+ //debug(">> onmessage");
|
|
|
var data = Base64.decode_array(e.data);
|
|
|
//debug("decoded array: " + data);
|
|
|
- if (rfb_state != 'normal') {
|
|
|
- rfb_init_msg(data);
|
|
|
+ if (RFB.state != 'normal') {
|
|
|
+ RFB.init_msg(data);
|
|
|
} else {
|
|
|
- rfb_msg(data);
|
|
|
+ RFB.normal_msg(data);
|
|
|
}
|
|
|
- if (rfb_state == 'reset') {
|
|
|
+ if (RFB.state == 'reset') {
|
|
|
/* close and reset connection */
|
|
|
ws.close();
|
|
|
- _init_ws();
|
|
|
+ RFB._init_ws();
|
|
|
+ } else if (RFB.state == 'failed') {
|
|
|
+ debug("Giving up!");
|
|
|
+ ws.close();
|
|
|
}
|
|
|
- debug("<< onmessage");
|
|
|
+ //debug("<< onmessage");
|
|
|
};
|
|
|
ws.onopen = function(e) {
|
|
|
debug(">> onopen");
|
|
|
- rfb_state = "ProtocolVersion";
|
|
|
+ RFB.state = "ProtocolVersion";
|
|
|
debug("<< onopen");
|
|
|
};
|
|
|
ws.onclose = function(e) {
|
|
|
debug(">> onclose");
|
|
|
- rfb_state = "closed";
|
|
|
+ RFB.state = "closed";
|
|
|
debug("<< onclose");
|
|
|
}
|
|
|
+ RFB.poller.delay(RFB.poll_rate);
|
|
|
+
|
|
|
debug("<< _init_ws");
|
|
|
-}
|
|
|
+},
|
|
|
|
|
|
-function init_ws(host, port) {
|
|
|
+init_ws: function (host, port) {
|
|
|
debug(">> init_ws");
|
|
|
vnc_host = host;
|
|
|
vnc_port = port;
|
|
|
if (ws) {
|
|
|
ws.close();
|
|
|
}
|
|
|
- _init_ws();
|
|
|
+ RFB._init_ws();
|
|
|
debug("<< init_ws");
|
|
|
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
-function draw() {
|
|
|
- var canvas = document.getElementById('vnc');
|
|
|
-
|
|
|
- if (! canvas.getContext) return;
|
|
|
-
|
|
|
- var ctx = canvas.getContext('2d');
|
|
|
-
|
|
|
- ctx.fillStyle = "rgb(50,50,50)";
|
|
|
- ctx.fillRect(0, 0, 800, 600);
|
|
|
-
|
|
|
- var img = new Image();
|
|
|
- img.src = "head_ani2.gif"
|
|
|
-
|
|
|
- ctx.drawImage(img, 10, 10);
|
|
|
-
|
|
|
- ctx.drawImage(canvas, 20, 20, 30, 30, 70, 70, 30, 30);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-function draw2() {
|
|
|
- var canvas = document.getElementById('tutorial');
|
|
|
-
|
|
|
- if (! canvas.getContext) return;
|
|
|
-
|
|
|
- var ctx = canvas.getContext('2d');
|
|
|
-
|
|
|
- roundedRect(ctx,12,12,150,150,15);
|
|
|
- roundedRect(ctx,19,19,150,150,9);
|
|
|
- roundedRect(ctx,53,53,49,33,10);
|
|
|
- roundedRect(ctx,53,119,49,16,6);
|
|
|
- roundedRect(ctx,135,53,49,33,10);
|
|
|
- roundedRect(ctx,135,119,25,49,10);
|
|
|
-
|
|
|
- ctx.beginPath();
|
|
|
- ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,true);
|
|
|
- ctx.lineTo(31,37);
|
|
|
- ctx.fill();
|
|
|
- for(var i=0;i<8;i++){
|
|
|
- ctx.fillRect(51+i*16,35,4,4);
|
|
|
- }
|
|
|
- for(i=0;i<6;i++){
|
|
|
- ctx.fillRect(115,51+i*16,4,4);
|
|
|
- }
|
|
|
- for(i=0;i<8;i++){
|
|
|
- ctx.fillRect(51+i*16,99,4,4);
|
|
|
- }
|
|
|
- ctx.beginPath();
|
|
|
- ctx.moveTo(83,116);
|
|
|
- ctx.lineTo(83,102);
|
|
|
- ctx.bezierCurveTo(83,94,89,88,97,88);
|
|
|
- ctx.bezierCurveTo(105,88,111,94,111,102);
|
|
|
- ctx.lineTo(111,116);
|
|
|
- ctx.lineTo(106.333,111.333);
|
|
|
- ctx.lineTo(101.666,116);
|
|
|
- ctx.lineTo(97,111.333);
|
|
|
- ctx.lineTo(92.333,116);
|
|
|
- ctx.lineTo(87.666,111.333);
|
|
|
- ctx.lineTo(83,116);
|
|
|
- ctx.fill();
|
|
|
- ctx.fillStyle = "white";
|
|
|
- ctx.beginPath();
|
|
|
- ctx.moveTo(91,96);
|
|
|
- ctx.bezierCurveTo(88,96,87,99,87,101);
|
|
|
- ctx.bezierCurveTo(87,103,88,106,91,106);
|
|
|
- ctx.bezierCurveTo(94,106,95,103,95,101);
|
|
|
- ctx.bezierCurveTo(95,99,94,96,91,96);
|
|
|
- ctx.moveTo(103,96);
|
|
|
- ctx.bezierCurveTo(100,96,99,99,99,101);
|
|
|
- ctx.bezierCurveTo(99,103,100,106,103,106);
|
|
|
- ctx.bezierCurveTo(106,106,107,103,107,101);
|
|
|
- ctx.bezierCurveTo(107,99,106,96,103,96);
|
|
|
- ctx.fill();
|
|
|
- ctx.fillStyle = "black";
|
|
|
- ctx.beginPath();
|
|
|
- ctx.arc(101,102,2,0,Math.PI*2,true);
|
|
|
- ctx.fill();
|
|
|
- ctx.beginPath();
|
|
|
- ctx.arc(89,102,2,0,Math.PI*2,true);
|
|
|
- ctx.fill();
|
|
|
-}
|
|
|
-function roundedRect(ctx,x,y,width,height,radius){
|
|
|
- ctx.beginPath();
|
|
|
- ctx.moveTo(x,y+radius);
|
|
|
- ctx.lineTo(x,y+height-radius);
|
|
|
- ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
|
|
|
- ctx.lineTo(x+width-radius,y+height);
|
|
|
- ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
|
|
|
- ctx.lineTo(x+width,y+radius);
|
|
|
- ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
|
|
|
- ctx.lineTo(x+radius,y);
|
|
|
- ctx.quadraticCurveTo(x,y,x,y+radius);
|
|
|
- ctx.stroke();
|
|
|
-}
|
|
|
-*/
|
|
|
-debug("here10");
|
|
|
+}; /* End of RFB */
|