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