]> git.proxmox.com Git - mirror_novnc.git/commitdiff
include/canvas.js: fix changeCursor data format.
authorJoel Martin <github@martintribe.org>
Wed, 19 Jan 2011 05:22:25 +0000 (23:22 -0600)
committerJoel Martin <github@martintribe.org>
Wed, 19 Jan 2011 05:22:25 +0000 (23:22 -0600)
Issues #27 (safari cursor rendering messed up) and #29 (firefox 3.6.10
segault).

Finally found some better reference on the icon/cursor format which is
added to the docs/links file.

It seems like I was missing the XOR section. So setting the cursor
would cause corruptin in Safari rendering or the segfault for firefox.

docs/links
include/canvas.js

index 7b4059be99130c701edbd646bcf15b1f20311057..31544ce0e12b85e049e4c809ac0dc79177eb26df 100644 (file)
@@ -35,6 +35,11 @@ Cursor appearance/style (for Cursor pseudo-encoding):
     https://developer.mozilla.org/en/Using_URL_values_for_the_cursor_property
     http://www.fileformat.info/format/bmp/egff.htm
 
+Icon/Cursor file format:
+    http://msdn.microsoft.com/en-us/library/ms997538
+    http://msdn.microsoft.com/en-us/library/aa921550.aspx
+    http://msdn.microsoft.com/en-us/library/aa930622.aspx
+
 
 RDP Protocol specification:
     http://msdn.microsoft.com/en-us/library/cc240445(v=PROT.10).aspx
index 3079a1af070861f0dc8d6577ce48f15d06c1c5c7..e8cfb8693195817d2a554d117da39f927d4ca1d8 100644 (file)
@@ -83,8 +83,6 @@ that.get_height = function() {
     return c_height;
 };
 
-
-
 //
 // Private functions
 //
@@ -192,7 +190,7 @@ function constructor() {
     }
     try {
         curSave = c.style.cursor;
-        that.changeCursor(curDat, curDat, 2, 2, 8, 8);
+        changeCursor(conf.target, curDat, curDat, 2, 2, 8, 8);
         if (c.style.cursor) {
             if (conf.cursor_uri === null) {
                 conf.cursor_uri = true;
@@ -596,14 +594,28 @@ that.blitStringImage = function(str, x, y) {
 };
 
 that.changeCursor = function(pixels, mask, hotx, hoty, w, h) {
-    var cur = [], cmap, rgb, IHDRsz, ANDsz, XORsz, url, idx, alpha, x, y;
-    //Util.Debug(">> changeCursor, x: " + hotx + ", y: " + hoty + ", w: " + w + ", h: " + h);
-    
     if (conf.cursor_uri === false) {
         Util.Warn("changeCursor called but no cursor data URI support");
         return;
     }
 
+    if (conf.true_color) {
+        changeCursor(conf.target, pixels, mask, hotx, hoty, w, h);
+    } else {
+        changeCursor(conf.target, pixels, mask, hotx, hoty, w, h, conf.colourMap);
+    }
+}
+
+return constructor();  // Return the public API interface
+
+}  // End of Canvas()
+
+
+/* Set CSS cursor property using data URI encoded cursor file */
+function changeCursor(target, pixels, mask, hotx, hoty, w, h, cmap) {
+    var cur = [], rgb, IHDRsz, RGBsz, ANDsz, XORsz, url, idx, alpha, x, y;
+    //Util.Debug(">> changeCursor, x: " + hotx + ", y: " + hoty + ", w: " + w + ", h: " + h);
+    
     // Push multi-byte little-endian values
     cur.push16le = function (num) {
         this.push((num     ) & 0xFF,
@@ -616,63 +628,77 @@ that.changeCursor = function(pixels, mask, hotx, hoty, w, h) {
                   (num >> 24) & 0xFF  );
     };
 
-    cmap = conf.colourMap;
     IHDRsz = 40;
-    ANDsz = w * h * 4;
+    RGBsz = w * h * 4;
     XORsz = Math.ceil( (w * h) / 8.0 );
+    ANDsz = Math.ceil( (w * h) / 8.0 );
 
     // Main header
-    cur.push16le(0);      // Reserved
-    cur.push16le(2);      // .CUR type
-    cur.push16le(1);      // Number of images, 1 for non-animated ico
-
-    // Cursor #1 header
-    cur.push(w);          // width
-    cur.push(h);          // height
-    cur.push(0);          // colors, 0 -> true-color
-    cur.push(0);          // reserved
-    cur.push16le(hotx);   // hotspot x coordinate
-    cur.push16le(hoty);   // hotspot y coordinate
-    cur.push32le(IHDRsz + XORsz + ANDsz); // cursor data byte size
-    cur.push32le(22);     // offset of cursor data in the file
-
-    // Cursor #1 InfoHeader
-    cur.push32le(IHDRsz); // Infoheader size
-    cur.push32le(w);      // Cursor width
-    cur.push32le(h*2);    // XOR+AND height
-    cur.push16le(1);      // number of planes
-    cur.push16le(32);     // bits per pixel
-    cur.push32le(0);      // Type of compression
-    cur.push32le(XORsz + ANDsz); // Size of Image
-    cur.push32le(0);
-    cur.push32le(0);
-    cur.push32le(0);
-    cur.push32le(0);
-
-    // XOR/color data
+    cur.push16le(0);      // 0: Reserved
+    cur.push16le(2);      // 2: .CUR type
+    cur.push16le(1);      // 4: Number of images, 1 for non-animated ico
+
+    // Cursor #1 header (ICONDIRENTRY)
+    cur.push(w);          // 6: width
+    cur.push(h);          // 7: height
+    cur.push(0);          // 8: colors, 0 -> true-color
+    cur.push(0);          // 9: reserved
+    cur.push16le(hotx);   // 10: hotspot x coordinate
+    cur.push16le(hoty);   // 12: hotspot y coordinate
+    cur.push32le(IHDRsz + RGBsz + XORsz + ANDsz);
+                          // 14: cursor data byte size
+    cur.push32le(22);     // 18: offset of cursor data in the file
+
+
+    // Cursor #1 InfoHeader (ICONIMAGE/BITMAPINFO)
+    cur.push32le(IHDRsz); // 22: Infoheader size
+    cur.push32le(w);      // 26: Cursor width
+    cur.push32le(h*2);    // 30: XOR+AND height
+    cur.push16le(1);      // 34: number of planes
+    cur.push16le(32);     // 36: bits per pixel
+    cur.push32le(0);      // 38: Type of compression
+
+    cur.push32le(XORsz + ANDsz); // 43: Size of Image
+                                 // Gimp leaves this as 0
+
+    cur.push32le(0);      // 46: reserved
+    cur.push32le(0);      // 50: reserved
+    cur.push32le(0);      // 54: reserved
+    cur.push32le(0);      // 58: reserved
+
+    // 62: color data (RGBQUAD icColors[])
     for (y = h-1; y >= 0; y -= 1) {
         for (x = 0; x < w; x += 1) {
             idx = y * Math.ceil(w / 8) + Math.floor(x/8);
             alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0;
 
-            if (conf.true_color) {
-                idx = ((w * y) + x) * 4;
-                cur.push(pixels[idx + 2]); // blue
-                cur.push(pixels[idx + 1]); // green
-                cur.push(pixels[idx + 0]); // red
-                cur.push(alpha); // red
-            } else {
+            if (cmap) {
                 idx = (w * y) + x;
                 rgb = cmap[pixels[idx]];
                 cur.push(rgb[2]);          // blue
                 cur.push(rgb[1]);          // green
                 cur.push(rgb[0]);          // red
                 cur.push(alpha);           // alpha
+            } else {
+                idx = ((w * y) + x) * 4;
+                cur.push(pixels[idx + 2]); // blue
+                cur.push(pixels[idx + 1]); // green
+                cur.push(pixels[idx + 0]); // red
+                cur.push(alpha);           // alpha
             }
         }
     }
 
-    // AND/bitmask data (ignored, just needs to be right size)
+    // XOR/bitmask data (BYTE icXOR[])
+    // (ignored, just needs to be right size)
+    for (y = 0; y < h; y += 1) {
+        for (x = 0; x < Math.ceil(w / 8); x += 1) {
+            cur.push(0x00);
+        }
+    }
+
+    // AND/bitmask data (BYTE icAND[])
+    // (ignored, just needs to be right size)
     for (y = 0; y < h; y += 1) {
         for (x = 0; x < Math.ceil(w / 8); x += 1) {
             cur.push(0x00);
@@ -680,17 +706,14 @@ that.changeCursor = function(pixels, mask, hotx, hoty, w, h) {
     }
 
     url = "data:image/x-icon;base64," + Base64.encode(cur);
-    conf.target.style.cursor = "url(" + url + ") " + hotx + " " + hoty + ", default";
+    Util.Info(url);
+    target.style.cursor = "url(" + url + ") " + hotx + " " + hoty + ", default";
+    //conf.target.style.cursor = "url(" + url + "), default";
     //Util.Debug("<< changeCursor, cur.length: " + cur.length);
 };
 
 
 
-return constructor();  // Return the public API interface
-
-}  // End of Canvas()
-
-
 /* Translate DOM key down/up event to keysym value */
 function getKeysym(e) {
     var evt, keysym;