Initial refactor of raster operations to real transfer functions.
[guacamole-common-js.git] / src / main / resources / guacamole.js
index 9461978..0d3dde7 100644 (file)
@@ -67,6 +67,36 @@ Guacamole.Client = function(tunnel) {
     var displayWidth = 0;
     var displayHeight = 0;
 
+    /**
+     * Map of all Guacamole binary raster operations to transfer functions.
+     * @private
+     */
+    var transferFunctions = {
+
+        0x10: function (src, dst) { return 0x00;         }, /* BLACK */
+        0x1F: function (src, dst) { return 0xFF;         }, /* WHITE */
+
+        0x13: function (src, dst) { return src;          }, /* SRC */
+        0x15: function (src, dst) { return dst;          }, /* DEST */
+        0x1C: function (src, dst) { return ~src;         }, /* NSRC */
+        0x1A: function (src, dst) { return ~dst;         }, /* NDEST */
+
+        0x11: function (src, dst) { return src & dst;    }, /* AND */
+        0x1E: function (src, dst) { return ~(src & dst); }, /* NAND */
+
+        0x17: function (src, dst) { return src | dst;    }, /* OR */
+        0x18: function (src, dst) { return ~(src | dst); }, /* NOR */
+
+        0x16: function (src, dst) { return src ^ dst;    }, /* XOR */
+        0x19: function (src, dst) { return ~(src ^ dst); }, /* XNOR */
+
+        0x14: function (src, dst) { return ~src & dst;   }, /* AND inverted source */
+        0x1D: function (src, dst) { return ~src | dst;   }, /* OR inverted source */
+        0x12: function (src, dst) { return src & ~dst;   }, /* AND inverted destination */
+        0x1B: function (src, dst) { return src | ~dst;   }  /* OR inverted destination */
+
+    };
+
     // Create display
     var display = document.createElement("div");
     display.style.position = "relative";
@@ -75,6 +105,8 @@ Guacamole.Client = function(tunnel) {
 
     // Create default layer
     var default_layer_container = new Guacamole.Client.LayerContainer(displayWidth, displayHeight);
+
+    // Position default layer
     var default_layer_container_element = default_layer_container.getElement();
     default_layer_container_element.style.position = "absolute";
     default_layer_container_element.style.left = "0px";
@@ -82,6 +114,9 @@ Guacamole.Client = function(tunnel) {
 
     // Create cursor layer
     var cursor = new Guacamole.Client.LayerContainer(0, 0);
+    cursor.getLayer().setChannelMask(Guacamole.Layer.SRC);
+
+    // Position cursor layer
     var cursor_element = cursor.getElement();
     cursor_element.style.position = "absolute";
     cursor_element.style.left = "0px";
@@ -118,22 +153,21 @@ Guacamole.Client = function(tunnel) {
     var cursorHotspotX = 0;
     var cursorHotspotY = 0;
 
-    var cursorHidden = 0;
+    var cursorX = 0;
+    var cursorY = 0;
 
     function moveCursor(x, y) {
 
         var element = cursor.getElement();
 
-        // Hide hardware cursor
-        if (cursorHidden == 0) {
-            display.className += " guac-hide-cursor";
-            cursorHidden = 1;
-        }
-
         // Update rect
         element.style.left = (x - cursorHotspotX) + "px";
         element.style.top  = (y - cursorHotspotY) + "px";
 
+        // Update stored position
+        cursorX = x;
+        cursorY = y;
+
     }
 
     guac_client.getDisplay = function() {
@@ -277,10 +311,6 @@ Guacamole.Client = function(tunnel) {
                     display.style.width = displayWidth + "px";
                     display.style.height = displayHeight + "px";
 
-                    // Set cursor layer width/height
-                    if (cursor != null)
-                        cursor.resize(displayWidth, displayHeight);
-
                 }
 
             } // end if layer (not buffer)
@@ -315,6 +345,32 @@ Guacamole.Client = function(tunnel) {
 
         },
 
+        "dispose": function(parameters) {
+            
+            var layer_index = parseInt(parameters[0]);
+
+            // If visible layer, remove from parent
+            if (layer_index > 0) {
+
+                // Get container element
+                var layer_container = getLayerContainer(layer_index).getElement();
+
+                // Remove from parent
+                layer_container.parentNode.removeChild(layer_container);
+
+                // Delete reference
+                delete layers[layer_index];
+
+            }
+
+            // If buffer, just delete reference
+            else if (layer_index < 0)
+                delete buffers[-1 - layer_index];
+
+            // Attempting to dispose the root layer currently has no effect.
+
+        },
+
         "png": function(parameters) {
 
             var channelMask = parseInt(parameters[0]);
@@ -363,6 +419,31 @@ Guacamole.Client = function(tunnel) {
 
         },
 
+        "transfer": function(parameters) {
+
+            var srcL = getLayer(parseInt(parameters[0]));
+            var srcX = parseInt(parameters[1]);
+            var srcY = parseInt(parameters[2]);
+            var srcWidth = parseInt(parameters[3]);
+            var srcHeight = parseInt(parameters[4]);
+            var transferFunction = transferFunctions[parameters[5]];
+            var dstL = getLayer(parseInt(parameters[6]));
+            var dstX = parseInt(parameters[7]);
+            var dstY = parseInt(parameters[8]);
+
+            dstL.transfer(
+                srcL,
+                srcX,
+                srcY,
+                srcWidth, 
+                srcHeight, 
+                dstX,
+                dstY,
+                transferFunction
+            );
+
+        },
+
         "rect": function(parameters) {
 
             var channelMask = parseInt(parameters[0]);
@@ -401,10 +482,28 @@ Guacamole.Client = function(tunnel) {
 
             cursorHotspotX = parseInt(parameters[0]);
             cursorHotspotY = parseInt(parameters[1]);
-            var data = parameters[2];
+            var srcL = getLayer(parseInt(parameters[2]));
+            var srcX = parseInt(parameters[3]);
+            var srcY = parseInt(parameters[4]);
+            var srcWidth = parseInt(parameters[5]);
+            var srcHeight = parseInt(parameters[6]);
+
+            // Reset cursor size
+            cursor.resize(srcWidth, srcHeight);
 
             // Draw cursor to cursor layer
-            cursor.draw(0, 0, "data:image/png;base64," + data);
+            cursor.getLayer().copyRect(
+                srcL,
+                srcX,
+                srcY,
+                srcWidth, 
+                srcHeight, 
+                0,
+                0 
+            );
+
+            // Update cursor position (hotspot may have changed)
+            moveCursor(cursorX, cursorY);
 
         },