forked from AuroraMiddleware/gtk
GtkCssProvider: Add a parser for 9slice typed properties.
The value it parses is similar to the border-image CSS3 property, so strings like this will be accepted: border-image: url (foo.png) 4 3 4 3 repeat repeat; the image path is relative to the parsed CSS file dirname if no absolute path is provided.
This commit is contained in:
parent
f363e31a09
commit
7ee564c7cd
@ -23,8 +23,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtkstyleprovider.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "gtkanimationdescription.h"
|
||||
#include "gtk9slice.h"
|
||||
#include "gtkcssprovider.h"
|
||||
|
||||
typedef struct GtkCssProviderPrivate GtkCssProviderPrivate;
|
||||
@ -125,8 +127,9 @@ static void gtk_css_style_provider_iface_init (GtkStyleProviderIface *iface);
|
||||
|
||||
static void css_provider_apply_scope (GtkCssProvider *css_provider,
|
||||
ParserScope scope);
|
||||
static gboolean css_provider_parse_value (const gchar *value_str,
|
||||
GValue *value);
|
||||
static gboolean css_provider_parse_value (GtkCssProvider *css_provider,
|
||||
const gchar *value_str,
|
||||
GValue *value);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (GtkCssProvider, gtk_css_provider, G_TYPE_OBJECT, 0,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
|
||||
@ -696,7 +699,7 @@ gtk_css_provider_get_style_property (GtkStyleProvider *provider,
|
||||
val_str = g_value_get_string (val);
|
||||
found = TRUE;
|
||||
|
||||
css_provider_parse_value (val_str, value);
|
||||
css_provider_parse_value (GTK_CSS_PROVIDER (provider), val_str, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1564,9 +1567,188 @@ gradient_parse (const gchar *str)
|
||||
return gradient;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
url_parse_str (const gchar *str,
|
||||
gchar **end_ptr)
|
||||
{
|
||||
gchar *path, *chr;
|
||||
|
||||
if (!g_str_has_prefix (str, "url"))
|
||||
{
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str += strlen ("url");
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
{
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chr = strchr (str, ')');
|
||||
|
||||
if (!chr)
|
||||
{
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
path = g_strndup (str, chr - str);
|
||||
g_strstrip (path);
|
||||
|
||||
*end_ptr = chr + 1;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static Gtk9Slice *
|
||||
slice_parse_str (GtkCssProvider *css_provider,
|
||||
const gchar *str,
|
||||
gchar **end_ptr)
|
||||
{
|
||||
gdouble distance_top, distance_bottom;
|
||||
gdouble distance_left, distance_right;
|
||||
GtkSliceSideModifier mods[2];
|
||||
GError *error = NULL;
|
||||
GdkPixbuf *pixbuf;
|
||||
gchar *path;
|
||||
gint i = 0;
|
||||
|
||||
SKIP_SPACES (str);
|
||||
|
||||
/* Parse image url */
|
||||
path = url_parse_str (str, end_ptr);
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
if (!g_path_is_absolute (path))
|
||||
{
|
||||
GtkCssProviderPrivate *priv;
|
||||
gchar *dirname, *full_path;
|
||||
|
||||
priv = css_provider->priv;
|
||||
|
||||
/* Use relative path to the current CSS file path, if any */
|
||||
dirname = g_path_get_dirname (priv->filename);
|
||||
|
||||
full_path = g_build_filename (dirname, path, NULL);
|
||||
g_free (path);
|
||||
path = full_path;
|
||||
}
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
/* Parse top/left/bottom/right distances */
|
||||
distance_top = g_strtod (str, end_ptr);
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
distance_right = g_strtod (str, end_ptr);
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
distance_bottom = g_strtod (str, end_ptr);
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
distance_left = g_strtod (str, end_ptr);
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
while (*str && i < 2)
|
||||
{
|
||||
if (g_str_has_prefix (str, "stretch"))
|
||||
{
|
||||
str += strlen ("stretch");
|
||||
mods[i] = GTK_SLICE_STRETCH;
|
||||
}
|
||||
else if (g_str_has_prefix (str, "repeat"))
|
||||
{
|
||||
str += strlen ("repeat");
|
||||
mods[i] = GTK_SLICE_REPEAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (path);
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SKIP_SPACES (str);
|
||||
i++;
|
||||
}
|
||||
|
||||
*end_ptr = (gchar *) str;
|
||||
|
||||
if (*str != '\0')
|
||||
{
|
||||
g_free (path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (i != 2)
|
||||
{
|
||||
/* Fill in second modifier, same as the first */
|
||||
mods[1] = mods[1];
|
||||
}
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file (path, &error);
|
||||
g_free (path);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Pixbuf could not be loaded: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gtk_9slice_new (pixbuf,
|
||||
distance_top, distance_bottom,
|
||||
distance_left, distance_right,
|
||||
mods[0], mods[1]);
|
||||
}
|
||||
|
||||
static Gtk9Slice *
|
||||
slice_parse (GtkCssProvider *css_provider,
|
||||
const gchar *str)
|
||||
{
|
||||
Gtk9Slice *slice;
|
||||
gchar *end;
|
||||
|
||||
slice = slice_parse_str (css_provider, str, &end);
|
||||
|
||||
if (*end != '\0')
|
||||
{
|
||||
g_warning ("Error parsing sliced image \"%s\", stopped at char %ld : '%c'",
|
||||
str, end - str, *end);
|
||||
|
||||
if (slice)
|
||||
{
|
||||
gtk_9slice_unref (slice);
|
||||
slice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
css_provider_parse_value (const gchar *value_str,
|
||||
GValue *value)
|
||||
css_provider_parse_value (GtkCssProvider *css_provider,
|
||||
const gchar *value_str,
|
||||
GValue *value)
|
||||
{
|
||||
GType type;
|
||||
gboolean parsed = TRUE;
|
||||
@ -1682,6 +1864,17 @@ css_provider_parse_value (const gchar *value_str,
|
||||
else
|
||||
parsed = FALSE;
|
||||
}
|
||||
else if (type == GTK_TYPE_9SLICE)
|
||||
{
|
||||
Gtk9Slice *slice;
|
||||
|
||||
slice = slice_parse (css_provider, value_str);
|
||||
|
||||
if (slice)
|
||||
g_value_take_boxed (value, slice);
|
||||
else
|
||||
parsed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Cannot parse string '%s' for type %s", value_str, g_type_name (type));
|
||||
@ -1814,7 +2007,7 @@ parse_rule (GtkCssProvider *css_provider,
|
||||
g_hash_table_insert (priv->cur_properties, prop, val);
|
||||
}
|
||||
else if ((parse_func && (parse_func) (value_str, val, &error)) ||
|
||||
(!parse_func && css_provider_parse_value (value_str, val)))
|
||||
(!parse_func && css_provider_parse_value (css_provider, value_str, val)))
|
||||
g_hash_table_insert (priv->cur_properties, prop, val);
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user