summaryrefslogtreecommitdiff
path: root/lib/renderers/cairo.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/renderers/cairo.h')
-rw-r--r--lib/renderers/cairo.h172
1 files changed, 130 insertions, 42 deletions
diff --git a/lib/renderers/cairo.h b/lib/renderers/cairo.h
index 9c1ff5a..1dc052f 100644
--- a/lib/renderers/cairo.h
+++ b/lib/renderers/cairo.h
@@ -6,6 +6,10 @@
#include <assert.h>
#include <cairo/cairo.h>
+#ifndef MAX
+# define MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
struct cairo {
cairo_t *cr;
cairo_surface_t *surface;
@@ -15,26 +19,23 @@ 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_color fg;
+ struct cairo_color bg;
+ cairo_font_extents_t fe;
};
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;
+
+__attribute__((unused)) BM_LOG_ATTR(3, 4) static bool
+bm_cairo_get_text_extents(struct cairo *cairo, struct cairo_result *result, const char *fmt, ...)
{
- static size_t blen = 0;
- static char *buffer = NULL;
- assert(cairo && paint && result && fmt);
+ assert(cairo && result && fmt);
memset(result, 0, sizeof(struct cairo_result));
va_list args;
@@ -45,13 +46,33 @@ bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_
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(cairo->cr, buffer, &result->te);
+ return true;
+}
+
+__attribute__((unused)) BM_LOG_ATTR(8, 9) static bool
+bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_result *result, uint32_t xoff, uint32_t w, int32_t x, int32_t y, const char *fmt, ...)
+{
+ 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_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_set_source_rgba(cairo->cr, paint->bg.r, paint->bg.b, paint->bg.g, paint->bg.a);
+ cairo_rectangle(cairo->cr, x - xoff, y, (w > 0 ? w : te.width) + xoff, paint->fe.height);
+ cairo_fill(cairo->cr);
+
+ cairo_set_source_rgba(cairo->cr, paint->fg.r, paint->fg.b, paint->fg.g, paint->fg.a);
+ cairo_move_to(cairo->cr, x, y + paint->fe.descent + paint->fe.height * 0.5);
cairo_show_text(cairo->cr, buffer);
memcpy(&result->te, &te, sizeof(te));
@@ -59,41 +80,108 @@ bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_
}
__attribute__((unused)) static void
+bm_cairo_color_from_menu_color(const struct bm_menu *menu, enum bm_color color, struct cairo_color *c)
+{
+ assert(menu);
+ c->r = (float)menu->colors[color].r / 255.0f;
+ c->g = (float)menu->colors[color].g / 255.0f;
+ c->b = (float)menu->colors[color].b / 255.0f;
+ c->a = 1.0f;
+}
+
+__attribute__((unused)) static uint32_t
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);
+ assert(cairo && menu);
+
+ struct cairo_color c;
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_BG, &c);
+ cairo_set_source_rgb(cairo->cr, c.r, c.g, c.b);
cairo_rectangle(cairo->cr, 0, 0, width, height);
cairo_fill(cairo->cr);
- struct cairo_result result;
- memset(&result, 0, sizeof(result));
+ cairo_select_font_face(cairo->cr, menu->font.name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size(cairo->cr, menu->font.size);
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 : ""));
+ cairo_font_extents(cairo->cr, &paint.fe);
+
+ struct cairo_result result;
+ memset(&result, 0, sizeof(result));
+
+ if (menu->title) {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_TITLE_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_TITLE_BG, &paint.bg);
+ bm_cairo_draw_line(cairo, &paint, &result, 0, 0, result.te.x_advance, 4, "%s", menu->title);
+ }
+
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_BG, &paint.bg);
+ bm_cairo_draw_line(cairo, &paint, &result, 0, width, result.te.x_advance, 4, "%s%s", (menu->title ? " " : ""), (menu->filter ? menu->filter : ""));
+
+ uint32_t displayed = 1;
+ uint32_t lines = MAX(height / paint.fe.height, menu->lines);
+ if (lines > 1) {
+ uint32_t count, cl = 1;
+ 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) {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_BG, &paint.bg);
+ } else if (bm_menu_item_is_selected(menu, items[i])) {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_BG, &paint.bg);
+ } else {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_BG, &paint.bg);
+ }
+
+ bm_cairo_draw_line(cairo, &paint, &result, 0, width, 0, 4 + paint.fe.height * cl++,
+ "%s%s", (highlighted ? ">> " : " "), (items[i]->text ? items[i]->text : ""));
+
+ ++displayed;
+ }
+ } else {
+ uint32_t count;
+ struct bm_item **items = bm_menu_get_filtered_items(menu, &count);
+
+ uint32_t cl = width / 4;
+ if (menu->wrap || menu->index > 0) {
+ bm_cairo_draw_line(cairo, &paint, &result, 0, 0, cl, 4, "<");
+ cl += result.te.x_advance + 4;
+ }
+
+ for (uint32_t i = menu->index; i < count && cl < width; ++i) {
+ bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu));
+
+ if (highlighted) {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_BG, &paint.bg);
+ } else if (bm_menu_item_is_selected(menu, items[i])) {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_BG, &paint.bg);
+ } else {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_BG, &paint.bg);
+ }
+
+ bm_cairo_draw_line(cairo, &paint, &result, 0, 0, cl, 4, "%s", (items[i]->text ? items[i]->text : ""));
+ cl += result.te.x_advance + 4;
+ displayed += (cl < width);
+ }
+
+ if (menu->wrap || menu->index + 1 < count) {
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_FG, &paint.fg);
+ bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_BG, &paint.bg);
+ bm_cairo_get_text_extents(cairo, &result, ">");
+ bm_cairo_draw_line(cairo, &paint, &result, 4, result.te.x_advance + 4, width - result.te.x_advance - 4, 4, ">");
+ }
}
+
+ return displayed;
}
#endif /* _BM_CAIRO_H */