1/*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <X11/Xlib.h>
30#include <X11/extensions/Xfixes.h>
31
32#include <stdint.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <png.h>
36
37int main(int argc, char **argv)
38{
39	Display *dpy;
40	XFixesCursorImage *cur;
41	unsigned long *src; /* XXX deep sigh */
42	unsigned x, y;
43	png_struct *png;
44	png_info *info;
45	png_byte **rows;
46	FILE *file;
47
48	dpy = XOpenDisplay(NULL);
49	if (dpy == NULL)
50		return 1;
51
52	if (!XFixesQueryExtension(dpy, (int *)&x, (int *)&y))
53		return 1;
54
55	cur = XFixesGetCursorImage(dpy);
56	if (cur == NULL)
57		return 1;
58
59	printf("Cursor on display '%s': %dx%d, (hotspot %dx%d)\n",
60	       DisplayString(dpy),
61	       cur->width, cur->height,
62	       cur->xhot, cur->yhot);
63
64	if (1) {
65		int x, y;
66
67		src = cur->pixels;
68		for (y = 0; y < cur->height; y++) {
69			for (x = 0; x < cur->width; x++) {
70				if (x == cur->xhot && y == cur->yhot)
71					printf("+");
72				else
73					printf("%c", *src ? *src >> 24 >= 127 ? 'x' : '.' : ' ');
74				src++;
75			}
76			printf("\n");
77		}
78	}
79
80	file = fopen("cursor.png", "wb");
81	if (file == NULL)
82		return 2;
83
84	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
85	info = png_create_info_struct(png);
86	png_init_io(png, file);
87	png_set_IHDR(png, info,
88		     cur->width, cur->height, 8,
89		     PNG_COLOR_TYPE_RGB_ALPHA,
90		     PNG_INTERLACE_NONE,
91		     PNG_COMPRESSION_TYPE_DEFAULT,
92		     PNG_FILTER_TYPE_DEFAULT);
93	png_write_info(png, info);
94
95	src = cur->pixels;
96	rows = malloc(cur->height*sizeof(png_byte*));
97	if (rows == NULL)
98		return 3;
99
100	for (y = 0; y < cur->height; y++) {
101		rows[y] = malloc(cur->width * 4);
102		for (x = 0; x < cur->width; x++) {
103			uint32_t p = *src++;
104			uint8_t r = p >> 0;
105			uint8_t g = p >> 8;
106			uint8_t b = p >> 16;
107			uint8_t a = p >> 24;
108
109			if (a > 0x00 && a < 0xff) {
110				r = (r * 0xff + a /2) / a;
111				g = (g * 0xff + a /2) / a;
112				b = (b * 0xff + a /2) / a;
113			}
114
115			rows[y][4*x + 0] = b;
116			rows[y][4*x + 1] = g;
117			rows[y][4*x + 2] = r;
118			rows[y][4*x + 3] = a;
119		}
120	}
121
122	png_write_image(png, rows);
123	png_write_end(png, NULL);
124	fclose(file);
125
126	return 0;
127}
128