diff options
Diffstat (limited to 'src/layout.c')
| -rw-r--r-- | src/layout.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/layout.c b/src/layout.c new file mode 100644 index 0000000..db6e435 --- /dev/null +++ b/src/layout.c @@ -0,0 +1,105 @@ +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "any_log.h" +#include "layout.h" + +layout_t *layout_create(block_t *block, layout_info_t info) +{ + assert(!block->hidden); + + layout_t *layout = calloc(1, sizeof(layout_t)); + layout->block = block; + layout->x = info.x_offset; + layout->y = 0; + layout->x_padding = block->x_padding; + layout->y_padding = block->y_padding; + layout->height = info.height; + + if (block->type == BLOCK_GROUP) { + layout->children = calloc(block->group.n_children, sizeof(layout_t)); + + for (int i = 0; i < block->group.n_children; i++) { + if (block->group.children[i].hidden) + continue; + + layout_t *child = layout_create(&block->group.children[i], info); + info.x_offset += child->width + block->group.spacing; + layout->children[layout->n_children++] = child; + } + } else if (block->type == BLOCK_TEXT) { + layout->pl = pango_layout_new(info.context); + + pango_layout_set_font_description(layout->pl, info.fontdesc); + pango_layout_set_alignment(layout->pl, block->text.text_align); + pango_layout_set_height(layout->pl, 0); + pango_layout_set_text(layout->pl, block->text.text, -1); + pango_layout_get_pixel_size(layout->pl, &layout->text_width, &layout->text_height); + + int length = strlen(block->text.text); + layout->width = info.height + (length != 1) * layout->text_width; + } + + return layout; +} + +void layout_render(layout_t *layout, cairo_t *cr) +{ + double degree = M_PI / 180.0; + int radius = layout->height / 2 - layout->y_padding; + int line_radius = radius - layout->block->line_width / 2; + + // Render background + color_t color = layout->block->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_padding + radius, layout->y + layout->y_padding + radius, radius, 90 * degree, 270 * degree); + cairo_arc(cr, layout->x + layout->width - layout->x_padding - radius, layout->y + layout->y_padding + radius, radius, 270 * degree, 450 * degree); + cairo_close_path(cr); + cairo_fill(cr); + + // Render border + color = layout->block->line_color; + cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); + cairo_set_line_width(cr, layout->block->line_width); + + cairo_new_sub_path(cr); + cairo_arc(cr, layout->x + layout->x_padding + radius, layout->y + layout->y_padding + radius, line_radius, 90 * degree, 270 * degree); + cairo_arc(cr, layout->x + layout->width - layout->x_padding - radius, layout->y + layout->y_padding + radius, line_radius, 270 * degree, 450 * degree); + cairo_close_path(cr); + cairo_stroke(cr); + + if (layout->block->type == BLOCK_GROUP) { + for (int i = 0; i < layout->n_children; i++) { + cairo_push_group(cr); + layout_render(layout->children[i], cr); + cairo_pop_group_to_source(cr); + cairo_paint(cr); + } + } else if (layout->block->type == BLOCK_TEXT) { + int text_x = layout->x + (layout->width - layout->text_width) / 2; + int text_y = layout->y + (layout->height - layout->text_height) / 2; + + color = layout->block->text.text_color; + cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); + cairo_move_to(cr, text_x, text_y); + + pango_layout_set_text(layout->pl, layout->block->text.text, -1); + pango_cairo_update_layout(cr, layout->pl); + pango_cairo_show_layout(cr, layout->pl); + } +} + +void layout_free(layout_t *layout) +{ + for (int i = 0; i < layout->n_children; i++) + layout_free(layout->children[i]); + + if (layout->pl != NULL) + g_object_unref(layout->pl); + + free(layout); +} |
