summaryrefslogtreecommitdiff
path: root/text.c
blob: f0bd0743af3dd3cac49c2c0db9f8e1e104f25a83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <stdint.h>
#include <stdio.h>

#include <cairo.h>
#include <cairo-xcb.h>
#include <glib-object.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
#include <xcb/xcb.h>
#include <xcb/xcb_util.h>

void draw_text(cairo_t *, const char *);
xcb_visualtype_t * find_visual(xcb_screen_t *);

static const int MARGIN = 20;
static const int WIDTH = 800;
static const int HEIGHT = 1131;
static const char * FONT = "Serif 34";


int main(int argc, const char ** argv)
{
	const char * text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
	if (2 == argc)
		text = argv[2];
	xcb_connection_t * c = xcb_connect(NULL, NULL);
	if (xcb_connection_has_error(c))
	{
		dprintf(2, "Could not connect to X11 server");
		return 1;
	}
	xcb_screen_t * s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
	xcb_window_t w = xcb_generate_id(c);
	const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	const uint32_t values[] = {s->white_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS};
	xcb_visualtype_t * visual = find_visual(s);
	xcb_create_window(
		c, XCB_COPY_FROM_PARENT, w, s->root, 0, 0, WIDTH, HEIGHT, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
		s->root_visual, mask, values);
	xcb_map_window(c, w);
	cairo_surface_t * surface = cairo_xcb_surface_create(c, w, visual, WIDTH, HEIGHT);
	cairo_t * ctx = cairo_create(surface);
	xcb_flush(c);
	int done = 0;
	xcb_generic_event_t * e;
	while (!done)
	{
		e = xcb_wait_for_event(c);
		if (NULL == e)
			break;
		switch (XCB_EVENT_RESPONSE_TYPE(e))
		{
		default:
			break;
		case XCB_KEY_PRESS:
			done = 1;
			break;
		case XCB_EXPOSE:
			cairo_set_source_rgb(ctx, 1., 1., 1.);
			cairo_paint(ctx);
			cairo_set_source_rgb(ctx, 0., 0., 0.);
			draw_text(ctx, text);
			cairo_surface_flush(surface);
			xcb_flush(c);
			break;
		}
		free(e);
	}
	cairo_destroy(ctx);
	cairo_surface_destroy(surface);
	xcb_disconnect(c);
}


xcb_visualtype_t * find_visual(xcb_screen_t * s)
{
	xcb_depth_iterator_t d = xcb_screen_allowed_depths_iterator(s);
	for (; d.rem; xcb_depth_next(&d))
	{
		xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator(d.data);
		for (; v.rem; xcb_visualtype_next(&v))
			if (v.data->visual_id == s->root_visual)
				return v.data;
	}
	return NULL;
}


void draw_text(cairo_t * ctx, const char * text)
{
	cairo_move_to(ctx, MARGIN, MARGIN);
	PangoLayout * layout = pango_cairo_create_layout(ctx);
	PangoFontDescription * desc = pango_font_description_from_string(FONT);
	pango_layout_set_font_description(layout, desc);
	pango_font_description_free(desc);
	pango_layout_set_text(layout, text, -1);
	pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
	pango_layout_set_width(layout, (WIDTH - 2 * MARGIN) * PANGO_SCALE);
	pango_cairo_update_layout(ctx, layout);
	pango_cairo_show_layout(ctx, layout);
	g_object_unref(layout);
}