billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=6dc89a5f6a94b9cbc62419e56fd028ff781feeaf

commit 6dc89a5f6a94b9cbc62419e56fd028ff781feeaf
Author: Boris Faure <[email protected]>
Date:   Thu Jun 4 00:20:08 2020 +0200

    termiolink: detect rgb() colors + utest
---
 src/bin/termiolink.c | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/bin/tytest.c     |   1 +
 src/bin/unit_tests.h |   1 +
 3 files changed, 335 insertions(+), 6 deletions(-)

diff --git a/src/bin/termiolink.c b/src/bin/termiolink.c
index 5e90662..c4bc112 100644
--- a/src/bin/termiolink.c
+++ b/src/bin/termiolink.c
@@ -1,6 +1,7 @@
 #include "private.h"
 #include <Elementary.h>
 #include <assert.h>
+#include <math.h>
 #include "termpty.h"
 #include "backlog.h"
 #include "termiolink.h"
@@ -834,6 +835,192 @@ _parse_uint8(struct ty_sb *sb,
    return ret;
 }
 
+static Eina_Bool
+_parse_one_css_rgb_color(struct ty_sb *sb,
+                         uint8_t *vp,
+                         Eina_Bool *is_percentp)
+{
+   char *endptr_double, *endptr_long;
+   double d;
+   long int l;
+
+   if (!sb->len)
+     return EINA_FALSE;
+
+   d = strtod(sb->buf, &endptr_double);
+   l = strtol(sb->buf, &endptr_long, 0);
+   if (isnan(d) || endptr_double == sb->buf || d < 0 || l < 0)
+       return EINA_FALSE;
+   if (endptr_double > endptr_long)
+     {
+        ty_sb_lskip(sb, endptr_double - sb->buf);
+        *is_percentp = sb->len && sb->buf[0] == '%';
+        if (*is_percentp)
+          {
+             ty_sb_lskip(sb, 1);
+             if (d > 100.0)
+               return EINA_FALSE;
+             d = (255.0 * d) / 100;
+          }
+        if (d > 255)
+          return EINA_FALSE;
+        *vp = round(d);
+     }
+   else
+     {
+        ty_sb_lskip(sb, endptr_long - sb->buf);
+        *is_percentp = sb->len && sb->buf[0] == '%';
+        if (*is_percentp)
+          {
+             ty_sb_lskip(sb, 1);
+             if (l > 100)
+               return EINA_FALSE;
+             l = (255 * l) / 100;
+          }
+        if (l > 255)
+          return EINA_FALSE;
+        *vp = (uint8_t)l;
+     }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_parse_one_css_alpha(struct ty_sb *sb,
+                     uint8_t *ap)
+{
+   char *endptr_double;
+   double d;
+
+   if (!sb->len)
+     return EINA_FALSE;
+
+   d = strtod(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] == '%')
+     {
+        ty_sb_lskip(sb, 1);
+        if (d > 100.0)
+          return EINA_FALSE;
+        d = (255.0 * d) / 100;
+     }
+   else
+     {
+        d *= 255.0;
+     }
+   if (d > 255)
+     return EINA_FALSE;
+   *ap = round(d);
+   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;
+
+   ty_sb_spaces_ltrim(sb);
+
+   if (!sbstartswith(sb, "hsl"))
+       return EINA_FALSE;
+   ty_sb_lskip(sb, 3);
+   if (sb->buf[0] == 'a')
+       ty_sb_lskip(sb, 1);
+   if (!sb->len) return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+   if (!sb->len || sb->buf[0] != '(')
+       return EINA_FALSE;
+   ty_sb_lskip(sb, 1);
+   if (!sb->len) return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+
+   /* TODO: boris */
+   *rp = r;
+   *gp = g;
+   *bp = b;
+   *ap = a;
+   return EINA_TRUE;
+}
+
+
+static Eina_Bool
+_parse_css_rgb_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;
+   Eina_Bool must_be_percent, is_percent, is_functional;
+
+   ty_sb_spaces_ltrim(sb);
+
+   if (!sbstartswith(sb, "rgb"))
+       return EINA_FALSE;
+   ty_sb_lskip(sb, 3);
+   if (sb->buf[0] == 'a')
+       ty_sb_lskip(sb, 1);
+   if (!sb->len) return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+   if (!sb->len || sb->buf[0] != '(')
+       return EINA_FALSE;
+   ty_sb_lskip(sb, 1);
+   if (!sb->len) return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+
+   if (!_parse_one_css_rgb_color(sb, &r, &must_be_percent))
+     return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+   is_functional = (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_css_rgb_color(sb, &g, &is_percent))
+     return EINA_FALSE;
+   if (is_percent != must_be_percent)
+     return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+   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_css_rgb_color(sb, &b, &is_percent))
+     return EINA_FALSE;
+   if (is_percent != must_be_percent)
+     return EINA_FALSE;
+   ty_sb_spaces_ltrim(sb);
+   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] != ')')
+          ty_sb_lskip(sb, 1);
+     }
+
+   *rp = r;
+   *gp = g;
+   *bp = b;
+   *ap = a;
+   return EINA_TRUE;
+}
+
 static Eina_Bool
 _parse_edc_color(struct ty_sb *sb,
                  uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
@@ -858,6 +1045,10 @@ _parse_edc_color(struct ty_sb *sb,
    if (!sb->len) return EINA_FALSE;
    if (sb->buf[0] == '#')
      return _parse_sharp_color(sb, rp, gp, bp, ap);
+   if (sbstartswith(sb, "rgb"))
+       return _parse_css_rgb_color(sb, rp, gp, bp, ap);
+   if (sbstartswith(sb, "hsl"))
+       return _parse_css_hsl_color(sb, rp, gp, bp, ap);
 
    if (!_parse_uint8(sb, &r)) return EINA_FALSE;
    ty_sb_spaces_ltrim(sb);
@@ -1050,7 +1241,9 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
 
         x1 = new_x1;
         y1 = new_y1;
-        if (sbstartswith(&sb, "color"))
+        if (sbstartswith(&sb, "rgb") ||
+            sbstartswith(&sb, "hsl") ||
+            sbstartswith(&sb, "color"))
           {
              goback = EINA_FALSE;
              goforward = EINA_TRUE;
@@ -1104,18 +1297,31 @@ termio_color_find(const Evas_Object *obj, int cx, int 
cy,
    if (!sb.len)
      goto end;
 
-   if (sb.len > 6 && strncmp(sb.buf, "color", 5) == 0)
+   if (sb.buf[0] == '#')
+     {
+        if (!_parse_sharp_color(&sb, &r, &g, &b, &a))
+          goto end;
+     }
+   else if (sbstartswith(&sb, "color"))
      {
         if (!_parse_edc_color(&sb, &r, &g, &b, &a))
           goto end;
-        found = EINA_TRUE;
      }
-   else if (sb.buf[0] == '#')
+   else if (sbstartswith(&sb, "rgb"))
      {
-        if (!_parse_sharp_color(&sb, &r, &g, &b, &a))
+        if (!_parse_css_rgb_color(&sb, &r, &g, &b, &a))
           goto end;
-        found = EINA_TRUE;
      }
+   else if (sbstartswith(&sb, "hsl"))
+     {
+        if (!_parse_css_hsl_color(&sb, &r, &g, &b, &a))
+          goto end;
+     }
+   else
+     goto end;
+
+   found = EINA_TRUE;
+   /* TODO: right trim */
 
 end:
    termpty_backlog_unlock();
@@ -1383,4 +1589,125 @@ tytest_color_parse_edc(void)
 
    return 0;
 }
+
+int
+tytest_color_parse_css_rgb(void)
+{
+   struct ty_sb sb = {};
+   uint8_t r = 0, g = 0, b = 0, a = 0;
+
+   /* (rgb) Functional syntax */
+   assert(TY_SB_ADD(&sb, "rgb(255,1,153)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 1 && b == 153 && a == 255);
+   ty_sb_free(&sb);
+
+   assert(TY_SB_ADD(&sb, "rgb(254, 2, 152)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 254 && g == 2 && b == 152 && a == 255);
+   ty_sb_free(&sb);
+
+   assert(TY_SB_ADD(&sb, "rgb(253, 3, 151.0)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 253 && g == 3 && b == 151 && a == 255);
+   ty_sb_free(&sb);
+
+   /* (rgb) Percents */
+   assert(TY_SB_ADD(&sb, "rgb(100%,4%,40%)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 10 && b == 102 && a == 255);
+   ty_sb_free(&sb);
+
+   assert(TY_SB_ADD(&sb, "rgb(50%, 0%, 60%)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 127 && g == 0 && b == 153 && a == 255);
+   ty_sb_free(&sb);
+
+   /* (rgb) ERROR! Don't mix numbers and percentages. */
+   assert(TY_SB_ADD(&sb, "rgb(100%, 0, 60%)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_FALSE);
+   ty_sb_free(&sb);
+
+   /* (rgb) Functional syntax with alpha value */
+   assert(TY_SB_ADD(&sb, "rgb(254, 1, 150, 0)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 254 && g == 1 && b == 150 && a == 0);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgb(253, 2, 149, 1)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 253 && g == 2 && b == 149 && a == 255);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgb(252, 3, 148, 50%)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 252 && g == 3 && b == 148 && a == 128);
+   ty_sb_free(&sb);
+
+   /* (rgb) Whitespace syntax */
+   assert(TY_SB_ADD(&sb, "rgb(255 0 153)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 0 && b == 153 && a == 255);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgb(254 1 152 / 0)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 254 && g == 1 && b == 152 && a == 0);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgb(253 2 151 / 100%)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 253 && g == 2 && b == 151 && a == 255);
+   ty_sb_free(&sb);
+
+   /* (rgb) Functional syntax with floats value */
+   assert(TY_SB_ADD(&sb, "rgb(255, 0, 153.6, 1)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 0 && b == 154 && a == 255);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgb(1e2, .5e1, .5e0, +.25e2%)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 100 && g == 5 && b == 1 && a == 64);
+   ty_sb_free(&sb);
+
+   /* (rgba) Functional syntax */
+   assert(TY_SB_ADD(&sb, "rgba(51, 170, 51, .1)") == 0); /*  10% opaque green 
*/
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 51 && g == 170 && b == 51 && a == 26);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgba(50, 171, 52, .4)") == 0); /*  40% opaque green 
*/
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 50 && g == 171 && b == 52 && a == 102);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgba(49, 172, 53, .7)") == 0); /*  70% opaque green 
*/
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 49 && g == 172 && b == 53 && a == 179);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgba(48, 173, 54,  1)") == 0); /* full opaque green 
*/
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 48 && g == 173 && b == 54 && a == 255);
+   ty_sb_free(&sb);
+
+   /* (rgba) Whitespace syntax */
+   assert(TY_SB_ADD(&sb, "rgba(51 170 51 / 0.4)") == 0); /*  40% opaque green 
*/
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 51 && g == 170 && b == 51 && a == 102);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgba(50 171 50 / 70%)") == 0); /*  40% opaque green 
*/
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 50 && g == 171 && b == 50 && a == 179);
+   ty_sb_free(&sb);
+   /* (rgba) ERROR! invalid alpha */
+   assert(TY_SB_ADD(&sb, "rgba(51 170 51 / 40)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_FALSE);
+   ty_sb_free(&sb);
+
+   /* (rgba) Functional syntax with floats value */
+   assert(TY_SB_ADD(&sb, "rgba(255, 0, 153.6, 1)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 255 && g == 0 && b == 154 && a == 255);
+   ty_sb_free(&sb);
+   assert(TY_SB_ADD(&sb, "rgba(1e2, .5e1, .5e0, +.25e2%)") == 0);
+   assert(_parse_css_rgb_color(&sb, &r, &g, &b, &a) == EINA_TRUE);
+   assert(r == 100 && g == 5 && b == 1 && a == 64);
+   ty_sb_free(&sb);
+
+   return 0;
+}
 #endif
diff --git a/src/bin/tytest.c b/src/bin/tytest.c
index ebe02b8..50a826c 100644
--- a/src/bin/tytest.c
+++ b/src/bin/tytest.c
@@ -38,6 +38,7 @@ static struct {
        { "color_parse_sharp", tytest_color_parse_sharp},
        { "color_parse_uint8", tytest_color_parse_uint8},
        { "color_parse_edc", tytest_color_parse_edc},
+       { "color_parse_css_rgb", tytest_color_parse_css_rgb},
        { NULL, NULL},
 };
 
diff --git a/src/bin/unit_tests.h b/src/bin/unit_tests.h
index f48e5d5..2894724 100644
--- a/src/bin/unit_tests.h
+++ b/src/bin/unit_tests.h
@@ -15,5 +15,6 @@ int tytest_color_parse_2hex(void);
 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);
 
 #endif

-- 


Reply via email to