diff --git a/gtk/gtkcssanimatedstyle.c b/gtk/gtkcssanimatedstyle.c index 7f9464338c..8393eb5688 100644 --- a/gtk/gtkcssanimatedstyle.c +++ b/gtk/gtkcssanimatedstyle.c @@ -37,9 +37,178 @@ #include "gtkstyleanimationprivate.h" #include "gtkstylepropertyprivate.h" #include "gtkstyleproviderprivate.h" +#include "gtkcsscustompropertypoolprivate.h" G_DEFINE_TYPE (GtkCssAnimatedStyle, gtk_css_animated_style, GTK_TYPE_CSS_STYLE) +static const int core_props[] = { + GTK_CSS_PROPERTY_COLOR, + GTK_CSS_PROPERTY_DPI, + GTK_CSS_PROPERTY_FONT_SIZE, + GTK_CSS_PROPERTY_ICON_PALETTE +}; + +static const int background_props[] = { + GTK_CSS_PROPERTY_BACKGROUND_COLOR, + GTK_CSS_PROPERTY_BOX_SHADOW, + GTK_CSS_PROPERTY_BACKGROUND_CLIP, + GTK_CSS_PROPERTY_BACKGROUND_ORIGIN, + GTK_CSS_PROPERTY_BACKGROUND_SIZE, + GTK_CSS_PROPERTY_BACKGROUND_POSITION, + GTK_CSS_PROPERTY_BACKGROUND_REPEAT, + GTK_CSS_PROPERTY_BACKGROUND_IMAGE, + GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE +}; + +static const int border_props[] = { + GTK_CSS_PROPERTY_BORDER_TOP_STYLE, + GTK_CSS_PROPERTY_BORDER_TOP_WIDTH, + GTK_CSS_PROPERTY_BORDER_LEFT_STYLE, + GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH, + GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE, + GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE, + GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH, + GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS, + GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS, + GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS, + GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS, + GTK_CSS_PROPERTY_BORDER_TOP_COLOR, + GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR, + GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR, + GTK_CSS_PROPERTY_BORDER_LEFT_COLOR, + GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE, + GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT, + GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE, + GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH +}; + +static const int icon_props[] = { + GTK_CSS_PROPERTY_ICON_SIZE, + GTK_CSS_PROPERTY_ICON_SHADOW, + GTK_CSS_PROPERTY_ICON_STYLE, +}; + +static const int outline_props[] = { + GTK_CSS_PROPERTY_OUTLINE_STYLE, + GTK_CSS_PROPERTY_OUTLINE_WIDTH, + GTK_CSS_PROPERTY_OUTLINE_OFFSET, + GTK_CSS_PROPERTY_OUTLINE_COLOR, +}; + +static const int font_props[] = { + GTK_CSS_PROPERTY_FONT_FAMILY, + GTK_CSS_PROPERTY_FONT_STYLE, + GTK_CSS_PROPERTY_FONT_WEIGHT, + GTK_CSS_PROPERTY_FONT_STRETCH, + GTK_CSS_PROPERTY_LETTER_SPACING, + GTK_CSS_PROPERTY_TEXT_SHADOW, + GTK_CSS_PROPERTY_CARET_COLOR, + GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR, + GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS, + GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS, + GTK_CSS_PROPERTY_LINE_HEIGHT, +}; +static const int font_variant_props[] = { + GTK_CSS_PROPERTY_TEXT_DECORATION_LINE, + GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR, + GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE, + GTK_CSS_PROPERTY_TEXT_TRANSFORM, + GTK_CSS_PROPERTY_FONT_KERNING, + GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES, + GTK_CSS_PROPERTY_FONT_VARIANT_POSITION, + GTK_CSS_PROPERTY_FONT_VARIANT_CAPS, + GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC, + GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES, + GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN, +}; + +static const int animation_props[] = { + GTK_CSS_PROPERTY_ANIMATION_NAME, + GTK_CSS_PROPERTY_ANIMATION_DURATION, + GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION, + GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT, + GTK_CSS_PROPERTY_ANIMATION_DIRECTION, + GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE, + GTK_CSS_PROPERTY_ANIMATION_DELAY, + GTK_CSS_PROPERTY_ANIMATION_FILL_MODE, +}; + +static const int transition_props[] = { + GTK_CSS_PROPERTY_TRANSITION_PROPERTY, + GTK_CSS_PROPERTY_TRANSITION_DURATION, + GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION, + GTK_CSS_PROPERTY_TRANSITION_DELAY, +}; + +static const int size_props[] = { + GTK_CSS_PROPERTY_MARGIN_TOP, + GTK_CSS_PROPERTY_MARGIN_LEFT, + GTK_CSS_PROPERTY_MARGIN_BOTTOM, + GTK_CSS_PROPERTY_MARGIN_RIGHT, + GTK_CSS_PROPERTY_PADDING_TOP, + GTK_CSS_PROPERTY_PADDING_LEFT, + GTK_CSS_PROPERTY_PADDING_BOTTOM, + GTK_CSS_PROPERTY_PADDING_RIGHT, + GTK_CSS_PROPERTY_BORDER_SPACING, + GTK_CSS_PROPERTY_MIN_WIDTH, + GTK_CSS_PROPERTY_MIN_HEIGHT, +}; + +static const int other_props[] = { + GTK_CSS_PROPERTY_ICON_SOURCE, + GTK_CSS_PROPERTY_ICON_TRANSFORM, + GTK_CSS_PROPERTY_ICON_FILTER, + GTK_CSS_PROPERTY_TRANSFORM, + GTK_CSS_PROPERTY_TRANSFORM_ORIGIN, + GTK_CSS_PROPERTY_OPACITY, + GTK_CSS_PROPERTY_FILTER, +}; + +#define DEFINE_VALUES(ENUM, TYPE, NAME) \ +static inline void \ +gtk_css_ ## NAME ## _values_recompute (GtkCssAnimatedStyle *animated) \ +{ \ + GtkCssStyle *style = (GtkCssStyle *)animated; \ + GtkCssValue **values = (GtkCssValue **)((guint8*)(animated->style->NAME) + sizeof (GtkCssValues)); \ + int i; \ +\ + for (i = 0; i < G_N_ELEMENTS (NAME ## _props); i++) \ + { \ + guint id = NAME ## _props[i]; \ + GtkCssValue *original, *computed; \ +\ + if (values[i] == NULL) \ + continue; \ +\ + original = gtk_css_style_get_original_value (style, id); \ + if (original == NULL) \ + continue; \ +\ + computed = _gtk_css_value_compute (original, \ + id, \ + animated->provider, \ + style, \ + animated->parent_style, \ + NULL); \ + if (computed == NULL) \ + continue; \ +\ + gtk_css_animated_style_set_animated_value (animated, id, computed); \ + } \ +} + +DEFINE_VALUES (CORE, Core, core) +DEFINE_VALUES (BACKGROUND, Background, background) +DEFINE_VALUES (BORDER, Border, border) +DEFINE_VALUES (ICON, Icon, icon) +DEFINE_VALUES (OUTLINE, Outline, outline) +DEFINE_VALUES (FONT, Font, font) +DEFINE_VALUES (FONT_VARIANT, FontVariant, font_variant) +DEFINE_VALUES (ANIMATION, Animation, animation) +DEFINE_VALUES (TRANSITION, Transition, transition) +DEFINE_VALUES (SIZE, Size, size) +DEFINE_VALUES (OTHER, Other, other) static GtkCssSection * gtk_css_animated_style_get_section (GtkCssStyle *style, @@ -74,6 +243,15 @@ gtk_css_animated_style_get_static_style (GtkCssStyle *style) return (GtkCssStaticStyle *)animated->style; } +static GtkCssValue * +gtk_css_animated_style_get_original_value (GtkCssStyle *style, + guint id) +{ + GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style); + + return gtk_css_style_get_original_value (animated->style, id); +} + static void gtk_css_animated_style_dispose (GObject *object) { @@ -115,6 +293,7 @@ gtk_css_animated_style_class_init (GtkCssAnimatedStyleClass *klass) style_class->get_section = gtk_css_animated_style_get_section; style_class->is_static = gtk_css_animated_style_is_static; style_class->get_static_style = gtk_css_animated_style_get_static_style; + style_class->get_original_value = gtk_css_animated_style_get_original_value; } static void @@ -549,6 +728,51 @@ gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style, return gtk_css_style_get_value (style->style, id); } +void +gtk_css_animated_style_set_animated_custom_value (GtkCssAnimatedStyle *animated, + int id, + GtkCssVariableValue *value) +{ + GtkCssStyle *style = (GtkCssStyle *)animated; + + gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style)); + gtk_internal_return_if_fail (value != NULL); + + if (style->variables == NULL) + { + style->variables = gtk_css_variable_set_new (); + if (animated->parent_style) + gtk_css_variable_set_set_parent (style->variables, + animated->parent_style->variables); + } + else if (style->variables == animated->style->variables) + { + gtk_css_variable_set_unref (style->variables); + style->variables = gtk_css_variable_set_copy (animated->style->variables); + } + + gtk_css_variable_set_add (style->variables, id, value); + + gtk_css_core_values_recompute (animated); + gtk_css_background_values_recompute (animated); + gtk_css_border_values_recompute (animated); + gtk_css_icon_values_recompute (animated); + gtk_css_outline_values_recompute (animated); + gtk_css_font_values_recompute (animated); + gtk_css_font_variant_values_recompute (animated); + gtk_css_animation_values_recompute (animated); + gtk_css_transition_values_recompute (animated); + gtk_css_size_values_recompute (animated); + gtk_css_other_values_recompute (animated); +} + +GtkCssVariableValue * +gtk_css_animated_style_get_intrinsic_custom_value (GtkCssAnimatedStyle *style, + int id) +{ + return gtk_css_style_get_custom_property (style->style, id); +} + static GPtrArray * gtk_css_animated_style_create_dynamic (GPtrArray *animations, GtkCssStyle *style, @@ -920,6 +1144,8 @@ gtk_css_animated_style_new (GtkCssStyle *base_style, style->transition = (GtkCssTransitionValues *)gtk_css_values_ref ((GtkCssValues *)base_style->transition); style->size = (GtkCssSizeValues *)gtk_css_values_ref ((GtkCssValues *)base_style->size); style->other = (GtkCssOtherValues *)gtk_css_values_ref ((GtkCssValues *)base_style->other); + if (base_style->variables) + style->variables = gtk_css_variable_set_ref (base_style->variables); gtk_css_animated_style_apply_animations (result); @@ -991,6 +1217,8 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source, style->transition = (GtkCssTransitionValues *)gtk_css_values_ref ((GtkCssValues *)base_style->transition); style->size = (GtkCssSizeValues *)gtk_css_values_ref ((GtkCssValues *)base_style->size); style->other = (GtkCssOtherValues *)gtk_css_values_ref ((GtkCssValues *)base_style->other); + if (base_style->variables) + style->variables = gtk_css_variable_set_ref (base_style->variables); gtk_css_animated_style_apply_animations (result); diff --git a/gtk/gtkcssanimatedstyleprivate.h b/gtk/gtkcssanimatedstyleprivate.h index fe3e45c990..d8eab1e458 100644 --- a/gtk/gtkcssanimatedstyleprivate.h +++ b/gtk/gtkcssanimatedstyleprivate.h @@ -67,10 +67,15 @@ GtkCssStyle * gtk_css_animated_style_new_advance (GtkCssAnimatedS void gtk_css_animated_style_set_animated_value(GtkCssAnimatedStyle *style, guint id, GtkCssValue *value); - GtkCssValue * gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style, guint id); +void gtk_css_animated_style_set_animated_custom_value (GtkCssAnimatedStyle *animated, + int id, + GtkCssVariableValue *value); +GtkCssVariableValue * gtk_css_animated_style_get_intrinsic_custom_value (GtkCssAnimatedStyle *style, + int id); + GtkCssStyle * gtk_css_animated_style_get_base_style (GtkCssAnimatedStyle *style); GtkCssStyle * gtk_css_animated_style_get_parent_style (GtkCssAnimatedStyle *style); GtkStyleProvider * gtk_css_animated_style_get_provider (GtkCssAnimatedStyle *style); diff --git a/gtk/gtkcssanimation.c b/gtk/gtkcssanimation.c index 5047586867..2f6b73cbf8 100644 --- a/gtk/gtkcssanimation.c +++ b/gtk/gtkcssanimation.c @@ -110,6 +110,20 @@ gtk_css_animation_apply_values (GtkStyleAnimation *style_animation, base_style, parent_style); + for (i = 0; i < _gtk_css_keyframes_get_n_variables (resolved_keyframes); i++) + { + GtkCssVariableValue *value; + int variable_id; + + variable_id = _gtk_css_keyframes_get_variable_id (resolved_keyframes, i); + + value = _gtk_css_keyframes_get_variable (resolved_keyframes, + i, + progress, + gtk_css_animated_style_get_intrinsic_custom_value (style, variable_id)); + gtk_css_animated_style_set_animated_custom_value (style, variable_id, value); + } + for (i = 0; i < _gtk_css_keyframes_get_n_properties (resolved_keyframes); i++) { GtkCssValue *value; diff --git a/gtk/gtkcsskeyframes.c b/gtk/gtkcsskeyframes.c index 4faeb801de..b6380be603 100644 --- a/gtk/gtkcsskeyframes.c +++ b/gtk/gtkcsskeyframes.c @@ -21,6 +21,8 @@ #include "gtkcssstyleprivate.h" #include "gtkcssarrayvalueprivate.h" +#include "gtkcsscustompropertypoolprivate.h" +#include "gtkcssreferencevalueprivate.h" #include "gtkcssshorthandpropertyprivate.h" #include "gtkcssstylepropertyprivate.h" #include "gtkstylepropertyprivate.h" @@ -31,12 +33,15 @@ #include struct _GtkCssKeyframes { - int ref_count; /* ref count */ - int n_keyframes; /* number of keyframes (at least 2 for 0% and 100% */ - double *keyframe_progress; /* ordered array of n_keyframes of [0..1] */ - int n_properties; /* number of properties used by keyframes */ - guint *property_ids; /* ordered array of n_properties property ids */ - GtkCssValue **values; /* 2D array: n_keyframes * n_properties of (value or NULL) for all the keyframes */ + int ref_count; /* ref count */ + int n_keyframes; /* number of keyframes (at least 2 for 0% and 100% */ + double *keyframe_progress; /* ordered array of n_keyframes of [0..1] */ + int n_properties; /* number of properties used by keyframes */ + guint *property_ids; /* ordered array of n_properties property ids */ + GtkCssValue **values; /* 2D array: n_keyframes * n_properties of (value or NULL) for all the keyframes */ + GtkCssVariableSet **variables; /* array of variable sets for each keyframe */ + int *variable_ids; /* ordered array of variable ids */ + int n_variables; /* number of variable used by keyframes */ }; #define KEYFRAMES_VALUE(keyframes, k, p) ((keyframes)->values[(k) * (keyframes)->n_properties + (p)]) @@ -72,8 +77,13 @@ _gtk_css_keyframes_unref (GtkCssKeyframes *keyframes) _gtk_css_value_unref (KEYFRAMES_VALUE (keyframes, k, p)); KEYFRAMES_VALUE (keyframes, k, p) = NULL; } + + if (keyframes->variables && keyframes->variables[k]) + gtk_css_variable_set_unref (keyframes->variables[k]); } g_free (keyframes->values); + g_free (keyframes->variables); + g_free (keyframes->variable_ids); g_free (keyframes); } @@ -120,6 +130,9 @@ gtk_css_keyframes_add_keyframe (GtkCssKeyframes *keyframes, memset (&KEYFRAMES_VALUE (keyframes, k, 0), 0, size); } + if (keyframes->variables) + keyframes->variables = g_realloc (keyframes->variables, sizeof (GtkCssVariableSet *) * keyframes->n_keyframes); + return k; } @@ -173,6 +186,26 @@ gtk_css_keyframes_lookup_property (GtkCssKeyframes *keyframes, return p; } +static void +gtk_css_keyframes_register_variable (GtkCssKeyframes *keyframes, + int variable_id) +{ + guint p; + + for (p = 0; p < keyframes->n_variables; p++) + { + if (keyframes->variable_ids[p] == variable_id) + return; + else if (keyframes->variable_ids[p] > variable_id) + break; + } + + keyframes->n_variables++; + keyframes->variable_ids = g_realloc (keyframes->variable_ids, sizeof (int) * keyframes->n_variables); + memmove (keyframes->variable_ids + p + 1, keyframes->variable_ids + p, sizeof (int) * (keyframes->n_variables - p - 1)); + keyframes->variable_ids[p] = variable_id; +} + static GtkCssKeyframes * gtk_css_keyframes_alloc (void) { @@ -235,6 +268,44 @@ gtk_css_keyframes_parse_declaration (GtkCssKeyframes *keyframes, return FALSE; } + /* This is a custom property */ + if (name[0] == '-' && name[1] == '-') + { + GtkCssVariableValue *var_value; + GtkCssCustomPropertyPool *pool; + int id; + + if (!gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COLON)) + { + gtk_css_parser_error_syntax (parser, "Expected a ':'"); + g_free (name); + return FALSE; + } + + var_value = gtk_css_parser_parse_value_into_token_stream (parser); + if (var_value == NULL) + { + g_free (name); + return FALSE; + } + + if (!keyframes->variables) + keyframes->variables = g_new0 (GtkCssVariableSet *, keyframes->n_keyframes); + + if (!keyframes->variables[k]) + keyframes->variables[k] = gtk_css_variable_set_new (); + + pool = gtk_css_custom_property_pool_get (); + id = gtk_css_custom_property_pool_add (pool, name); + gtk_css_keyframes_register_variable (keyframes, id); + + gtk_css_variable_set_add (keyframes->variables[k], id, var_value); + + gtk_css_custom_property_pool_unref (pool, id); + + return TRUE; + } + property = _gtk_style_property_lookup (name); if (property == NULL) { @@ -251,9 +322,53 @@ gtk_css_keyframes_parse_declaration (GtkCssKeyframes *keyframes, return FALSE; } - value = _gtk_style_property_parse_value (property, parser); - if (value == NULL) - return FALSE; + if (gtk_css_parser_has_references (parser)) + { + GtkCssVariableValue *var_value; + + var_value = gtk_css_parser_parse_value_into_token_stream (parser); + if (var_value == NULL) + return FALSE; + + if (GTK_IS_CSS_SHORTHAND_PROPERTY (property)) + { + GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property); + guint i, n; + GtkCssValue **values; + + n = _gtk_css_shorthand_property_get_n_subproperties (shorthand); + + values = g_new (GtkCssValue *, n); + + for (i = 0; i < n; i++) + { + GtkCssValue *child = + _gtk_css_reference_value_new (property, + var_value, + gtk_css_parser_get_file (parser)); + _gtk_css_reference_value_set_subproperty (child, i); + + values[i] = _gtk_css_array_value_get_nth (child, i); + } + + value = _gtk_css_array_value_new_from_array (values, n); + g_free (values); + } + else + { + value = _gtk_css_reference_value_new (property, + var_value, + gtk_css_parser_get_file (parser)); + } + + gtk_css_variable_value_unref (var_value); + } + else + { + value = _gtk_style_property_parse_value (property, parser); + if (value == NULL) + return FALSE; + } if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF)) { @@ -314,6 +429,9 @@ gtk_css_keyframes_parse_block (GtkCssKeyframes *keyframes, gtk_css_parser_end_block (parser); } + if (keyframes->variables && keyframes->variables[k]) + gtk_css_variable_set_resolve_cycles (keyframes->variables[k]); + gtk_css_parser_end_block (parser); return TRUE; @@ -462,10 +580,26 @@ _gtk_css_keyframes_compute (GtkCssKeyframes *keyframes, provider, style, parent_style, - NULL); + keyframes->variables ? keyframes->variables[k] : NULL); } } + if (keyframes->variables) + { + resolved->variables = g_new0 (GtkCssVariableSet *, resolved->n_keyframes); + + for (k = 0; k < resolved->n_keyframes; k++) + { + if (keyframes->variables[k]) + resolved->variables[k] = gtk_css_variable_set_ref (keyframes->variables[k]); + } + } + else + resolved->variables = NULL; + + resolved->variable_ids = g_memdup2 (keyframes->variable_ids, keyframes->n_variables * sizeof (int)); + resolved->n_variables = keyframes->n_variables; + return resolved; } @@ -541,3 +675,78 @@ _gtk_css_keyframes_get_value (GtkCssKeyframes *keyframes, return result; } +guint +_gtk_css_keyframes_get_n_variables (GtkCssKeyframes *keyframes) +{ + g_return_val_if_fail (keyframes != NULL, 0); + + return keyframes->n_variables; +} + +int +_gtk_css_keyframes_get_variable_id (GtkCssKeyframes *keyframes, + guint id) +{ + g_return_val_if_fail (keyframes != NULL, 0); + g_return_val_if_fail (id < keyframes->n_variables, 0); + + return keyframes->variable_ids[id]; +} + +GtkCssVariableValue * +_gtk_css_keyframes_get_variable (GtkCssKeyframes *keyframes, + guint id, + double progress, + GtkCssVariableValue *default_value) +{ + GtkCssVariableValue *start_value, *end_value, *result; + double start_progress, end_progress; + int variable_id; + guint k; + + g_return_val_if_fail (keyframes != NULL, 0); + g_return_val_if_fail (id < keyframes->n_variables, 0); + + start_value = default_value; + start_progress = 0.0; + end_value = default_value; + end_progress = 1.0; + + variable_id = keyframes->variable_ids[id]; + + for (k = 0; k < keyframes->n_keyframes; k++) + { + GtkCssVariableValue *value = gtk_css_variable_set_lookup (keyframes->variables[k], variable_id, NULL); + + if (value == NULL) + continue; + + if (keyframes->keyframe_progress[k] == progress) + { + return gtk_css_variable_value_ref (value); + } + else if (keyframes->keyframe_progress[k] < progress) + { + start_value = value; + start_progress = keyframes->keyframe_progress[k]; + } + else + { + end_value = value; + end_progress = keyframes->keyframe_progress[k]; + break; + } + } + + progress = (progress - start_progress) / (end_progress - start_progress); + + result = gtk_css_variable_value_transition (start_value, + end_value, + progress); + + /* XXX: Dear spec, what's the correct thing to do here? */ + if (result == NULL) + return start_value ? gtk_css_variable_value_ref (start_value) : NULL; + + return result; +} diff --git a/gtk/gtkcsskeyframesprivate.h b/gtk/gtkcsskeyframesprivate.h index a87651649b..4a1dc14aa0 100644 --- a/gtk/gtkcsskeyframesprivate.h +++ b/gtk/gtkcsskeyframesprivate.h @@ -50,5 +50,13 @@ GtkCssValue * _gtk_css_keyframes_get_value (GtkCssKeyframes double progress, GtkCssValue *default_value); +guint _gtk_css_keyframes_get_n_variables (GtkCssKeyframes *keyframes); +int _gtk_css_keyframes_get_variable_id (GtkCssKeyframes *keyframes, + guint id); +GtkCssVariableValue *_gtk_css_keyframes_get_variable (GtkCssKeyframes *keyframes, + guint id, + double progress, + GtkCssVariableValue *default_value); + G_END_DECLS diff --git a/gtk/gtkcssstaticstyle.c b/gtk/gtkcssstaticstyle.c index 15a8f7f595..4f4d130e9a 100644 --- a/gtk/gtkcssstaticstyle.c +++ b/gtk/gtkcssstaticstyle.c @@ -322,6 +322,12 @@ gtk_css_static_style_dispose (GObject *object) style->sections = NULL; } + if (style->original_values) + { + g_ptr_array_unref (style->original_values); + style->original_values = NULL; + } + G_OBJECT_CLASS (gtk_css_static_style_parent_class)->dispose (object); } @@ -331,6 +337,19 @@ gtk_css_static_style_get_static_style (GtkCssStyle *style) return (GtkCssStaticStyle *)style; } +static GtkCssValue * +gtk_css_static_style_get_original_value (GtkCssStyle *style, + guint id) +{ + GtkCssStaticStyle *sstyle = GTK_CSS_STATIC_STYLE (style); + + if (sstyle->original_values == NULL || + id >= sstyle->original_values->len) + return NULL; + + return g_ptr_array_index (sstyle->original_values, id); +} + static void gtk_css_static_style_class_init (GtkCssStaticStyleClass *klass) { @@ -341,6 +360,7 @@ gtk_css_static_style_class_init (GtkCssStaticStyleClass *klass) style_class->get_section = gtk_css_static_style_get_section; style_class->get_static_style = gtk_css_static_style_get_static_style; + style_class->get_original_value = gtk_css_static_style_get_original_value; gtk_css_core_values_init (); gtk_css_background_values_init (); @@ -369,6 +389,13 @@ maybe_unref_section (gpointer section) gtk_css_section_unref (section); } +static void +maybe_unref_value (gpointer value) +{ + if (value) + _gtk_css_value_unref (value); +} + static inline void gtk_css_take_value (GtkCssValue **variable, GtkCssValue *value) @@ -382,6 +409,7 @@ static void gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle, guint id, GtkCssValue *value, + GtkCssValue *original_value, GtkCssSection *section) { GtkCssStyle *style = (GtkCssStyle *)sstyle; @@ -684,6 +712,22 @@ gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle, g_ptr_array_set_size (sstyle->sections, id + 1); g_ptr_array_index (sstyle->sections, id) = gtk_css_section_ref (section); } + + if (sstyle->original_values && sstyle->original_values->len > id && + g_ptr_array_index (sstyle->original_values, id)) + { + _gtk_css_value_unref (g_ptr_array_index (sstyle->original_values, id)); + g_ptr_array_index (sstyle->original_values, id) = NULL; + } + + if (original_value) + { + if (sstyle->original_values == NULL) + sstyle->original_values = g_ptr_array_new_with_free_func (maybe_unref_value); + if (sstyle->original_values->len <= id) + g_ptr_array_set_size (sstyle->original_values, id + 1); + g_ptr_array_index (sstyle->original_values, id) = _gtk_css_value_ref (original_value); + } } static GtkCssStyle *default_style; @@ -1076,7 +1120,7 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style, GtkCssValue *specified, GtkCssSection *section) { - GtkCssValue *value; + GtkCssValue *value, *original_value; GtkBorderStyle border_style; gtk_internal_return_if_fail (id < GTK_CSS_PROPERTY_N_PROPERTIES); @@ -1097,7 +1141,7 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style, border_style = _gtk_css_border_style_value_get (gtk_css_style_get_value ((GtkCssStyle *)style, id - 1)); if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN) { - gtk_css_static_style_set_value (style, id, gtk_css_dimension_value_new (0, GTK_CSS_NUMBER), section); + gtk_css_static_style_set_value (style, id, gtk_css_dimension_value_new (0, GTK_CSS_NUMBER), NULL, section); return; } break; @@ -1115,18 +1159,33 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style, if (specified) { value = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, parent_style, NULL); + + if (gtk_css_value_contains_variables (specified)) + original_value = specified; + else + original_value = NULL; } else if (parent_style && _gtk_css_style_property_is_inherit (_gtk_css_style_property_lookup_by_id (id))) { + GtkCssValue *parent_original_value; + /* Just take the style from the parent */ value = _gtk_css_value_ref (gtk_css_style_get_value (parent_style, id)); + + parent_original_value = gtk_css_style_get_original_value (parent_style, id); + + if (parent_original_value) + original_value = parent_original_value; + else + original_value = NULL; } else { value = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, parent_style); + original_value = NULL; } - gtk_css_static_style_set_value (style, id, value, section); + gtk_css_static_style_set_value (style, id, value, original_value, section); } GtkCssChange diff --git a/gtk/gtkcssstaticstyleprivate.h b/gtk/gtkcssstaticstyleprivate.h index 61d4ba964e..1699e4d595 100644 --- a/gtk/gtkcssstaticstyleprivate.h +++ b/gtk/gtkcssstaticstyleprivate.h @@ -40,6 +40,7 @@ struct _GtkCssStaticStyle GtkCssStyle parent; GPtrArray *sections; /* sections the values are defined in */ + GPtrArray *original_values; GtkCssChange change; /* change as returned by value lookup */ }; diff --git a/gtk/gtkcssstyle.c b/gtk/gtkcssstyle.c index 0f9ee23c54..cdc58e85bb 100644 --- a/gtk/gtkcssstyle.c +++ b/gtk/gtkcssstyle.c @@ -315,6 +315,15 @@ gtk_css_style_get_static_style (GtkCssStyle *style) return GTK_CSS_STYLE_GET_CLASS (style)->get_static_style (style); } +GtkCssValue * +gtk_css_style_get_original_value (GtkCssStyle *style, + guint id) +{ + gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL); + + return GTK_CSS_STYLE_GET_CLASS (style)->get_original_value (style, id); +} + /* * gtk_css_style_print: * @style: a `GtkCssStyle` diff --git a/gtk/gtkcssstyleprivate.h b/gtk/gtkcssstyleprivate.h index e3e3364b2d..e72b6694ad 100644 --- a/gtk/gtkcssstyleprivate.h +++ b/gtk/gtkcssstyleprivate.h @@ -252,6 +252,9 @@ struct _GtkCssStyleClass gboolean (* is_static) (GtkCssStyle *style); GtkCssStaticStyle * (* get_static_style) (GtkCssStyle *style); + + GtkCssValue * (* get_original_value) (GtkCssStyle *style, + guint id); }; GType gtk_css_style_get_type (void) G_GNUC_CONST; @@ -263,6 +266,9 @@ GtkCssSection * gtk_css_style_get_section (GtkCssStyle gboolean gtk_css_style_is_static (GtkCssStyle *style) G_GNUC_PURE; GtkCssStaticStyle * gtk_css_style_get_static_style (GtkCssStyle *style); +GtkCssValue * gtk_css_style_get_original_value (GtkCssStyle *style, + guint id) G_GNUC_PURE; + char * gtk_css_style_to_string (GtkCssStyle *style); gboolean gtk_css_style_print (GtkCssStyle *style, GString *string,