forked from enlightenment/terminology
termiolink: detect rgb() colors + utest
This commit is contained in:
parent
1e8d5db14c
commit
6dc89a5f6a
|
@ -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 (!_parse_edc_color(&sb, &r, &g, &b, &a))
|
||||
goto end;
|
||||
found = EINA_TRUE;
|
||||
}
|
||||
else if (sb.buf[0] == '#')
|
||||
if (sb.buf[0] == '#')
|
||||
{
|
||||
if (!_parse_sharp_color(&sb, &r, &g, &b, &a))
|
||||
goto end;
|
||||
found = EINA_TRUE;
|
||||
}
|
||||
else if (sbstartswith(&sb, "color"))
|
||||
{
|
||||
if (!_parse_edc_color(&sb, &r, &g, &b, &a))
|
||||
goto end;
|
||||
}
|
||||
else if (sbstartswith(&sb, "rgb"))
|
||||
{
|
||||
if (!_parse_css_rgb_color(&sb, &r, &g, &b, &a))
|
||||
goto end;
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue