summaryrefslogtreecommitdiff
path: root/lib/renderers/cairo.h
blob: 9c1ff5ab9e6ee602aabc218aa5238a36177f0115 (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
#ifndef _BM_CAIRO_H_
#define _BM_CAIRO_H_

#include "internal.h"
#include <string.h>
#include <assert.h>
#include <cairo/cairo.h>

struct cairo {
    cairo_t *cr;
    cairo_surface_t *surface;
};

struct cairo_color {
    float r, g, b, a;
};

struct cairo_font {
    const char *name;
    uint32_t size;
};

struct cairo_paint {
    struct cairo_color color;
    struct cairo_font font;
};

struct cairo_result {
    cairo_text_extents_t te;
};

__attribute__((unused)) BM_LOG_ATTR(6, 7) static bool
bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_result *result, int32_t x, int32_t y, const char *fmt, ...)
{
    static size_t blen = 0;
    static char *buffer = NULL;
    assert(cairo && paint && result && fmt);
    memset(result, 0, sizeof(struct cairo_result));

    va_list args;
    va_start(args, fmt);
    bool ret = bm_vrprintf(&buffer, &blen, fmt, args);
    va_end(args);

    if (!ret)
        return false;

    cairo_set_source_rgba(cairo->cr, paint->color.r, paint->color.b, paint->color.g, paint->color.a);

    cairo_text_extents_t te;
    cairo_select_font_face(cairo->cr, paint->font.name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(cairo->cr, paint->font.size);
    cairo_text_extents(cairo->cr, buffer, &te);
    cairo_move_to(cairo->cr, x, y * te.height + te.height);
    cairo_show_text(cairo->cr, buffer);

    memcpy(&result->te, &te, sizeof(te));
    return true;
}

__attribute__((unused)) static void
bm_cairo_paint(struct cairo *cairo, uint32_t width, uint32_t height, const struct bm_menu *menu)
{
    cairo_set_source_rgb(cairo->cr, 18.0f / 255.0f, 18 / 255.0f, 18.0f / 255.0f);
    cairo_rectangle(cairo->cr, 0, 0, width, height);
    cairo_fill(cairo->cr);

    struct cairo_result result;
    memset(&result, 0, sizeof(result));

    struct cairo_paint paint;
    memset(&paint, 0, sizeof(paint));
    paint.font.name = "Terminus";
    paint.font.size = 12;
    paint.color = (struct cairo_color){ 1.0, 0.0, 0.0, 1.0 };

    if (menu->title)
        bm_cairo_draw_line(cairo, &paint, &result, result.te.x_advance, 0, "%s ", menu->title);
    if (menu->filter)
        bm_cairo_draw_line(cairo, &paint, &result, result.te.x_advance, 0, "%s", menu->filter);

    uint32_t count, cl = 1;
    uint32_t lines = height / paint.font.size;
    struct bm_item **items = bm_menu_get_filtered_items(menu, &count);
    for (uint32_t i = (menu->index / (lines - 1)) * (lines - 1); i < count && cl < lines; ++i) {
        bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu));

        if (highlighted)
            paint.color = (struct cairo_color){ 1.0, 0.0, 0.0, 1.0 };
        else if (bm_menu_item_is_selected(menu, items[i]))
            paint.color = (struct cairo_color){ 1.0, 0.0, 0.0, 1.0 };
        else
            paint.color = (struct cairo_color){ 1.0, 1.0, 1.0, 1.0 };

        bm_cairo_draw_line(cairo, &paint, &result, 0, cl++, "%s%s", (highlighted ? ">> " : "   "), (items[i]->text ? items[i]->text : ""));
    }
}

#endif /* _BM_CAIRO_H */

/* vim: set ts=8 sw=4 tw=0 :*/