From 57d4b1e4ccfc98d7b9ae645a0525a0181394e793 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 12:23:38 -0800 Subject: [PATCH] Initial refactor of raster operations to real transfer functions. --- src/main/resources/guacamole.js | 63 ++++++++++++++- src/main/resources/layer.js | 166 ++++++++++++++++++++------------------- 2 files changed, 146 insertions(+), 83 deletions(-) diff --git a/src/main/resources/guacamole.js b/src/main/resources/guacamole.js index 345a972..0d3dde7 100644 --- a/src/main/resources/guacamole.js +++ b/src/main/resources/guacamole.js @@ -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"; @@ -84,7 +114,7 @@ Guacamole.Client = function(tunnel) { // Create cursor layer var cursor = new Guacamole.Client.LayerContainer(0, 0); - cursor.getLayer().setCompositeOperation(Guacamole.Layer.SRC); + cursor.getLayer().setChannelMask(Guacamole.Layer.SRC); // Position cursor layer var cursor_element = cursor.getElement(); @@ -349,7 +379,7 @@ Guacamole.Client = function(tunnel) { var y = parseInt(parameters[3]); var data = parameters[4]; - layer.setCompositeOperation(channelMask); + layer.setChannelMask(channelMask); layer.draw( x, @@ -375,7 +405,7 @@ Guacamole.Client = function(tunnel) { var dstX = parseInt(parameters[7]); var dstY = parseInt(parameters[8]); - dstL.setCompositeOperation(channelMask); + dstL.setChannelMask(channelMask); dstL.copyRect( srcL, @@ -389,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]); @@ -402,7 +457,7 @@ Guacamole.Client = function(tunnel) { var b = parseInt(parameters[8]); var a = parseInt(parameters[9]); - layer.setCompositeOperation(channelMask); + layer.setChannelMask(channelMask); layer.drawRect( x, y, w, h, diff --git a/src/main/resources/layer.js b/src/main/resources/layer.js index 2938f76..32faa32 100644 --- a/src/main/resources/layer.js +++ b/src/main/resources/layer.js @@ -75,12 +75,6 @@ Guacamole.Layer = function(width, height) { displayContext.save(); /** - * The function to apply when drawing arbitrary source pixels over - * destination pixels. - */ - var transferFunction = null; - - /** * The queue of all pending Tasks. Tasks will be run in order, with new * tasks added at the end of the queue and old tasks removed from the * front of the queue (FIFO). @@ -113,36 +107,6 @@ Guacamole.Layer = function(width, height) { }; /** - * Map of all Guacamole binary raster operations to transfer functions. - * @private - */ - var binaryCompositeTransferFunction = { - - 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 */ - - }; - - /** * Resizes the canvas element backing this Layer without testing the * new size. This function should only be used internally. * @@ -429,6 +393,86 @@ Guacamole.Layer = function(width, height) { this.sync = scheduleTask; /** + * Transfer a rectangle of image data from one Layer to this Layer using the + * specified transfer function. + * + * @param {Guacamole.Layer} srcLayer The Layer to copy image data from. + * @param {Number} srcx The X coordinate of the upper-left corner of the + * rectangle within the source Layer's coordinate + * space to copy data from. + * @param {Number} srcy The Y coordinate of the upper-left corner of the + * rectangle within the source Layer's coordinate + * space to copy data from. + * @param {Number} srcw The width of the rectangle within the source Layer's + * coordinate space to copy data from. + * @param {Number} srch The height of the rectangle within the source + * Layer's coordinate space to copy data from. + * @param {Number} x The destination X coordinate. + * @param {Number} y The destination Y coordinate. + * @param {Function} transferFunction The transfer function to use to + * transfer data from source to + * destination. + */ + this.transfer = function(srcLayer, srcx, srcy, srcw, srch, x, y, transferFunction) { + + var drawComplete = false; + var srcLock = null; + + function doTransfer() { + if (layer.autosize != 0) fitRect(x, y, srcw, srch); + + var srcCanvas = srcLayer.getCanvas(); + if (srcCanvas.width != 0 && srcCanvas.height != 0) { + + // Get image data from src and dst + var src = srcLayer.getCanvas().getContext("2d").getImageData(srcx, srcy, srcw, srch); + var dst = displayContext.getImageData(x , y, srcw, srch); + + // Apply transfer for each pixel + for (var i=0; i