[gnome-shell] Work around libcroco < 0.6.2 parsing bug for 'rgba'



commit 4ddc1118bb745a489f3b37c4d2475131ba4c36ae
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Mon Oct 5 10:10:23 2009 -0400

    Work around libcroco < 0.6.2 parsing bug for 'rgba'
    
    To work around a problem where libcroco < 0.6.2 can't handle
    functions starting with 'r' or 'u', preconvert 'rgba' to 'RGBA'
    when parsing stylesheets and then check for rgba()
    case-insensitively.
    
    (libcroco is uniformly case-sensitive, though the CSS spec requires
    that ASCII should be handled case-insensitively.)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=597054

 src/st/st-theme-node.c    |   15 +++++--
 src/st/st-theme-private.h |    2 +
 src/st/st-theme.c         |   94 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+), 4 deletions(-)
---
diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c
index 0b48e47..d0e9135 100644
--- a/src/st/st-theme-node.c
+++ b/src/st/st-theme-node.c
@@ -258,9 +258,7 @@ ensure_properties (StThemeNode *node)
           if (!properties)
             properties = g_ptr_array_new ();
 
-          node->inline_properties = cr_declaration_parse_list_from_buf ((const guchar *)node->inline_style,
-                                                                        CR_UTF_8);
-
+          node->inline_properties = _st_theme_parse_declaration_list (node->inline_style);
           for (cur_decl = node->inline_properties; cur_decl; cur_decl = cur_decl->next)
             g_ptr_array_add (properties, cur_decl);
         }
@@ -408,12 +406,21 @@ get_color_from_term (StThemeNode  *node,
   /* rgba () colors - a CSS3 addition, are not supported by libcroco,
    * but they are parsed as a "function", so we can emulate the
    * functionality.
+   *
+   * libcroco < 0.6.2 has a bug where functions starting with 'r' are
+   * misparsed. We workaround this by pre-converting 'rgba' to 'RGBA'
+   * before parsing the stylesheet. Since libcroco isn't
+   * case-insensitive (a bug), it's fine with functions starting with
+   * 'R'. (In theory, we should be doing a case-insensitive compare
+   * everywhere, not just here, but that doesn't make much sense when
+   * the built-in parsing of libcroco is case-sensitive and things
+   * like 10PX don't work.)
    */
   else if (term->type == TERM_FUNCTION &&
            term->content.str &&
            term->content.str->stryng &&
            term->content.str->stryng->str &&
-           strcmp (term->content.str->stryng->str, "rgba") == 0)
+           g_ascii_strcasecmp (term->content.str->stryng->str, "rgba") == 0)
     {
       return get_color_from_rgba_term (term, color);
     }
diff --git a/src/st/st-theme-private.h b/src/st/st-theme-private.h
index a307b08..92e87e8 100644
--- a/src/st/st-theme-private.h
+++ b/src/st/st-theme-private.h
@@ -15,6 +15,8 @@ char *_st_theme_resolve_url (StTheme      *theme,
                              CRStyleSheet *base_stylesheet,
                              const char   *url);
 
+CRDeclaration *_st_theme_parse_declaration_list (const char *str);
+
 G_END_DECLS
 
 #endif /* __ST_THEME_PRIVATE_H__ */
diff --git a/src/st/st-theme.c b/src/st/st-theme.c
index 420f1fa..9447832 100644
--- a/src/st/st-theme.c
+++ b/src/st/st-theme.c
@@ -156,6 +156,92 @@ st_theme_class_init (StThemeClass *klass)
 
 }
 
+/* This is a workaround for a bug in libcroco < 0.6.2 where
+ * function starting with 'r' (and 'u') are misparsed. We work
+ * around this by exploiting the fact that libcroco is incomformant
+ * with the CSS-spec and case sensitive and pre-convert all
+ * occurrences of rgba to RGBA. Then we make our own parsing
+ * code check for RGBA as well.
+ */
+#if LIBCROCO_VERSION_NUMBER < 602
+static gboolean
+is_identifier_character (char c)
+{
+  /* Actual CSS rules allow for unicode > 0x00a1 and escaped
+   * characters, but we'll assume we won't do that in our stylesheets
+   * or at least not next to the string 'rgba'.
+   */
+  return g_ascii_isalnum(c) || c == '-' || c == '_';
+}
+
+static void
+convert_rgba_RGBA (char *buf)
+{
+  char *p;
+
+  p = strstr (buf, "rgba");
+  while (p)
+    {
+      /* Check if this looks like a complete token; this is to
+       * avoiding mangling, say, a selector '.rgba-entry' */
+      if (!((p > buf && is_identifier_character (*(p - 1))) ||
+            (is_identifier_character (*(p + 4)))))
+        memcpy(p, "RGBA", 4);
+      p += 4;
+      p = strstr (p, "rgba");
+    }
+}
+
+static CRStyleSheet *
+parse_stylesheet (const char *filename)
+{
+  enum CRStatus status;
+  char *contents;
+  gsize length;
+  GError *error = NULL;
+  CRStyleSheet *stylesheet = NULL;
+
+  if (filename == NULL)
+    return NULL;
+
+  if (!g_file_get_contents (filename, &contents ,&length, &error))
+    {
+      g_warning("Couldn't read stylesheet: %s", error->message);
+      g_error_free (error);
+
+      return NULL;
+    }
+
+  convert_rgba_RGBA (contents);
+
+  status = cr_om_parser_simply_parse_buf ((const guchar *) contents,
+                                          length,
+                                          CR_UTF_8,
+                                          &stylesheet);
+
+  if (status != CR_OK)
+    g_warning ("Error parsing stylesheet '%s'", filename);
+
+  g_free (contents);
+
+  return stylesheet;
+}
+
+CRDeclaration *
+_st_theme_parse_declaration_list (const char *str)
+{
+  char *copy = g_strdup (str);
+  CRDeclaration *result;
+
+  convert_rgba_RGBA (copy);
+
+  result = cr_declaration_parse_list_from_buf ((const guchar *)copy,
+                                               CR_UTF_8);
+  g_free (copy);
+
+  return result;
+}
+#else /* LIBCROCO_VERSION_NUMBER >= 602 */
 static CRStyleSheet *
 parse_stylesheet (const char *filename)
 {
@@ -178,6 +264,14 @@ parse_stylesheet (const char *filename)
   return stylesheet;
 }
 
+CRDeclaration *
+_st_theme_parse_declaration_list (const char *str)
+{
+  return cr_declaration_parse_list_from_buf ((const guchar *)str,
+                                             CR_UTF_8);
+}
+#endif /* LIBCROCO_VERSION_NUMBER < 602 */
+
 static void
 insert_stylesheet (StTheme      *theme,
                    const char   *filename,



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