From 8e71e0f64f1517438337b5eb6634f1324a61dc22 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 12 Jul 2025 18:26:55 +0100 Subject: [PATCH 1/5] parse: properties: utils: hsl: Allow for hue --- src/parse/properties/utils.c | 50 +++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c index 687e8d9..ccd2044 100644 --- a/src/parse/properties/utils.c +++ b/src/parse/properties/utils.c @@ -501,20 +501,62 @@ static bool parse_hsl( size_t consumed = 0; css_fixed hue, sat, lit; int32_t alpha = 255; + css_error error; uint8_t r = 0, g = 0, b = 0, a = 0xff; /* hue is a number without a unit representing an - * angle (0-360) degrees + * angle (0-360) degrees, or it can be an angle dimension. */ consumeWhitespace(vector, ctx); token = parserutils_vector_iterate(vector, ctx); - if ((token == NULL) || (token->type != CSS_TOKEN_NUMBER)) + if ((token == NULL) || + (token->type != CSS_TOKEN_NUMBER && + token->type != CSS_TOKEN_DIMENSION)) { return false; + } hue = css__number_from_lwc_string(token->idata, false, &consumed); - if (consumed != lwc_string_length(token->idata)) - return false; /* failed to consume the whole string as a number */ + + switch (token->type) { + case CSS_TOKEN_NUMBER: + if (consumed != lwc_string_length(token->idata)) { + return false; /* failed to consume the whole string as a number */ + } + break; + case CSS_TOKEN_DIMENSION: { + size_t len = lwc_string_length(token->idata); + const char *data = lwc_string_data(token->idata); + uint32_t unit = UNIT_DEG; + + error = css__parse_unit_keyword( + data + consumed, + len - consumed, + &unit); + if (error != CSS_OK) { + return false; + } + + switch (unit) { + case UNIT_DEG: + break; + case UNIT_RAD: + hue = FDIV(FMUL(hue, F_180), F_PI); + break; + case UNIT_GRAD: + hue = FMUL(hue, FLTTOFIX(0.9)); + break; + case UNIT_TURN: + hue = FMUL(hue, F_360); + break; + default: + return false; + } + } + break; + default: + return false; /* unexpected token type */ + } /* Normalise hue to the range [0, 360) */ while (hue < 0) From bf5ec81353e11abdf300cce714c2bfe8022c8ccb Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 12 Jul 2025 18:49:20 +0100 Subject: [PATCH 2/5] parse: properties: utils: hsl and hsla are interchangable --- src/parse/properties/utils.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c index ccd2044..8463dcb 100644 --- a/src/parse/properties/utils.c +++ b/src/parse/properties/utils.c @@ -487,14 +487,12 @@ static bool parse_rgb( * * \param vector Vector of tokens to process * \param ctx Pointer to vector iteration context - * \param colour_channels Number of colour channels to expect * \param result Pointer to location to receive result (AARRGGBB) * \return true on success, false on error. */ static bool parse_hsl( const parserutils_vector *vector, int32_t *ctx, - int colour_channels, uint32_t *result) { const css_token *token; @@ -616,12 +614,7 @@ static bool parse_hsl( token = parserutils_vector_iterate(vector, ctx); - if (colour_channels == 6) { - /* alpha */ - - if (!tokenIsChar(token, ',')) - return false; - + if (tokenIsChar(token, ',')) { consumeWhitespace(vector, ctx); token = parserutils_vector_iterate(vector, ctx); @@ -773,7 +766,7 @@ css_error css__parse_colour_specifier(css_language *c, goto invalid; } } else if (colour_channels == 5 || colour_channels == 6) { - if (!parse_hsl(vector, ctx, colour_channels, result)) { + if (!parse_hsl(vector, ctx, result)) { goto invalid; } } else { From 73002dbbf8a32e70b5d02ea9facb2c0a9ffe7536 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 13 Jul 2025 12:21:40 +0100 Subject: [PATCH 3/5] parse: properties: utils: hsl: Alpha can be percentage --- src/parse/properties/utils.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c index 8463dcb..985accd 100644 --- a/src/parse/properties/utils.c +++ b/src/parse/properties/utils.c @@ -618,19 +618,27 @@ static bool parse_hsl( consumeWhitespace(vector, ctx); token = parserutils_vector_iterate(vector, ctx); - if ((token == NULL) || (token->type != CSS_TOKEN_NUMBER)) + if ((token == NULL) || + (token->type != CSS_TOKEN_NUMBER && + token->type != CSS_TOKEN_PERCENTAGE)) { return false; + } alpha = css__number_from_lwc_string(token->idata, false, &consumed); - if (consumed != lwc_string_length(token->idata)) - return false; /* failed to consume the whole string as a number */ + if (consumed != lwc_string_length(token->idata)) { + /* failed to consume the whole string as a number */ + return false; + } - alpha = FIXTOINT(FMUL(alpha, F_255)); + if (token->type != CSS_TOKEN_NUMBER) { + alpha = FIXTOINT(FMUL(alpha, F_255)); + } else { + alpha = FIXTOINT(FDIV(FMUL(alpha, F_255), F_100)); + } consumeWhitespace(vector, ctx); token = parserutils_vector_iterate(vector, ctx); - } if (!tokenIsChar(token, ')')) From ea9ffb927a47367e243b4867a6d84ee3ac8679ea Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 13 Jul 2025 12:22:31 +0100 Subject: [PATCH 4/5] parse: properties: utils: hsl: Support modern syntax --- src/parse/properties/utils.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c index 985accd..8ce8273 100644 --- a/src/parse/properties/utils.c +++ b/src/parse/properties/utils.c @@ -499,6 +499,7 @@ static bool parse_hsl( size_t consumed = 0; css_fixed hue, sat, lit; int32_t alpha = 255; + bool legacy = false; css_error error; uint8_t r = 0, g = 0, b = 0, a = 0xff; @@ -564,14 +565,18 @@ static bool parse_hsl( consumeWhitespace(vector, ctx); - token = parserutils_vector_iterate(vector, ctx); - if (!tokenIsChar(token, ',')) + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) { return false; + } + if (tokenIsChar(token, ',')) { + parserutils_vector_iterate(vector, ctx); + consumeWhitespace(vector, ctx); + legacy = true; + } /* saturation */ - consumeWhitespace(vector, ctx); - token = parserutils_vector_iterate(vector, ctx); if ((token == NULL) || (token->type != CSS_TOKEN_PERCENTAGE)) return false; @@ -588,14 +593,16 @@ static bool parse_hsl( consumeWhitespace(vector, ctx); - token = parserutils_vector_iterate(vector, ctx); - if (!tokenIsChar(token, ',')) - return false; + if (legacy) { + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || !tokenIsChar(token, ',')) { + return false; + } + consumeWhitespace(vector, ctx); + } /* lightness */ - consumeWhitespace(vector, ctx); - token = parserutils_vector_iterate(vector, ctx); if ((token == NULL) || (token->type != CSS_TOKEN_PERCENTAGE)) return false; @@ -614,7 +621,8 @@ static bool parse_hsl( token = parserutils_vector_iterate(vector, ctx); - if (tokenIsChar(token, ',')) { + if (( legacy && tokenIsChar(token, ',')) || + (!legacy && tokenIsChar(token, '/'))) { consumeWhitespace(vector, ctx); token = parserutils_vector_iterate(vector, ctx); From 6194a24890e5cbfc18e6b66113c4b4d5b27ba62b Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 13 Jul 2025 12:40:46 +0100 Subject: [PATCH 5/5] parse: properties: utils: hsl: Percentage optional with modern syntax --- src/parse/properties/utils.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c index 8ce8273..01e1219 100644 --- a/src/parse/properties/utils.c +++ b/src/parse/properties/utils.c @@ -578,12 +578,19 @@ static bool parse_hsl( /* saturation */ token = parserutils_vector_iterate(vector, ctx); - if ((token == NULL) || (token->type != CSS_TOKEN_PERCENTAGE)) + if (token == NULL) + return false; + + if ((token->type != CSS_TOKEN_PERCENTAGE) && + (token->type != CSS_TOKEN_NUMBER || legacy)) { return false; + } sat = css__number_from_lwc_string(token->idata, false, &consumed); - if (consumed != lwc_string_length(token->idata)) - return false; /* failed to consume the whole string as a number */ + if (consumed != lwc_string_length(token->idata)) { + /* failed to consume the whole string as a number */ + return false; + } /* Normalise saturation to the range [0, 100] */ if (sat < INTTOFIX(0)) @@ -604,12 +611,19 @@ static bool parse_hsl( /* lightness */ token = parserutils_vector_iterate(vector, ctx); - if ((token == NULL) || (token->type != CSS_TOKEN_PERCENTAGE)) + if (token == NULL) + return false; + + if ((token->type != CSS_TOKEN_PERCENTAGE) && + (token->type != CSS_TOKEN_NUMBER || legacy)) { return false; + } lit = css__number_from_lwc_string(token->idata, false, &consumed); - if (consumed != lwc_string_length(token->idata)) - return false; /* failed to consume the whole string as a number */ + if (consumed != lwc_string_length(token->idata)) { + /* failed to consume the whole string as a number */ + return false; + } /* Normalise lightness to the range [0, 100] */ if (lit < INTTOFIX(0))