Add a new cursor type to console.h and a bunch of functions to deal with cursors the (new) cursor.c file.
Signed-off-by: Gerd Hoffmann <kra...@redhat.com> --- Makefile.objs | 3 +- console.h | 24 ++++++- cursor.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 cursor.c diff --git a/Makefile.objs b/Makefile.objs index ecdd53e..1ee6e9d 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -48,7 +48,8 @@ common-obj-y = $(block-obj-y) common-obj-y += $(net-obj-y) common-obj-y += $(qobject-obj-y) common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) -common-obj-y += readline.o console.o async.o qemu-error.o +common-obj-y += readline.o console.o cursor.o async.o qemu-error.o + common-obj-y += tcg-runtime.o host-utils.o common-obj-y += irq.o ioport.o input.o common-obj-$(CONFIG_PTIMER) += ptimer.o diff --git a/console.h b/console.h index 6def115..88861cb 100644 --- a/console.h +++ b/console.h @@ -126,6 +126,27 @@ struct DisplaySurface { struct PixelFormat pf; }; +/* cursor data format is 32bit RGBA */ +typedef struct QEMUCursor { + int width, height; + int hot_x, hot_y; + int refcount; + uint32_t data[]; +} QEMUCursor; + +QEMUCursor *cursor_alloc(int width, int height); +void cursor_get(QEMUCursor *c); +void cursor_put(QEMUCursor *c); +QEMUCursor *cursor_builtin_hidden(void); +QEMUCursor *cursor_builtin_left_ptr(void); +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix); +int cursor_get_mono_bpl(QEMUCursor *c); +void cursor_set_mono(QEMUCursor *c, + uint32_t foreground, uint32_t background, uint8_t *image, + int transparent, uint8_t *mask); +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask); +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); + struct DisplayChangeListener { int idle; uint64_t gui_timer_interval; @@ -158,8 +179,7 @@ struct DisplayState { struct DisplayChangeListener* listeners; void (*mouse_set)(int x, int y, int on); - void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y, - uint8_t *image, uint8_t *mask); + void (*cursor_define)(QEMUCursor *cursor); struct DisplayState *next; }; diff --git a/cursor.c b/cursor.c new file mode 100644 index 0000000..3995a31 --- /dev/null +++ b/cursor.c @@ -0,0 +1,208 @@ +#include "qemu-common.h" +#include "console.h" + +static const char cursor_hidden_32[32*32]; +static const char cursor_left_ptr_32[32*32] = { + " " + " X " + " XX " + " X.X " + " X..X " + " X...X " + " X....X " + " X.....X " + " X......X " + " X.......X " + " X........X " + " X.....XXXXX " + " X..X..X " + " X.X X..X " + " XX X..X " + " X X..X " + " X..X " + " X..X " + " X..X " + " XX " + " " +}; + +/* for creating built-in cursors */ +static void cursor_parse_ascii_art(QEMUCursor *c, const char *ptr) +{ + int i, pixels; + + pixels = c->width * c->height; + for (i = 0; i < pixels; i++) { + switch (ptr[i]) { + case 'X': /* black */ + c->data[i] = 0xff000000; + break; + case '.': /* white */ + c->data[i] = 0xffffffff; + break; + case ' ': /* transparent */ + default: + c->data[i] = 0x00000000; + break; + } + } +} + +/* nice for debugging */ +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix) +{ + uint32_t *data = c->data; + int x,y; + + for (y = 0; y < c->height; y++) { + fprintf(stderr, "%s: %2d: |", prefix, y); + for (x = 0; x < c->width; x++, data++) { + if ((*data & 0xff000000) != 0xff000000) { + fprintf(stderr, " "); /* transparent */ + } else if ((*data & 0x00ffffff) == 0x00ffffff) { + fprintf(stderr, "."); /* white */ + } else if ((*data & 0x00ffffff) == 0x00000000) { + fprintf(stderr, "X"); /* black */ + } else { + fprintf(stderr, "o"); /* other */ + } + } + fprintf(stderr, "|\n"); + } +} + +QEMUCursor *cursor_builtin_hidden(void) +{ + QEMUCursor *c; + + c = cursor_alloc(32, 32); + cursor_parse_ascii_art(c, cursor_hidden_32); + return c; +} + +QEMUCursor *cursor_builtin_left_ptr(void) +{ + QEMUCursor *c; + + c = cursor_alloc(32, 32); + cursor_parse_ascii_art(c, cursor_left_ptr_32); + c->hot_x = 1; + c->hot_y = 1; + return c; +} + +QEMUCursor *cursor_alloc(int width, int height) +{ + QEMUCursor *c; + int datasize = width * height * sizeof(uint32_t); + + c = qemu_mallocz(sizeof(QEMUCursor) + datasize); + c->width = width; + c->height = height; + c->refcount = 1; + return c; +} + +void cursor_get(QEMUCursor *c) +{ + c->refcount++; +} + +void cursor_put(QEMUCursor *c) +{ + if (c == NULL) + return; + c->refcount--; + if (c->refcount) + return; + qemu_free(c); +} + +int cursor_get_mono_bpl(QEMUCursor *c) +{ + return (c->width + 7) / 8; +} + +void cursor_set_mono(QEMUCursor *c, + uint32_t foreground, uint32_t background, uint8_t *image, + int transparent, uint8_t *mask) +{ + uint32_t *data = c->data; + uint8_t bit; + int x,y,bpl; + + bpl = cursor_get_mono_bpl(c); + for (y = 0; y < c->height; y++) { + bit = 0x80; + for (x = 0; x < c->width; x++, data++) { + if (transparent && mask[x/8] & bit) { + *data = 0x00000000; + } else if (!transparent && !(mask[x/8] & bit)) { + *data = 0x00000000; + } else if (image[x/8] & bit) { + *data = 0xff000000 | foreground; + } else { + *data = 0xff000000 | background; + } + bit >>= 1; + if (bit == 0) { + bit = 0x80; + } + } + mask += bpl; + image += bpl; + } +} + +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *image) +{ + uint32_t *data = c->data; + uint8_t bit; + int x,y,bpl; + + bpl = cursor_get_mono_bpl(c); + memset(image, 0, bpl * c->height); + for (y = 0; y < c->height; y++) { + bit = 0x80; + for (x = 0; x < c->width; x++, data++) { + if (((*data & 0xff000000) == 0xff000000) && + ((*data & 0x00ffffff) == foreground)) { + image[x/8] |= bit; + } + bit >>= 1; + if (bit == 0) { + bit = 0x80; + } + } + image += bpl; + } +} + +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask) +{ + uint32_t *data = c->data; + uint8_t bit; + int x,y,bpl; + + bpl = cursor_get_mono_bpl(c); + memset(mask, 0, bpl * c->height); + for (y = 0; y < c->height; y++) { + bit = 0x80; + for (x = 0; x < c->width; x++, data++) { + if ((*data & 0xff000000) != 0xff000000) { + if (transparent != 0) { + mask[x/8] |= bit; + } + } else { + if (transparent == 0) { + mask[x/8] |= bit; + } + } + bit >>= 1; + if (bit == 0) { + bit = 0x80; + } + } + mask += bpl; + } +} -- 1.6.6.1