/* the actual parsers we have */
#include "gtkanimationdescription.h"
#include "gtkbindings.h"
-#include "gtk9slice.h"
+#include "gtkborderimageprivate.h"
#include "gtkgradient.h"
#include "gtkshadowprivate.h"
#include "gtkthemingengine.h"
#include "gtktypebuiltins.h"
+/* this is in case round() is not provided by the compiler,
+ * such as in the case of C89 compilers, like MSVC
+ */
+#include "fallback-c89.c"
+
static GHashTable *parse_funcs = NULL;
static GHashTable *print_funcs = NULL;
static GHashTable *properties = NULL;
GValue *value)
{
PangoFontDescription *font_desc;
+ guint mask;
char *str;
str = _gtk_css_parser_read_value (parser);
return FALSE;
font_desc = pango_font_description_from_string (str);
+ mask = pango_font_description_get_set_fields (font_desc);
+ /* These values are not really correct,
+ * but the fields must be set, so we set them to something */
+ if ((mask & PANGO_FONT_MASK_FAMILY) == 0)
+ pango_font_description_set_family_static (font_desc, "Sans");
+ if ((mask & PANGO_FONT_MASK_SIZE) == 0)
+ pango_font_description_set_size (font_desc, 10 * PANGO_SCALE);
g_free (str);
g_value_take_boxed (value, font_desc);
return TRUE;
{
/* XXX: gtk_theming_engine_get_name()? */
g_object_get (engine, "name", &name, NULL);
- g_string_append (string, name);
+ g_string_append (string, name ? name : "none");
g_free (name);
}
}
error = g_error_new_literal (GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_DEPRECATED,
- "Whitespace between 'url' and '(' is not allowed");
+ "Whitespace between 'url' and '(' is deprecated");
_gtk_css_parser_take_error (parser, error);
}
return TRUE;
}
+static cairo_status_t
+surface_write (void *closure,
+ const unsigned char *data,
+ unsigned int length)
+{
+ g_byte_array_append (closure, data, length);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+surface_print (cairo_surface_t *surface,
+ GString * string)
+{
+#if CAIRO_HAS_PNG_FUNCTIONS
+ GByteArray *array;
+ char *base64;
+
+ array = g_byte_array_new ();
+ cairo_surface_write_to_png_stream (surface, surface_write, array);
+ base64 = g_base64_encode (array->data, array->len);
+ g_byte_array_free (array, TRUE);
+
+ g_string_append (string, "url(\"data:image/png;base64,");
+ g_string_append (string, base64);
+ g_string_append (string, "\")");
+
+ g_free (base64);
+#else
+ g_string_append (string, "none /* you need cairo png functions enabled to make this work */");
+#endif
+}
+
+static void
+pattern_value_print (const GValue *value,
+ GString *string)
+{
+ cairo_pattern_t *pattern;
+ cairo_surface_t *surface;
+
+ pattern = g_value_get_boxed (value);
+
+ if (pattern == NULL)
+ {
+ g_string_append (string, "none");
+ return;
+ }
+
+ switch (cairo_pattern_get_type (pattern))
+ {
+ case CAIRO_PATTERN_TYPE_SURFACE:
+ if (cairo_pattern_get_surface (pattern, &surface) != CAIRO_STATUS_SUCCESS)
+ {
+ g_assert_not_reached ();
+ }
+ surface_print (surface, string);
+ break;
+ case CAIRO_PATTERN_TYPE_SOLID:
+ case CAIRO_PATTERN_TYPE_LINEAR:
+ case CAIRO_PATTERN_TYPE_RADIAL:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
static gboolean
shadow_value_parse (GtkCssParser *parser,
GFile *base,
GValue *value)
{
- gboolean inset;
+ gboolean have_inset, have_color, have_lengths;
gdouble hoffset, voffset, blur, spread;
GtkSymbolicColor *color;
GtkShadow *shadow;
+ guint i;
shadow = _gtk_shadow_new ();
do
{
- inset = _gtk_css_parser_try (parser, "inset", TRUE);
+ have_inset = have_lengths = have_color = FALSE;
- if (!_gtk_css_parser_try_double (parser, &hoffset) ||
- !_gtk_css_parser_try_double (parser, &voffset))
+ for (i = 0; i < 3; i++)
{
- _gtk_css_parser_error (parser, "Horizontal and vertical offsets are required");
- _gtk_shadow_unref (shadow);
- return FALSE;
- }
+ if (!have_inset &&
+ _gtk_css_parser_try (parser, "inset", TRUE))
+ {
+ have_inset = TRUE;
+ continue;
+ }
+
+ if (!have_lengths &&
+ _gtk_css_parser_try_double (parser, &hoffset))
+ {
+ have_lengths = TRUE;
- if (!_gtk_css_parser_try_double (parser, &blur))
- blur = 0;
+ if (!_gtk_css_parser_try_double (parser, &voffset))
+ {
+ _gtk_css_parser_error (parser, "Horizontal and vertical offsets are required");
+ _gtk_shadow_unref (shadow);
+ return FALSE;
+ }
- if (!_gtk_css_parser_try_double (parser, &spread))
- spread = 0;
+ if (!_gtk_css_parser_try_double (parser, &blur))
+ blur = 0;
- /* XXX: the color is optional and UA-defined if it's missing,
- * but it doesn't really make sense for us...
- */
- color = _gtk_css_parser_read_symbolic_color (parser);
+ if (!_gtk_css_parser_try_double (parser, &spread))
+ spread = 0;
- if (color == NULL)
+ continue;
+ }
+
+ if (!have_color)
+ {
+ have_color = TRUE;
+
+ /* XXX: the color is optional and UA-defined if it's missing,
+ * but it doesn't really make sense for us...
+ */
+ color = _gtk_css_parser_read_symbolic_color (parser);
+
+ if (color == NULL)
+ {
+ _gtk_shadow_unref (shadow);
+ return FALSE;
+ }
+ }
+ }
+
+ if (!have_color || !have_lengths)
{
+ _gtk_css_parser_error (parser, "Must specify at least color and offsets");
_gtk_shadow_unref (shadow);
return FALSE;
}
_gtk_shadow_append (shadow,
hoffset, voffset,
blur, spread,
- inset, color);
+ have_inset, color);
gtk_symbolic_color_unref (color);
_gtk_shadow_print (shadow, string);
}
-static gboolean
-slice_value_parse (GtkCssParser *parser,
- GFile *base,
- GValue *value)
+static gboolean
+border_image_repeat_value_parse (GtkCssParser *parser,
+ GFile *file,
+ GValue *value)
{
- gdouble distance_top, distance_bottom;
- gdouble distance_left, distance_right;
- GtkSliceSideModifier mods[2];
- GdkPixbuf *pixbuf;
- Gtk9Slice *slice;
- GFile *file;
- GError *error = NULL;
+ GtkCssBorderImageRepeat image_repeat;
+ GtkCssBorderRepeatStyle styles[2];
gint i;
- char *path;
-
- /* Parse image url */
- file = gtk_css_parse_url (parser, base);
- if (!file)
- return FALSE;
-
- if (!_gtk_css_parser_try_double (parser, &distance_top) ||
- !_gtk_css_parser_try_double (parser, &distance_right) ||
- !_gtk_css_parser_try_double (parser, &distance_bottom) ||
- !_gtk_css_parser_try_double (parser, &distance_left))
- {
- _gtk_css_parser_error (parser, "Expected a number");
- g_object_unref (file);
- return FALSE;
- }
for (i = 0; i < 2; i++)
{
if (_gtk_css_parser_try (parser, "stretch", TRUE))
- mods[i] = GTK_SLICE_STRETCH;
+ styles[i] = GTK_CSS_REPEAT_STYLE_NONE;
else if (_gtk_css_parser_try (parser, "repeat", TRUE))
- mods[i] = GTK_SLICE_REPEAT;
+ styles[i] = GTK_CSS_REPEAT_STYLE_REPEAT;
+ else if (_gtk_css_parser_try (parser, "round", TRUE))
+ styles[i] = GTK_CSS_REPEAT_STYLE_ROUND;
+ else if (_gtk_css_parser_try (parser, "space", TRUE))
+ styles[i] = GTK_CSS_REPEAT_STYLE_SPACE;
else if (i == 0)
{
- mods[1] = mods[0] = GTK_SLICE_STRETCH;
+ styles[1] = styles[0] = GTK_CSS_REPEAT_STYLE_NONE;
break;
}
else
- mods[i] = mods[0];
+ styles[i] = styles[0];
}
- path = g_file_get_path (file);
- g_object_unref (file);
- pixbuf = gdk_pixbuf_new_from_file (path, &error);
- g_free (path);
- if (!pixbuf)
+ image_repeat.hrepeat = styles[0];
+ image_repeat.vrepeat = styles[1];
+
+ g_value_set_boxed (value, &image_repeat);
+
+ return TRUE;
+}
+
+static const gchar *
+border_image_repeat_style_to_string (GtkCssBorderRepeatStyle repeat)
+{
+ switch (repeat)
{
- _gtk_css_parser_take_error (parser, error);
- return FALSE;
+ case GTK_CSS_REPEAT_STYLE_NONE:
+ return "stretch";
+ case GTK_CSS_REPEAT_STYLE_REPEAT:
+ return "repeat";
+ case GTK_CSS_REPEAT_STYLE_ROUND:
+ return "round";
+ case GTK_CSS_REPEAT_STYLE_SPACE:
+ return "space";
+ default:
+ return NULL;
}
+}
- slice = _gtk_9slice_new (pixbuf,
- distance_top, distance_bottom,
- distance_left, distance_right,
- mods[0], mods[1]);
- g_object_unref (pixbuf);
+static void
+border_image_repeat_value_print (const GValue *value,
+ GString *string)
+{
+ GtkCssBorderImageRepeat *image_repeat;
- g_value_take_boxed (value, slice);
- return TRUE;
+ image_repeat = g_value_get_boxed (value);
+
+ g_string_append (string, border_image_repeat_style_to_string (image_repeat->hrepeat));
+ if (image_repeat->hrepeat != image_repeat->vrepeat)
+ {
+ g_string_append (string, " ");
+ g_string_append (string, border_image_repeat_style_to_string (image_repeat->vrepeat));
+ }
+}
+
+static gboolean
+border_image_value_parse (GtkCssParser *parser,
+ GFile *base,
+ GValue *value)
+{
+ GValue temp = G_VALUE_INIT;
+ cairo_pattern_t *pattern = NULL;
+ GtkGradient *gradient = NULL;
+ GtkBorder slice, *width = NULL, *parsed_slice;
+ GtkCssBorderImageRepeat repeat, *parsed_repeat;
+ gboolean retval = FALSE;
+ GtkBorderImage *image = NULL;
+
+ g_value_init (&temp, CAIRO_GOBJECT_TYPE_PATTERN);
+
+ if (!pattern_value_parse (parser, base, &temp))
+ return FALSE;
+
+ if (G_VALUE_TYPE (&temp) == GTK_TYPE_GRADIENT)
+ gradient = g_value_dup_boxed (&temp);
+ else
+ pattern = g_value_dup_boxed (&temp);
+
+ g_value_unset (&temp);
+ g_value_init (&temp, GTK_TYPE_BORDER);
+
+ if (!border_value_parse (parser, base, &temp))
+ goto out;
+
+ parsed_slice = g_value_get_boxed (&temp);
+ slice = *parsed_slice;
+
+ if (_gtk_css_parser_try (parser, "/", TRUE))
+ {
+ g_value_unset (&temp);
+ g_value_init (&temp, GTK_TYPE_BORDER);
+
+ if (!border_value_parse (parser, base, &temp))
+ goto out;
+
+ width = g_value_dup_boxed (&temp);
+ }
+
+ g_value_unset (&temp);
+ g_value_init (&temp, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
+
+ if (!border_image_repeat_value_parse (parser, base, &temp))
+ goto out;
+
+ parsed_repeat = g_value_get_boxed (&temp);
+ repeat = *parsed_repeat;
+
+ g_value_unset (&temp);
+
+ if (gradient != NULL)
+ image = _gtk_border_image_new_for_gradient (gradient, &slice, width, &repeat);
+ else if (pattern != NULL)
+ image = _gtk_border_image_new (pattern, &slice, width, &repeat);
+
+ if (image != NULL)
+ {
+ retval = TRUE;
+ g_value_take_boxed (value, image);
+ }
+
+ out:
+ if (pattern != NULL)
+ cairo_pattern_destroy (pattern);
+
+ if (gradient != NULL)
+ gtk_gradient_unref (gradient);
+
+ if (width != NULL)
+ gtk_border_free (width);
+
+ return retval;
}
static gboolean
}
}
+static gboolean
+transparent_color_value_parse (GtkCssParser *parser,
+ GFile *base,
+ GValue *value)
+{
+ if (_gtk_css_parser_try (parser, "transparent", TRUE))
+ {
+ GdkRGBA transparent = { 0, 0, 0, 0 };
+
+ g_value_set_boxed (value, &transparent);
+
+ return TRUE;
+ }
+
+ return rgba_value_parse (parser, base, value);
+}
+
+static gboolean
+border_color_shorthand_value_parse (GtkCssParser *parser,
+ GFile *base,
+ GValue *value)
+{
+ GtkSymbolicColor *symbolic;
+ GPtrArray *array;
+
+ array = g_ptr_array_new_with_free_func ((GDestroyNotify) gtk_symbolic_color_unref);
+
+ do
+ {
+ if (_gtk_css_parser_try (parser, "transparent", TRUE))
+ {
+ GdkRGBA transparent = { 0, 0, 0, 0 };
+
+ symbolic = gtk_symbolic_color_new_literal (&transparent);
+ }
+ else
+ {
+ symbolic = _gtk_css_parser_read_symbolic_color (parser);
+
+ if (symbolic == NULL)
+ return FALSE;
+ }
+
+ g_ptr_array_add (array, symbolic);
+ }
+ while (array->len < 4 &&
+ !_gtk_css_parser_is_eof (parser) &&
+ !_gtk_css_parser_begins_with (parser, ';') &&
+ !_gtk_css_parser_begins_with (parser, '}'));
+
+ switch (array->len)
+ {
+ default:
+ g_assert_not_reached ();
+ break;
+ case 1:
+ g_ptr_array_add (array, gtk_symbolic_color_ref (g_ptr_array_index (array, 0)));
+ /* fall through */
+ case 2:
+ g_ptr_array_add (array, gtk_symbolic_color_ref (g_ptr_array_index (array, 0)));
+ /* fall through */
+ case 3:
+ g_ptr_array_add (array, gtk_symbolic_color_ref (g_ptr_array_index (array, 1)));
+ /* fall through */
+ case 4:
+ break;
+ }
+
+ g_value_unset (value);
+ g_value_init (value, G_TYPE_PTR_ARRAY);
+ g_value_take_boxed (value, array);
+
+ return TRUE;
+}
+
/*** PACKING ***/
static GParameter *
pango_font_description_set_variant (description, variant);
pango_font_description_set_weight (description, weight);
- g_free (families);
+ g_strfreev (families);
g_value_take_boxed (value, description);
}
+static GParameter *
+unpack_border_color (const GValue *value,
+ guint *n_params)
+{
+ GParameter *parameter = g_new0 (GParameter, 4);
+ GType type;
+
+ type = G_VALUE_TYPE (value);
+ if (type == G_TYPE_PTR_ARRAY)
+ type = GTK_TYPE_SYMBOLIC_COLOR;
+
+ parameter[0].name = "border-top-color";
+ g_value_init (¶meter[0].value, type);
+ parameter[1].name = "border-right-color";
+ g_value_init (¶meter[1].value, type);
+ parameter[2].name = "border-bottom-color";
+ g_value_init (¶meter[2].value, type);
+ parameter[3].name = "border-left-color";
+ g_value_init (¶meter[3].value, type);
+
+ if (G_VALUE_TYPE (value) == G_TYPE_PTR_ARRAY)
+ {
+ GPtrArray *array = g_value_get_boxed (value);
+ guint i;
+
+ for (i = 0; i < 4; i++)
+ g_value_set_boxed (¶meter[i].value, g_ptr_array_index (array, i));
+ }
+ else
+ {
+ /* can be RGBA or symbolic color */
+ gpointer p = g_value_get_boxed (value);
+
+ g_value_set_boxed (¶meter[0].value, p);
+ g_value_set_boxed (¶meter[1].value, p);
+ g_value_set_boxed (¶meter[2].value, p);
+ g_value_set_boxed (¶meter[3].value, p);
+ }
+
+ *n_params = 4;
+ return parameter;
+}
+
+static void
+pack_border_color (GValue *value,
+ GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ /* NB: We are a color property, so we have to resolve to a color here.
+ * So we just resolve to a color. We pick one and stick to it.
+ * Lesson learned: Don't query border-color shorthand, query the
+ * real properties instead. */
+ g_value_unset (value);
+ gtk_style_properties_get_property (props, "border-top-color", state, value);
+}
+
+/*** UNSET FUNCS ***/
+
+static void
+unset_font_description (GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ gtk_style_properties_unset_property (props, "font-family", state);
+ gtk_style_properties_unset_property (props, "font-style", state);
+ gtk_style_properties_unset_property (props, "font-variant", state);
+ gtk_style_properties_unset_property (props, "font-weight", state);
+ gtk_style_properties_unset_property (props, "font-size", state);
+}
+
+static void
+unset_margin (GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ gtk_style_properties_unset_property (props, "margin-top", state);
+ gtk_style_properties_unset_property (props, "margin-right", state);
+ gtk_style_properties_unset_property (props, "margin-bottom", state);
+ gtk_style_properties_unset_property (props, "margin-left", state);
+}
+
+static void
+unset_padding (GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ gtk_style_properties_unset_property (props, "padding-top", state);
+ gtk_style_properties_unset_property (props, "padding-right", state);
+ gtk_style_properties_unset_property (props, "padding-bottom", state);
+ gtk_style_properties_unset_property (props, "padding-left", state);
+}
+
+static void
+unset_border_width (GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ gtk_style_properties_unset_property (props, "border-top-width", state);
+ gtk_style_properties_unset_property (props, "border-right-width", state);
+ gtk_style_properties_unset_property (props, "border-bottom-width", state);
+ gtk_style_properties_unset_property (props, "border-left-width", state);
+}
+
+static void
+unset_border_radius (GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ gtk_style_properties_unset_property (props, "border-top-right-radius", state);
+ gtk_style_properties_unset_property (props, "border-bottom-right-radius", state);
+ gtk_style_properties_unset_property (props, "border-bottom-left-radius", state);
+ gtk_style_properties_unset_property (props, "border-top-left-radius", state);
+}
+
+static void
+unset_border_color (GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ gtk_style_properties_unset_property (props, "border-top-color", state);
+ gtk_style_properties_unset_property (props, "border-right-color", state);
+ gtk_style_properties_unset_property (props, "border-bottom-color", state);
+ gtk_style_properties_unset_property (props, "border-left-color", state);
+}
+
+static void
+unset_border_image (GtkStyleProperties *props,
+ GtkStateFlags state)
+{
+ gtk_style_properties_unset_property (props, "border-image-source", state);
+ gtk_style_properties_unset_property (props, "border-image-slice", state);
+ gtk_style_properties_unset_property (props, "border-image-repeat", state);
+ gtk_style_properties_unset_property (props, "border-image-width", state);
+}
+
+/*** default values ***/
+
+static void
+border_image_width_default_value (GtkStyleProperties *props,
+ GtkStateFlags state,
+ GValue *value)
+{
+}
+
+static void
+background_color_default_value (GtkStyleProperties *props,
+ GtkStateFlags state,
+ GValue *value)
+{
+ GdkRGBA transparent_black = { 0, 0, 0, 0 };
+
+ g_value_set_boxed (value, &transparent_black);
+}
+
+static void
+border_color_default_value (GtkStyleProperties *props,
+ GtkStateFlags state,
+ GValue *value)
+{
+ g_value_unset (value);
+ gtk_style_properties_get_property (props, "color", state, value);
+}
+
/*** API ***/
static void
gradient_value_print);
register_conversion_function (CAIRO_GOBJECT_TYPE_PATTERN,
pattern_value_parse,
+ pattern_value_print);
+ register_conversion_function (GTK_TYPE_BORDER_IMAGE,
+ border_image_value_parse,
NULL);
- register_conversion_function (GTK_TYPE_9SLICE,
- slice_value_parse,
- NULL);
+ register_conversion_function (GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
+ border_image_repeat_value_parse,
+ border_image_repeat_value_print);
register_conversion_function (GTK_TYPE_SHADOW,
shadow_value_parse,
shadow_value_print);
void
_gtk_style_property_default_value (const GtkStyleProperty *property,
GtkStyleProperties *properties,
+ GtkStateFlags state,
GValue *value)
{
if (property->default_value_func)
- property->default_value_func (properties, value);
+ property->default_value_func (properties, state, value);
else if (property->pspec->value_type == GTK_TYPE_THEMING_ENGINE)
g_value_set_object (value, gtk_theming_engine_load (NULL));
else if (property->pspec->value_type == PANGO_TYPE_FONT_DESCRIPTION)
{
g_return_val_if_fail (property != NULL, FALSE);
- return gtk_style_param_get_inherit (property->pspec);
+ return property->flags & GTK_STYLE_PROPERTY_INHERIT ? TRUE : FALSE;
+}
+
+static gboolean
+resolve_color (GtkStyleProperties *props,
+ GValue *value)
+{
+ GdkRGBA color;
+
+ /* Resolve symbolic color to GdkRGBA */
+ if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &color))
+ return FALSE;
+
+ /* Store it back, this is where GdkRGBA caching happens */
+ g_value_unset (value);
+ g_value_init (value, GDK_TYPE_RGBA);
+ g_value_set_boxed (value, &color);
+
+ return TRUE;
+}
+
+static gboolean
+resolve_color_rgb (GtkStyleProperties *props,
+ GValue *value)
+{
+ GdkColor color = { 0 };
+ GdkRGBA rgba;
+
+ if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &rgba))
+ return FALSE;
+
+ color.red = rgba.red * 65535. + 0.5;
+ color.green = rgba.green * 65535. + 0.5;
+ color.blue = rgba.blue * 65535. + 0.5;
+
+ g_value_unset (value);
+ g_value_init (value, GDK_TYPE_COLOR);
+ g_value_set_boxed (value, &color);
+
+ return TRUE;
+}
+
+static gboolean
+resolve_gradient (GtkStyleProperties *props,
+ GValue *value)
+{
+ cairo_pattern_t *gradient;
+
+ if (!gtk_gradient_resolve (g_value_get_boxed (value), props, &gradient))
+ return FALSE;
+
+ /* Store it back, this is where cairo_pattern_t caching happens */
+ g_value_unset (value);
+ g_value_init (value, CAIRO_GOBJECT_TYPE_PATTERN);
+ g_value_take_boxed (value, gradient);
+
+ return TRUE;
+}
+
+static gboolean
+resolve_shadow (GtkStyleProperties *props,
+ GValue *value)
+{
+ GtkShadow *resolved, *base;
+
+ base = g_value_get_boxed (value);
+
+ if (base == NULL)
+ return TRUE;
+
+ if (_gtk_shadow_get_resolved (base))
+ return TRUE;
+
+ resolved = _gtk_shadow_resolve (base, props);
+ if (resolved == NULL)
+ return FALSE;
+
+ g_value_take_boxed (value, resolved);
+
+ return TRUE;
+}
+
+void
+_gtk_style_property_resolve (const GtkStyleProperty *property,
+ GtkStyleProperties *props,
+ GtkStateFlags state,
+ GValue *val)
+{
+ if (G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
+ {
+ if (property->pspec->value_type == GDK_TYPE_RGBA)
+ {
+ if (resolve_color (props, val))
+ return;
+ }
+ else if (property->pspec->value_type == GDK_TYPE_COLOR)
+ {
+ if (resolve_color_rgb (props, val))
+ return;
+ }
+
+ g_value_unset (val);
+ g_value_init (val, property->pspec->value_type);
+ _gtk_style_property_default_value (property, props, state, val);
+ }
+ else if (G_VALUE_TYPE (val) == GDK_TYPE_RGBA)
+ {
+ if (g_value_get_boxed (val) == NULL)
+ _gtk_style_property_default_value (property, props, state, val);
+ }
+ else if (G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
+ {
+ g_return_if_fail (property->pspec->value_type == CAIRO_GOBJECT_TYPE_PATTERN);
+
+ if (!resolve_gradient (props, val))
+ {
+ g_value_unset (val);
+ g_value_init (val, CAIRO_GOBJECT_TYPE_PATTERN);
+ _gtk_style_property_default_value (property, props, state, val);
+ }
+ }
+ else if (G_VALUE_TYPE (val) == GTK_TYPE_SHADOW)
+ {
+ if (!resolve_shadow (props, val))
+ _gtk_style_property_default_value (property, props, state, val);
+ }
}
gboolean
static void
gtk_style_property_init (void)
{
- GParamSpec *pspec;
-
if (G_LIKELY (properties))
return;
/* note that gtk_style_properties_register_property() calls this function,
* so make sure we're sanely inited to avoid infloops */
- pspec = g_param_spec_boxed ("color",
- "Foreground color",
- "Foreground color",
- GDK_TYPE_RGBA, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- gtk_style_properties_register_property (NULL, pspec);
-
- gtk_style_properties_register_property (NULL,
- g_param_spec_boxed ("background-color",
- "Background color",
- "Background color",
- GDK_TYPE_RGBA, 0));
+ _gtk_style_property_register (g_param_spec_boxed ("color",
+ "Foreground color",
+ "Foreground color",
+ GDK_TYPE_RGBA, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ _gtk_style_property_register (g_param_spec_boxed ("background-color",
+ "Background color",
+ "Background color",
+ GDK_TYPE_RGBA, 0),
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ transparent_color_value_parse,
+ NULL,
+ background_color_default_value,
+ NULL);
- pspec = g_param_spec_boxed ("font-family",
- "Font family",
- "Font family",
- G_TYPE_STRV, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- _gtk_style_property_register (pspec,
+ _gtk_style_property_register (g_param_spec_boxed ("font-family",
+ "Font family",
+ "Font family",
+ G_TYPE_STRV, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
NULL,
NULL,
NULL,
font_family_parse,
font_family_value_print,
+ NULL,
+ NULL);
+ _gtk_style_property_register (g_param_spec_enum ("font-style",
+ "Font style",
+ "Font style",
+ PANGO_TYPE_STYLE,
+ PANGO_STYLE_NORMAL, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ _gtk_style_property_register (g_param_spec_enum ("font-variant",
+ "Font variant",
+ "Font variant",
+ PANGO_TYPE_VARIANT,
+ PANGO_VARIANT_NORMAL, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
NULL);
- pspec = g_param_spec_enum ("font-style",
- "Font style",
- "Font style",
- PANGO_TYPE_STYLE,
- PANGO_STYLE_NORMAL, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- gtk_style_properties_register_property (NULL, pspec);
- pspec = g_param_spec_enum ("font-variant",
- "Font variant",
- "Font variant",
- PANGO_TYPE_VARIANT,
- PANGO_VARIANT_NORMAL, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- gtk_style_properties_register_property (NULL, pspec);
/* xxx: need to parse this properly, ie parse the numbers */
- pspec = g_param_spec_enum ("font-weight",
- "Font weight",
- "Font weight",
- PANGO_TYPE_WEIGHT,
- PANGO_WEIGHT_NORMAL, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- gtk_style_properties_register_property (NULL, pspec);
- pspec = g_param_spec_double ("font-size",
- "Font size",
- "Font size",
- 0, G_MAXDOUBLE, 0, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- gtk_style_properties_register_property (NULL, pspec);
- pspec = g_param_spec_boxed ("font",
- "Font Description",
- "Font Description",
- PANGO_TYPE_FONT_DESCRIPTION, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- _gtk_style_property_register (pspec,
+ _gtk_style_property_register (g_param_spec_enum ("font-weight",
+ "Font weight",
+ "Font weight",
+ PANGO_TYPE_WEIGHT,
+ PANGO_WEIGHT_NORMAL, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ _gtk_style_property_register (g_param_spec_double ("font-size",
+ "Font size",
+ "Font size",
+ 0, G_MAXDOUBLE, 0, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ _gtk_style_property_register (g_param_spec_boxed ("font",
+ "Font Description",
+ "Font Description",
+ PANGO_TYPE_FONT_DESCRIPTION, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
NULL,
unpack_font_description,
pack_font_description,
font_description_value_parse,
font_description_value_print,
+ NULL,
+ unset_font_description);
+
+ _gtk_style_property_register (g_param_spec_boxed ("text-shadow",
+ "Text shadow",
+ "Text shadow",
+ GTK_TYPE_SHADOW, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
NULL);
- pspec = g_param_spec_boxed ("text-shadow",
- "Text shadow",
- "Text shadow",
- GTK_TYPE_SHADOW, 0);
- gtk_style_param_set_inherit (pspec, TRUE);
- gtk_style_properties_register_property (NULL, pspec);
+ _gtk_style_property_register (g_param_spec_boxed ("icon-shadow",
+ "Icon shadow",
+ "Icon shadow",
+ GTK_TYPE_SHADOW, 0),
+ GTK_STYLE_PROPERTY_INHERIT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ gtk_style_properties_register_property (NULL,
+ g_param_spec_boxed ("box-shadow",
+ "Box shadow",
+ "Box shadow",
+ GTK_TYPE_SHADOW, 0));
gtk_style_properties_register_property (NULL,
g_param_spec_int ("margin-top",
"margin top",
"Margin",
"Margin",
GTK_TYPE_BORDER, 0),
+ 0,
NULL,
unpack_margin,
pack_margin,
NULL,
NULL,
- NULL);
+ NULL,
+ unset_margin);
gtk_style_properties_register_property (NULL,
g_param_spec_int ("padding-top",
"padding top",
"Padding",
"Padding",
GTK_TYPE_BORDER, 0),
+ 0,
NULL,
unpack_padding,
pack_padding,
NULL,
NULL,
- NULL);
+ NULL,
+ unset_padding);
gtk_style_properties_register_property (NULL,
g_param_spec_int ("border-top-width",
"border top width",
"Border width",
"Border width, in pixels",
GTK_TYPE_BORDER, 0),
+ 0,
NULL,
unpack_border_width,
pack_border_width,
NULL,
NULL,
- NULL);
+ NULL,
+ unset_border_width);
_gtk_style_property_register (g_param_spec_boxed ("border-top-left-radius",
"Border top left radius",
"Border radius of top left corner, in pixels",
GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ 0,
NULL,
NULL,
NULL,
border_corner_radius_value_parse,
border_corner_radius_value_print,
+ NULL,
NULL);
_gtk_style_property_register (g_param_spec_boxed ("border-top-right-radius",
"Border top right radius",
"Border radius of top right corner, in pixels",
GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ 0,
NULL,
NULL,
NULL,
border_corner_radius_value_parse,
border_corner_radius_value_print,
+ NULL,
NULL);
_gtk_style_property_register (g_param_spec_boxed ("border-bottom-right-radius",
"Border bottom right radius",
"Border radius of bottom right corner, in pixels",
GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ 0,
NULL,
NULL,
NULL,
border_corner_radius_value_parse,
border_corner_radius_value_print,
+ NULL,
NULL);
_gtk_style_property_register (g_param_spec_boxed ("border-bottom-left-radius",
"Border bottom left radius",
"Border radius of bottom left corner, in pixels",
GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
+ 0,
NULL,
NULL,
NULL,
border_corner_radius_value_parse,
border_corner_radius_value_print,
+ NULL,
NULL);
_gtk_style_property_register (g_param_spec_int ("border-radius",
"Border radius",
"Border radius, in pixels",
0, G_MAXINT, 0, 0),
+ 0,
NULL,
unpack_border_radius,
pack_border_radius,
border_radius_value_parse,
border_radius_value_print,
- NULL);
+ NULL,
+ unset_border_radius);
gtk_style_properties_register_property (NULL,
g_param_spec_enum ("border-style",
"Border style",
GTK_TYPE_BORDER_STYLE,
GTK_BORDER_STYLE_NONE, 0));
- gtk_style_properties_register_property (NULL,
- g_param_spec_boxed ("border-color",
+ _gtk_style_property_register (g_param_spec_boxed ("border-top-color",
+ "Border top color",
+ "Border top color",
+ GDK_TYPE_RGBA, 0),
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ transparent_color_value_parse,
+ NULL,
+ border_color_default_value,
+ NULL);
+ _gtk_style_property_register (g_param_spec_boxed ("border-right-color",
+ "Border right color",
+ "Border right color",
+ GDK_TYPE_RGBA, 0),
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ transparent_color_value_parse,
+ NULL,
+ border_color_default_value,
+ NULL);
+ _gtk_style_property_register (g_param_spec_boxed ("border-bottom-color",
+ "Border bottom color",
+ "Border bottom color",
+ GDK_TYPE_RGBA, 0),
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ transparent_color_value_parse,
+ NULL,
+ border_color_default_value,
+ NULL);
+ _gtk_style_property_register (g_param_spec_boxed ("border-left-color",
+ "Border left color",
+ "Border left color",
+ GDK_TYPE_RGBA, 0),
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ transparent_color_value_parse,
+ NULL,
+ border_color_default_value,
+ NULL);
+ _gtk_style_property_register (g_param_spec_boxed ("border-color",
"Border color",
"Border color",
- GDK_TYPE_RGBA, 0));
+ GDK_TYPE_RGBA, 0),
+ 0,
+ NULL,
+ unpack_border_color,
+ pack_border_color,
+ border_color_shorthand_value_parse,
+ NULL,
+ NULL,
+ unset_border_color);
+
gtk_style_properties_register_property (NULL,
g_param_spec_boxed ("background-image",
"Background Image",
"Background Image",
CAIRO_GOBJECT_TYPE_PATTERN, 0));
gtk_style_properties_register_property (NULL,
- g_param_spec_boxed ("border-image",
+ g_param_spec_boxed ("border-image-source",
+ "Border image source",
+ "Border image source",
+ CAIRO_GOBJECT_TYPE_PATTERN, 0));
+ gtk_style_properties_register_property (NULL,
+ g_param_spec_boxed ("border-image-repeat",
+ "Border image repeat",
+ "Border image repeat",
+ GTK_TYPE_CSS_BORDER_IMAGE_REPEAT, 0));
+ gtk_style_properties_register_property (NULL,
+ g_param_spec_boxed ("border-image-slice",
+ "Border image slice",
+ "Border image slice",
+ GTK_TYPE_BORDER, 0));
+ _gtk_style_property_register (g_param_spec_boxed ("border-image-width",
+ "Border image width",
+ "Border image width",
+ GTK_TYPE_BORDER, 0),
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ border_image_width_default_value,
+ NULL);
+ _gtk_style_property_register (g_param_spec_boxed ("border-image",
"Border Image",
"Border Image",
- GTK_TYPE_9SLICE, 0));
+ GTK_TYPE_BORDER_IMAGE, 0),
+ 0,
+ NULL,
+ _gtk_border_image_unpack,
+ _gtk_border_image_pack,
+ NULL,
+ NULL,
+ NULL,
+ unset_border_image);
gtk_style_properties_register_property (NULL,
g_param_spec_object ("engine",
"Theming Engine",
"Key bindings",
"Key bindings",
G_TYPE_PTR_ARRAY, 0),
+ 0,
NULL,
NULL,
NULL,
bindings_value_parse,
bindings_value_print,
+ NULL,
NULL);
}
void
_gtk_style_property_register (GParamSpec *pspec,
+ GtkStylePropertyFlags flags,
GtkStylePropertyParser property_parse_func,
GtkStyleUnpackFunc unpack_func,
GtkStylePackFunc pack_func,
GtkStyleParseFunc parse_func,
GtkStylePrintFunc print_func,
- GtkStyleDefaultValueFunc default_value_func)
+ GtkStyleDefaultValueFunc default_value_func,
+ GtkStyleUnsetFunc unset_func)
{
const GtkStyleProperty *existing;
GtkStyleProperty *node;
}
node = g_slice_new0 (GtkStyleProperty);
+ node->flags = flags;
node->pspec = pspec;
node->property_parse_func = property_parse_func;
node->pack_func = pack_func;
node->parse_func = parse_func;
node->print_func = print_func;
node->default_value_func = default_value_func;
+ node->unset_func = unset_func;
- g_hash_table_insert (properties, pspec->name, node);
+ /* pspec owns name */
+ g_hash_table_insert (properties, (gchar *)pspec->name, node);
}