diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e6b28f..71789ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ add_executable(f00bar yml.c yml.h decorations/background.c decorations/background.h + decorations/stack.c decorations/stack.h decorations/underline.c decorations/underline.h particles/list.c particles/list.h diff --git a/config.c b/config.c index 5e30473..54320da 100644 --- a/config.c +++ b/config.c @@ -9,6 +9,7 @@ #include "decoration.h" #include "decorations/background.h" +#include "decorations/stack.h" #include "decorations/underline.h" #include "particle.h" @@ -115,6 +116,29 @@ deco_underline_from_config(const struct yml_node *node) yml_value_as_int(size), color_from_hexstr(yml_value_as_string(color))); } +static struct deco *deco_from_config(const struct yml_node *node); + +static struct deco * +deco_stack_from_config(const struct yml_node *node) +{ + assert(yml_is_list(node)); + + size_t count = yml_list_length(node); + assert(count > 0); + + struct deco *decos[count]; + size_t idx = 0; + + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it), idx++) + { + decos[idx] = deco_from_config(it.node); + } + + return deco_stack(decos, count); +} + static struct deco * deco_from_config(const struct yml_node *node) { @@ -126,7 +150,6 @@ deco_from_config(const struct yml_node *node) const struct yml_node *deco_data = it.value; assert(yml_is_scalar(deco_type)); - assert(yml_is_dict(deco_data)); const char *type = yml_value_as_string(deco_type); @@ -134,6 +157,8 @@ deco_from_config(const struct yml_node *node) return deco_background_from_config(deco_data); else if (strcmp(type, "underline") == 0) return deco_underline_from_config(deco_data); + else if (strcmp(type, "stack") == 0) + return deco_stack_from_config(deco_data); else assert(false); } diff --git a/decorations/stack.c b/decorations/stack.c new file mode 100644 index 0000000..d7410e4 --- /dev/null +++ b/decorations/stack.c @@ -0,0 +1,45 @@ +#include "underline.h" + +#include + +struct private { + struct deco **decos; + size_t count; +}; + +static void +destroy(struct deco *deco) +{ + struct private *d = deco->private; + for (size_t i = 0; i < d->count; i++) + d->decos[i]->destroy(d->decos[i]); + free(d->decos); + free(d); + free(deco); +} + +static void +expose(const struct deco *deco, cairo_t *cr, int x, int y, int width, int height) +{ + const struct private *d = deco->private; + for (size_t i = 0; i < d->count; i++) + d->decos[i]->expose(d->decos[i], cr, x, y, width, height); +} + +struct deco * +deco_stack(struct deco *decos[], size_t count) +{ + struct private *priv = malloc(sizeof(*priv)); + priv->decos = malloc(count * sizeof(priv->decos[0])); + priv->count = count; + + for (size_t i = 0; i < count; i++) + priv->decos[i] = decos[i]; + + struct deco *deco = malloc(sizeof(*deco)); + deco->private = priv; + deco->expose = &expose; + deco->destroy = &destroy; + + return deco; +} diff --git a/decorations/stack.h b/decorations/stack.h new file mode 100644 index 0000000..ab0380a --- /dev/null +++ b/decorations/stack.h @@ -0,0 +1,6 @@ +#pragma once + +#include "../color.h" +#include "../decoration.h" + +struct deco *deco_stack(struct deco *decos[], size_t count);