cssparser: Make gsk_renderer_consume_url() return a string
authorBenjamin Otte <otte@redhat.com>
Sun, 12 May 2019 13:18:46 +0000 (15:18 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 12 May 2019 15:28:19 +0000 (17:28 +0200)
We don't want to return a GFile because GFile can't handle can't deal
with data: urls.
That makes the code a bit more complicated that doesn't deal with those
URLs, but it makes the other code actually work.

GtkCssImageUrl also now decodes data urls immediately instead of only at
the first load. So don't use data urls if you care about performance.

gsk/gskrendernodeparser.c
gtk/css/gtkcssparser.c
gtk/css/gtkcssparserprivate.h
gtk/gtkcssimagerecolor.c
gtk/gtkcssimageurl.c
gtk/gtkcssprovider.c

index 9f164a93aa7ef532b0a304cf12fa41f92b8fd4d5..06b2b183c78c16877b22b557dac031f02f4eb48a 100644 (file)
@@ -71,27 +71,26 @@ static gboolean
 parse_texture (GtkCssParser *parser,
                gpointer      out_data)
 {
-  GFile *file;
   GdkTexture *texture;
   GError *error = NULL;
   GtkCssLocation start_location;
+  char *url, *scheme;
 
   start_location = *gtk_css_parser_get_start_location (parser);
-  file = gtk_css_parser_consume_url (parser);
-  if (file == NULL)
+  url = gtk_css_parser_consume_url (parser);
+  if (url == NULL)
     return FALSE;
 
-  if (g_file_has_uri_scheme (file, "data"))
+  scheme = g_uri_parse_scheme (url);
+  if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
     {
       GInputStream *stream;
-      char *uri;
       GdkPixbuf *pixbuf;
       GBytes *bytes;
 
-      uri = g_file_get_uri (file);
       texture = NULL;
 
-      bytes = gtk_css_data_url_parse (uri, NULL, &error);
+      bytes = gtk_css_data_url_parse (url, NULL, &error);
       if (bytes)
         {
           stream = g_memory_input_stream_new_from_bytes (bytes);
@@ -103,14 +102,18 @@ parse_texture (GtkCssParser *parser,
               g_object_unref (pixbuf);
             }
         }
-
-      g_free (uri);
     }
   else
     {
+      GFile *file;
+
+      file = gtk_css_parser_resolve_url (parser, url);
       texture = gdk_texture_new_from_file (file, &error);
+      g_object_unref (file);
     }
-  g_object_unref (file);
+
+  g_free (scheme);
+  g_free (url);
 
   if (texture == NULL)
     {
index 5ba0997b4d608383db412e7d7459843b0d559c74..84bc4fc8e755173972553a076c31f96fa8e84b28 100644 (file)
@@ -973,11 +973,10 @@ gtk_css_parser_parse_url_arg (GtkCssParser *parser,
  *
  * Returns: (nullable) (transfer full): the resulting URL or %NULL on error
  **/
-GFile *
+char *
 gtk_css_parser_consume_url (GtkCssParser *self)
 {
   const GtkCssToken *token;
-  GFile *result;
   char *url;
 
   token = gtk_css_parser_get_token (self);
@@ -998,16 +997,7 @@ gtk_css_parser_consume_url (GtkCssParser *self)
       return NULL;
     }
   
-  result = gtk_css_parser_resolve_url (self, url);
-  if (result == NULL)
-    {
-      gtk_css_parser_error_import (self, "Could not resolve \"%s\" to a valid URL", url);
-      g_free (url);
-      return NULL;
-    }
-  g_free (url);
-
-  return result;
+  return url;
 }
 
 gboolean
index 520d0eeaa01ce298cd1f2ca137667cedf62929a7..349ad6799927fbb7d12dc594b218a16a601d5a9e 100644 (file)
@@ -134,7 +134,7 @@ gboolean                gtk_css_parser_try_token                (GtkCssParser
 
 char *                  gtk_css_parser_consume_ident            (GtkCssParser                   *self) G_GNUC_WARN_UNUSED_RESULT;
 char *                  gtk_css_parser_consume_string           (GtkCssParser                   *self) G_GNUC_WARN_UNUSED_RESULT;
-GFile *                 gtk_css_parser_consume_url              (GtkCssParser                   *self) G_GNUC_WARN_UNUSED_RESULT;
+char *                  gtk_css_parser_consume_url              (GtkCssParser                   *self) G_GNUC_WARN_UNUSED_RESULT;
 gboolean                gtk_css_parser_consume_number           (GtkCssParser                   *self,
                                                                  double                         *number);
 gboolean                gtk_css_parser_consume_integer          (GtkCssParser                   *self,
index 7dadd660a0047ed0323587aa39be91b96c2af371..98e1ff2e80e7df87ffaef4d1ec766ba8b655c479 100644 (file)
@@ -245,10 +245,16 @@ gtk_css_image_recolor_parse_arg (GtkCssParser *parser,
   switch (arg)
   {
     case 0:
-      self->file = gtk_css_parser_consume_url (parser);
-      if (self->file == NULL)
-        return 0;
-      return 1;
+      {
+        char *url = gtk_css_parser_consume_url (parser);
+        if (url == NULL)
+          return 0;
+        self->file = gtk_css_parser_resolve_url (parser, url);
+        g_free (url);
+        if (self->file == NULL)
+          return 0;
+        return 1;
+      }
 
     case 1:
       self->palette = gtk_css_palette_value_parse (parser);
index 361844394d25d6add113d23ee39ee7d0a03c7375..398e9c370596ef76315a50bddec60cb147f60124 100644 (file)
@@ -54,31 +54,6 @@ gtk_css_image_url_load_image (GtkCssImageUrl  *url,
       g_free (resource_path);
       g_free (uri);
     }
-  else if (g_file_has_uri_scheme (url->file, "data"))
-    {
-      GInputStream *stream;
-      char *uri;
-      GdkPixbuf *pixbuf;
-      GBytes *bytes;
-
-      uri = g_file_get_uri (url->file);
-      texture = NULL;
-
-      bytes = gtk_css_data_url_parse (uri, NULL, &local_error);
-      if (bytes)
-        {
-          stream = g_memory_input_stream_new_from_bytes (bytes);
-          pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &local_error);
-          g_object_unref (stream);
-          if (pixbuf != NULL)
-            {
-              texture = gdk_texture_new_for_pixbuf (pixbuf);
-              g_object_unref (pixbuf);
-            }
-        }
-
-      g_free (uri);
-    }
   else
     {
       texture = gdk_texture_new_from_file (url->file, &local_error);
@@ -190,12 +165,52 @@ static gboolean
 gtk_css_image_url_parse (GtkCssImage  *image,
                          GtkCssParser *parser)
 {
-  GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
+  GtkCssImageUrl *self = GTK_CSS_IMAGE_URL (image);
+  char *url, *scheme;
 
-  url->file = gtk_css_parser_consume_url (parser);
-  if (url->file == NULL)
+  url = gtk_css_parser_consume_url (parser);
+  if (url == NULL)
     return FALSE;
 
+  scheme = g_uri_parse_scheme (url);
+  if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
+    {
+      GInputStream *stream;
+      GdkPixbuf *pixbuf;
+      GBytes *bytes;
+      GError *error = NULL;
+
+      bytes = gtk_css_data_url_parse (url, NULL, &error);
+      if (bytes)
+        {
+          stream = g_memory_input_stream_new_from_bytes (bytes);
+          pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
+          g_object_unref (stream);
+          if (pixbuf == NULL)
+            {
+              gtk_css_parser_emit_error (parser,
+                                         gtk_css_parser_get_start_location (parser),
+                                         gtk_css_parser_get_end_location (parser),
+                                         error);
+              g_clear_error (&error);
+            }
+          else
+            {
+              GdkTexture *texture = gdk_texture_new_for_pixbuf (pixbuf);
+              self->loaded_image = gtk_css_image_paintable_new (GDK_PAINTABLE (texture), GDK_PAINTABLE (texture));
+              g_object_unref (texture);
+              g_object_unref (pixbuf);
+            }
+        }
+    }
+  else
+    {
+      self->file = gtk_css_parser_resolve_url (parser, url);
+    }
+
+  g_free (url);
+  g_free (scheme);
+
   return TRUE;
 }
 
index ab4a1cb2a873bd13a44132250ac5ee36b7972c7f..f3dfa9922b8064b64cd71814d44d806ee39c6814 100644 (file)
@@ -695,7 +695,14 @@ parse_import (GtkCssScanner *scanner)
     }
   else
     {
-      file = gtk_css_parser_consume_url (scanner->parser);
+      char *url = gtk_css_parser_consume_url (scanner->parser);
+      if (url)
+        {
+          file = gtk_css_parser_resolve_url (scanner->parser, url);
+          g_free (url);
+        }
+      else
+        file = NULL;
     }
 
   if (file == NULL)