[Spice-devel] [PATCH] channel-cursor: mono cursors edge highlighting
Alon Levy
alevy at redhat.com
Fri Oct 18 13:37:42 CEST 2013
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);
More information about the Spice-devel
mailing list