summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/asc/asc.c202
1 files changed, 157 insertions, 45 deletions
diff --git a/src/modules/asc/asc.c b/src/modules/asc/asc.c
index d47ac6d..98455a7 100644
--- a/src/modules/asc/asc.c
+++ b/src/modules/asc/asc.c
@@ -16,29 +16,31 @@
/* 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:
- * - 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_JUSTIFY ASC_JUSTIFY_ALIGNED
#define ASC_DEFAULT_HALIGN TXT_HALIGN_CENTER
#define ASC_DEFAULT_VALIGN TXT_VALIGN_CENTER
+#define ASC_DEFAULT_HOFFSET "auto"
+#define ASC_DEFAULT_VOFFSET "auto"
#define ASC_DEFAULT_X 0
#define ASC_DEFAULT_Y 0
+typedef enum asc_justify_t {
+ ASC_JUSTIFY_ALIGNED,
+ ASC_JUSTIFY_OFFSETTED,
+ ASC_JUSITFY_CNT
+} asc_justify_t;
+
typedef struct asc_setup_t {
til_setup_t til_setup;
const char *string;
- txt_halign_t halign;
- txt_valign_t valign;
+ asc_justify_t justify;
+ txt_halign_t halign, valign;
+ float hoffset, voffset;
float x, y;
} asc_setup_t;
@@ -47,13 +49,16 @@ typedef struct asc_context_t {
struct {
til_tap_t x, y;
+ til_tap_t hoffset, voffset;
} taps;
struct {
float x, y;
+ float hoffset, voffset;
} vars;
float *x, *y;
+ float *hoffset, *voffset;
txt_t *txt;
} asc_context_t;
@@ -71,9 +76,22 @@ static void asc_update_taps(asc_context_t *ctxt, til_stream_t *stream)
else
ctxt->vars.y = *ctxt->y;
- /* XXX: maybe clamp to -1.0..+1.0 ? It's not a crash risk since txt_render_fragment()
+ /* XXX: maybe clamp to -1.0..+1.0 ? It's not a crash risk since txt_render_fragment_aligned()
* clips to the fragment by using ...put_pixel_checked() *shrug*
*/
+
+ if (((asc_setup_t *)ctxt->til_module_context.setup)->justify != ASC_JUSTIFY_OFFSETTED)
+ return;
+
+ if (!til_stream_tap_context(stream, &ctxt->til_module_context, NULL, &ctxt->taps.hoffset))
+ *ctxt->hoffset = ((asc_setup_t *)ctxt->til_module_context.setup)->hoffset;
+ else
+ ctxt->vars.hoffset = *ctxt->hoffset;
+
+ if (!til_stream_tap_context(stream, &ctxt->til_module_context, NULL, &ctxt->taps.voffset))
+ *ctxt->voffset = ((asc_setup_t *)ctxt->til_module_context.setup)->voffset;
+ else
+ ctxt->vars.voffset = *ctxt->voffset;
}
@@ -92,6 +110,11 @@ static til_module_context_t * asc_create_context(const til_module_t *module, til
ctxt->taps.x = til_tap_init_float(ctxt, &ctxt->x, 1, &ctxt->vars.x, "x");
ctxt->taps.y = til_tap_init_float(ctxt, &ctxt->y, 1, &ctxt->vars.y, "y");
+ if (((asc_setup_t *)setup)->justify == ASC_JUSTIFY_OFFSETTED) {
+ ctxt->taps.hoffset = til_tap_init_float(ctxt, &ctxt->hoffset, 1, &ctxt->vars.hoffset, "hoffset");
+ ctxt->taps.voffset = til_tap_init_float(ctxt, &ctxt->voffset, 1, &ctxt->vars.voffset, "voffset");
+ }
+
asc_update_taps(ctxt, stream);
return &ctxt->til_module_context;
@@ -108,13 +131,35 @@ static void asc_render_fragment(til_module_context_t *context, til_stream_t *str
til_fb_fragment_clear(fragment);
- txt_render_fragment_aligned(ctxt->txt, fragment, 0xffffffff,
- ctxt->vars.x * ((float)fragment->frame_width) * .5f + .5f * ((float)fragment->frame_width),
- ctxt->vars.y * ((float)fragment->frame_height) * .5f + .5f * ((float)fragment->frame_height),
- (txt_align_t){
- .horiz = s->halign,
- .vert = s->valign
- });
+ switch (s->justify) {
+ case ASC_JUSTIFY_ALIGNED:
+ return txt_render_fragment_aligned(ctxt->txt, fragment, 0xffffffff,
+ ctxt->vars.x * ((float)fragment->frame_width) * .5f + .5f * ((float)fragment->frame_width),
+ ctxt->vars.y * ((float)fragment->frame_height) * .5f + .5f * ((float)fragment->frame_height),
+ (txt_align_t){
+ .horiz = s->halign,
+ .vert = s->valign
+ });
+
+ case ASC_JUSTIFY_OFFSETTED: {
+ float hoffset = ctxt->vars.hoffset,
+ voffset = ctxt->vars.voffset;
+
+ if (isnan(hoffset))
+ hoffset = ctxt->vars.x;
+
+ if (isnan(voffset))
+ voffset = ctxt->vars.y;
+
+ return txt_render_fragment_offsetted(ctxt->txt, fragment, 0xffffffff,
+ ctxt->vars.x * ((float)fragment->frame_width) * .5f + .5f * ((float)fragment->frame_width),
+ ctxt->vars.y * ((float)fragment->frame_height) * .5f + .5f * ((float)fragment->frame_height),
+ hoffset, voffset);
+ }
+
+ default:
+ assert(0);
+ }
}
@@ -146,9 +191,15 @@ til_module_t asc_module = {
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 *justify;
+ til_setting_t *valign, *voffset;
+ til_setting_t *halign, *hoffset;
til_setting_t *x, *y;
+ const char *justify_values[] = {
+ "aligned",
+ "offsetted",
+ NULL
+ };
const char *valign_values[] = {
"center",
"top",
@@ -178,33 +229,78 @@ static int asc_setup(const til_settings_t *settings, til_setting_t **res_setting
r = til_settings_get_and_describe_setting(settings,
&(til_setting_spec_t){
- .name = "Vertical alignment",
- .key = "valign",
+ .name = "Justification",
+ .key = "justify",
/* .regex = "" TODO */
- .preferred = valign_values[ASC_DEFAULT_VALIGN],
- .values = valign_values,
+ .preferred = justify_values[ASC_DEFAULT_JUSTIFY],
+ .values = justify_values,
.annotations = NULL
},
- &valign,
+ &justify,
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;
+ if (!strcasecmp(justify->value, justify_values[ASC_JUSTIFY_ALIGNED])) {
+ 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;
+ } else {
+ r = til_settings_get_and_describe_setting(settings,
+ &(til_setting_spec_t){
+ .name = "Vertical offset [-1.0...1.0] or 'auto'",
+ .key = "voffset",
+ /* .regex = "" TODO */
+ .preferred = ASC_DEFAULT_VOFFSET,
+ .annotations = NULL
+ },
+ &voffset,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ r = til_settings_get_and_describe_setting(settings,
+ &(til_setting_spec_t){
+ .name = "Horizontal offset [-1.0...1.0] or 'auto'",
+ .key = "hoffset",
+ /* .regex = "" TODO */
+ .preferred = ASC_DEFAULT_HOFFSET,
+ .annotations = NULL
+ },
+ &hoffset,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+ }
r = til_settings_get_and_describe_setting(settings,
&(til_setting_spec_t){
@@ -245,13 +341,29 @@ static int asc_setup(const til_settings_t *settings, til_setting_t **res_setting
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);
+ r = til_value_to_pos(justify_values, justify->value, (unsigned *)&setup->justify);
if (r < 0)
- return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, valign, res_setting, -EINVAL);
+ return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, justify, res_setting, -EINVAL);
+
+ if (setup->justify == ASC_JUSTIFY_ALIGNED) {
+ 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);
+ } else {
+ if (!strcasecmp(hoffset->value, "auto"))
+ setup->hoffset = NAN;
+ else if (sscanf(hoffset->value, "%f", &setup->hoffset) != 1)
+ return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, hoffset, res_setting, -EINVAL);
+
+ if (!strcasecmp(voffset->value, "auto"))
+ setup->voffset = NAN;
+ else if (sscanf(voffset->value, "%f", &setup->voffset) != 1)
+ return til_setup_free_with_failed_setting_ret_err(&setup->til_setup, voffset, 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);
© All Rights Reserved