File: | cursor.c |
Location: | line 445, column 9 |
Description: | Assigned value is garbage or undefined |
1 | /* | |||
2 | * Copyright © 2002 Keith Packard | |||
3 | * | |||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | |||
5 | * documentation for any purpose is hereby granted without fee, provided that | |||
6 | * the above copyright notice appear in all copies and that both that | |||
7 | * copyright notice and this permission notice appear in supporting | |||
8 | * documentation, and that the name of Keith Packard not be used in | |||
9 | * advertising or publicity pertaining to distribution of the software without | |||
10 | * specific, written prior permission. Keith Packard makes no | |||
11 | * representations about the suitability of this software for any purpose. It | |||
12 | * is provided "as is" without express or implied warranty. | |||
13 | * | |||
14 | * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
16 | * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
20 | * PERFORMANCE OF THIS SOFTWARE. | |||
21 | */ | |||
22 | ||||
23 | #include "xcursorint.h" | |||
24 | #include <X11/Xlibint.h> | |||
25 | #include <X11/Xutil.h> | |||
26 | ||||
27 | XcursorCursors * | |||
28 | XcursorCursorsCreate (Display *dpy, int size) | |||
29 | { | |||
30 | XcursorCursors *cursors; | |||
31 | ||||
32 | cursors = malloc (sizeof (XcursorCursors) + | |||
33 | size * sizeof (Cursor)); | |||
34 | if (!cursors) | |||
35 | return NULL((void*)0); | |||
36 | cursors->ref = 1; | |||
37 | cursors->dpy = dpy; | |||
38 | cursors->ncursor = 0; | |||
39 | cursors->cursors = (Cursor *) (cursors + 1); | |||
40 | return cursors; | |||
41 | } | |||
42 | ||||
43 | void | |||
44 | XcursorCursorsDestroy (XcursorCursors *cursors) | |||
45 | { | |||
46 | int n; | |||
47 | ||||
48 | if (!cursors) | |||
49 | return; | |||
50 | ||||
51 | --cursors->ref; | |||
52 | if (cursors->ref > 0) | |||
53 | return; | |||
54 | ||||
55 | for (n = 0; n < cursors->ncursor; n++) | |||
56 | XFreeCursor (cursors->dpy, cursors->cursors[n]); | |||
57 | free (cursors); | |||
58 | } | |||
59 | ||||
60 | XcursorAnimate * | |||
61 | XcursorAnimateCreate (XcursorCursors *cursors) | |||
62 | { | |||
63 | XcursorAnimate *animate; | |||
64 | ||||
65 | animate = malloc (sizeof (XcursorAnimate)); | |||
66 | if (!animate) | |||
67 | return NULL((void*)0); | |||
68 | animate->cursors = cursors; | |||
69 | cursors->ref++; | |||
70 | animate->sequence = 0; | |||
71 | return animate; | |||
72 | } | |||
73 | ||||
74 | void | |||
75 | XcursorAnimateDestroy (XcursorAnimate *animate) | |||
76 | { | |||
77 | if (!animate) | |||
78 | return; | |||
79 | ||||
80 | XcursorCursorsDestroy (animate->cursors); | |||
81 | free (animate); | |||
82 | } | |||
83 | ||||
84 | Cursor | |||
85 | XcursorAnimateNext (XcursorAnimate *animate) | |||
86 | { | |||
87 | Cursor cursor = animate->cursors->cursors[animate->sequence++]; | |||
88 | ||||
89 | if (animate->sequence >= animate->cursors->ncursor) | |||
90 | animate->sequence = 0; | |||
91 | return cursor; | |||
92 | } | |||
93 | ||||
94 | static int | |||
95 | nativeByteOrder (void) | |||
96 | { | |||
97 | int x = 1; | |||
98 | ||||
99 | return (*((char *) &x) == 1) ? LSBFirst0 : MSBFirst1; | |||
100 | } | |||
101 | ||||
102 | static XcursorUInt | |||
103 | _XcursorPixelBrightness (XcursorPixel p) | |||
104 | { | |||
105 | XcursorPixel alpha = p >> 24; | |||
106 | XcursorPixel r, g, b; | |||
107 | ||||
108 | if (!alpha) | |||
109 | return 0; | |||
110 | r = ((p >> 8) & 0xff00) / alpha; | |||
111 | if (r > 0xff) r = 0xff; | |||
112 | g = ((p >> 0) & 0xff00) / alpha; | |||
113 | if (g > 0xff) g = 0xff; | |||
114 | b = ((p << 8) & 0xff00) / alpha; | |||
115 | if (b > 0xff) b = 0xff; | |||
116 | return (r * 153 + g * 301 + b * 58) >> 9; | |||
117 | } | |||
118 | ||||
119 | static unsigned short | |||
120 | _XcursorDivideAlpha (XcursorUInt value, XcursorUInt alpha) | |||
121 | { | |||
122 | if (!alpha) | |||
123 | return 0; | |||
124 | value = value * 255 / alpha; | |||
125 | if (value > 255) | |||
126 | value = 255; | |||
127 | return value | (value << 8); | |||
128 | } | |||
129 | ||||
130 | static void | |||
131 | _XcursorPixelToColor (XcursorPixel p, XColor *color) | |||
132 | { | |||
133 | XcursorPixel alpha = p >> 24; | |||
134 | ||||
135 | color->pixel = 0; | |||
136 | color->red = _XcursorDivideAlpha ((p >> 16) & 0xff, alpha); | |||
137 | color->green = _XcursorDivideAlpha ((p >> 8) & 0xff, alpha); | |||
138 | color->blue = _XcursorDivideAlpha ((p >> 0) & 0xff, alpha); | |||
139 | color->flags = DoRed(1<<0)|DoGreen(1<<1)|DoBlue(1<<2); | |||
140 | } | |||
141 | ||||
142 | #undef DEBUG_IMAGE | |||
143 | #ifdef DEBUG_IMAGE | |||
144 | static void | |||
145 | _XcursorDumpImage (XImage *image) | |||
146 | { | |||
147 | FILE *f = fopen ("/tmp/images", "a"); | |||
148 | int x, y; | |||
149 | if (!f) | |||
150 | return; | |||
151 | fprintf (f, "%d x %x\n", image->width, image->height); | |||
152 | for (y = 0; y < image->height; y++) | |||
153 | { | |||
154 | for (x = 0; x < image->width; x++) | |||
155 | fprintf (f, "%c", XGetPixel (image, x, y)((*((image)->f.get_pixel))((image), (x), (y))) ? '*' : ' '); | |||
156 | fprintf (f, "\n"); | |||
157 | } | |||
158 | fflush (f); | |||
159 | fclose (f); | |||
160 | } | |||
161 | ||||
162 | static void | |||
163 | _XcursorDumpColor (XColor *color, char *name) | |||
164 | { | |||
165 | FILE *f = fopen ("/tmp/images", "a"); | |||
166 | fprintf (f, "%s: %x %x %x\n", name, | |||
167 | color->red, color->green, color->blue); | |||
168 | fflush (f); | |||
169 | fclose (f); | |||
170 | } | |||
171 | #endif | |||
172 | ||||
173 | static int | |||
174 | _XcursorCompareRed (const void *a, const void *b) | |||
175 | { | |||
176 | const XcursorPixel *ap = a, *bp = b; | |||
177 | ||||
178 | return (int) (((*ap >> 16) & 0xff) - ((*bp >> 16) & 0xff)); | |||
179 | } | |||
180 | ||||
181 | static int | |||
182 | _XcursorCompareGreen (const void *a, const void *b) | |||
183 | { | |||
184 | const XcursorPixel *ap = a, *bp = b; | |||
185 | ||||
186 | return (int) (((*ap >> 8) & 0xff) - ((*bp >> 8) & 0xff)); | |||
187 | } | |||
188 | ||||
189 | static int | |||
190 | _XcursorCompareBlue (const void *a, const void *b) | |||
191 | { | |||
192 | const XcursorPixel *ap = a, *bp = b; | |||
193 | ||||
194 | return (int) (((*ap >> 0) & 0xff) - ((*bp >> 0) & 0xff)); | |||
195 | } | |||
196 | ||||
197 | static XcursorPixel | |||
198 | _XcursorAverageColor (XcursorPixel *pixels, int npixels) | |||
199 | { | |||
200 | XcursorPixel p; | |||
201 | XcursorPixel red, green, blue; | |||
202 | int n = npixels; | |||
203 | ||||
204 | if (n < 1) | |||
205 | return 0; | |||
206 | ||||
207 | blue = green = red = 0; | |||
208 | while (n--) | |||
209 | { | |||
210 | p = *pixels++; | |||
211 | red += (p >> 16) & 0xff; | |||
212 | green += (p >> 8) & 0xff; | |||
213 | blue += (p >> 0) & 0xff; | |||
214 | } | |||
215 | return (0xffU << 24) | ((red/npixels) << 16) | ((green/npixels) << 8) | (blue/npixels); | |||
216 | } | |||
217 | ||||
218 | typedef struct XcursorCoreCursor { | |||
219 | XImage *src_image; | |||
220 | XImage *msk_image; | |||
221 | XColor on_color; | |||
222 | XColor off_color; | |||
223 | } XcursorCoreCursor; | |||
224 | ||||
225 | static Boolint | |||
226 | _XcursorHeckbertMedianCut (const XcursorImage *image, XcursorCoreCursor *core) | |||
227 | { | |||
228 | XImage *src_image = core->src_image, *msk_image = core->msk_image; | |||
229 | unsigned int npixels = image->width * image->height; | |||
230 | int ncolors; | |||
231 | int n; | |||
232 | XcursorPixel *po, *pn, *pc; | |||
233 | XcursorPixel p; | |||
234 | XcursorPixel red, green, blue, alpha; | |||
235 | XcursorPixel max_red, min_red, max_green, min_green, max_blue, min_blue; | |||
236 | XcursorPixel *temp, *pixels, *colors; | |||
237 | int split; | |||
238 | XcursorPixel leftColor, centerColor, rightColor; | |||
239 | int (*compare) (const void *, const void *); | |||
240 | int x, y; | |||
241 | ||||
242 | /* | |||
243 | * Temp space for converted image and converted colors | |||
244 | */ | |||
245 | temp = malloc (npixels * sizeof (XcursorPixel) * 2); | |||
246 | if (!temp) | |||
247 | return False0; | |||
248 | ||||
249 | pixels = temp; | |||
250 | colors = pixels + npixels; | |||
251 | ||||
252 | /* | |||
253 | * Convert to 2-value alpha and build | |||
254 | * array of opaque color values and an | |||
255 | */ | |||
256 | po = image->pixels; | |||
257 | pn = pixels; | |||
258 | pc = colors; | |||
259 | max_blue = max_green = max_red = 0; | |||
260 | min_blue = min_green = min_red = 255; | |||
261 | n = npixels; | |||
262 | while (n--) | |||
263 | { | |||
264 | p = *po++; | |||
265 | alpha = (p >> 24) & 0xff; | |||
266 | red = (p >> 16) & 0xff; | |||
267 | green = (p >> 8) & 0xff; | |||
268 | blue = (p >> 0) & 0xff; | |||
269 | if (alpha >= 0x80) | |||
270 | { | |||
271 | red = red * 255 / alpha; | |||
272 | green = green * 255 / alpha; | |||
273 | blue = blue * 255 / alpha; | |||
274 | if (red < min_red) min_red = red; | |||
275 | if (red > max_red) max_red = red; | |||
276 | if (green < min_green) min_green = green; | |||
277 | if (green > max_green) max_green = green; | |||
278 | if (blue < min_blue) min_blue = blue; | |||
279 | if (blue > max_blue) max_blue = blue; | |||
280 | p = ((0xffU << 24) | (red << 16) | | |||
281 | (green << 8) | (blue << 0)); | |||
282 | *pc++ = p; | |||
283 | } | |||
284 | else | |||
285 | p = 0; | |||
286 | *pn++ = p; | |||
287 | } | |||
288 | ncolors = pc - colors; | |||
289 | ||||
290 | /* | |||
291 | * Compute longest dimension and sort | |||
292 | */ | |||
293 | if ((max_green - min_green) >= (max_red - min_red) && | |||
294 | (max_green - min_green) >= (max_blue - min_blue)) | |||
295 | compare = _XcursorCompareGreen; | |||
296 | else if ((max_red - min_red) >= (max_blue - min_blue)) | |||
297 | compare = _XcursorCompareRed; | |||
298 | else | |||
299 | compare = _XcursorCompareBlue; | |||
300 | qsort (colors, ncolors, sizeof (XcursorPixel), compare); | |||
301 | /* | |||
302 | * Compute average colors on both sides of the cut | |||
303 | */ | |||
304 | split = ncolors >> 1; | |||
305 | leftColor = _XcursorAverageColor (colors, split); | |||
306 | centerColor = colors[split]; | |||
307 | rightColor = _XcursorAverageColor (colors + split, ncolors - split); | |||
308 | /* | |||
309 | * Select best color for each pixel | |||
310 | */ | |||
311 | pn = pixels; | |||
312 | for (y = 0; y < image->height; y++) | |||
313 | for (x = 0; x < image->width; x++) | |||
314 | { | |||
315 | p = *pn++; | |||
316 | if (p & 0xff000000) | |||
317 | { | |||
318 | XPutPixel (msk_image, x, y, 1)((*((msk_image)->f.put_pixel))((msk_image), (x), (y), (1)) ); | |||
319 | if ((*compare) (&p, ¢erColor) >= 0) | |||
320 | XPutPixel (src_image, x, y, 0)((*((src_image)->f.put_pixel))((src_image), (x), (y), (0)) ); | |||
321 | else | |||
322 | XPutPixel (src_image, x, y, 1)((*((src_image)->f.put_pixel))((src_image), (x), (y), (1)) ); | |||
323 | } | |||
324 | else | |||
325 | { | |||
326 | XPutPixel (msk_image, x, y, 0)((*((msk_image)->f.put_pixel))((msk_image), (x), (y), (0)) ); | |||
327 | XPutPixel (src_image, x, y, 0)((*((src_image)->f.put_pixel))((src_image), (x), (y), (0)) ); | |||
328 | } | |||
329 | } | |||
330 | free (temp); | |||
331 | _XcursorPixelToColor (rightColor, &core->off_color); | |||
332 | _XcursorPixelToColor (leftColor, &core->on_color); | |||
333 | return True1; | |||
334 | } | |||
335 | ||||
336 | #if 0 | |||
337 | #define DITHER_DIM2 4 | |||
338 | static XcursorPixel orderedDither[4][4] = { | |||
339 | { 1, 9, 3, 11 }, | |||
340 | { 13, 5, 15, 7 }, | |||
341 | { 4, 12, 2, 10 }, | |||
342 | { 16, 8, 14, 6 } | |||
343 | }; | |||
344 | #else | |||
345 | #define DITHER_DIM2 2 | |||
346 | static XcursorPixel orderedDither[2][2] = { | |||
347 | { 1, 3, }, | |||
348 | { 4, 2, }, | |||
349 | }; | |||
350 | #endif | |||
351 | ||||
352 | #define DITHER_SIZE((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) | |||
353 | ||||
354 | static Boolint | |||
355 | _XcursorBayerOrderedDither (const XcursorImage *image, XcursorCoreCursor *core) | |||
356 | { | |||
357 | int x, y; | |||
358 | XcursorPixel *pixel, p; | |||
359 | XcursorPixel a, i, d; | |||
360 | ||||
361 | pixel = image->pixels; | |||
362 | for (y = 0; y < image->height; y++) | |||
363 | for (x = 0; x < image->width; x++) | |||
364 | { | |||
365 | p = *pixel++; | |||
366 | a = ((p >> 24) * DITHER_SIZE((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + 127) / 255; | |||
367 | i = (_XcursorPixelBrightness (p) * DITHER_SIZE((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + 127) / 255; | |||
368 | d = orderedDither[y&(DITHER_DIM2-1)][x&(DITHER_DIM2-1)]; | |||
369 | if (a > d) | |||
370 | { | |||
371 | XPutPixel (core->msk_image, x, y, 1)((*((core->msk_image)->f.put_pixel))((core->msk_image ), (x), (y), (1))); | |||
372 | if (i > d) | |||
373 | XPutPixel (core->src_image, x, y, 0)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (0))); /* white */ | |||
374 | else | |||
375 | XPutPixel (core->src_image, x, y, 1)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (1))); /* black */ | |||
376 | } | |||
377 | else | |||
378 | { | |||
379 | XPutPixel (core->msk_image, x, y, 0)((*((core->msk_image)->f.put_pixel))((core->msk_image ), (x), (y), (0))); | |||
380 | XPutPixel (core->src_image, x, y, 0)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (0))); | |||
381 | } | |||
382 | } | |||
383 | core->on_color.red = 0; | |||
384 | core->on_color.green = 0; | |||
385 | core->on_color.blue = 0; | |||
386 | core->off_color.red = 0xffff; | |||
387 | core->off_color.green = 0xffff; | |||
388 | core->off_color.blue = 0xffff; | |||
389 | return True1; | |||
390 | } | |||
391 | ||||
392 | static Boolint | |||
393 | _XcursorFloydSteinberg (const XcursorImage *image, XcursorCoreCursor *core) | |||
394 | { | |||
395 | int *aPicture, *iPicture, *aP, *iP; | |||
396 | XcursorPixel *pixel, p; | |||
397 | int aR, iR, aA, iA; | |||
398 | unsigned int npixels = image->width * image->height; | |||
399 | int n; | |||
400 | int right = 1; | |||
401 | int belowLeft = image->width - 1; | |||
402 | int below = image->width; | |||
403 | int belowRight = image->width + 1; | |||
404 | int iError, aError; | |||
405 | int iErrorRight, aErrorRight; | |||
406 | int iErrorBelowLeft, aErrorBelowLeft; | |||
407 | int iErrorBelow, aErrorBelow; | |||
408 | int iErrorBelowRight, aErrorBelowRight; | |||
409 | int x, y; | |||
410 | int max_inten, min_inten, mean_inten; | |||
411 | ||||
412 | iPicture = malloc (npixels * sizeof (int) * 2); | |||
413 | if (!iPicture) | |||
414 | return False0; | |||
415 | aPicture = iPicture + npixels; | |||
416 | ||||
417 | /* | |||
418 | * Compute raw gray and alpha arrays | |||
419 | */ | |||
420 | pixel = image->pixels; | |||
421 | iP = iPicture; | |||
422 | aP = aPicture; | |||
423 | n = npixels; | |||
424 | max_inten = 0; | |||
425 | min_inten = 0xff; | |||
426 | while (n--) | |||
427 | { | |||
428 | p = *pixel++; | |||
429 | *aP++ = (int) (p >> 24); | |||
430 | iR = (int) _XcursorPixelBrightness (p); | |||
431 | if (iR > max_inten) max_inten = iR; | |||
432 | if (iR < min_inten) min_inten = iR; | |||
433 | *iP++ = iR; | |||
434 | } | |||
435 | /* | |||
436 | * Draw the image while diffusing the error | |||
437 | */ | |||
438 | iP = iPicture; | |||
439 | aP = aPicture; | |||
440 | mean_inten = (max_inten + min_inten + 1) >> 1; | |||
441 | for (y = 0; y < image->height; y++) | |||
442 | for (x = 0; x < image->width; x++) | |||
443 | { | |||
444 | aR = *aP; | |||
445 | iR = *iP; | |||
| ||||
446 | if (aR >= 0x80) | |||
447 | { | |||
448 | XPutPixel (core->msk_image, x, y, 1)((*((core->msk_image)->f.put_pixel))((core->msk_image ), (x), (y), (1))); | |||
449 | aA = 0xff; | |||
450 | } | |||
451 | else | |||
452 | { | |||
453 | XPutPixel (core->msk_image, x, y, 0)((*((core->msk_image)->f.put_pixel))((core->msk_image ), (x), (y), (0))); | |||
454 | aA = 0x00; | |||
455 | } | |||
456 | if (iR >= mean_inten) | |||
457 | { | |||
458 | XPutPixel (core->src_image, x, y, 0)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (0))); | |||
459 | iA = max_inten; | |||
460 | } | |||
461 | else | |||
462 | { | |||
463 | XPutPixel (core->src_image, x, y, 1)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (1))); | |||
464 | iA = min_inten; | |||
465 | } | |||
466 | iError = iR - iA; | |||
467 | aError = aR - aA; | |||
468 | iErrorRight = (iError * 7) >> 4; | |||
469 | iErrorBelowLeft = (iError * 3) >> 4; | |||
470 | iErrorBelow = (iError * 5) >> 4; | |||
471 | iErrorBelowRight = (iError - iErrorRight - | |||
472 | iErrorBelowLeft - iErrorBelow); | |||
473 | aErrorRight = (aError * 7) >> 4; | |||
474 | aErrorBelowLeft = (aError * 3) >> 4; | |||
475 | aErrorBelow = (aError * 5) >> 4; | |||
476 | aErrorBelowRight = (aError - aErrorRight - | |||
477 | aErrorBelowLeft - aErrorBelow); | |||
478 | if (x < image->width - 1) | |||
479 | { | |||
480 | iP[right] += iErrorRight; | |||
481 | aP[right] += aErrorRight; | |||
482 | } | |||
483 | if (y < image->height - 1) | |||
484 | { | |||
485 | if (x) | |||
486 | { | |||
487 | iP[belowLeft] += iErrorBelowLeft; | |||
488 | aP[belowLeft] += aErrorBelowLeft; | |||
489 | } | |||
490 | iP[below] += iErrorBelow; | |||
491 | aP[below] += aErrorBelow; | |||
492 | if (x < image->width - 1) | |||
493 | { | |||
494 | iP[belowRight] += iErrorBelowRight; | |||
495 | aP[belowRight] += aErrorBelowRight; | |||
496 | } | |||
497 | } | |||
498 | aP++; | |||
499 | iP++; | |||
500 | } | |||
501 | free (iPicture); | |||
502 | core->on_color.red = | |||
503 | core->on_color.green = | |||
504 | core->on_color.blue = (min_inten | min_inten << 8); | |||
505 | core->off_color.red = | |||
506 | core->off_color.green = | |||
507 | core->off_color.blue = (max_inten | max_inten << 8); | |||
508 | return True1; | |||
509 | } | |||
510 | ||||
511 | static Boolint | |||
512 | _XcursorThreshold (const XcursorImage *image, XcursorCoreCursor *core) | |||
513 | { | |||
514 | XcursorPixel *pixel, p; | |||
515 | int x, y; | |||
516 | ||||
517 | /* | |||
518 | * Draw the image, picking black for dark pixels and white for light | |||
519 | */ | |||
520 | pixel = image->pixels; | |||
521 | for (y = 0; y < image->height; y++) | |||
522 | for (x = 0; x < image->width; x++) | |||
523 | { | |||
524 | p = *pixel++; | |||
525 | if ((p >> 24) >= 0x80) | |||
526 | { | |||
527 | XPutPixel (core->msk_image, x, y, 1)((*((core->msk_image)->f.put_pixel))((core->msk_image ), (x), (y), (1))); | |||
528 | if (_XcursorPixelBrightness (p) > 0x80) | |||
529 | XPutPixel (core->src_image, x, y, 0)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (0))); | |||
530 | else | |||
531 | XPutPixel (core->src_image, x, y, 1)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (1))); | |||
532 | } | |||
533 | else | |||
534 | { | |||
535 | XPutPixel (core->msk_image, x, y, 0)((*((core->msk_image)->f.put_pixel))((core->msk_image ), (x), (y), (0))); | |||
536 | XPutPixel (core->src_image, x, y, 0)((*((core->src_image)->f.put_pixel))((core->src_image ), (x), (y), (0))); | |||
537 | } | |||
538 | } | |||
539 | core->on_color.red = | |||
540 | core->on_color.green = | |||
541 | core->on_color.blue = 0; | |||
542 | core->off_color.red = | |||
543 | core->off_color.green = | |||
544 | core->off_color.blue = 0xffff; | |||
545 | return True1; | |||
546 | } | |||
547 | ||||
548 | Cursor | |||
549 | XcursorImageLoadCursor (Display *dpy, const XcursorImage *image) | |||
550 | { | |||
551 | Cursor cursor; | |||
552 | ||||
553 | #if RENDER_MAJOR0 > 0 || RENDER_MINOR11 >= 5 | |||
554 | if (XcursorSupportsARGB (dpy)) | |||
555 | { | |||
556 | XImage ximage; | |||
557 | int screen = DefaultScreen (dpy)(((_XPrivDisplay)(dpy))->default_screen); | |||
558 | Pixmap pixmap; | |||
559 | Picture picture; | |||
560 | GC gc; | |||
561 | XRenderPictFormat *format; | |||
562 | ||||
563 | ximage.width = image->width; | |||
564 | ximage.height = image->height; | |||
565 | ximage.xoffset = 0; | |||
566 | ximage.format = ZPixmap2; | |||
567 | ximage.data = (char *) image->pixels; | |||
568 | ximage.byte_order = nativeByteOrder (); | |||
569 | ximage.bitmap_unit = 32; | |||
570 | ximage.bitmap_bit_order = ximage.byte_order; | |||
571 | ximage.bitmap_pad = 32; | |||
572 | ximage.depth = 32; | |||
573 | ximage.bits_per_pixel = 32; | |||
574 | ximage.bytes_per_line = image->width * 4; | |||
575 | ximage.red_mask = 0xff0000; | |||
576 | ximage.green_mask = 0x00ff00; | |||
577 | ximage.blue_mask = 0x0000ff; | |||
578 | ximage.obdata = NULL((void*)0); | |||
579 | if (!XInitImage (&ximage)) | |||
580 | return None0L; | |||
581 | pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->root), | |||
582 | image->width, image->height, 32); | |||
583 | gc = XCreateGC (dpy, pixmap, 0, NULL((void*)0)); | |||
584 | XPutImage (dpy, pixmap, gc, &ximage, | |||
585 | 0, 0, 0, 0, image->width, image->height); | |||
586 | XFreeGC (dpy, gc); | |||
587 | format = XRenderFindStandardFormat (dpy, PictStandardARGB320); | |||
588 | picture = XRenderCreatePicture (dpy, pixmap, format, 0, NULL((void*)0)); | |||
589 | XFreePixmap (dpy, pixmap); | |||
590 | cursor = XRenderCreateCursor (dpy, picture, | |||
591 | image->xhot, image->yhot); | |||
592 | XRenderFreePicture (dpy, picture); | |||
593 | } | |||
594 | else | |||
595 | #endif | |||
596 | { | |||
597 | XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy); | |||
598 | int screen = DefaultScreen (dpy)(((_XPrivDisplay)(dpy))->default_screen); | |||
599 | XcursorCoreCursor core; | |||
600 | Pixmap src_pixmap, msk_pixmap; | |||
601 | GC gc; | |||
602 | XGCValues gcv; | |||
603 | ||||
604 | if (!info) | |||
605 | return 0; | |||
606 | ||||
607 | core.src_image = XCreateImage (dpy, NULL((void*)0), 1, ZPixmap2, | |||
608 | 0, NULL((void*)0), image->width, image->height, | |||
609 | 32, 0); | |||
610 | core.src_image->data = Xmalloc (image->height *malloc(((image->height * core.src_image->bytes_per_line ) == 0 ? 1 : (image->height * core.src_image->bytes_per_line ))) | |||
611 | core.src_image->bytes_per_line)malloc(((image->height * core.src_image->bytes_per_line ) == 0 ? 1 : (image->height * core.src_image->bytes_per_line ))); | |||
612 | core.msk_image = XCreateImage (dpy, NULL((void*)0), 1, ZPixmap2, | |||
613 | 0, NULL((void*)0), image->width, image->height, | |||
614 | 32, 0); | |||
615 | core.msk_image->data = Xmalloc (image->height *malloc(((image->height * core.msk_image->bytes_per_line ) == 0 ? 1 : (image->height * core.msk_image->bytes_per_line ))) | |||
616 | core.msk_image->bytes_per_line)malloc(((image->height * core.msk_image->bytes_per_line ) == 0 ? 1 : (image->height * core.msk_image->bytes_per_line ))); | |||
617 | ||||
618 | switch (info->dither) { | |||
619 | case XcursorDitherThreshold: | |||
620 | if (!_XcursorThreshold (image, &core)) | |||
621 | return 0; | |||
622 | break; | |||
623 | case XcursorDitherMedian: | |||
624 | if (!_XcursorHeckbertMedianCut (image, &core)) | |||
625 | return 0; | |||
626 | break; | |||
627 | case XcursorDitherOrdered: | |||
628 | if (!_XcursorBayerOrderedDither (image, &core)) | |||
629 | return 0; | |||
630 | break; | |||
631 | case XcursorDitherDiffuse: | |||
632 | if (!_XcursorFloydSteinberg (image, &core)) | |||
633 | return 0; | |||
634 | break; | |||
635 | default: | |||
636 | return 0; | |||
637 | } | |||
638 | ||||
639 | /* | |||
640 | * Create the cursor | |||
641 | */ | |||
642 | src_pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->root), | |||
643 | image->width, image->height, 1); | |||
644 | msk_pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->root), | |||
645 | image->width, image->height, 1); | |||
646 | gcv.foreground = 1; | |||
647 | gcv.background = 0; | |||
648 | gc = XCreateGC (dpy, src_pixmap, | |||
649 | GCForeground(1L<<2)|GCBackground(1L<<3), | |||
650 | &gcv); | |||
651 | XPutImage (dpy, src_pixmap, gc, core.src_image, | |||
652 | 0, 0, 0, 0, image->width, image->height); | |||
653 | ||||
654 | XPutImage (dpy, msk_pixmap, gc, core.msk_image, | |||
655 | 0, 0, 0, 0, image->width, image->height); | |||
656 | XFreeGC (dpy, gc); | |||
657 | ||||
658 | #ifdef DEBUG_IMAGE | |||
659 | _XcursorDumpColor (&core.on_color, "on_color"); | |||
660 | _XcursorDumpColor (&core.off_color, "off_color"); | |||
661 | _XcursorDumpImage (core.src_image); | |||
662 | _XcursorDumpImage (core.msk_image); | |||
663 | #endif | |||
664 | XDestroyImage (core.src_image)((*((core.src_image)->f.destroy_image))((core.src_image))); | |||
665 | XDestroyImage (core.msk_image)((*((core.msk_image)->f.destroy_image))((core.msk_image))); | |||
666 | ||||
667 | cursor = XCreatePixmapCursor (dpy, src_pixmap, msk_pixmap, | |||
668 | &core.on_color, &core.off_color, | |||
669 | image->xhot, image->yhot); | |||
670 | XFreePixmap (dpy, src_pixmap); | |||
671 | XFreePixmap (dpy, msk_pixmap); | |||
672 | } | |||
673 | return cursor; | |||
674 | } | |||
675 | ||||
676 | XcursorCursors * | |||
677 | XcursorImagesLoadCursors (Display *dpy, const XcursorImages *images) | |||
678 | { | |||
679 | XcursorCursors *cursors = XcursorCursorsCreate (dpy, images->nimage); | |||
680 | int n; | |||
681 | ||||
682 | if (!cursors) | |||
683 | return NULL((void*)0); | |||
684 | for (n = 0; n < images->nimage; n++) | |||
685 | { | |||
686 | cursors->cursors[n] = XcursorImageLoadCursor (dpy, images->images[n]); | |||
687 | if (!cursors->cursors[n]) | |||
688 | { | |||
689 | XcursorCursorsDestroy (cursors); | |||
690 | return NULL((void*)0); | |||
691 | } | |||
692 | cursors->ncursor++; | |||
693 | } | |||
694 | return cursors; | |||
695 | } | |||
696 | ||||
697 | Cursor | |||
698 | XcursorImagesLoadCursor (Display *dpy, const XcursorImages *images) | |||
699 | { | |||
700 | Cursor cursor; | |||
701 | if (images->nimage == 1 || !XcursorSupportsAnim (dpy)) | |||
702 | cursor = XcursorImageLoadCursor (dpy, images->images[0]); | |||
703 | else | |||
704 | { | |||
705 | XcursorCursors *cursors = XcursorImagesLoadCursors (dpy, images); | |||
706 | XAnimCursor *anim; | |||
707 | int n; | |||
708 | ||||
709 | if (!cursors) | |||
710 | return 0; | |||
711 | anim = malloc (cursors->ncursor * sizeof (XAnimCursor)); | |||
712 | if (!anim) | |||
713 | { | |||
714 | XcursorCursorsDestroy (cursors); | |||
715 | return 0; | |||
716 | } | |||
717 | for (n = 0; n < cursors->ncursor; n++) | |||
718 | { | |||
719 | anim[n].cursor = cursors->cursors[n]; | |||
720 | anim[n].delay = images->images[n]->delay; | |||
721 | } | |||
722 | cursor = XRenderCreateAnimCursor (dpy, cursors->ncursor, anim); | |||
723 | XcursorCursorsDestroy(cursors); | |||
724 | free (anim); | |||
725 | } | |||
726 | #if defined HAVE_XFIXES1 && XFIXES_MAJOR5 >= 2 | |||
727 | if (images->name) | |||
728 | XFixesSetCursorName (dpy, cursor, images->name); | |||
729 | #endif | |||
730 | return cursor; | |||
731 | } | |||
732 | ||||
733 | ||||
734 | Cursor | |||
735 | XcursorFilenameLoadCursor (Display *dpy, const char *file) | |||
736 | { | |||
737 | int size = XcursorGetDefaultSize (dpy); | |||
738 | XcursorImages *images = XcursorFilenameLoadImages (file, size); | |||
739 | Cursor cursor; | |||
740 | ||||
741 | if (!images) | |||
742 | return None0L; | |||
743 | cursor = XcursorImagesLoadCursor (dpy, images); | |||
744 | XcursorImagesDestroy (images); | |||
745 | return cursor; | |||
746 | } | |||
747 | ||||
748 | XcursorCursors * | |||
749 | XcursorFilenameLoadCursors (Display *dpy, const char *file) | |||
750 | { | |||
751 | int size = XcursorGetDefaultSize (dpy); | |||
752 | XcursorImages *images = XcursorFilenameLoadImages (file, size); | |||
753 | XcursorCursors *cursors; | |||
754 | ||||
755 | if (!images) | |||
| ||||
756 | return NULL((void*)0); | |||
757 | cursors = XcursorImagesLoadCursors (dpy, images); | |||
758 | XcursorImagesDestroy (images); | |||
759 | return cursors; | |||
760 | } | |||
761 | ||||
762 | /* | |||
763 | * Stolen from XCreateGlyphCursor (which we cruelly override) | |||
764 | */ | |||
765 | ||||
766 | Cursor | |||
767 | _XcursorCreateGlyphCursor(Display *dpy, | |||
768 | Font source_font, | |||
769 | Font mask_font, | |||
770 | unsigned int source_char, | |||
771 | unsigned int mask_char, | |||
772 | XColor _Xconstconst *foreground, | |||
773 | XColor _Xconstconst *background) | |||
774 | { | |||
775 | Cursor cid; | |||
776 | register xCreateGlyphCursorReq *req; | |||
777 | ||||
778 | LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display )(dpy); | |||
779 | GetReq(CreateGlyphCursor, req)req = (xCreateGlyphCursorReq *) _XGetRequest(dpy, 94, 32); | |||
780 | cid = req->cid = XAllocID(dpy)((*((_XPrivDisplay)(dpy))->resource_alloc)((dpy))); | |||
781 | req->source = source_font; | |||
782 | req->mask = mask_font; | |||
783 | req->sourceChar = source_char; | |||
784 | req->maskChar = mask_char; | |||
785 | req->foreRed = foreground->red; | |||
786 | req->foreGreen = foreground->green; | |||
787 | req->foreBlue = foreground->blue; | |||
788 | req->backRed = background->red; | |||
789 | req->backGreen = background->green; | |||
790 | req->backBlue = background->blue; | |||
791 | UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(dpy); | |||
792 | SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy); | |||
793 | return (cid); | |||
794 | } | |||
795 | ||||
796 | /* | |||
797 | * Stolen from XCreateFontCursor (which we cruelly override) | |||
798 | */ | |||
799 | ||||
800 | Cursor | |||
801 | _XcursorCreateFontCursor (Display *dpy, unsigned int shape) | |||
802 | { | |||
803 | static XColor _Xconstconst foreground = { 0, 0, 0, 0 }; /* black */ | |||
804 | static XColor _Xconstconst background = { 0, 65535, 65535, 65535 }; /* white */ | |||
805 | ||||
806 | /* | |||
807 | * the cursor font contains the shape glyph followed by the mask | |||
808 | * glyph; so character position 0 contains a shape, 1 the mask for 0, | |||
809 | * 2 a shape, etc. <X11/cursorfont.h> contains hash define names | |||
810 | * for all of these. | |||
811 | */ | |||
812 | ||||
813 | if (dpy->cursor_font == None0L) | |||
814 | { | |||
815 | dpy->cursor_font = XLoadFont (dpy, CURSORFONT"cursor"); | |||
816 | if (dpy->cursor_font == None0L) | |||
817 | return None0L; | |||
818 | } | |||
819 | ||||
820 | return _XcursorCreateGlyphCursor (dpy, dpy->cursor_font, dpy->cursor_font, | |||
821 | shape, shape + 1, &foreground, &background); | |||
822 | } | |||
823 |