[Spice-devel] [PATCH spice-html5 v2 1/3] cursor: Add support for mono cursor type

Tomáš Bohdálek tom.bohdalek at gmail.com
Thu Sep 14 10:06:55 UTC 2017


---
 cursor.js                |  18 +++++++--
 png.js                   |   2 +-
 spice.html               |   1 +
 spice_auto.html          |   1 +
 thirdparty/monocursor.js | 100 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+), 5 deletions(-)
 create mode 100644 thirdparty/monocursor.js

diff --git a/cursor.js b/cursor.js
index d3f4d55..1fb1ede 100644
--- a/cursor.js
+++ b/cursor.js
@@ -62,7 +62,8 @@ SpiceCursorConn.prototype.process_channel_message = function(msg)
         if (cursor_set.flags > 0)
             this.log_warn("FIXME: No support for cursor flags " + cursor_set.flags);
 
-        if (cursor_set.cursor.header.type != SPICE_CURSOR_TYPE_ALPHA)
+        if (cursor_set.cursor.header.type != SPICE_CURSOR_TYPE_ALPHA &&
+            cursor_set.cursor.header.type != SPICE_CURSOR_TYPE_MONO)
         {
             this.log_warn("FIXME: No support for cursor type " + cursor_set.cursor.header.type);
             return false;
@@ -117,9 +118,18 @@ SpiceCursorConn.prototype.process_channel_message = function(msg)
 
 SpiceCursorConn.prototype.set_cursor = function(cursor)
 {
-    var pngstr = create_rgba_png(cursor.header.height, cursor.header.width, cursor.data);
-    var curstr = 'url(data:image/png,' + pngstr + ') ' +
-        cursor.header.hot_spot_x + ' ' + cursor.header.hot_spot_y + ", default";
+    var pngstr = null;
+    if (cursor.header.type == SPICE_CURSOR_TYPE_ALPHA)
+    {
+        pngstr = create_rgba_png(cursor.header.height, cursor.header.width, cursor.data);
+    }
+    if (cursor.header.type == SPICE_CURSOR_TYPE_MONO)
+    {
+        pngstr = mono_cursor(cursor.header.height, cursor.header.width, cursor.data);
+    }
+
+    var curstr = 'url(' + pngstr + ') ' +
+    cursor.header.hot_spot_x + ' ' + cursor.header.hot_spot_y + ", default";
     var screen = document.getElementById(this.parent.screen_id);
     screen.style.cursor = 'auto';
     screen.style.cursor = curstr;
diff --git a/png.js b/png.js
index 6a26151..5b52ed5 100644
--- a/png.js
+++ b/png.js
@@ -252,5 +252,5 @@ function create_rgba_png(width, height, bytes)
     }
 
 
-    return "%89PNG%0D%0A%1A%0A" + str;
+    return "data:image/png,%89PNG%0D%0A%1A%0A" + str;
 }
diff --git a/spice.html b/spice.html
index 7abfcff..3a74e21 100644
--- a/spice.html
+++ b/spice.html
@@ -54,6 +54,7 @@
         <script src="thirdparty/prng4.js"></script>
         <script src="thirdparty/rng.js"></script>
         <script src="thirdparty/sha1.js"></script>
+        <script src="thirdparty/monocursor.js"></script>
         <script src="ticket.js"></script>
         <script src="resize.js"></script>
         <script src="filexfer.js"></script>
diff --git a/spice_auto.html b/spice_auto.html
index 2f04fc9..10f5508 100644
--- a/spice_auto.html
+++ b/spice_auto.html
@@ -54,6 +54,7 @@
         <script src="thirdparty/prng4.js"></script>
         <script src="thirdparty/rng.js"></script>
         <script src="thirdparty/sha1.js"></script>
+        <script src="thirdparty/monocursor.js"></script>
         <script src="ticket.js"></script>
         <script src="resize.js"></script>
         <script src="filexfer.js"></script>
diff --git a/thirdparty/monocursor.js b/thirdparty/monocursor.js
new file mode 100644
index 0000000..36ebd88
--- /dev/null
+++ b/thirdparty/monocursor.js
@@ -0,0 +1,100 @@
+/*  Downloaded 1/6/2017 from https://github.com/eyeos/spice-web-client/blob/master/lib/graphic.js by Tomáš Bohdálek.
+
+License reproduce here for completeness:
+
+ eyeOS Spice Web Client
+Copyright (c) 2015 eyeOS S.L.
+
+Contact Jose Carlos Norte (jose at eyeos.com) for more information about this software.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Affero General Public License version 3 as published by the
+Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+details.
+
+You should have received a copy of the GNU Affero General Public License
+version 3 along with this program in the file "LICENSE".  If not, see 
+<http://www.gnu.org/licenses/agpl-3.0.txt>.
+
+See www.eyeos.org for more details. All requests should be sent to licensing at eyeos.org
+
+The interactive user interfaces in modified source and object code versions
+of this program must display Appropriate Legal Notices, as required under
+Section 5 of the GNU Affero General Public License version 3.
+
+In accordance with Section 7(b) of the GNU Affero General Public License version 3,
+these Appropriate Legal Notices must retain the display of the "Powered by
+eyeos" logo and retain the original copyright notice. If the display of the 
+logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+must display the words "Powered by eyeos" and retain the original copyright notice.
+*/
+
+function mono_cursor(height, width, data)
+{
+    var monoMask = [1, 2, 4, 8, 16, 32, 64, 128];
+    var bytes = new Uint8Array(data);
+    var length = bytes.length;
+    var half = length / 2;
+
+    var canvas = document.createElement("canvas");
+        canvas.setAttribute('width', width);
+        canvas.setAttribute('height', height);
+    var context = canvas.getContext("2d");
+    var result = context.createImageData(width, height);
+
+    var andMask = [];
+    var xorMask = [];
+
+    for (var i = 0; i < length; i++) {
+        var currentByte = bytes[i];
+        var bitsLeft = 8;
+
+        if (i >= half) {
+            while (bitsLeft--) {
+                var bit = (currentByte & monoMask[bitsLeft]) && true;
+                andMask.push(bit);
+            }
+        } else if (i < half) {
+            while (bitsLeft--) {
+                var bit = (currentByte & monoMask[bitsLeft]) && true;
+                xorMask.push(bit);
+            }
+        }
+    }
+
+    var pos = 0;
+    half = xorMask.length;
+
+    for (i = 0; i < half; i++) {
+        pos = i * 4;
+        if (!andMask[i] && !xorMask[i]) {
+            result.data[pos] = 0;
+            result.data[pos + 1] = 0;
+            result.data[pos + 2] = 0;
+            result.data[pos + 3] = 255;
+        } else if (!andMask[i] && xorMask[i]) {
+            result.data[pos] = 255;
+            result.data[pos + 1] = 255;
+            result.data[pos + 2] = 255;
+            result.data[pos + 3] = 0;
+        } else if (andMask[i] && !xorMask[i]) {
+            result.data[pos] = 255;
+            result.data[pos + 1] = 255;
+            result.data[pos + 2] = 255;
+            result.data[pos + 3] = 255;
+        } else if (andMask[i] && xorMask[i]) {
+            result.data[pos] = 0;
+            result.data[pos + 1] = 0;
+            result.data[pos + 2] = 0;
+            result.data[pos + 3] = 255;
+        }
+    }
+
+    context.putImageData(result, 0, 0);
+
+    return canvas.toDataURL("image/png");
+}
-- 
2.9.5



More information about the Spice-devel mailing list