[librsvg] css: Add support for parsing rgba() colors



commit b864307868d3977dfa5e127ff95d7efded854850
Author: Benjamin Otte <otte redhat com>
Date:   Fri Oct 4 16:55:51 2013 +0200

    css: Add support for parsing rgba() colors
    
    This also requires adding alpha support to the solid color paint server.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=639750

 rsvg-cairo-draw.c   |   18 ++++++++----------
 rsvg-css.c          |   44 +++++++++++++++++++++++++++++++++++++++++++-
 rsvg-paint-server.c |   10 +++++-----
 rsvg-paint-server.h |    2 +-
 4 files changed, 57 insertions(+), 17 deletions(-)
---
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 11bc8f3..da703c6 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -162,20 +162,18 @@ _set_source_rsvg_solid_colour (RsvgDrawingCtx * ctx,
 {
     RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
     cairo_t *cr = render->cr;
-    guint32 rgb = colour->rgb;
-    double r, g, b;
+    guint32 argb = colour->argb;
+    double r, g, b, a;
 
     if (colour->currentcolour)
-        rgb = current_colour;
+        argb = current_colour;
 
-    r = ((rgb >> 16) & 0xff) / 255.0;
-    g = ((rgb >> 8) & 0xff) / 255.0;
-    b = ((rgb >> 0) & 0xff) / 255.0;
+    r = ((argb >> 16) & 0xff) / 255.0;
+    g = ((argb >>  8) & 0xff) / 255.0;
+    b = ((argb >>  0) & 0xff) / 255.0;
+    a =  (argb >> 24) / 255.0 * (opacity / 255.0);
 
-    if (opacity == 0xff)
-        cairo_set_source_rgb (cr, r, g, b);
-    else
-        cairo_set_source_rgba (cr, r, g, b, opacity / 255.0);
+    cairo_set_source_rgba (cr, r, g, b, a);
 }
 
 static void
diff --git a/rsvg-css.c b/rsvg-css.c
index 3f703cc..649ccf4 100644
--- a/rsvg-css.c
+++ b/rsvg-css.c
@@ -304,7 +304,8 @@ rsvg_css_clip_rgb (gint rgb)
 }
 
 /* pack 3 [0,255] ints into one 32 bit one */
-#define PACK_RGB(r,g,b) (((r) << 16) | ((g) << 8) | (b))
+#define PACK_RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+#define PACK_RGB(r,g,b) PACK_RGBA(r, g, b, 255)
 
 /**
  * rsvg_css_parse_color:
@@ -343,6 +344,46 @@ rsvg_css_parse_color (const char *str, gboolean * inherit)
         }
     }
     /* i want to use g_str_has_prefix but it isn't in my gstrfuncs.h?? */
+    else if (strstr (str, "rgba") != NULL) {
+        gint r, g, b, a;
+        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);
+            }
+        }
+
+        val = PACK_RGBA (r, g, b, a);
+    }
     else if (strstr (str, "rgb") != NULL) {
         gint r, g, b;
         r = g = b = 0;
@@ -396,6 +437,7 @@ rsvg_css_parse_color (const char *str, gboolean * inherit)
 }
 
 #undef PACK_RGB
+#undef PACK_RGBA
 
 guint
 rsvg_css_parse_opacity (const char *str)
diff --git a/rsvg-paint-server.c b/rsvg-paint-server.c
index 3a318c7..07c76be 100644
--- a/rsvg-paint-server.c
+++ b/rsvg-paint-server.c
@@ -37,14 +37,14 @@
 #include "rsvg-css.h"
 
 static RsvgPaintServer *
-rsvg_paint_server_solid (guint32 rgb)
+rsvg_paint_server_solid (guint32 argb)
 {
     RsvgPaintServer *result = g_new (RsvgPaintServer, 1);
 
     result->refcnt = 1;
     result->type = RSVG_PAINT_SERVER_SOLID;
     result->core.colour = g_new (RsvgSolidColour, 1);
-    result->core.colour->rgb = rgb;
+    result->core.colour->argb = argb;
     result->core.colour->currentcolour = FALSE;
 
     return result;
@@ -115,7 +115,7 @@ rsvg_paint_server_parse (gboolean * inherit, const RsvgDefs * defs, const char *
                          guint32 current_color)
 {
     char *name;
-    guint32 rgb;
+    guint32 argb;
     if (inherit != NULL)
         *inherit = 1;
     if (str == NULL || !strcmp (str, "none"))
@@ -146,8 +146,8 @@ rsvg_paint_server_parse (gboolean * inherit, const RsvgDefs * defs, const char *
         ps = rsvg_paint_server_solid_current_colour ();
         return ps;
     } else {
-        rgb = rsvg_css_parse_color (str, inherit);
-        return rsvg_paint_server_solid (rgb);
+        argb = rsvg_css_parse_color (str, inherit);
+        return rsvg_paint_server_solid (argb);
     }
 }
 
diff --git a/rsvg-paint-server.h b/rsvg-paint-server.h
index 51f783f..65a7060 100644
--- a/rsvg-paint-server.h
+++ b/rsvg-paint-server.h
@@ -109,7 +109,7 @@ struct _RsvgPattern {
 
 struct _RsvgSolidColour {
     gboolean currentcolour;
-    guint32 rgb;
+    guint32 argb;
 };
 
 typedef struct _RsvgSolidColour RsvgPaintServerColour;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]