termiolink: parse css hsl color + unit test
This commit is contained in:
parent
8d1d854bdf
commit
1866e43386
|
@ -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
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue