billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=1866e4338667b346378a3fe5bb0c82d98b547d54

commit 1866e4338667b346378a3fe5bb0c82d98b547d54
Author: Boris Faure <[email protected]>
Date:   Thu Jun 11 00:44:52 2020 +0200

    termiolink: parse css hsl color + unit test
---
 src/bin/termiolink.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/bin/tytest.c     |   1 +
 src/bin/unit_tests.h |   1 +
 3 files changed, 264 insertions(+), 1 deletion(-)

diff --git a/src/bin/termiolink.c b/src/bin/termiolink.c
index dba8d3c..6f2b225 100644
--- a/src/bin/termiolink.c
+++ b/src/bin/termiolink.c
@@ -904,11 +904,106 @@ _parse_one_css_alpha(struct ty_sb *sb,
    return EINA_TRUE;
 }
 
+/* return hue between 0 and 1 */
+static Eina_Bool
+_parse_one_hue(struct ty_sb *sb,
+               double *dp)
+{
+   char *endptr_double;
+   double d;
+
+   if (!sb->len)
+     return EINA_FALSE;
+
+   d = eina_convert_strtod_c(sb->buf, &endptr_double);
+   if (isnan(d) || endptr_double == sb->buf || d < 0)
+       return EINA_FALSE;
+   ty_sb_lskip(sb, endptr_double - sb->buf);
+   if (sbstartswith(sb, "turn"))
+     {
+        ty_sb_lskip(sb, strlen("turn"));
+     }
+   else if (sbstartswith(sb, "rad"))
+     {
+          ty_sb_lskip(sb, strlen("rad"));
+          d /= 2 * M_PI;
+     }
+   else if (sbstartswith(sb, "grad"))
+     {
+          ty_sb_lskip(sb, strlen("grad"));
+          d /= 400;
+     }
+   else if (sbstartswith(sb, "deg") || sb->buf[0] == ',' || sb->buf[0] == ' ')
+     {
+        if (sbstartswith(sb, "deg"))
+          ty_sb_lskip(sb, strlen("deg"));
+        d /= 360;
+     }
+   else
+     return EINA_FALSE;
+   d = d - (long) d;
+   if (d < 0)
+     d = 1 + d;
+   *dp = d;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_parse_one_percent(struct ty_sb *sb,
+                   double *dp)
+{
+   char *endptr_double;
+   double d;
+
+   if (!sb->len)
+     return EINA_FALSE;
+
+   d = eina_convert_strtod_c(sb->buf, &endptr_double);
+   if (isnan(d) || endptr_double == sb->buf || d < 0)
+       return EINA_FALSE;
+   ty_sb_lskip(sb, endptr_double - sb->buf);
+   if (!sb->len || sb->buf[0] != '%') return EINA_FALSE;
+   ty_sb_lskip(sb, 1);
+   if (d > 100.0)
+     return EINA_FALSE;
+   d /= 100.0;
+   *dp = d;
+   return EINA_TRUE;
+}
+
+
+/* From http://en.wikipedia.org/wiki/HSL_color_space */
+static Eina_Bool
+_hsl_to_rgb(double hue, double saturation, double lightness,
+            uint8_t *rp, uint8_t *gp, uint8_t *bp)
+{
+   double a = saturation * MIN(lightness, 1.0 - lightness);
+   int n[3] = {0, 8, 4};
+   double res[3] = {};
+   int i;
+
+   for (i = 0; i < 3; i++)
+     {
+        double k = fmod(n[i] + hue / 12., 12.);
+        double f = lightness - a * MAX(-1, MIN(MIN(k - 3, 9 - k), 1));
+        if (f > 1 || f < 0)
+          return EINA_FALSE;
+        res[i] = f * 255.0;
+     }
+
+   *rp = res[0];
+   *gp = res[1];
+   *bp = res[2];
+   return EINA_TRUE;
+}
+
 static Eina_Bool
 _parse_css_hsl_color(struct ty_sb *sb,
                      uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
 {
    uint8_t r = 0, g = 0, b = 0, a = 255;
+   double hue, saturation, lightness;
+   Eina_Bool is_functional;
 
    ty_sb_spaces_ltrim(sb);
 
@@ -925,7 +1020,54 @@ _parse_css_hsl_color(struct ty_sb *sb,
    if (!sb->len) return EINA_FALSE;
    ty_sb_spaces_ltrim(sb);
 
-   /* TODO: boris */
+   if (!_parse_one_hue(sb, &hue))
+     return EINA_FALSE;
+   is_functional = (sb->len && sb->buf[0] == ',');
+   if (is_functional)
+     {
+        ty_sb_lskip(sb, 1);
+     }
+   ty_sb_spaces_ltrim(sb);
+   if (!sb->len) return EINA_FALSE;
+
+   if (!_parse_one_percent(sb, &saturation))
+     return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+   if (!sb->len) return EINA_FALSE;
+   if (is_functional != (sb->buf[0] == ','))
+     return EINA_FALSE;
+   if (is_functional)
+     ty_sb_lskip(sb, 1);
+   ty_sb_spaces_ltrim(sb);
+   if (!sb->len) return EINA_FALSE;
+
+   if (!_parse_one_percent(sb, &lightness))
+     return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+   if (!sb->len) return EINA_FALSE;
+   if (sb->buf[0] == ')')
+     {
+        ty_sb_lskip(sb, 1);
+        a = 255;
+     }
+   else
+     {
+        if ((is_functional && (sb->buf[0] != ',')) ||
+            (!is_functional && (sb->buf[0] != '/')))
+          return EINA_FALSE;
+        if (!sb->len) return EINA_FALSE;
+        ty_sb_lskip(sb, 1);
+        ty_sb_spaces_ltrim(sb);
+        if (!sb->len) return EINA_FALSE;
+        if (!_parse_one_css_alpha(sb, &a))
+          return EINA_FALSE;
+        ty_sb_spaces_ltrim(sb);
+        if (sb->buf[0] != ')')
+          return EINA_FALSE;
+     }
+   if (!_hsl_to_rgb(hue, saturation, lightness, &r, &g, &b))
+     return EINA_FALSE;
+
    *rp = r;
    *gp = g;
    *bp = b;
@@ -1692,4 +1834,123 @@ tytest_color_parse_css_rgb(void)
 
    return 0;
 }
+
+int
+tytest_color_parse_css_hsl(void)
+{
+   struct ty_sb sb = {};
+   uint8_t r = 0, g = 0, b = 0, a = 0;
+
+
+   /* These examples all specify the same color: a lavender. */
+   assert(TY_SB_ADD(&sb, "hsl(270,60%,70%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 224 && g == 135 && b == 132 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(270, 60%, 70%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 224 && g == 135 && b == 132 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(270 60% 70%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 224 && g == 135 && b == 132 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(270deg, 60%, 70%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 224 && g == 135 && b == 132 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(4.71239rad, 60%, 70%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 224 && g == 135 && b == 132 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(300grad, 60%, 70%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 224 && g == 135 && b == 132 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(.75turn, 60%, 70%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 224 && g == 135 && b == 132 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+
+   /* These examples all specify the same color: a lavender that is 15% 
opaque. */
+   assert(TY_SB_ADD(&sb, "hsl(270, 60%, 50%, .15)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 204 && g == 55 && b == 51 && a == 38);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(270, 60%, 50%, 15%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 204 && g == 55 && b == 51 && a == 38);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(270 60% 50% / .15)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 204 && g == 55 && b == 51 && a == 38);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsl(270 60% 50% / 15%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 204 && g == 55 && b == 51 && a == 38);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+
+   /* Different shades */
+   assert(TY_SB_ADD(&sb, "hsla(240, 100%, 50%, .05)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 7 && b == 0 && a == 13);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsla(240, 100%, 50%, .4)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 7 && b == 0 && a == 102);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsla(240, 100%, 50%, .7)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 7 && b == 0 && a == 179);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   assert(TY_SB_ADD(&sb, "hsla(240, 100%, 50%, 1)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 7 && b == 0 && a == 255);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   /* Whitespace syntax */
+   assert(TY_SB_ADD(&sb, "hsla(240 100% 50% / .05)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 7 && b == 0 && a == 13);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   /* Percentage value for alpha */
+   assert(TY_SB_ADD(&sb, "hsla(240 100% 50% / 5%)") == 0);
+   assert(_parse_css_hsl_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 7 && b == 0 && a == 13);
+   ty_sb_free(&sb);
+   r = g = b = a = 0;
+
+   return 0;
+}
 #endif
diff --git a/src/bin/tytest.c b/src/bin/tytest.c
index 50a826c..b501ee5 100644
--- a/src/bin/tytest.c
+++ b/src/bin/tytest.c
@@ -39,6 +39,7 @@ static struct {
        { "color_parse_uint8", tytest_color_parse_uint8},
        { "color_parse_edc", tytest_color_parse_edc},
        { "color_parse_css_rgb", tytest_color_parse_css_rgb},
+       { "color_parse_css_hsl", tytest_color_parse_css_hsl},
        { NULL, NULL},
 };
 
diff --git a/src/bin/unit_tests.h b/src/bin/unit_tests.h
index 2894724..d429f7b 100644
--- a/src/bin/unit_tests.h
+++ b/src/bin/unit_tests.h
@@ -16,5 +16,6 @@ int tytest_color_parse_sharp(void);
 int tytest_color_parse_uint8(void);
 int tytest_color_parse_edc(void);
 int tytest_color_parse_css_rgb(void);
+int tytest_color_parse_css_hsl(void);
 
 #endif

-- 


Reply via email to