cssparser: Make gsk_renderer_consume_url() return a string

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.
This commit is contained in:
Benjamin Otte 2019-05-12 15:18:46 +02:00
parent 0103704171
commit 0886ade182
6 changed files with 77 additions and 56 deletions

View 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_free (scheme);
g_free (url);
if (texture == NULL)
{

View 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

View 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,

View 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);
{
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);

View 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;
}

View 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)