with the changes from jmb/tlsa and split out...still doesnt work, if
anything its worse than before :-(
--
Regards Vincent
http://www.kyllikki.org/
Index: test/data/parse/colours.dat
===================================================================
--- test/data/parse/colours.dat (revision 11426)
+++ test/data/parse/colours.dat (working copy)
@@ -40,6 +40,37 @@
| 0x02000018 0xffff0000
#reset
+## test HSL
+
+
+## red
+#data
+* { color: hsl(0, 100%, 50%) }
+#errors
+#expected
+| 1 *
+| 0x02000018 0xffff0000
+#reset
+
+## green
+#data
+* { color: hsl(120, 100%, 50%) }
+#errors
+#expected
+| 1 *
+| 0x02000018 0xff00ff00
+#reset
+
+## blue
+#data
+* { color: hsl(240, 100%, 50%) }
+#errors
+#expected
+| 1 *
+| 0x02000018 0xff0000ff
+#reset
+
+
## Out-of-range rgb() parameters
#data
Index: src/parse/propstrings.h
===================================================================
--- src/parse/propstrings.h (revision 11426)
+++ src/parse/propstrings.h (working copy)
@@ -84,7 +84,7 @@
NE_RESIZE, NW_RESIZE, N_RESIZE, SE_RESIZE, SW_RESIZE, S_RESIZE,
W_RESIZE, LIBCSS_TEXT, WAIT, HELP, PROGRESS, SERIF, SANS_SERIF, CURSIVE,
FANTASY, MONOSPACE, MALE, FEMALE, CHILD, MIX, UNDERLINE, OVERLINE,
- LINE_THROUGH, BLINK, RGB, RGBA, LIBCSS_LEFT, LIBCSS_CENTER,
+ LINE_THROUGH, BLINK, RGB, RGBA, HSL, HSLA, LIBCSS_LEFT, LIBCSS_CENTER,
LIBCSS_RIGHT,
/* Named colours */
Index: src/parse/propstrings.c
===================================================================
--- src/parse/propstrings.c (revision 11426)
+++ src/parse/propstrings.c (working copy)
@@ -331,6 +331,8 @@
{ "blink", SLEN("blink") },
{ "rgb", SLEN("rgb") },
{ "rgba", SLEN("rgba") },
+ { "hsl", SLEN("hsl") },
+ { "hsla", SLEN("hsla") },
{ "-libcss-left", SLEN("-libcss-left") },
{ "-libcss-center", SLEN("-libcss-center") },
{ "-libcss-right", SLEN("-libcss-right") },
Index: src/parse/properties/utils.c
===================================================================
--- src/parse/properties/utils.c (revision 11426)
+++ src/parse/properties/utils.c (working copy)
@@ -248,7 +248,126 @@
return error;
}
+#define INTEGER_HSL
+
+#if defined(INTEGER_HSL)
/**
+ * Convert Hue Sauration Lightness value to RGB integer version
+ *
+ * \param hue Hue in degrees 0..360
+ * \param sat Saturation value in percent 0..100
+ * \param lit Lightness value in percent 0..100
+ * \param r red component
+ * \param g green component
+ * \param b blue component
+ */
+static void HSL_to_RGB(int32_t hue, int32_t sat, int32_t lit, uint8_t *r,
uint8_t *g, uint8_t *b)
+{
+ int v;
+ int m;
+ int sextant;
+ int fract, vsf, mid1, mid2;
+ int red,green,blue;
+
+ hue = (hue * 1023) / 360;
+ sat = (sat * 1023) / 100;
+ lit = (lit * 1023) / 100;
+
+ if (lit < 511)
+ v = (lit * (512 + sat)) >> 10;
+ else
+ v = (((lit + sat) << 10) - lit * sat) >> 10;
+
+ if (v <= 0) {
+ *r = *g = *b = 0;
+ return;
+ }
+
+ m = lit + lit - v;
+ hue *= 6;
+ sextant = hue >> 10;
+ fract = hue - (sextant << 10);
+ vsf = v * fract * (v - m) / v >> 10;
+ mid1 = m + vsf;
+ mid2 = v - vsf;
+
+#define ORGB(R,G,B) red = (R)>>2; green = (G)>>2; blue = (B)>>2
+ switch (sextant) {
+ case 0: ORGB(v, mid1, m); break;
+ case 1: ORGB(mid2, v, m); break;
+ case 2: ORGB(m, v, mid1); break;
+ case 3: ORGB(m, mid2, v); break;
+ case 4: ORGB(mid1, m, v); break;
+ case 5: ORGB(v, m, mid2); break;
+ }
+#undef ORGB
+ *r = red;
+ *g = green;
+ *b = blue;
+}
+
+#else
+
+/* CSS standard definition
+
+ HOW TO RETURN hsl.to.rgb(h, s, l):
+ SELECT:
+ l<=0.5: PUT l*(s+1) IN m2
+ ELSE: PUT l+s-l*s IN m2
+ PUT l*2-m2 IN m1
+ PUT hue.to.rgb(m1, m2, h+1/3) IN r
+ PUT hue.to.rgb(m1, m2, h ) IN g
+ PUT hue.to.rgb(m1, m2, h-1/3) IN b
+ RETURN (r, g, b)
+
+ HOW TO RETURN hue.to.rgb(m1, m2, h):
+ IF h<0: PUT h+1 IN h
+ IF h>1: PUT h-1 IN h
+ IF h*6<1: RETURN m1+(m2-m1)*h*6
+ IF h*2<1: RETURN m2
+ IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6
+ RETURN m1
+*/
+static inline int hue_to_RGB(float m1, float m2, float h)
+{
+ h = (h < 0) ? h + 1 : h;
+ h = (h > 1) ? h - 1 : h;
+
+ if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
+ if (h * 2 < 1) return m2;
+ if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
+ return m1;
+}
+
+/**
+ * Convert Hue Sauration Lightness value to RGB float version from CSS standard
+ *
+ * \param hue Hue in degrees 0..360
+ * \param sat Saturation value in percent 0..100
+ * \param lit Lightness value in percent 0..100
+ * \param r red component
+ * \param g green component
+ * \param b blue component
+ */
+static void HSL_to_RGB(int32_t hue, int32_t sat, int32_t lit, uint8_t *r,
uint8_t *g, uint8_t *b)
+{
+ float m1, m2;
+ float h, s, l;
+
+ h = hue/360;
+ s = sat/100;
+ l = lit/100;
+
+ m2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
+ m1 = l * 2 - m2;
+
+ *r = hue_to_RGB(m1, m2, h + 1/3);
+ *g = hue_to_RGB(m1, m2, h );
+ *b = hue_to_RGB(m1, m2, h - 1/3);
+}
+#endif
+
+/**
* Parse a colour specifier
*
* \param c Parsing context
@@ -273,9 +392,12 @@
consumeWhitespace(vector, ctx);
- /* IDENT(<colour name>) | HASH(rgb | rrggbb) |
+ /* IDENT(<colour name>) |
+ * HASH(rgb | rrggbb) |
* FUNCTION(rgb) [ [ NUMBER | PERCENTAGE ] ',' ] {3} ')'
* FUNCTION(rgba) [ [ NUMBER | PERCENTAGE ] ',' ] {4} ')'
+ * FUNCTION(hsl) ANGLE ',' PERCENTAGE ',' PERCENTAGE ')'
+ * FUNCTION(hsla) ANGLE ',' PERCENTAGE ',' PERCENTAGE ',' NUMBER ')'
*
* For quirks, NUMBER | DIMENSION | IDENT, too
* I.E. "123456" -> NUMBER, "1234f0" -> DIMENSION, "f00000" -> IDENT
@@ -338,6 +460,14 @@
token->idata, c->strings[RGBA],
&match) == lwc_error_ok && match)) {
colour_channels = 4;
+ } if ((lwc_string_caseless_isequal(
+ token->idata, c->strings[HSL],
+ &match) == lwc_error_ok && match)) {
+ colour_channels = 5;
+ } else if ((lwc_string_caseless_isequal(
+ token->idata, c->strings[HSLA],
+ &match) == lwc_error_ok && match)) {
+ colour_channels = 6;
}
if (colour_channels == 3 || colour_channels == 4) {
@@ -418,8 +548,111 @@
goto invalid;
}
}
- } else
+ } else if (colour_channels == 5 || colour_channels == 6) {
+ /* hue - saturation - lightness */
+ size_t consumed = 0;
+ css_fixed num;
+ int32_t alpha = 255, hue, sat, lit;
+
+ /* hue is a number without a unit representing an
+ * angle (0-360) degrees
+ */
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if ((token == NULL) || (token->type !=
CSS_TOKEN_NUMBER))
+ goto invalid;
+
+ num = css__number_from_lwc_string(token->idata, true,
&consumed);
+ if (consumed != lwc_string_length(token->idata))
+ goto invalid; /* failed to consume the whole
string as a number */
+
+ hue = (((FIXTOINT(num) % 360) + 360) % 360);
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if (!tokenIsChar(token, ','))
+ goto invalid;
+
+
+ /* saturation */
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if ((token == NULL) || (token->type !=
CSS_TOKEN_PERCENTAGE))
+ goto invalid;
+
+ num = css__number_from_lwc_string(token->idata, true,
&consumed);
+ if (consumed != lwc_string_length(token->idata))
+ goto invalid; /* failed to consume the whole
string as a number */
+ sat = FIXTOINT(100);
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if (!tokenIsChar(token, ','))
+ goto invalid;
+
+
+ /* lightness */
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if ((token == NULL) || (token->type !=
CSS_TOKEN_PERCENTAGE))
+ goto invalid;
+
+ num = css__number_from_lwc_string(token->idata, true,
&consumed);
+ if (consumed != lwc_string_length(token->idata))
+ goto invalid; /* failed to consume the whole
string as a number */
+
+ lit = FIXTOINT(num);
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+
+ if (colour_channels == 6) {
+ /* alpha */
+
+ if (!tokenIsChar(token, ','))
+ goto invalid;
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if ((token == NULL) || (token->type !=
CSS_TOKEN_NUMBER))
+ goto invalid;
+
+ num = css__number_from_lwc_string(token->idata,
true, &consumed);
+ if (consumed != lwc_string_length(token->idata))
+ goto invalid; /* failed to consume the
whole string as a number */
+
+ alpha = FIXTOINT(FMULI(num, 255));
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+
+ }
+
+ if (!tokenIsChar(token, ')'))
+ goto invalid;
+
+ /* have a valid HSV entry, convert to RGB */
+
+ HSL_to_RGB(hue, sat, lit, &r, &g, &b);
+ /* apply alpha */
+ if (alpha > 255)
+ a = 255;
+ else if (alpha < 0)
+ a = 0;
+ else
+ a = alpha;
+
+ } else {
goto invalid;
+ }
}
*result = (a << 24) | (r << 16) | (g << 8) | b;