summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-10-03 12:36:00 -0700
committerVito Caputo <vcaputo@pengaru.com>2023-10-03 12:36:00 -0700
commit9a086395644521854ca450821b552fcb67c95aea (patch)
treebd2d70ff8b07461c6aa1b8fbe964b5b3a73ec9a5
parent914c5e5752eb30e1d1108fac2d94897e92b937bd (diff)
modules/asc: implement a simple ascii text module
This just binds the simple libs/txt/txt.c stuff to a rendering module, exposing the minimal options as settings. It's handy for testing libs/txt/txt.c, and introduces a module requiring free-form strings potentially including newlines be handled properly as settings values. This latter aspect is important for improving settings syntax, any improvements must handle these more complicated scenarios and now there's a good test case for exercising those nuances. I suppose there might also be use in the creative process if you want a text element but haven't got around to hacking up a prettier module for it yet. Just use this one temporarily. See commit for some remaining TODO items.
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/modules/Makefile.am2
-rw-r--r--src/modules/asc/Makefile.am3
-rw-r--r--src/modules/asc/asc.c231
-rw-r--r--src/til.c2
6 files changed, 239 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 6129aed..9ebc957 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,7 @@ AC_CONFIG_FILES([
src/libs/sig/Makefile
src/libs/txt/Makefile
src/modules/Makefile
+ src/modules/asc/Makefile
src/modules/blinds/Makefile
src/modules/checkers/Makefile
src/modules/compose/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 149d2d1..5d4c982 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@ SUBDIRS = libs modules
noinst_LTLIBRARIES = libtil.la
libtil_la_SOURCES = til.c til.h til_args.c til_args.h til_builtins.c til_fb.c til_fb.h til_jenkins.c til_jenkins.h til_limits.h til_module_context.c til_module_context.h til_settings.h til_settings.c til_setup.c til_setup.h til_str.c til_str.h til_stream.c til_stream.h til_tap.h til_threads.c til_threads.h til_util.c til_util.h
libtil_la_CPPFLAGS = -I@top_srcdir@/src
-libtil_la_LIBADD = modules/blinds/libblinds.la modules/checkers/libcheckers.la modules/compose/libcompose.la modules/drizzle/libdrizzle.la modules/flow/libflow.la modules/flui2d/libflui2d.la modules/julia/libjulia.la modules/meta2d/libmeta2d.la modules/mixer/libmixer.la modules/moire/libmoire.la modules/montage/libmontage.la modules/pixbounce/libpixbounce.la modules/plasma/libplasma.la modules/plato/libplato.la modules/ray/libray.la modules/rkt/librkt.la modules/roto/libroto.la modules/rtv/librtv.la modules/shapes/libshapes.la modules/signals/libsignals.la modules/snow/libsnow.la modules/sparkler/libsparkler.la modules/spiro/libspiro.la modules/stars/libstars.la modules/strobe/libstrobe.la modules/submit/libsubmit.la modules/swab/libswab.la modules/swarm/libswarm.la modules/voronoi/libvoronoi.la libs/grid/libgrid.la libs/puddle/libpuddle.la libs/ray/libray.la libs/rocket/librocket.la libs/sig/libsig.la libs/txt/libtxt.la libs/ascii/libascii.la libs/din/libdin.la
+libtil_la_LIBADD = modules/asc/libasc.la modules/blinds/libblinds.la modules/checkers/libcheckers.la modules/compose/libcompose.la modules/drizzle/libdrizzle.la modules/flow/libflow.la modules/flui2d/libflui2d.la modules/julia/libjulia.la modules/meta2d/libmeta2d.la modules/mixer/libmixer.la modules/moire/libmoire.la modules/montage/libmontage.la modules/pixbounce/libpixbounce.la modules/plasma/libplasma.la modules/plato/libplato.la modules/ray/libray.la modules/rkt/librkt.la modules/roto/libroto.la modules/rtv/librtv.la modules/shapes/libshapes.la modules/signals/libsignals.la modules/snow/libsnow.la modules/sparkler/libsparkler.la modules/spiro/libspiro.la modules/stars/libstars.la modules/strobe/libstrobe.la modules/submit/libsubmit.la modules/swab/libswab.la modules/swarm/libswarm.la modules/voronoi/libvoronoi.la libs/grid/libgrid.la libs/puddle/libpuddle.la libs/ray/libray.la libs/rocket/librocket.la libs/sig/libsig.la libs/txt/libtxt.la libs/ascii/libascii.la libs/din/libdin.la
bin_PROGRAMS = rototiller
rototiller_SOURCES = fps.c fps.h main.c mem_fb.c setup.h setup.c til.h til_fb.c til_fb.h til_settings.c til_settings.h til_threads.c til_threads.h til_util.c til_util.h
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;
+}
diff --git a/src/til.c b/src/til.c
index 2ebc0a8..6b4fd99 100644
--- a/src/til.c
+++ b/src/til.c
@@ -28,6 +28,7 @@
static til_threads_t *til_threads;
static struct timeval til_start_tv;
+extern til_module_t asc_module;
extern til_module_t blinds_module;
extern til_module_t checkers_module;
extern til_module_t compose_module;
@@ -65,6 +66,7 @@ extern til_module_t _noop_module;
extern til_module_t _ref_module;
static const til_module_t *modules[] = {
+ &asc_module,
&blinds_module,
&checkers_module,
&compose_module,
© All Rights Reserved