1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright (c) 2014 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
6428d7b3dSmrg * to deal in the Software without restriction, including without limitation
7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
10428d7b3dSmrg *
11428d7b3dSmrg * The above copyright notice and this permission notice (including the next
12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
13428d7b3dSmrg * Software.
14428d7b3dSmrg *
15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21428d7b3dSmrg * SOFTWARE.
22428d7b3dSmrg *
23428d7b3dSmrg */
24428d7b3dSmrg
25428d7b3dSmrg#ifdef HAVE_CONFIG_H
26428d7b3dSmrg#include "config.h"
27428d7b3dSmrg#endif
28428d7b3dSmrg
29428d7b3dSmrg#include <stdio.h>
30428d7b3dSmrg#include <stdlib.h>
31428d7b3dSmrg#include <unistd.h>
32428d7b3dSmrg#include <cairo.h>
33428d7b3dSmrg#include <cairo-xlib.h>
34428d7b3dSmrg#include <cairo-xlib-xrender.h>
35428d7b3dSmrg#include <X11/Xlib.h>
36428d7b3dSmrg#include <X11/extensions/Xrender.h>
37428d7b3dSmrg
38428d7b3dSmrg#include <string.h>
39428d7b3dSmrg
40428d7b3dSmrgstatic void core_cursor(Display *dpy, int width, int height)
41428d7b3dSmrg{
42428d7b3dSmrg	char text[256];
43428d7b3dSmrg	cairo_surface_t *surface;
44428d7b3dSmrg	cairo_text_extents_t extents;
45428d7b3dSmrg	cairo_t *cr;
46428d7b3dSmrg	Pixmap bitmap;
47428d7b3dSmrg	int scr = DefaultScreen(dpy);
48428d7b3dSmrg	Window root = RootWindow(dpy, scr);
49428d7b3dSmrg	XColor bg, fg;
50428d7b3dSmrg	int pitch;
51428d7b3dSmrg	char *data;
52428d7b3dSmrg	GC gc;
53428d7b3dSmrg
54428d7b3dSmrg	sprintf(text, "%dx%d", width, height);
55428d7b3dSmrg
56428d7b3dSmrg	pitch = (width + 31) >> 5 << 2;
57428d7b3dSmrg	data = calloc(pitch, height);
58428d7b3dSmrg
59428d7b3dSmrg	surface = cairo_image_surface_create_for_data((unsigned char *)data, CAIRO_FORMAT_A1, width, height, pitch);
60428d7b3dSmrg	cr = cairo_create(surface);
61428d7b3dSmrg	cairo_text_extents(cr, text, &extents);
62428d7b3dSmrg	cairo_move_to(cr, 0, extents.height);
63428d7b3dSmrg	cairo_show_text(cr, text);
64428d7b3dSmrg	cairo_destroy(cr);
65428d7b3dSmrg	cairo_surface_destroy(surface);
66428d7b3dSmrg
67428d7b3dSmrg	bitmap = XCreatePixmap(dpy, root, width, height, 1);
68428d7b3dSmrg	gc = XCreateGC(dpy, bitmap, 0, NULL);
69428d7b3dSmrg	if (gc != NULL) {
70428d7b3dSmrg		XImage ximage = {
71428d7b3dSmrg			.height = height,
72428d7b3dSmrg			.width = width,
73428d7b3dSmrg			.depth = 1,
74428d7b3dSmrg			.bits_per_pixel = 1,
75428d7b3dSmrg			.xoffset = 0,
76428d7b3dSmrg			.format = XYPixmap,
77428d7b3dSmrg			.data = data,
78428d7b3dSmrg			.byte_order = LSBFirst,
79428d7b3dSmrg			.bitmap_unit = 32,
80428d7b3dSmrg			.bitmap_bit_order = LSBFirst,
81428d7b3dSmrg			.bitmap_pad = 32,
82428d7b3dSmrg			.bytes_per_line = pitch,
83428d7b3dSmrg		};
84428d7b3dSmrg		XPutImage(dpy, bitmap, gc, &ximage, 0, 0, 0, 0, width, height);
85428d7b3dSmrg		XFreeGC(dpy, gc);
86428d7b3dSmrg	}
87428d7b3dSmrg	free(data);
88428d7b3dSmrg
89428d7b3dSmrg	XParseColor(dpy, DefaultColormap(dpy, scr), "green", &fg);
90428d7b3dSmrg	XParseColor(dpy, DefaultColormap(dpy, scr), "black", &bg);
91428d7b3dSmrg
92428d7b3dSmrg	XDefineCursor(dpy, root, XCreatePixmapCursor(dpy, bitmap, bitmap, &fg, &bg, 0, 0));
93428d7b3dSmrg	XFreePixmap(dpy, bitmap);
94428d7b3dSmrg}
95428d7b3dSmrg
96428d7b3dSmrgstatic void render_cursor(Display *dpy, int width, int height)
97428d7b3dSmrg{
98428d7b3dSmrg	char text[256];
99428d7b3dSmrg	cairo_surface_t *surface;
100428d7b3dSmrg	cairo_text_extents_t extents;
101428d7b3dSmrg	cairo_t *cr;
102428d7b3dSmrg	Pixmap pixmap;
103428d7b3dSmrg	Picture picture;
104428d7b3dSmrg
105428d7b3dSmrg	sprintf(text, "%dx%d", width, height);
106428d7b3dSmrg
107428d7b3dSmrg	pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 32);
108428d7b3dSmrg	surface = cairo_xlib_surface_create_with_xrender_format(dpy, pixmap,
109428d7b3dSmrg								DefaultScreenOfDisplay(dpy),
110428d7b3dSmrg								XRenderFindStandardFormat(dpy, PictStandardARGB32),
111428d7b3dSmrg								width, height);
112428d7b3dSmrg	cr = cairo_create(surface);
113428d7b3dSmrg	cairo_surface_destroy(surface);
114428d7b3dSmrg
115428d7b3dSmrg	cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
116428d7b3dSmrg	cairo_paint(cr);
117428d7b3dSmrg	cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
118428d7b3dSmrg
119428d7b3dSmrg	cairo_text_extents(cr, text, &extents);
120428d7b3dSmrg	cairo_move_to(cr, 0, extents.height);
121428d7b3dSmrg	cairo_set_source_rgb(cr, 1, 0, 1);
122428d7b3dSmrg	cairo_show_text(cr, text);
123428d7b3dSmrg	cairo_destroy(cr);
124428d7b3dSmrg
125428d7b3dSmrg	picture = XRenderCreatePicture(dpy, pixmap, XRenderFindStandardFormat(dpy, PictStandardARGB32), 0, NULL);
126428d7b3dSmrg	XFreePixmap(dpy, pixmap);
127428d7b3dSmrg
128428d7b3dSmrg	XDefineCursor(dpy, DefaultRootWindow(dpy), XRenderCreateCursor(dpy, picture, 0, 0));
129428d7b3dSmrg	XRenderFreePicture(dpy, picture);
130428d7b3dSmrg}
131428d7b3dSmrg
132428d7b3dSmrgint main(void)
133428d7b3dSmrg{
134428d7b3dSmrg	Display *dpy;
135428d7b3dSmrg	int sizes[] = { 24, 32, 48, 64, 72, 128, 160, 256 };
136428d7b3dSmrg	int x, y;
137428d7b3dSmrg
138428d7b3dSmrg	dpy = XOpenDisplay(NULL);
139428d7b3dSmrg	if (dpy == NULL)
140428d7b3dSmrg		dpy = XOpenDisplay(":0"); /* lazy */
141428d7b3dSmrg	if (dpy == NULL)
142428d7b3dSmrg		return 77;
143428d7b3dSmrg
144428d7b3dSmrg	for (x = 0; x < sizeof(sizes)/sizeof(sizes[0]); x++) {
145428d7b3dSmrg		for (y = 0; y < sizeof(sizes)/sizeof(sizes[0]); y++) {
146428d7b3dSmrg			printf("Testing %dx%d (core)\n", sizes[x], sizes[y]);
147428d7b3dSmrg			core_cursor(dpy, sizes[x], sizes[y]);
148428d7b3dSmrg			XSync(dpy, True);
149428d7b3dSmrg			sleep(2);
150428d7b3dSmrg
151428d7b3dSmrg			printf("Testing %dx%d (render)\n", sizes[x], sizes[y]);
152428d7b3dSmrg			render_cursor(dpy, sizes[x], sizes[y]);
153428d7b3dSmrg			XSync(dpy, True);
154428d7b3dSmrg			sleep(2);
155428d7b3dSmrg		}
156428d7b3dSmrg	}
157428d7b3dSmrg
158428d7b3dSmrg	return 0;
159428d7b3dSmrg}
160