Skip to content

Commit c16ad84

Browse files
committed
parse: properties: utils: Update rgb(a) handling to css-color-4
These changes * make rgb and rgba interchangable * add support for the "modern" style
1 parent 1e14b42 commit c16ad84

File tree

2 files changed

+163
-44
lines changed

2 files changed

+163
-44
lines changed

src/parse/properties/utils.c

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -356,94 +356,122 @@ static void HSL_to_RGB(css_fixed hue, css_fixed sat, css_fixed lit, uint8_t *r,
356356
*
357357
* It's up to the caller to reset the ctx if this fails.
358358
*
359+
* \param c Parsing context
359360
* \param vector Vector of tokens to process
360361
* \param ctx Pointer to vector iteration context
361-
* \param colour_channels Number of colour channels to expect
362362
* \param result Pointer to location to receive result (AARRGGBB)
363363
* \return true on success, false on error.
364364
*/
365365
static bool parse_rgb(
366+
css_language *c,
366367
const parserutils_vector *vector,
367368
int32_t *ctx,
368-
int colour_channels,
369369
uint32_t *result)
370370
{
371371
const css_token *token;
372372
css_token_type valid = CSS_TOKEN_NUMBER;
373373
uint8_t r = 0, g = 0, b = 0, a = 0xff;
374374
uint8_t *components[4] = { &r, &g, &b, &a };
375+
bool legacy = false;
376+
bool had_none = false;
375377

376-
for (int i = 0; i < colour_channels; i++) {
378+
for (int i = 0; i < 4; i++) {
377379
uint8_t *component;
378380
css_fixed num;
379381
size_t consumed = 0;
380382
int32_t intval;
381383
bool int_only;
384+
bool match;
382385

383386
component = components[i];
384387

385388
consumeWhitespace(vector, ctx);
386389

387390
token = parserutils_vector_peek(vector, *ctx);
388-
if (token == NULL || (token->type !=
389-
CSS_TOKEN_NUMBER &&
390-
token->type !=
391-
CSS_TOKEN_PERCENTAGE))
391+
if (token == NULL) {
392392
return false;
393+
} else if (!legacy && token->type == CSS_TOKEN_IDENT &&
394+
lwc_string_caseless_isequal(
395+
token->idata, c->strings[NONE],
396+
&match) == lwc_error_ok && match) {
397+
had_none = true;
398+
} else {
399+
if (token->type != CSS_TOKEN_NUMBER &&
400+
token->type != CSS_TOKEN_PERCENTAGE) {
401+
return false;
402+
}
393403

394-
if (i == 0)
395-
valid = token->type;
396-
else if (i < 3 && token->type != valid)
397-
return false;
404+
if (i == 0) {
405+
valid = token->type;
406+
} else if (legacy && i < 3 && token->type != valid) {
407+
return false;
408+
} else {
409+
valid = token->type;
410+
}
398411

399-
/* The alpha channel may be a float */
400-
if (i < 3)
401-
int_only = (valid == CSS_TOKEN_NUMBER);
402-
else
403-
int_only = false;
412+
/* The alpha channel may be a float */
413+
if (i < 3) {
414+
int_only = (valid == CSS_TOKEN_NUMBER);
415+
} else {
416+
int_only = false;
417+
}
404418

405-
num = css__number_from_lwc_string(token->idata,
406-
int_only, &consumed);
407-
if (consumed != lwc_string_length(token->idata))
408-
return false;
419+
num = css__number_from_lwc_string(token->idata,
420+
int_only, &consumed);
421+
if (consumed != lwc_string_length(token->idata)) {
422+
return false;
423+
}
409424

410-
if (valid == CSS_TOKEN_NUMBER) {
411-
if (i == 3) {
412-
/* alpha channel */
425+
if (valid == CSS_TOKEN_NUMBER) {
426+
if (i == 3) {
427+
/* alpha channel */
428+
intval = FIXTOINT(FMUL(num, F_255));
429+
} else {
430+
/* colour channels */
431+
intval = FIXTOINT(num);
432+
}
433+
} else {
413434
intval = FIXTOINT(
414-
FMUL(num, F_255));
435+
FDIV(FMUL(num, F_255), F_100));
436+
}
437+
438+
if (intval > 255) {
439+
*component = 255;
440+
} else if (intval < 0) {
441+
*component = 0;
415442
} else {
416-
/* colour channels */
417-
intval = FIXTOINT(num);
443+
*component = intval;
418444
}
419-
} else {
420-
intval = FIXTOINT(
421-
FDIV(FMUL(num, F_255), F_100));
422445
}
423446

424-
if (intval > 255)
425-
*component = 255;
426-
else if (intval < 0)
427-
*component = 0;
428-
else
429-
*component = intval;
430-
431447
parserutils_vector_iterate(vector, ctx);
432448

433449
consumeWhitespace(vector, ctx);
434450

435451
token = parserutils_vector_peek(vector, *ctx);
436-
if (token == NULL)
452+
if (token == NULL) {
437453
return false;
454+
}
455+
456+
if (i == 0 && tokenIsChar(token, ',') && !had_none) {
457+
legacy = true;
458+
}
438459

439-
if (i != (colour_channels - 1) &&
440-
tokenIsChar(token, ',')) {
460+
if (i >= 2 && tokenIsChar(token, ')')) {
441461
parserutils_vector_iterate(vector, ctx);
442-
} else if (i == (colour_channels - 1) &&
443-
tokenIsChar(token, ')')) {
462+
break;
463+
464+
} else if (legacy) {
465+
if (!tokenIsChar(token, ',')) {
466+
return false;
467+
}
468+
parserutils_vector_iterate(vector, ctx);
469+
470+
} else if (i == 2) {
471+
if (!tokenIsChar(token, '/')) {
472+
return false;
473+
}
444474
parserutils_vector_iterate(vector, ctx);
445-
} else {
446-
return false;
447475
}
448476
}
449477

@@ -699,7 +727,7 @@ css_error css__parse_colour_specifier(css_language *c,
699727
}
700728

701729
if (colour_channels == 3 || colour_channels == 4) {
702-
if (!parse_rgb(vector, ctx, colour_channels, result)) {
730+
if (!parse_rgb(c, vector, ctx, result)) {
703731
goto invalid;
704732
}
705733
} else if (colour_channels == 5 || colour_channels == 6) {

test/data/parse/colours.dat

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,97 @@
3232
| 0x02000018 0xffff0000
3333
#reset
3434

35+
#data
36+
* { color: rgb(255 0 0) }
37+
#errors
38+
#expected
39+
| 1 *
40+
| 0x02000018 0xffff0000
41+
#reset
42+
43+
#data
44+
* { color: rgb(255 none none) }
45+
#errors
46+
#expected
47+
| 1 *
48+
| 0x02000018 0xffff0000
49+
#reset
50+
51+
#data
52+
* { color: rgb(255 0% none) }
53+
#errors
54+
#expected
55+
| 1 *
56+
| 0x02000018 0xffff0000
57+
#reset
58+
59+
#data
60+
* { color: rgb(none 0% 255) }
61+
#errors
62+
#expected
63+
| 1 *
64+
| 0x02000018 0xff0000ff
65+
#reset
66+
67+
#data
68+
* { color: rgb(none 0% 255 / none) }
69+
#errors
70+
#expected
71+
| 1 *
72+
| 0x02000018 0xff0000ff
73+
#reset
74+
75+
#data
76+
* { color: rgb(none 0% 255 / 0.5) }
77+
#errors
78+
#expected
79+
| 1 *
80+
| 0x02000018 0x7f0000ff
81+
#reset
82+
83+
#data
84+
* { color: rgb(none 0% 255 none) }
85+
#errors
86+
#expected
87+
| 1 *
88+
#reset
89+
90+
#data
91+
* { color: rgba(255, 0, 0) }
92+
#errors
93+
#expected
94+
| 1 *
95+
| 0x02000018 0xffff0000
96+
#reset
97+
98+
#data
99+
* { color: rgba(none, 0, 0) }
100+
#errors
101+
#expected
102+
| 1 *
103+
#reset
104+
105+
#data
106+
* { color: rgba(0, none, 0) }
107+
#errors
108+
#expected
109+
| 1 *
110+
#reset
111+
112+
#data
113+
* { color: rgb(255, 0%, 0) }
114+
#errors
115+
#expected
116+
| 1 *
117+
#reset
118+
119+
#data
120+
* { color: rgba(255, 0%, 0) }
121+
#errors
122+
#expected
123+
| 1 *
124+
#reset
125+
35126
#data
36127
* { color: rgb(100%, 0%, 0%) }
37128
#errors

0 commit comments

Comments
 (0)