[librsvg] css: Improve rgb()/rgba() color parsing
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] css: Improve rgb()/rgba() color parsing
- Date: Sat, 5 Oct 2013 19:31:35 +0000 (UTC)
commit 30991cd1299da9b81f2f3c176a38b10f992b2aaf
Author: Benjamin Otte <otte redhat com>
Date: Sat Oct 5 21:12:01 2013 +0200
css: Improve rgb()/rgba() color parsing
- Don't crash when there's no '('
- Allow mixed numbers and percentages
- Accept real numbers and not just ints
- Allow '.' as the only separator
- Use less code
rsvg-css.c | 129 +++++++++++++++++++++---------------------------------------
1 files changed, 45 insertions(+), 84 deletions(-)
---
diff --git a/rsvg-css.c b/rsvg-css.c
index 649ccf4..f098d34 100644
--- a/rsvg-css.c
+++ b/rsvg-css.c
@@ -282,25 +282,21 @@ _rsvg_css_hand_normalize_length (const RsvgLength * in, gdouble pixels_per_inch,
}
static gint
-rsvg_css_clip_rgb_percent (gdouble in_percent)
+rsvg_css_clip_rgb_percent (const char *s, double max)
{
- /* spec says to clip these values */
- if (in_percent > 100.)
- return 255;
- else if (in_percent <= 0.)
- return 0;
- return (gint) floor (255. * in_percent / 100. + 0.5);
-}
+ double value;
+ char *end;
-static gint
-rsvg_css_clip_rgb (gint rgb)
-{
- /* spec says to clip these values */
- if (rgb > 255)
- return 255;
- else if (rgb < 0)
- return 0;
- return rgb;
+ value = g_ascii_strtod (s, &end);
+
+ if (*end == '%') {
+ value = CLAMP (value, 0, 100) / 100.0;
+ }
+ else {
+ value = CLAMP (value, 0, max) / max;
+ }
+
+ return (gint) floor (value * 255 + 0.5);
}
/* pack 3 [0,255] ints into one 32 bit one */
@@ -343,82 +339,47 @@ rsvg_css_parse_color (const char *str, gboolean * inherit)
val |= val << 4;
}
}
- /* i want to use g_str_has_prefix but it isn't in my gstrfuncs.h?? */
- else if (strstr (str, "rgba") != NULL) {
+ else if (g_str_has_prefix (str, "rgb")) {
gint r, g, b, a;
+ gboolean has_alpha;
+ guint nb_toks;
+ char **toks;
+
r = g = b = 0;
a = 255;
- if (strstr (str, "%") != 0) {
- guint i, nb_toks;
- char **toks;
-
- /* assume rgba (9%, 100%, 23%, 100%) */
- for (i = 0; str[i] != '('; i++);
-
- i++;
-
- toks = rsvg_css_parse_list (str + i, &nb_toks);
-
- if (toks) {
- if (nb_toks == 4) {
- r = rsvg_css_clip_rgb_percent (g_ascii_strtod (toks[0], NULL));
- g = rsvg_css_clip_rgb_percent (g_ascii_strtod (toks[1], NULL));
- b = rsvg_css_clip_rgb_percent (g_ascii_strtod (toks[2], NULL));
- a = rsvg_css_clip_rgb_percent (g_ascii_strtod (toks[3], NULL));
- }
-
- g_strfreev (toks);
- }
- } else {
- float alpha;
-
- /* assume "rgb (r, g, b)" */
- if (4 == sscanf (str, " rgba ( %d , %d , %d , %g ) ", &r, &g, &b, &alpha)) {
- r = rsvg_css_clip_rgb (r);
- g = rsvg_css_clip_rgb (g);
- b = rsvg_css_clip_rgb (b);
- a = CLAMP (alpha * 255, 0, 255);
- }
+ if (str[3] == 'a') {
+ /* "rgba" */
+ has_alpha = TRUE;
+ str += 4;
+ }
+ else {
+ /* "rgb" */
+ has_alpha = FALSE;
+ str += 3;
}
- val = PACK_RGBA (r, g, b, a);
- }
- else if (strstr (str, "rgb") != NULL) {
- gint r, g, b;
- r = g = b = 0;
-
- if (strstr (str, "%") != 0) {
- guint i, nb_toks;
- char **toks;
-
- /* assume rgb (9%, 100%, 23%) */
- for (i = 0; str[i] != '('; i++);
-
- i++;
-
- toks = rsvg_css_parse_list (str + i, &nb_toks);
-
- if (toks) {
- if (nb_toks == 3) {
- r = rsvg_css_clip_rgb_percent (g_ascii_strtod (toks[0], NULL));
- g = rsvg_css_clip_rgb_percent (g_ascii_strtod (toks[1], NULL));
- b = rsvg_css_clip_rgb_percent (g_ascii_strtod (toks[2], NULL));
- }
-
- g_strfreev (toks);
+ str = strchr (str, '(');
+ if (str == NULL)
+ return val;
+
+ toks = rsvg_css_parse_list (str + 1, &nb_toks);
+
+ if (toks) {
+ if (nb_toks == (has_alpha ? 4 : 3)) {
+ r = rsvg_css_clip_rgb_percent (toks[0], 255.0);
+ g = rsvg_css_clip_rgb_percent (toks[1], 255.0);
+ b = rsvg_css_clip_rgb_percent (toks[2], 255.0);
+ if (has_alpha)
+ a = rsvg_css_clip_rgb_percent (toks[3], 1.0);
+ else
+ a = 255;
}
- } else {
- /* assume "rgb (r, g, b)" */
- if (3 == sscanf (str, " rgb ( %d , %d , %d ) ", &r, &g, &b)) {
- r = rsvg_css_clip_rgb (r);
- g = rsvg_css_clip_rgb (g);
- b = rsvg_css_clip_rgb (b);
- } else
- r = g = b = 0;
+
+ g_strfreev (toks);
}
- val = PACK_RGB (r, g, b);
+ val = PACK_RGBA (r, g, b, a);
} else if (!strcmp (str, "inherit"))
UNSETINHERIT ();
else {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]