[gtk+/wip/otte/tokenizer: 37/42] cssimage: Add token parser for url() images
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/tokenizer: 37/42] cssimage: Add token parser for url() images
- Date: Sun, 20 Mar 2016 05:04:08 +0000 (UTC)
commit b0a0d5b285df19cba294d473e63852b85042221f
Author: Benjamin Otte <otte redhat com>
Date: Sat Mar 19 05:02:43 2016 +0100
cssimage: Add token parser for url() images
This requires adding location information to GtkCssTokenSource, so that
we can resolve relative URLs.
gtk/gtkcssimageurl.c | 14 +++++
gtk/gtkcssrule.c | 11 ++++-
gtk/gtkcsstokensource.c | 109 +++++++++++++++++++++++++++++++++++++++-
gtk/gtkcsstokensourceprivate.h | 10 +++-
gtk/inspector/css-editor.c | 7 +++
5 files changed, 147 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkcssimageurl.c b/gtk/gtkcssimageurl.c
index 7e83f13..9f610c5 100644
--- a/gtk/gtkcssimageurl.c
+++ b/gtk/gtkcssimageurl.c
@@ -163,6 +163,19 @@ gtk_css_image_url_parse (GtkCssImage *image,
return TRUE;
}
+static gboolean
+gtk_css_image_url_token_parse (GtkCssImage *image,
+ GtkCssTokenSource *source)
+{
+ GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
+
+ url->file = gtk_css_token_source_consume_url (source);
+ if (url->file == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
static void
gtk_css_image_url_print (GtkCssImage *image,
GString *string)
@@ -195,6 +208,7 @@ _gtk_css_image_url_class_init (GtkCssImageUrlClass *klass)
image_class->compute = gtk_css_image_url_compute;
image_class->draw = gtk_css_image_url_draw;
image_class->parse = gtk_css_image_url_parse;
+ image_class->token_parse = gtk_css_image_url_token_parse;
image_class->print = gtk_css_image_url_print;
object_class->dispose = gtk_css_image_url_dispose;
diff --git a/gtk/gtkcssrule.c b/gtk/gtkcssrule.c
index ef65c61..70ed6d8 100644
--- a/gtk/gtkcssrule.c
+++ b/gtk/gtkcssrule.c
@@ -93,11 +93,20 @@ gtk_css_token_source_at_error (GtkCssTokenSource *source,
gtk_css_token_source_emit_error (at->source, error);
}
+static GFile *
+gtk_css_token_source_at_get_location (GtkCssTokenSource *source)
+{
+ GtkCssTokenSourceAt *at = (GtkCssTokenSourceAt *) source;
+
+ return gtk_css_token_source_get_location (at->source);
+}
+
static const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_AT = {
gtk_css_token_source_at_finalize,
gtk_css_token_source_at_consume_token,
gtk_css_token_source_at_peek_token,
- gtk_css_token_source_at_error
+ gtk_css_token_source_at_error,
+ gtk_css_token_source_at_get_location,
};
static GtkCssTokenSource *
diff --git a/gtk/gtkcsstokensource.c b/gtk/gtkcsstokensource.c
index aec0cb3..12e4232 100644
--- a/gtk/gtkcsstokensource.c
+++ b/gtk/gtkcsstokensource.c
@@ -28,6 +28,7 @@ typedef struct _GtkCssTokenSourceTokenizer GtkCssTokenSourceTokenizer;
struct _GtkCssTokenSourceTokenizer {
GtkCssTokenSource parent;
GtkCssTokenizer *tokenizer;
+ GFile *location;
GtkCssToken current_token;
};
@@ -38,6 +39,8 @@ gtk_css_token_source_tokenizer_finalize (GtkCssTokenSource *source)
gtk_css_token_clear (&tok->current_token);
gtk_css_tokenizer_unref (tok->tokenizer);
+ if (tok->location)
+ g_object_unref (tok->location);
}
static void
@@ -80,22 +83,35 @@ gtk_css_token_source_tokenizer_error (GtkCssTokenSource *source,
g_print ("ERROR: %s\n", error->message);
}
+static GFile *
+gtk_css_token_source_tokenizer_get_location (GtkCssTokenSource *source)
+{
+ GtkCssTokenSourceTokenizer *tok = (GtkCssTokenSourceTokenizer *) source;
+
+ return tok->location;
+}
+
const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_TOKENIZER = {
gtk_css_token_source_tokenizer_finalize,
gtk_css_token_source_tokenizer_consume_token,
gtk_css_token_source_tokenizer_peek_token,
gtk_css_token_source_tokenizer_error,
+ gtk_css_token_source_tokenizer_get_location,
};
GtkCssTokenSource *
-gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer)
+gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer,
+ GFile *location)
{
GtkCssTokenSourceTokenizer *source;
g_return_val_if_fail (tokenizer != NULL, NULL);
+ g_return_val_if_fail (location == NULL || G_IS_FILE (location), NULL);
source = gtk_css_token_source_new (GtkCssTokenSourceTokenizer, >K_CSS_TOKEN_SOURCE_TOKENIZER);
source->tokenizer = gtk_css_tokenizer_ref (tokenizer);
+ if (location)
+ source->location = g_object_ref (location);
return &source->parent;
}
@@ -156,11 +172,20 @@ gtk_css_token_source_part_error (GtkCssTokenSource *source,
gtk_css_token_source_emit_error (part->source, error);
}
+static GFile *
+gtk_css_token_source_part_get_location (GtkCssTokenSource *source)
+{
+ GtkCssTokenSourcePart *part = (GtkCssTokenSourcePart *) source;
+
+ return gtk_css_token_source_get_location (part->source);
+}
+
const GtkCssTokenSourceClass GTK_CSS_TOKEN_SOURCE_PART = {
gtk_css_token_source_part_finalize,
gtk_css_token_source_part_consume_token,
gtk_css_token_source_part_peek_token,
gtk_css_token_source_part_error,
+ gtk_css_token_source_part_get_location,
};
GtkCssTokenSource *
@@ -414,6 +439,82 @@ gtk_css_token_source_consume_number (GtkCssTokenSource *source,
return TRUE;
}
+GFile *
+gtk_css_token_source_resolve_url (GtkCssTokenSource *source,
+ const char *url)
+{
+ char *scheme;
+ GFile *file, *location, *base;
+
+ scheme = g_uri_parse_scheme (url);
+ if (scheme != NULL)
+ {
+ file = g_file_new_for_uri (url);
+ g_free (scheme);
+ return file;
+ }
+
+ location = gtk_css_token_source_get_location (source);
+ if (location)
+ {
+ base = g_file_get_parent (location);
+ }
+ else
+ {
+ char *dir = g_get_current_dir ();
+ base = g_file_new_for_path (dir);
+ g_free (dir);
+ }
+
+ file = g_file_resolve_relative_path (base, url);
+ g_object_unref (base);
+
+ return file;
+}
+
+GFile *
+gtk_css_token_source_consume_url (GtkCssTokenSource *source)
+{
+ const GtkCssToken *token;
+ GFile *file;
+
+ token = gtk_css_token_source_get_token (source);
+ if (gtk_css_token_is (token, GTK_CSS_TOKEN_URL))
+ {
+ file = gtk_css_token_source_resolve_url (source, token->string.string);
+ gtk_css_token_source_consume_token (source);
+ return file;
+ }
+ else if (gtk_css_token_is_function (token, "url"))
+ {
+ gtk_css_token_source_consume_token (source);
+ token = gtk_css_token_source_get_token (source);
+ if (!gtk_css_token_is (token, GTK_CSS_TOKEN_STRING))
+ {
+ gtk_css_token_source_error (source, "Expected string inside url()");
+ gtk_css_token_source_consume_all (source);
+ return NULL;
+ }
+ file = gtk_css_token_source_resolve_url (source, token->string.string);
+ gtk_css_token_source_consume_token (source);
+ token = gtk_css_token_source_get_token (source);
+ if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
+ {
+ gtk_css_token_source_error (source, "Expected closing ')' for url()");
+ gtk_css_token_source_consume_all (source);
+ g_object_unref (file);
+ return NULL;
+ }
+ return file;
+ }
+ else
+ {
+ gtk_css_token_source_error (source, "Expected url()");
+ gtk_css_token_source_consume_all (source);
+ return NULL;
+ }
+}
+
GtkCssTokenType
gtk_css_token_get_pending_block (GtkCssTokenSource *source)
{
@@ -481,6 +582,12 @@ gtk_css_token_source_deprecated (GtkCssTokenSource *source,
va_end (args);
}
+GFile *
+gtk_css_token_source_get_location (GtkCssTokenSource *source)
+{
+ return source->klass->get_location (source);
+}
+
GObject *
gtk_css_token_source_get_consumer (GtkCssTokenSource *source)
{
diff --git a/gtk/gtkcsstokensourceprivate.h b/gtk/gtkcsstokensourceprivate.h
index 8547611..7b82762 100644
--- a/gtk/gtkcsstokensourceprivate.h
+++ b/gtk/gtkcsstokensourceprivate.h
@@ -20,7 +20,7 @@
#ifndef __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__
#define __GTK_CSS_TOKEN_SOURCE_PRIVATE_H__
-#include <glib-object.h>
+#include <gio/gio.h>
#include "gtk/gtkcsstokenizerprivate.h"
G_BEGIN_DECLS
@@ -44,9 +44,11 @@ struct _GtkCssTokenSourceClass
const GtkCssToken * (* peek_token) (GtkCssTokenSource *source);
void (* error) (GtkCssTokenSource *source,
const GError *error);
+ GFile * (* get_location) (GtkCssTokenSource *source);
};
-GtkCssTokenSource * gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer);
+GtkCssTokenSource * gtk_css_token_source_new_for_tokenizer (GtkCssTokenizer *tokenizer,
+ GFile *location);
GtkCssTokenSource * gtk_css_token_source_new_for_part (GtkCssTokenSource *source,
GtkCssTokenType end_type);
@@ -75,6 +77,9 @@ gboolean gtk_css_token_source_consume_function (GtkCssTokenSour
gpointer data);
gboolean gtk_css_token_source_consume_number (GtkCssTokenSource *source,
double *number);
+GFile * gtk_css_token_source_resolve_url (GtkCssTokenSource *source,
+ const char *url);
+GFile * gtk_css_token_source_consume_url (GtkCssTokenSource *source);
void gtk_css_token_source_emit_error (GtkCssTokenSource *source,
const GError *error);
@@ -88,6 +93,7 @@ void gtk_css_token_source_deprecated (GtkCssTokenSour
const char *format,
...) G_GNUC_PRINTF(2, 3);
+GFile * gtk_css_token_source_get_location (GtkCssTokenSource *source);
GObject * gtk_css_token_source_get_consumer (GtkCssTokenSource *source);
void gtk_css_token_source_set_consumer (GtkCssTokenSource *source,
GObject *consumer);
diff --git a/gtk/inspector/css-editor.c b/gtk/inspector/css-editor.c
index 3b3210a..21da13e 100644
--- a/gtk/inspector/css-editor.c
+++ b/gtk/inspector/css-editor.c
@@ -194,11 +194,18 @@ gtk_css_chunk_token_source_error (GtkCssTokenSource *source,
chunk->error = g_error_copy (error);
}
+static GFile *
+gtk_css_chunk_token_source_get_location (GtkCssTokenSource *source)
+{
+ return NULL;
+}
+
const GtkCssTokenSourceClass GTK_CSS_CHUNK_TOKEN_SOURCE = {
gtk_css_chunk_token_source_finalize,
gtk_css_chunk_token_source_consume_token,
gtk_css_chunk_token_source_get_token,
gtk_css_chunk_token_source_error,
+ gtk_css_chunk_token_source_get_location,
};
static GtkCssTokenSource *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]