~earboxer/suggpicker

suggpicker/drw.c -rw-r--r-- 3.2 KiB
fd0edc9aZach DeCook release: minor version bump 4 months ago
                                                                                
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <sys/mman.h>
#include <unistd.h>
#include <wayland-client.h>

#include "drw.h"
#include "shm_open.h"

void
drwsurf_resize(struct drwsurf *ds, uint32_t w, uint32_t h, uint32_t s) {
	if (ds->buf) {
		munmap(ds->pool_data, ds->size);
		wl_buffer_destroy(ds->buf);
		ds->buf = NULL;
	}

	ds->scale = s;
	ds->width = w * s;
	ds->height = h * s;

	setup_buffer(ds);
}

void
drwsurf_flip(struct drwsurf *ds) {
	wl_surface_attach(ds->surf, ds->buf, 0, 0);
	wl_surface_commit(ds->surf);
}

void
drw_draw_text(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
              uint32_t w, uint32_t h, const char *label) {

	cairo_save(d->cairo);

	cairo_set_source_rgba(
	  d->cairo, color.bgra[2] / (double)255, color.bgra[1] / (double)255,
	  color.bgra[0] / (double)255, color.bgra[3] / (double)255);
	cairo_move_to(d->cairo, x + (double)w / 2.0, y + (double)h / 2.0);

	pango_layout_set_text(d->layout, label, -1);

	int width, height;
	pango_layout_get_size(d->layout, &width, &height);

	cairo_rel_move_to(d->cairo, -((double)width / PANGO_SCALE) / 2,
	                  -((double)height / PANGO_SCALE) / 2);
	pango_cairo_show_layout(d->cairo, d->layout);
	cairo_restore(d->cairo);

	wl_surface_damage(d->surf, x, y, w, h);
}

void
drw_do_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
                 uint32_t w, uint32_t h, bool over) {
	cairo_save(d->cairo);

	if (over) {
		cairo_set_operator(d->cairo, CAIRO_OPERATOR_OVER);
	} else {
		cairo_set_operator(d->cairo, CAIRO_OPERATOR_SOURCE);
	}

	cairo_rectangle(d->cairo, x, y, w, h);
	cairo_set_source_rgba(
	  d->cairo, color.bgra[2] / (double)255, color.bgra[1] / (double)255,
	  color.bgra[0] / (double)255, color.bgra[3] / (double)255);
	cairo_fill(d->cairo);

	cairo_restore(d->cairo);

	wl_surface_damage(d->surf, x, y, w, h);
}

void
drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
                   uint32_t w, uint32_t h) {
	drw_do_rectangle(d, color, x, y, w, h, false);
}

void
drw_over_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
                   uint32_t w, uint32_t h) {
	drw_do_rectangle(d, color, x, y, w, h, true);
}

uint32_t
setup_buffer(struct drwsurf *drwsurf) {
	int stride = drwsurf->width * 4;
	drwsurf->size = stride * drwsurf->height;

	int fd = allocate_shm_file(drwsurf->size);
	if (fd == -1) {
		return 1;
	}

	drwsurf->pool_data =
	  mmap(NULL, drwsurf->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (drwsurf->pool_data == MAP_FAILED) {
		close(fd);
		return 1;
	}

	struct wl_shm_pool *pool =
	  wl_shm_create_pool(drwsurf->ctx->shm, fd, drwsurf->size);
	drwsurf->buf = wl_shm_pool_create_buffer(
	  pool, 0, drwsurf->width, drwsurf->height, stride, WL_SHM_FORMAT_ARGB8888);
	wl_shm_pool_destroy(pool);
	close(fd);

	cairo_surface_t *s = cairo_image_surface_create_for_data(
	  drwsurf->pool_data, CAIRO_FORMAT_ARGB32, drwsurf->width, drwsurf->height,
	  stride);

	drwsurf->cairo = cairo_create(s);
	cairo_scale(drwsurf->cairo, drwsurf->scale, drwsurf->scale);
	drwsurf->layout = pango_cairo_create_layout(drwsurf->cairo);
	pango_layout_set_font_description(drwsurf->layout,
	                                  drwsurf->ctx->font_description);
	cairo_save(drwsurf->cairo);

	wl_surface_set_buffer_scale(drwsurf->surf, drwsurf->scale);

	return 0;
}