X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcssvalue.c;h=6d77cf80c94fe299ddb11897e658de4991fab853;hb=d0895d6c0feb6c6ca14bfc05910926051b2bf63b;hp=367818116e9f693cc315353f7a74f7ea9b3b5e00;hpb=1ceed037b24c78b48a5319f465e4c489eb373413;p=~andy%2Fgtk diff --git a/gtk/gtkcssvalue.c b/gtk/gtkcssvalue.c index 367818116..6d77cf80c 100644 --- a/gtk/gtkcssvalue.c +++ b/gtk/gtkcssvalue.c @@ -17,329 +17,28 @@ #include "config.h" +#include "gtkprivate.h" #include "gtkcssvalueprivate.h" -#include "gtktypebuiltins.h" -#include "gtkgradient.h" -#include -#include "gtkprivatetypebuiltins.h" -#include "fallback-c89.c" +#include "gtkcsscomputedvaluesprivate.h" +#include "gtkstyleproviderprivate.h" -struct _GtkCssValue -{ - volatile gint ref_count; - GType type; - union { - gpointer ptr; - gint gint; - double dbl; - } u; +struct _GtkCssValue { + GTK_CSS_VALUE_BASE }; G_DEFINE_BOXED_TYPE (GtkCssValue, _gtk_css_value, _gtk_css_value_ref, _gtk_css_value_unref) -static GtkCssValue * -_gtk_css_value_new (GType type) -{ - GtkCssValue *value; - - value = g_slice_new0 (GtkCssValue); - - value->ref_count = 1; - value->type = type; - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_gvalue (const GValue *g_value) -{ - GtkCssValue *value; - GType type; - - g_return_val_if_fail (g_value != NULL, NULL); - - type = G_VALUE_TYPE (g_value); - - /* Make sure we reuse the int/number singletons */ - if (type == G_TYPE_INT) - value = _gtk_css_value_new_from_int (g_value_get_int (g_value)); - else if (type == GTK_TYPE_CSS_NUMBER) - value = _gtk_css_value_new_from_number (g_value_get_boxed (g_value)); - else - { - value = _gtk_css_value_new (type); - - if (g_type_is_a (type, G_TYPE_OBJECT)) - value->u.ptr = g_value_dup_object (g_value); - else if (g_type_is_a (type, G_TYPE_BOXED)) - value->u.ptr = g_value_dup_boxed (g_value); - else if (g_type_is_a (type, G_TYPE_INT)) - value->u.gint = g_value_get_int (g_value); - else if (g_type_is_a (type, G_TYPE_BOOLEAN)) - value->u.gint = g_value_get_boolean (g_value); - else if (g_type_is_a (type, G_TYPE_ENUM)) - value->u.gint = g_value_get_enum (g_value); - else if (g_type_is_a (type, G_TYPE_STRING)) - value->u.ptr = g_value_dup_string (g_value); - else if (g_type_is_a (type, G_TYPE_DOUBLE)) - value->u.dbl = g_value_get_double (g_value); - else - g_assert_not_reached (); - } - - return value; -} - -GtkCssValue * -_gtk_css_value_new_take_gvalue (GValue *g_value) -{ - GtkCssValue *value; - GType type; - - g_return_val_if_fail (g_value != NULL, NULL); - - type = G_VALUE_TYPE (g_value); - - /* Make sure we reuse the int/number singletons */ - if (type == G_TYPE_INT) - { - value = _gtk_css_value_new_from_int (g_value_get_int (g_value)); - g_value_unset (g_value); - } - else if (type == GTK_TYPE_CSS_NUMBER) - { - value = _gtk_css_value_new_from_number (g_value_get_boxed (g_value)); - g_value_unset (g_value); - } - else - { - value = _gtk_css_value_new (type); - - if (g_type_is_a (type, G_TYPE_OBJECT)) - value->u.ptr = g_value_get_object (g_value); - else if (g_type_is_a (type, G_TYPE_BOXED)) - value->u.ptr = g_value_get_boxed (g_value); - else if (g_type_is_a (type, G_TYPE_INT)) - value->u.gint = g_value_get_int (g_value); - else if (g_type_is_a (type, G_TYPE_BOOLEAN)) - value->u.gint = g_value_get_boolean (g_value); - else if (g_type_is_a (type, G_TYPE_ENUM)) - value->u.gint = g_value_get_enum (g_value); - else if (g_type_is_a (type, G_TYPE_STRING)) - value->u.ptr = g_value_dup_string (g_value); - else if (g_type_is_a (type, G_TYPE_DOUBLE)) - value->u.dbl = g_value_get_double (g_value); - else - g_assert_not_reached (); - } - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_int (gint val) -{ - GtkCssValue *value; - static GtkCssValue *singletons[4] = {NULL}; - - if (val >= 0 && val < G_N_ELEMENTS (singletons)) - { - if (singletons[val] == NULL) - { - value = _gtk_css_value_new (G_TYPE_INT); - value->u.gint = val; - singletons[val] = value; - } - return _gtk_css_value_ref (singletons[val]); - } - - value = _gtk_css_value_new (G_TYPE_INT); - value->u.gint = val; - - return value; -} - -GtkCssValue * -_gtk_css_value_new_take_string (char *string) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (G_TYPE_STRING); - value->u.ptr = string; - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_string (const char *string) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (G_TYPE_STRING); - value->u.ptr = g_strdup (string); - - return value; -} - -static gpointer -g_boxed_copy0 (GType boxed_type, - gconstpointer src_boxed) -{ - if (src_boxed == NULL) - return NULL; - return g_boxed_copy (boxed_type, src_boxed); -} - -GtkCssValue * -_gtk_css_value_new_from_border (const GtkBorder *border) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (GTK_TYPE_BORDER); - value->u.ptr = g_boxed_copy0 (GTK_TYPE_BORDER, border); - - return value; -} - -GtkCssValue * -_gtk_css_value_new_take_pattern (cairo_pattern_t *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN); - value->u.ptr = v; - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_pattern (const cairo_pattern_t *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN); - value->u.ptr = g_boxed_copy0 (CAIRO_GOBJECT_TYPE_PATTERN, v); - - return value; -} - GtkCssValue * -_gtk_css_value_new_take_shadow (GtkShadow *v) +_gtk_css_value_alloc (const GtkCssValueClass *klass, + gsize size) { GtkCssValue *value; - value = _gtk_css_value_new (GTK_TYPE_SHADOW); - value->u.ptr = v; + value = g_slice_alloc0 (size); - return value; -} - -GtkCssValue * -_gtk_css_value_new_take_font_description (PangoFontDescription *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (PANGO_TYPE_FONT_DESCRIPTION); - value->u.ptr = v; - - return value; -} - -GtkCssValue * -_gtk_css_value_new_take_image (GtkCssImage *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (GTK_TYPE_CSS_IMAGE); - value->u.ptr = v; - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_number (const GtkCssNumber *v) -{ - GtkCssValue *value; - static GtkCssValue *zero_singleton = NULL; - static GtkCssValue *px_singletons[5] = {NULL}; - - if (v->unit == GTK_CSS_NUMBER && - v->value == 0) - { - if (zero_singleton == NULL) - { - value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER); - value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v); - zero_singleton = value; - } - return _gtk_css_value_ref (zero_singleton); - } - - if (v->unit == GTK_CSS_PX && - (v->value == 0 || - v->value == 1 || - v->value == 2 || - v->value == 3 || - v->value == 4)) - { - int i = round (v->value); - if (px_singletons[i] == NULL) - { - value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER); - value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v); - px_singletons[i] = value; - } - - return _gtk_css_value_ref (px_singletons[i]); - } - - value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER); - value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v); - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_rgba (const GdkRGBA *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (GDK_TYPE_RGBA); - value->u.ptr = g_boxed_copy0 (GDK_TYPE_RGBA, v); - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_color (const GdkColor *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (GDK_TYPE_COLOR); - value->u.ptr = g_boxed_copy0 (GDK_TYPE_COLOR, v); - - return value; -} - -GtkCssValue * -_gtk_css_value_new_from_background_size (const GtkCssBackgroundSize *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (GTK_TYPE_CSS_BACKGROUND_SIZE); - value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_BACKGROUND_SIZE, v); - - return value; -} - -GtkCssValue * -_gtk_css_value_new_take_symbolic_color (GtkSymbolicColor *v) -{ - GtkCssValue *value; - - value = _gtk_css_value_new (GTK_TYPE_SYMBOLIC_COLOR); - value->u.ptr = v; + value->class = klass; + value->ref_count = 1; return value; } @@ -347,7 +46,7 @@ _gtk_css_value_new_take_symbolic_color (GtkSymbolicColor *v) GtkCssValue * _gtk_css_value_ref (GtkCssValue *value) { - g_return_val_if_fail (value != NULL, NULL); + gtk_internal_return_val_if_fail (value != NULL, NULL); g_atomic_int_add (&value->ref_count, 1); @@ -357,259 +56,129 @@ _gtk_css_value_ref (GtkCssValue *value) void _gtk_css_value_unref (GtkCssValue *value) { - GType type; - if (value == NULL) return; if (!g_atomic_int_dec_and_test (&value->ref_count)) return; - type = value->type; - - if (g_type_is_a (type, G_TYPE_OBJECT) && value->u.ptr != NULL) - g_object_unref (value->u.ptr); - else if (g_type_is_a (type, G_TYPE_BOXED) && value->u.ptr != NULL) - g_boxed_free (type, value->u.ptr); - else if (g_type_is_a (type, G_TYPE_STRING)) - g_free (value->u.ptr); - - g_slice_free (GtkCssValue, value); -} - -GType -_gtk_css_value_get_content_type (GtkCssValue *value) -{ - return value->type; + value->class->free (value); } -gboolean -_gtk_css_value_holds (GtkCssValue *value, GType type) +/** + * _gtk_css_value_compute: + * @value: the value to compute from + * @property_id: the ID of the property to compute + * @provider: Style provider for looking up extra information + * @values: values to compute for + * @parent_values: parent values to use for inherited values + * @dependencies: (out) (allow-none): Set to the dependencies of the + * computed values that indicate when this value needs to be + * recomputed and how. + * + * Converts the specified @value into the computed value for the CSS + * property given by @property_id using the information in @context. + * This step is explained in detail in + * type), - G_VALUE_TYPE_NAME (g_value)); + return value->class->compute (value, property_id, provider, values, parent_values, dependencies); } gboolean -_gtk_css_value_is_special (GtkCssValue *value) +_gtk_css_value_equal (const GtkCssValue *value1, + const GtkCssValue *value2) { - return _gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE); -} + gtk_internal_return_val_if_fail (value1 != NULL, FALSE); + gtk_internal_return_val_if_fail (value2 != NULL, FALSE); -GtkCssSpecialValue -_gtk_css_value_get_special_kind (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE), 0); - return value->u.gint; -} + if (value1 == value2) + return TRUE; -GtkCssNumber * -_gtk_css_value_get_number (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_NUMBER), NULL); - return value->u.ptr; -} + if (value1->class != value2->class) + return FALSE; -GtkSymbolicColor * -_gtk_css_value_get_symbolic_color (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SYMBOLIC_COLOR), NULL); - return value->u.ptr; -} - -int -_gtk_css_value_get_int (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_INT), 0); - return value->u.gint; -} - -double -_gtk_css_value_get_double (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_DOUBLE), 0); - return value->u.dbl; -} - -const char * -_gtk_css_value_get_string (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRING), 0); - return value->u.ptr; -} - -gpointer -_gtk_css_value_dup_object (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL); - if (value->u.ptr) - return g_object_ref (value->u.ptr); - return NULL; -} - -gpointer -_gtk_css_value_get_object (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL); - return value->u.ptr; -} - -gpointer -_gtk_css_value_get_boxed (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_BOXED), NULL); - return value->u.ptr; -} - -const char ** -_gtk_css_value_get_strv (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRV), NULL); - return value->u.ptr; + return value1->class->equal (value1, value2); } -GtkCssImage * -_gtk_css_value_get_image (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_IMAGE), NULL); - return value->u.ptr; -} - -GtkBorderStyle -_gtk_css_value_get_border_style (GtkCssValue *value) +gboolean +_gtk_css_value_equal0 (const GtkCssValue *value1, + const GtkCssValue *value2) { - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_BORDER_STYLE), 0); - return value->u.gint; -} + /* Inclues both values being NULL */ + if (value1 == value2) + return TRUE; -GtkCssBackgroundSize * -_gtk_css_value_get_background_size (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BACKGROUND_SIZE), NULL); - return value->u.ptr; -} + if (value1 == NULL || value2 == NULL) + return FALSE; -GtkCssBorderImageRepeat * -_gtk_css_value_get_border_image_repeat (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT), NULL); - return value->u.ptr; + return _gtk_css_value_equal (value1, value2); } -GtkCssBorderCornerRadius * -_gtk_css_value_get_border_corner_radius (GtkCssValue *value) +GtkCssValue * +_gtk_css_value_transition (GtkCssValue *start, + GtkCssValue *end, + guint property_id, + double progress) { - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS), NULL); - return value->u.ptr; -} + gtk_internal_return_val_if_fail (start != NULL, FALSE); + gtk_internal_return_val_if_fail (end != NULL, FALSE); -PangoFontDescription * -_gtk_css_value_get_font_description (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_FONT_DESCRIPTION), 0); - return value->u.ptr; -} + if (start->class != end->class) + return NULL; -PangoStyle -_gtk_css_value_get_pango_style (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_STYLE), 0); - return value->u.gint; + return start->class->transition (start, end, property_id, progress); } -PangoVariant -_gtk_css_value_get_pango_variant (GtkCssValue *value) +char * +_gtk_css_value_to_string (const GtkCssValue *value) { - g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_VARIANT), 0); - return value->u.gint; -} + GString *string; -PangoWeight -_gtk_css_value_get_pango_weight (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_WEIGHT), 0); - return value->u.gint; -} + gtk_internal_return_val_if_fail (value != NULL, NULL); -GdkRGBA * -_gtk_css_value_get_rgba (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GDK_TYPE_RGBA), NULL); - return value->u.ptr; + string = g_string_new (NULL); + _gtk_css_value_print (value, string); + return g_string_free (string, FALSE); } -cairo_pattern_t * -_gtk_css_value_get_pattern (GtkCssValue *value) +/** + * _gtk_css_value_print: + * @value: the value to print + * @string: the string to print to + * + * Prints @value to the given @string in CSS format. The @value must be a + * valid specified value as parsed using the parse functions or as assigned + * via _gtk_style_property_assign(). + **/ +void +_gtk_css_value_print (const GtkCssValue *value, + GString *string) { - g_return_val_if_fail (_gtk_css_value_holds (value, CAIRO_GOBJECT_TYPE_PATTERN), NULL); - return value->u.ptr; -} + gtk_internal_return_if_fail (value != NULL); + gtk_internal_return_if_fail (string != NULL); -GtkGradient * -_gtk_css_value_get_gradient (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_GRADIENT), NULL); - return value->u.ptr; + value->class->print (value, string); } -GtkShadow * -_gtk_css_value_get_shadow (GtkCssValue *value) -{ - g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SHADOW), NULL); - return value->u.ptr; -}