xref: /openbmc/qemu/ui/cursor.c (revision e16f4c8770b73f530dad842a31298963b6c7e41d)
1*e16f4c87SPeter Maydell #include "qemu/osdep.h"
228ecbaeeSPaolo Bonzini #include "qemu-common.h"
328ecbaeeSPaolo Bonzini #include "ui/console.h"
428ecbaeeSPaolo Bonzini 
528ecbaeeSPaolo Bonzini #include "cursor_hidden.xpm"
628ecbaeeSPaolo Bonzini #include "cursor_left_ptr.xpm"
728ecbaeeSPaolo Bonzini 
828ecbaeeSPaolo Bonzini /* for creating built-in cursors */
928ecbaeeSPaolo Bonzini static QEMUCursor *cursor_parse_xpm(const char *xpm[])
1028ecbaeeSPaolo Bonzini {
1128ecbaeeSPaolo Bonzini     QEMUCursor *c;
1228ecbaeeSPaolo Bonzini     uint32_t ctab[128];
1328ecbaeeSPaolo Bonzini     unsigned int width, height, colors, chars;
1428ecbaeeSPaolo Bonzini     unsigned int line = 0, i, r, g, b, x, y, pixel;
1528ecbaeeSPaolo Bonzini     char name[16];
1628ecbaeeSPaolo Bonzini     uint8_t idx;
1728ecbaeeSPaolo Bonzini 
1828ecbaeeSPaolo Bonzini     /* parse header line: width, height, #colors, #chars */
1928ecbaeeSPaolo Bonzini     if (sscanf(xpm[line], "%u %u %u %u",
2028ecbaeeSPaolo Bonzini                &width, &height, &colors, &chars) != 4) {
2128ecbaeeSPaolo Bonzini         fprintf(stderr, "%s: header parse error: \"%s\"\n",
2228ecbaeeSPaolo Bonzini                 __FUNCTION__, xpm[line]);
2328ecbaeeSPaolo Bonzini         return NULL;
2428ecbaeeSPaolo Bonzini     }
2528ecbaeeSPaolo Bonzini     if (chars != 1) {
2628ecbaeeSPaolo Bonzini         fprintf(stderr, "%s: chars != 1 not supported\n", __FUNCTION__);
2728ecbaeeSPaolo Bonzini         return NULL;
2828ecbaeeSPaolo Bonzini     }
2928ecbaeeSPaolo Bonzini     line++;
3028ecbaeeSPaolo Bonzini 
3128ecbaeeSPaolo Bonzini     /* parse color table */
3228ecbaeeSPaolo Bonzini     for (i = 0; i < colors; i++, line++) {
3328ecbaeeSPaolo Bonzini         if (sscanf(xpm[line], "%c c %15s", &idx, name) == 2) {
3428ecbaeeSPaolo Bonzini             if (sscanf(name, "#%02x%02x%02x", &r, &g, &b) == 3) {
3528ecbaeeSPaolo Bonzini                 ctab[idx] = (0xff << 24) | (b << 16) | (g << 8) | r;
3628ecbaeeSPaolo Bonzini                 continue;
3728ecbaeeSPaolo Bonzini             }
3828ecbaeeSPaolo Bonzini             if (strcmp(name, "None") == 0) {
3928ecbaeeSPaolo Bonzini                 ctab[idx] = 0x00000000;
4028ecbaeeSPaolo Bonzini                 continue;
4128ecbaeeSPaolo Bonzini             }
4228ecbaeeSPaolo Bonzini         }
4328ecbaeeSPaolo Bonzini         fprintf(stderr, "%s: color parse error: \"%s\"\n",
4428ecbaeeSPaolo Bonzini                 __FUNCTION__, xpm[line]);
4528ecbaeeSPaolo Bonzini         return NULL;
4628ecbaeeSPaolo Bonzini     }
4728ecbaeeSPaolo Bonzini 
4828ecbaeeSPaolo Bonzini     /* parse pixel data */
4928ecbaeeSPaolo Bonzini     c = cursor_alloc(width, height);
5028ecbaeeSPaolo Bonzini     for (pixel = 0, y = 0; y < height; y++, line++) {
5128ecbaeeSPaolo Bonzini         for (x = 0; x < height; x++, pixel++) {
5228ecbaeeSPaolo Bonzini             idx = xpm[line][x];
5328ecbaeeSPaolo Bonzini             c->data[pixel] = ctab[idx];
5428ecbaeeSPaolo Bonzini         }
5528ecbaeeSPaolo Bonzini     }
5628ecbaeeSPaolo Bonzini     return c;
5728ecbaeeSPaolo Bonzini }
5828ecbaeeSPaolo Bonzini 
5928ecbaeeSPaolo Bonzini /* nice for debugging */
6028ecbaeeSPaolo Bonzini void cursor_print_ascii_art(QEMUCursor *c, const char *prefix)
6128ecbaeeSPaolo Bonzini {
6228ecbaeeSPaolo Bonzini     uint32_t *data = c->data;
6328ecbaeeSPaolo Bonzini     int x,y;
6428ecbaeeSPaolo Bonzini 
6528ecbaeeSPaolo Bonzini     for (y = 0; y < c->height; y++) {
6628ecbaeeSPaolo Bonzini         fprintf(stderr, "%s: %2d: |", prefix, y);
6728ecbaeeSPaolo Bonzini         for (x = 0; x < c->width; x++, data++) {
6828ecbaeeSPaolo Bonzini             if ((*data & 0xff000000) != 0xff000000) {
6928ecbaeeSPaolo Bonzini                 fprintf(stderr, " "); /* transparent */
7028ecbaeeSPaolo Bonzini             } else if ((*data & 0x00ffffff) == 0x00ffffff) {
7128ecbaeeSPaolo Bonzini                 fprintf(stderr, "."); /* white */
7228ecbaeeSPaolo Bonzini             } else if ((*data & 0x00ffffff) == 0x00000000) {
7328ecbaeeSPaolo Bonzini                 fprintf(stderr, "X"); /* black */
7428ecbaeeSPaolo Bonzini             } else {
7528ecbaeeSPaolo Bonzini                 fprintf(stderr, "o"); /* other */
7628ecbaeeSPaolo Bonzini             }
7728ecbaeeSPaolo Bonzini         }
7828ecbaeeSPaolo Bonzini         fprintf(stderr, "|\n");
7928ecbaeeSPaolo Bonzini     }
8028ecbaeeSPaolo Bonzini }
8128ecbaeeSPaolo Bonzini 
8228ecbaeeSPaolo Bonzini QEMUCursor *cursor_builtin_hidden(void)
8328ecbaeeSPaolo Bonzini {
8428ecbaeeSPaolo Bonzini     QEMUCursor *c;
8528ecbaeeSPaolo Bonzini 
8628ecbaeeSPaolo Bonzini     c = cursor_parse_xpm(cursor_hidden_xpm);
8728ecbaeeSPaolo Bonzini     return c;
8828ecbaeeSPaolo Bonzini }
8928ecbaeeSPaolo Bonzini 
9028ecbaeeSPaolo Bonzini QEMUCursor *cursor_builtin_left_ptr(void)
9128ecbaeeSPaolo Bonzini {
9228ecbaeeSPaolo Bonzini     QEMUCursor *c;
9328ecbaeeSPaolo Bonzini 
9428ecbaeeSPaolo Bonzini     c = cursor_parse_xpm(cursor_left_ptr_xpm);
9528ecbaeeSPaolo Bonzini     return c;
9628ecbaeeSPaolo Bonzini }
9728ecbaeeSPaolo Bonzini 
9828ecbaeeSPaolo Bonzini QEMUCursor *cursor_alloc(int width, int height)
9928ecbaeeSPaolo Bonzini {
10028ecbaeeSPaolo Bonzini     QEMUCursor *c;
10128ecbaeeSPaolo Bonzini     int datasize = width * height * sizeof(uint32_t);
10228ecbaeeSPaolo Bonzini 
10328ecbaeeSPaolo Bonzini     c = g_malloc0(sizeof(QEMUCursor) + datasize);
10428ecbaeeSPaolo Bonzini     c->width  = width;
10528ecbaeeSPaolo Bonzini     c->height = height;
10628ecbaeeSPaolo Bonzini     c->refcount = 1;
10728ecbaeeSPaolo Bonzini     return c;
10828ecbaeeSPaolo Bonzini }
10928ecbaeeSPaolo Bonzini 
11028ecbaeeSPaolo Bonzini void cursor_get(QEMUCursor *c)
11128ecbaeeSPaolo Bonzini {
11228ecbaeeSPaolo Bonzini     c->refcount++;
11328ecbaeeSPaolo Bonzini }
11428ecbaeeSPaolo Bonzini 
11528ecbaeeSPaolo Bonzini void cursor_put(QEMUCursor *c)
11628ecbaeeSPaolo Bonzini {
11728ecbaeeSPaolo Bonzini     if (c == NULL)
11828ecbaeeSPaolo Bonzini         return;
11928ecbaeeSPaolo Bonzini     c->refcount--;
12028ecbaeeSPaolo Bonzini     if (c->refcount)
12128ecbaeeSPaolo Bonzini         return;
12228ecbaeeSPaolo Bonzini     g_free(c);
12328ecbaeeSPaolo Bonzini }
12428ecbaeeSPaolo Bonzini 
12528ecbaeeSPaolo Bonzini int cursor_get_mono_bpl(QEMUCursor *c)
12628ecbaeeSPaolo Bonzini {
12728ecbaeeSPaolo Bonzini     return (c->width + 7) / 8;
12828ecbaeeSPaolo Bonzini }
12928ecbaeeSPaolo Bonzini 
13028ecbaeeSPaolo Bonzini void cursor_set_mono(QEMUCursor *c,
13128ecbaeeSPaolo Bonzini                      uint32_t foreground, uint32_t background, uint8_t *image,
13228ecbaeeSPaolo Bonzini                      int transparent, uint8_t *mask)
13328ecbaeeSPaolo Bonzini {
13428ecbaeeSPaolo Bonzini     uint32_t *data = c->data;
13528ecbaeeSPaolo Bonzini     uint8_t bit;
13628ecbaeeSPaolo Bonzini     int x,y,bpl;
13728ecbaeeSPaolo Bonzini 
13828ecbaeeSPaolo Bonzini     bpl = cursor_get_mono_bpl(c);
13928ecbaeeSPaolo Bonzini     for (y = 0; y < c->height; y++) {
14028ecbaeeSPaolo Bonzini         bit = 0x80;
14128ecbaeeSPaolo Bonzini         for (x = 0; x < c->width; x++, data++) {
14228ecbaeeSPaolo Bonzini             if (transparent && mask[x/8] & bit) {
14328ecbaeeSPaolo Bonzini                 *data = 0x00000000;
14428ecbaeeSPaolo Bonzini             } else if (!transparent && !(mask[x/8] & bit)) {
14528ecbaeeSPaolo Bonzini                 *data = 0x00000000;
14628ecbaeeSPaolo Bonzini             } else if (image[x/8] & bit) {
14728ecbaeeSPaolo Bonzini                 *data = 0xff000000 | foreground;
14828ecbaeeSPaolo Bonzini             } else {
14928ecbaeeSPaolo Bonzini                 *data = 0xff000000 | background;
15028ecbaeeSPaolo Bonzini             }
15128ecbaeeSPaolo Bonzini             bit >>= 1;
15228ecbaeeSPaolo Bonzini             if (bit == 0) {
15328ecbaeeSPaolo Bonzini                 bit = 0x80;
15428ecbaeeSPaolo Bonzini             }
15528ecbaeeSPaolo Bonzini         }
15628ecbaeeSPaolo Bonzini         mask  += bpl;
15728ecbaeeSPaolo Bonzini         image += bpl;
15828ecbaeeSPaolo Bonzini     }
15928ecbaeeSPaolo Bonzini }
16028ecbaeeSPaolo Bonzini 
16128ecbaeeSPaolo Bonzini void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *image)
16228ecbaeeSPaolo Bonzini {
16328ecbaeeSPaolo Bonzini     uint32_t *data = c->data;
16428ecbaeeSPaolo Bonzini     uint8_t bit;
16528ecbaeeSPaolo Bonzini     int x,y,bpl;
16628ecbaeeSPaolo Bonzini 
16728ecbaeeSPaolo Bonzini     bpl = cursor_get_mono_bpl(c);
16828ecbaeeSPaolo Bonzini     memset(image, 0, bpl * c->height);
16928ecbaeeSPaolo Bonzini     for (y = 0; y < c->height; y++) {
17028ecbaeeSPaolo Bonzini         bit = 0x80;
17128ecbaeeSPaolo Bonzini         for (x = 0; x < c->width; x++, data++) {
17228ecbaeeSPaolo Bonzini             if (((*data & 0xff000000) == 0xff000000) &&
17328ecbaeeSPaolo Bonzini                 ((*data & 0x00ffffff) == foreground)) {
17428ecbaeeSPaolo Bonzini                 image[x/8] |= bit;
17528ecbaeeSPaolo Bonzini             }
17628ecbaeeSPaolo Bonzini             bit >>= 1;
17728ecbaeeSPaolo Bonzini             if (bit == 0) {
17828ecbaeeSPaolo Bonzini                 bit = 0x80;
17928ecbaeeSPaolo Bonzini             }
18028ecbaeeSPaolo Bonzini         }
18128ecbaeeSPaolo Bonzini         image += bpl;
18228ecbaeeSPaolo Bonzini     }
18328ecbaeeSPaolo Bonzini }
18428ecbaeeSPaolo Bonzini 
18528ecbaeeSPaolo Bonzini void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask)
18628ecbaeeSPaolo Bonzini {
18728ecbaeeSPaolo Bonzini     uint32_t *data = c->data;
18828ecbaeeSPaolo Bonzini     uint8_t bit;
18928ecbaeeSPaolo Bonzini     int x,y,bpl;
19028ecbaeeSPaolo Bonzini 
19128ecbaeeSPaolo Bonzini     bpl = cursor_get_mono_bpl(c);
19228ecbaeeSPaolo Bonzini     memset(mask, 0, bpl * c->height);
19328ecbaeeSPaolo Bonzini     for (y = 0; y < c->height; y++) {
19428ecbaeeSPaolo Bonzini         bit = 0x80;
19528ecbaeeSPaolo Bonzini         for (x = 0; x < c->width; x++, data++) {
19628ecbaeeSPaolo Bonzini             if ((*data & 0xff000000) != 0xff000000) {
19728ecbaeeSPaolo Bonzini                 if (transparent != 0) {
19828ecbaeeSPaolo Bonzini                     mask[x/8] |= bit;
19928ecbaeeSPaolo Bonzini                 }
20028ecbaeeSPaolo Bonzini             } else {
20128ecbaeeSPaolo Bonzini                 if (transparent == 0) {
20228ecbaeeSPaolo Bonzini                     mask[x/8] |= bit;
20328ecbaeeSPaolo Bonzini                 }
20428ecbaeeSPaolo Bonzini             }
20528ecbaeeSPaolo Bonzini             bit >>= 1;
20628ecbaeeSPaolo Bonzini             if (bit == 0) {
20728ecbaeeSPaolo Bonzini                 bit = 0x80;
20828ecbaeeSPaolo Bonzini             }
20928ecbaeeSPaolo Bonzini         }
21028ecbaeeSPaolo Bonzini         mask += bpl;
21128ecbaeeSPaolo Bonzini     }
21228ecbaeeSPaolo Bonzini }
213