From 5d170a634ead0119f6e5a9f63c23b2b064126f75 Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Mon, 8 Jul 2024 15:22:41 +0200 Subject: Remove old files --- src/draw.c | 391 ------------------------------------------------------------- 1 file changed, 391 deletions(-) delete mode 100644 src/draw.c (limited to 'src/draw.c') diff --git a/src/draw.c b/src/draw.c deleted file mode 100644 index 44baba6..0000000 --- a/src/draw.c +++ /dev/null @@ -1,391 +0,0 @@ -#include -#include -#include -#include -#include - -#include "draw.h" -#include "button.h" -#include "log.h" - -#define ANIMATION(btn, which, ...) \ - do { \ - if ((btn)->anim != NULL && (btn)->anim->which##_func != NULL) { \ - if ((btn)->anim->start == 0) { \ - (btn)->anim->start = g_get_monotonic_time(); \ - log_debug("Starting animation [type=%d, func=%s, start=%ld, duration=%ld, button=%p]", \ - (btn)->anim->type, #which, (btn)->anim->start, (btn)->anim->duration, (btn)); \ - } \ - if (!(btn)->anim->which##_func((btn)->anim, __VA_ARGS__)) \ - (btn)->anim->which##_func = NULL; \ - } \ - } while (false) - -Drawer *draw_create() -{ - Drawer *draw = g_malloc0(sizeof(Drawer)); - g_assert_nonnull(draw); - return draw; -} - -static void paint_button(cairo_t *cr, const Layout *layout) -{ - double degree = M_PI / 180.0; - int radius = (layout->height - 2 * layout->y_pad) / 2; - int line_radius = radius - layout->line_w / 2; - -#if 0 - // Debug lines - - // Layout size - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_move_to(cr, layout->x, layout->y); - cairo_line_to(cr, layout->x, layout->y + layout->height); - cairo_stroke(cr); - - cairo_move_to(cr, layout->x + layout->width, layout->y); - cairo_line_to(cr, layout->x + layout->width, layout->y + layout->height); - cairo_stroke(cr); - - // Layout padding - cairo_set_source_rgb(cr, 0.5, 0.1, 0.1); - cairo_rectangle(cr, layout->x + layout->x_pad, layout->y + layout->y_pad, layout->width - 2 * layout->x_pad, layout->height - 2 * layout->y_pad); - cairo_stroke(cr); -#endif - - cairo_set_line_width(cr, layout->line_w); - - // Button background - Color color = layout->btn->color; - cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); - cairo_new_sub_path(cr); - cairo_arc(cr, layout->x + layout->x_pad + radius, layout->y + layout->y_pad + radius, radius, 90 * degree, 270 * degree); - cairo_arc(cr, layout->x + layout->width - layout->x_pad - radius, layout->y + layout->y_pad + radius, radius, 270 * degree, 450 * degree); - cairo_close_path(cr); - cairo_fill(cr); - - // Button border - color = layout->btn->line_color; - cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); - cairo_new_sub_path(cr); - cairo_arc(cr, layout->x + layout->x_pad + radius, layout->y + layout->y_pad + radius, line_radius, 90 * degree, 270 * degree); - cairo_arc(cr, layout->x + layout->width - layout->x_pad - radius, layout->y + layout->y_pad + radius, line_radius, 270 * degree, 450 * degree); - cairo_close_path(cr); - cairo_stroke(cr); -} - -static void paint_text(cairo_t *cr, const Layout *layout) -{ - int text_x = layout->x + layout->width / 2 - layout->text_w / 2; - int text_y = layout->y + layout->height / 2 - layout->text_h / 2; - - Color color = CAST(layout->btn, ButtonSimple)->text_color; - cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); - cairo_move_to(cr, text_x, text_y); - - // NOTE: This works only if the text didn't change in size after the layouting - pango_layout_set_text(layout->pl, CAST(layout->btn, ButtonSimple)->text, -1); - pango_cairo_update_layout(cr, layout->pl); - pango_cairo_show_layout(cr, layout->pl); -} - -static void paint_button_list(cairo_t *cr, GList *layouts) -{ - for (GList *it = layouts; it; it = it->next) { - Layout *layout = it->data; - Button *btn = layout->btn; - - cairo_push_group(cr); - - // Apply before_func on the layout and cairo context - ANIMATION(btn, before, layout, cr); - - paint_button(cr, layout); - - if (btn->simple) { - g_assert_null(layout->children); - paint_text(cr, layout); - } else { - g_assert_nonnull(layout->children); - paint_button_list(cr, layout->children); - } - - // Apply after_func on the layout and cairo context - ANIMATION(btn, after, layout, cr); - - cairo_pop_group_to_source(cr); - cairo_paint(cr); - } -} - -void draw_paint(Drawer *draw, Window *win) -{ - // Back buffering - cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, draw->width, draw->height); - - cairo_t *cr = cairo_create(surface); - cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - - // Fill the background - cairo_set_source_rgba(cr, draw->background.r, draw->background.g, draw->background.b, draw->background.a); - cairo_paint(cr); - - // Treat the top-level buttons similarly to a button group - paint_button_list(cr, draw->layouts); - cairo_destroy(cr); - - // Use device pixels - double scale = window_get_scale(win); - window_move(win, draw->left_pad * scale, draw->top_pad * scale); - window_resize(win, draw->width * scale, draw->height * scale); - - window_paint_surface(win, surface, draw->width * scale, draw->height * scale); - cairo_surface_destroy(surface); -} - -void layout_destroy(Layout *layout) -{ - if (layout->pl != NULL) - g_object_unref(layout->pl); - - g_list_free_full(layout->children, (GDestroyNotify)layout_destroy); - g_free(layout); -} - -static void layout_invalidate(GList *layouts) -{ - g_list_free_full(layouts, (GDestroyNotify)layout_destroy); -} - -static void layout_adjust(GList *start, GList *end, int off) -{ - // NOTE: end must be present in the list or segfault - for (GList *it = start; it != end; it = it->next) { - Layout *layout = it->data; - layout->x += off; - layout_adjust(layout->children, NULL, off); - } -} - -static void layout_set_text(Layout *layout, PangoFontDescription *desc, int height) -{ - g_assert(layout->btn->simple); - const char *text = CAST(layout->btn, ButtonSimple)->text; - - pango_layout_set_font_description(layout->pl, desc); - pango_layout_set_alignment(layout->pl, PANGO_ALIGN_CENTER); - pango_layout_set_height(layout->pl, 0); - pango_layout_set_text(layout->pl, text, -1); - pango_layout_get_pixel_size(layout->pl, &layout->text_w, &layout->text_h); - - // If there is only one glyph the button should be round - size_t text_l = g_utf8_strlen(text, -1); - layout->width = text_l == 1 ? height : layout->text_w + height; -} - -static void compute_width(Drawer *draw, Window *win) -{ - int screen_width = win->con->screen_size->width; - double scale = window_get_scale(win); - draw->width = (screen_width - draw->right_pad - draw->left_pad) / scale; - log_debug("Draw context width calculated [scale=%lf, width=%d]", scale, draw->width); -} - -static void layout_check_width(Layout *layout) -{ - // FIXME: Max width is not implemented correctly - if (layout->btn->max_width > 0) - layout->width = MIN(layout->btn->max_width, layout->width); - - if (layout->btn->min_width > 0) - layout->width = MAX(layout->btn->min_width, layout->width); -} - -static GList *compute_group_layout(Drawer *draw, GList *btns, int bx, bool root) -{ - GList *layouts = NULL; - for (GList *it = btns; it; it = it->next) { - Button *btn = it->data; - PangoAlignment align = btn->align; - - Layout *layout = g_malloc0(sizeof(Layout)); - layouts = g_list_prepend(layouts, layout); - - layout->btn = btn; - layout->height = draw->height; - layout->line_w = btn->line_width; - layout->x_pad = btn->x_pad; - layout->y_pad = btn->y_pad; - layout->x = bx; - layout->y = 0; - -retry: - if (!btn->simple) { - ButtonGroup *group = CAST(btn, ButtonGroup); - g_assert_nonnull(group->children); - - // NOTE: If a group has only one children treat it as a single button - // As a consequence btn->align can't be trusted - if (group->children->next == NULL) { - // XXX: We should also keep track of the group animation - // Is this the right way to do it? Can it loop? - ANIMATION(btn, layout, layout); - - layout->btn = btn = group->children->data; - goto retry; - } else { - layout->children = compute_group_layout(draw, group->children, bx, false); - g_assert_nonnull(layout->children); - - Layout *last = g_list_last(layout->children)->data; - layout->width = last->x + last->width - bx; - - // FIXME: Temporary solution to make the antialiasing (or the circles not - // overlapping correctly) problem less noticeable - bool fix_left = CAST(layout->children->data, Layout)->x_pad == 0; - if (fix_left) { - layout->x += 1; - layout->width -= 1; - } - - bool fix_right = last->x_pad == 0; - if (fix_right) - layout->width -= 1; - } - } else { - layout->pl = pango_layout_new(draw->context); - layout_set_text(layout, draw->desc, draw->height); - } - - // NOTE: We add half a line width on both sides - layout->width += layout->line_w; - layout_check_width(layout); - - // Apply layout_func on the layout - ANIMATION(btn, layout, layout); - - bx += layout->width; - if (root) { - draw->layout_bx[align] = bx; - draw->layout_end[align] = layouts; - } - - if (it->next != NULL && (!root || CAST(it->next->data, Button)->align == align)) - bx += draw->sep; - } - - // Otherwise button_action_find will not work! - layouts = g_list_reverse(layouts); - return layouts; -} - -void draw_compute_layout(Drawer *draw, Window *win, GList *btns) -{ - // Move this somewhere else - compute_width(draw, win); - - double scale = window_get_scale(win); - cairo_surface_set_device_scale(win->surface, scale, scale); - pango_cairo_context_set_resolution(draw->context, scale * 96); - pango_cairo_update_context(win->cr, draw->context); - - memset(draw->layout_end, 0, sizeof(draw->layout_end)); - memset(draw->layout_bx, 0, sizeof(draw->layout_bx)); - - g_clear_pointer(&draw->layouts, layout_invalidate); - draw->layouts = compute_group_layout(draw, btns, 0, true); - - draw->layout_width[PANGO_ALIGN_LEFT] = draw->layout_bx[PANGO_ALIGN_LEFT]; - draw->layout_width[PANGO_ALIGN_CENTER] = draw->layout_bx[PANGO_ALIGN_CENTER] - draw->layout_bx[PANGO_ALIGN_LEFT]; - draw->layout_width[PANGO_ALIGN_RIGHT] = draw->layout_bx[PANGO_ALIGN_RIGHT] - MAX(draw->layout_bx[PANGO_ALIGN_CENTER], draw->layout_bx[PANGO_ALIGN_LEFT]); - - if (draw->layout_bx[PANGO_ALIGN_RIGHT] > draw->width) { - log_error("Layout is bigger than the window (%d vs %d)", draw->layout_bx[PANGO_ALIGN_RIGHT], draw->width); - } - - bool has_left = draw->layout_end[PANGO_ALIGN_LEFT] != NULL; - bool has_center = draw->layout_end[PANGO_ALIGN_CENTER] != NULL; - - GList *center_start = has_left ? draw->layout_end[PANGO_ALIGN_LEFT]->next : draw->layouts; - GList *right_start = has_center ? draw->layout_end[PANGO_ALIGN_CENTER]->next : - has_left ? draw->layout_end[PANGO_ALIGN_LEFT]->next : draw->layouts; - - if (center_start != NULL) { - int center = round(draw->width / 2); - int center_off = center - draw->layout_width[PANGO_ALIGN_CENTER] / 2 - draw->layout_bx[PANGO_ALIGN_LEFT]; - - log_debug("Aligning center layout [center=%d, off=%d]", center, center_off); - layout_adjust(center_start, right_start, center_off); - } - - if (right_start != NULL) { - int right = draw->width - draw->layout_width[PANGO_ALIGN_RIGHT]; - int right_off = right - MAX(draw->layout_bx[PANGO_ALIGN_LEFT], draw->layout_bx[PANGO_ALIGN_CENTER]); - - log_debug("Aligning right layout [x=%d, off=%d]", right, right_off); - layout_adjust(right_start, NULL, right_off); - } - - log_debug("Updated layouts"); -} - -void draw_compute_text_size(Drawer *draw, const char *text, int *text_w, int *text_h) -{ - PangoLayout *pl = pango_layout_new(draw->context); - pango_layout_set_font_description(pl, draw->desc); - pango_layout_set_height(pl, 0); - pango_layout_set_alignment(pl, PANGO_ALIGN_CENTER); - pango_layout_set_text(pl, text, -1); - pango_layout_get_pixel_size(pl, text_w, text_h); - g_object_unref(pl); -} - -void draw_set_background(Drawer *draw, Color background) -{ - draw->background = background; -} - -void draw_set_separator(Drawer *draw, int sep) -{ - g_assert(sep >= 0); - draw->sep = sep; -} - -void draw_set_font(Drawer *draw, const char *font) -{ - log_debug("Pango loading font description '%s'", font); - draw->desc = pango_font_description_from_string(font); - g_assert_nonnull(draw->desc); - log_debug("Pango found matching font '%s'", pango_font_description_get_family(draw->desc)); -} - -// NOTE: Don't call this between layout and paint! -void draw_set_context(Drawer *draw, PangoContext *context) -{ - g_assert_nonnull(context); - draw->context = context; - log_debug("Pango context updated [context=%p]", context); -} - -void draw_set_size(Drawer *draw, int height, int left_pad, int right_pad, int top_pad) -{ - g_assert(height > 0); - - draw->height = height; - draw->left_pad = left_pad; - draw->right_pad = right_pad; - draw->top_pad = top_pad; - - log_debug("Draw context size updated [height=%d, left_pad=%d, right_pad=%d, top_pad=%d]", - height, left_pad, right_pad, top_pad); -} - -void draw_destroy(Drawer *draw) -{ - g_clear_pointer(&draw->layouts, layout_invalidate); - pango_font_description_free(draw->desc); - g_free(draw); -} - -// vim: ts=4 sw=4 et -- cgit v1.2.3