diff options
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/Makefile.am | 2 | ||||
-rw-r--r-- | src/modules/asc/Makefile.am | 3 | ||||
-rw-r--r-- | src/modules/asc/asc.c | 231 |
3 files changed, 235 insertions, 1 deletions
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index b29eef9..ea82374 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -1 +1 @@ -SUBDIRS = blinds checkers compose drizzle flow flui2d julia meta2d mixer moire montage pixbounce plasma plato ray rkt roto rtv shapes signals snow sparkler spiro stars strobe submit swab swarm voronoi +SUBDIRS = asc blinds checkers compose drizzle flow flui2d julia meta2d mixer moire montage pixbounce plasma plato ray rkt roto rtv shapes signals snow sparkler spiro stars strobe submit swab swarm voronoi diff --git a/src/modules/asc/Makefile.am b/src/modules/asc/Makefile.am new file mode 100644 index 0000000..c9f7a6e --- /dev/null +++ b/src/modules/asc/Makefile.am @@ -0,0 +1,3 @@ +noinst_LTLIBRARIES = libasc.la +libasc_la_SOURCES = asc.c +libasc_la_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs diff --git a/src/modules/asc/asc.c b/src/modules/asc/asc.c new file mode 100644 index 0000000..2d50021 --- /dev/null +++ b/src/modules/asc/asc.c @@ -0,0 +1,231 @@ +#include <errno.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "til.h" +#include "til_fb.h" +#include "til_module_context.h" + +#include "txt/txt.h" + +/* Copyright (C) 2023 Vito Caputo <vcaputo@pengaru.com> */ + +/* This is intended primarily for diagnostic purposes or as a stand-in you'd eventually + * replace with something a more visually interesting font/style. + * + * TODO: + * - Wire up taps for the x/y coordinates, making this a handy taps diagnostic + * + * - Maybe add a dynamic justification mode where the h/v alignment offsets are + * just the inverse of the normalized x/y coordinates. This requires extending + * libs/txt to support precise offsetting when rendering as an alternative to the + * enum'd txt_align_t variant. But it would allow a tapped x/y coordinate user to + * sweep the coordinates edge-to-edge with the text smoothly adjusting its offset + * throughout the sweep so it doesn't extend off-screen at the nearest edge. + */ + +#define ASC_DEFAULT_STRING "Hello rototiller!" +#define ASC_DEFAULT_HALIGN TXT_HALIGN_CENTER +#define ASC_DEFAULT_VALIGN TXT_VALIGN_CENTER +#define ASC_DEFAULT_X 0 +#define ASC_DEFAULT_Y 0 + + +typedef struct asc_setup_t { + til_setup_t til_setup; + + const char *string; + txt_halign_t halign; + txt_valign_t valign; + float x, y; +} asc_setup_t; + +typedef struct asc_context_t { + til_module_context_t til_module_context; + + txt_t *txt; +} asc_context_t; + + +static til_module_context_t * asc_create_context(const til_module_t *module, til_stream_t *stream, unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup) +{ + asc_context_t *ctxt; + + ctxt = til_module_context_new(module, sizeof(asc_context_t), stream, seed, ticks, n_cpus, setup); + if (!ctxt) + return NULL; + + ctxt->txt = txt_new(((asc_setup_t *)setup)->string); + if (!ctxt->txt) + return til_module_context_free(&ctxt->til_module_context); + + return &ctxt->til_module_context; +} + + +static void asc_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr) +{ + asc_context_t *ctxt = (asc_context_t *)context; + asc_setup_t *s = (asc_setup_t *)context->setup; + til_fb_fragment_t *fragment = *fragment_ptr; + + til_fb_fragment_clear(fragment); + + txt_render_fragment(ctxt->txt, fragment, 0xffffffff, + s->x * ((float)fragment->frame_width) * .5f + .5f * ((float)fragment->frame_width), + s->y * ((float)fragment->frame_height) * .5f + .5f * ((float)fragment->frame_height), + (txt_align_t){ + .horiz = s->halign, + .vert = s->valign + }); +} + + +static void asc_setup_free(til_setup_t *setup) +{ + asc_setup_t *s = (asc_setup_t *)setup; + + if (s) { + free((void *)s->string); + free(s); + } +} + + +static int asc_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup); + + +til_module_t asc_module = { + .create_context = asc_create_context, + .render_fragment = asc_render_fragment, + .setup = asc_setup, + .name = "asc", + .description = "ASCII text", + .author = "Vito Caputo <vcaputo@pengaru.com>", + .flags = TIL_MODULE_OVERLAYABLE, +}; + + +static int asc_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup) +{ + til_setting_t *string; + til_setting_t *valign; + til_setting_t *halign; + til_setting_t *x, *y; + const char *valign_values[] = { + "center", + "top", + "bottom", + NULL + }; + const char *halign_values[] = { + "center", + "left", + "right", + NULL + }; + int r; + + r = til_settings_get_and_describe_setting(settings, + &(til_setting_spec_t){ + .name = "Text string", + .key = "string", + /* .regex = "" TODO */ + .preferred = ASC_DEFAULT_STRING, + }, + &string, + res_setting, + res_desc); + if (r) + return r; + + r = til_settings_get_and_describe_setting(settings, + &(til_setting_spec_t){ + .name = "Vertical alignment", + .key = "valign", + /* .regex = "" TODO */ + .preferred = valign_values[ASC_DEFAULT_VALIGN], + .values = valign_values, + .annotations = NULL + }, + &valign, + res_setting, + res_desc); + if (r) + return r; + + r = til_settings_get_and_describe_setting(settings, + &(til_setting_spec_t){ + .name = "Horizontal alignment", + .key = "halign", + /* .regex = "" TODO */ + .preferred = halign_values[ASC_DEFAULT_HALIGN], + .values = halign_values, + .annotations = NULL + }, + &halign, + res_setting, + res_desc); + if (r) + return r; + + r = til_settings_get_and_describe_setting(settings, + &(til_setting_spec_t){ + .name = "X coordinate [-1.0...1.0]", + .key = "x", + /* .regex = "" TODO */ + .preferred = TIL_SETTINGS_STR(ASC_DEFAULT_X), + .annotations = NULL + }, + &x, + res_setting, + res_desc); + if (r) + return r; + + r = til_settings_get_and_describe_setting(settings, + &(til_setting_spec_t){ + .name = "Y coordinate [-1.0...1.0]", + .key = "y", + /* .regex = "" TODO */ + .preferred = TIL_SETTINGS_STR(ASC_DEFAULT_Y), + .annotations = NULL + }, + &y, + res_setting, + res_desc); + if (r) + return r; + + if (res_setup) { + asc_setup_t *setup; + + setup = til_setup_new(settings, sizeof(*setup), asc_setup_free, &asc_module); + if (!setup) + return -ENOMEM; + + setup->string = strdup(string->value); + if (!setup->string) + return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, string, res_setting, -ENOMEM); + + r = til_value_to_pos(halign_values, halign->value, (unsigned *)&setup->halign); + if (r < 0) + return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, halign, res_setting, -EINVAL); + + r = til_value_to_pos(valign_values, valign->value, (unsigned *)&setup->valign); + if (r < 0) + return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, valign, res_setting, -EINVAL); + + if (sscanf(x->value, "%f", &setup->x) != 1) + return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, x, res_setting, -EINVAL); + + if (sscanf(y->value, "%f", &setup->y) != 1) + return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, y, res_setting, -EINVAL); + + *res_setup = &setup->til_setup; + } + + return 0; +} |