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