Re: [PATCH] channel-cursor: mono cursors edge highlighting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/18/2013 02:30 PM, Alon Levy wrote:

Please ignore, I'll send a new version.
Fix 998529, mono (invert) cursors not visible on a black background, by doing
simple edge detection on the cursor (this is done once when the cursor
is changed and then cached, cursors are 32x32 generally) and thus having
a cursor with contrast on both dark and light backgrounds.

When (if) GDK gets invert cursor support (wayland?) then we can just use
the cursor as is. Until then X doesn't provide any way I see of solving
this otherwise. The end result was tested with the I beam cursor that
the original bug was referring to (run putty on a windows 7 vm) and
looks ok to me.
---
  gtk/channel-cursor.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--
  1 file changed, 75 insertions(+), 3 deletions(-)

diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c
index d1d2c34..322afd9 100644
--- a/gtk/channel-cursor.c
+++ b/gtk/channel-cursor.c
@@ -246,19 +246,90 @@ static void do_emit_main_context(GObject *object, int signum, gpointer params)
/* ------------------------------------------------------------------ */ -static void mono_cursor(display_cursor *cursor, const guint8 *data)
+#ifdef DEBUG_CURSOR
+static void print_cursor(display_cursor *cursor, const guint8 *data)
  {
+    int x, y, bpl;
      const guint8 *xor, *and;
+
+    bpl = (cursor->hdr.width + 7) / 8;
+    and = data;
+    xor = and + bpl * cursor->hdr.height;
+
+    printf("data (%d x %d):\n", cursor->hdr.width, cursor->hdr.height);
+    for (y = 0 ; y < cursor->hdr.height; ++y) {
+        for (x = 0 ; x < cursor->hdr.width / 8; x++) {
+            printf("%02X", and[x]);
+        }
+        and += bpl;
+        printf("\n");
+    }
+    printf("xor:\n");
+    for (y = 0 ; y < cursor->hdr.height; ++y) {
+        for (x = 0 ; x < cursor->hdr.width / 8; ++x) {
+            printf("%02X", xor[x]);
+        }
+        xor += bpl;
+        printf("\n");
+    }
+}
+#endif
+
+static bool cursor_xor_pixel(const guint8 *xor, int bpl, int x, int y)
+{
+    return (xor[bpl * y + (x / 8)] & (0x80 >> (x % 8))) > 0;
+}
+
+static guint8 cursor_is_xor_edge(display_cursor *cursor, const guint8 *xor, int bpl, int x, int y)
+{
+    if (x == 0 || x == cursor->hdr.width -1 || y == 0 || y == cursor->hdr.height - 1) {
+        return 0;
+    }
+#define P(x, y) cursor_xor_pixel(xor, bpl, x, y)
+    return !P(x, y) && (P(x - 1, y + 1) || P(x, y + 1) || P(x + 1, y + 1) ||
+                        P(x - 1, y)     ||                P(x + 1, y)     ||
+                        P(x - 1, y - 1) || P(x, y - 1) || P(x + 1, y - 1));
+#undef P
+}
+
+static bool cursor_is_and_ones(display_cursor *cursor, const guint8 *data)
+{
+    int x, y, bpl;
+
+    bpl = (cursor->hdr.width + 7) / 8;
+    for (y = 0 ; y < cursor->hdr.height; ++y) {
+        for (x = 0 ; x < cursor->hdr.width / 8; ++x) {
+            if (data[x] != 0xff) {
+                return false;
+            }
+        }
+        data += bpl;
+    }
+    return true;
+}
+
+static void mono_cursor(SpiceChannel *channel, display_cursor *cursor, const guint8 *data)
+{
+    const guint8 *xor, *xor_base, *and;
      guint8 *dest;
      int bpl, x, y, bit;
+    bool and_ones = cursor_is_and_ones(cursor, data);
bpl = (cursor->hdr.width + 7) / 8;
      and = data;
-    xor = and + bpl * cursor->hdr.height;
+    xor_base = xor = and + bpl * cursor->hdr.height;
      dest  = (uint8_t *)cursor->data;
+#ifdef DEBUG_CURSOR
+    print_cursor(cursor, data);
+#endif
      for (y = 0; y < cursor->hdr.height; y++) {
          bit = 0x80;
          for (x = 0; x < cursor->hdr.width; x++, dest += 4) {
+            if (cursor_is_xor_edge(cursor, xor_base, bpl, x, y) && and_ones) {
+                dest[0] = dest[1] = dest[2] = 0x00;
+                dest[3] = 0xff;
+                goto next_bit;
+            }
              if (and[x/8] & bit) {
                  if (xor[x/8] & bit) {
                      /*
@@ -301,6 +372,7 @@ static void mono_cursor(display_cursor *cursor, const guint8 *data)
                      dest[3] = 0xff;
                  }
              }
+        next_bit:
              bit >>= 1;
              if (bit == 0) {
                  bit = 0x80;
@@ -395,7 +467,7 @@ static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor *scursor)
switch (hdr->type) {
      case SPICE_CURSOR_TYPE_MONO:
-        mono_cursor(cursor, data);
+        mono_cursor(channel, cursor, data);
          break;
      case SPICE_CURSOR_TYPE_ALPHA:
          memcpy(cursor->data, data, size);

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/spice-devel




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]