csskeyframes: Support variables

This commit is contained in:
Alice Mikhaylenko
2024-03-20 23:11:03 +04:00
parent 4a3894e820
commit 17ccb849b3
9 changed files with 553 additions and 14 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 <string.h>
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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 */
};

View File

@@ -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`

View File

@@ -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,