1 #include "qemu/osdep.h" 2 #include "qemu-common.h" 3 #include "ui/console.h" 4 5 #include "cursor_hidden.xpm" 6 #include "cursor_left_ptr.xpm" 7 8 /* for creating built-in cursors */ 9 static QEMUCursor *cursor_parse_xpm(const char *xpm[]) 10 { 11 QEMUCursor *c; 12 uint32_t ctab[128]; 13 unsigned int width, height, colors, chars; 14 unsigned int line = 0, i, r, g, b, x, y, pixel; 15 char name[16]; 16 uint8_t idx; 17 18 /* parse header line: width, height, #colors, #chars */ 19 if (sscanf(xpm[line], "%u %u %u %u", 20 &width, &height, &colors, &chars) != 4) { 21 fprintf(stderr, "%s: header parse error: \"%s\"\n", 22 __func__, xpm[line]); 23 return NULL; 24 } 25 if (chars != 1) { 26 fprintf(stderr, "%s: chars != 1 not supported\n", __func__); 27 return NULL; 28 } 29 line++; 30 31 /* parse color table */ 32 for (i = 0; i < colors; i++, line++) { 33 if (sscanf(xpm[line], "%c c %15s", &idx, name) == 2) { 34 if (sscanf(name, "#%02x%02x%02x", &r, &g, &b) == 3) { 35 ctab[idx] = (0xff << 24) | (b << 16) | (g << 8) | r; 36 continue; 37 } 38 if (strcmp(name, "None") == 0) { 39 ctab[idx] = 0x00000000; 40 continue; 41 } 42 } 43 fprintf(stderr, "%s: color parse error: \"%s\"\n", 44 __func__, xpm[line]); 45 return NULL; 46 } 47 48 /* parse pixel data */ 49 c = cursor_alloc(width, height); 50 for (pixel = 0, y = 0; y < height; y++, line++) { 51 for (x = 0; x < height; x++, pixel++) { 52 idx = xpm[line][x]; 53 c->data[pixel] = ctab[idx]; 54 } 55 } 56 return c; 57 } 58 59 /* nice for debugging */ 60 void cursor_print_ascii_art(QEMUCursor *c, const char *prefix) 61 { 62 uint32_t *data = c->data; 63 int x,y; 64 65 for (y = 0; y < c->height; y++) { 66 fprintf(stderr, "%s: %2d: |", prefix, y); 67 for (x = 0; x < c->width; x++, data++) { 68 if ((*data & 0xff000000) != 0xff000000) { 69 fprintf(stderr, " "); /* transparent */ 70 } else if ((*data & 0x00ffffff) == 0x00ffffff) { 71 fprintf(stderr, "."); /* white */ 72 } else if ((*data & 0x00ffffff) == 0x00000000) { 73 fprintf(stderr, "X"); /* black */ 74 } else { 75 fprintf(stderr, "o"); /* other */ 76 } 77 } 78 fprintf(stderr, "|\n"); 79 } 80 } 81 82 QEMUCursor *cursor_builtin_hidden(void) 83 { 84 return cursor_parse_xpm(cursor_hidden_xpm); 85 } 86 87 QEMUCursor *cursor_builtin_left_ptr(void) 88 { 89 return cursor_parse_xpm(cursor_left_ptr_xpm); 90 } 91 92 QEMUCursor *cursor_alloc(int width, int height) 93 { 94 QEMUCursor *c; 95 int datasize = width * height * sizeof(uint32_t); 96 97 c = g_malloc0(sizeof(QEMUCursor) + datasize); 98 c->width = width; 99 c->height = height; 100 c->refcount = 1; 101 return c; 102 } 103 104 void cursor_get(QEMUCursor *c) 105 { 106 c->refcount++; 107 } 108 109 void cursor_put(QEMUCursor *c) 110 { 111 if (c == NULL) 112 return; 113 c->refcount--; 114 if (c->refcount) 115 return; 116 g_free(c); 117 } 118 119 int cursor_get_mono_bpl(QEMUCursor *c) 120 { 121 return DIV_ROUND_UP(c->width, 8); 122 } 123 124 void cursor_set_mono(QEMUCursor *c, 125 uint32_t foreground, uint32_t background, uint8_t *image, 126 int transparent, uint8_t *mask) 127 { 128 uint32_t *data = c->data; 129 uint8_t bit; 130 int x,y,bpl; 131 132 bpl = cursor_get_mono_bpl(c); 133 for (y = 0; y < c->height; y++) { 134 bit = 0x80; 135 for (x = 0; x < c->width; x++, data++) { 136 if (transparent && mask[x/8] & bit) { 137 *data = 0x00000000; 138 } else if (!transparent && !(mask[x/8] & bit)) { 139 *data = 0x00000000; 140 } else if (image[x/8] & bit) { 141 *data = 0xff000000 | foreground; 142 } else { 143 *data = 0xff000000 | background; 144 } 145 bit >>= 1; 146 if (bit == 0) { 147 bit = 0x80; 148 } 149 } 150 mask += bpl; 151 image += bpl; 152 } 153 } 154 155 void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *image) 156 { 157 uint32_t *data = c->data; 158 uint8_t bit; 159 int x,y,bpl; 160 161 bpl = cursor_get_mono_bpl(c); 162 memset(image, 0, bpl * c->height); 163 for (y = 0; y < c->height; y++) { 164 bit = 0x80; 165 for (x = 0; x < c->width; x++, data++) { 166 if (((*data & 0xff000000) == 0xff000000) && 167 ((*data & 0x00ffffff) == foreground)) { 168 image[x/8] |= bit; 169 } 170 bit >>= 1; 171 if (bit == 0) { 172 bit = 0x80; 173 } 174 } 175 image += bpl; 176 } 177 } 178 179 void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask) 180 { 181 uint32_t *data = c->data; 182 uint8_t bit; 183 int x,y,bpl; 184 185 bpl = cursor_get_mono_bpl(c); 186 memset(mask, 0, bpl * c->height); 187 for (y = 0; y < c->height; y++) { 188 bit = 0x80; 189 for (x = 0; x < c->width; x++, data++) { 190 if ((*data & 0xff000000) != 0xff000000) { 191 if (transparent != 0) { 192 mask[x/8] |= bit; 193 } 194 } else { 195 if (transparent == 0) { 196 mask[x/8] |= bit; 197 } 198 } 199 bit >>= 1; 200 if (bit == 0) { 201 bit = 0x80; 202 } 203 } 204 mask += bpl; 205 } 206 } 207