Compare commits

...

22 Commits

Author SHA1 Message Date
Matthias Clasen
e5d0f32d8c css: Improve error reporting for variables
Emit errors for all the variables that were being expanded
if an error occurs while parsing a property value at compute time.

Include the variables that are being expanded in the error message.
2024-05-09 23:13:53 -04:00
Matthias Clasen
e825fd901f css parser: Keep variables for tokenizers
Add a function that gets the names of the variables that the
parser is currently in the process of expanding. This will
be used for error reporting.
2024-05-09 23:13:53 -04:00
Matthias Clasen
e3543f37d3 css parser: Inline the tokenizer array
This is in preparation of associating more data with the token streams.
2024-05-09 23:13:53 -04:00
Matthias Clasen
e9bf0322ac css provider: Set bytes on sections
Pass the bytes we're parsing to the sections, and keep a pointer
to them around, so we can compare them in the has_section
implementation.

This commit also corrects some of the location information that
we add into the section for variables to be more accurate.
2024-05-09 23:13:53 -04:00
Matthias Clasen
6d5cb0a083 css parser: Add gtk_css_parser_get_bytes
Gets the bytes that the parser is operating on.
2024-05-09 23:13:53 -04:00
Matthias Clasen
8b5aab459a css provider: Set sections on all variable values
We were doing it in one case, but forgetting it in another.
These sections are necessary to report meaningful error locations
when parsing property values at compute time.
2024-05-09 23:13:53 -04:00
Matthias Clasen
8da3cc10fd style cascade: Propagate errors
When we compute values, the provider we use ends up being the
style cascade. If we hit a parser error when parsing variable-bearing
property values at compute time, we emit the error on that provider.

By making the cascade propagate the error back to the proper css
provider that contains the section in question, we get it reported
back to the css editor in the inspector.
2024-05-09 23:13:53 -04:00
Matthias Clasen
f48a4e84af style provider: Add a has_section api
Add gtk_style_provider_has_section and implement it for
GtkCssProvider. This will be used later to direct error
emissions to the right provider.
2024-05-09 23:13:53 -04:00
Matthias Clasen
09c76208a2 css parser: Add bytes to sections
We will use this later to link sections back to the providers
they come from.
2024-05-09 23:13:53 -04:00
Matthias Clasen
62b1d21556 css parser: Add gtk_css_parser_skip_whitespace
Does what it says.
2024-05-09 23:13:53 -04:00
Matthias Clasen
8fba58eaa9 css: Don't accept junk
Check that there is no junk at the end of the property value
when parsing variable-bearing properties at compute time.
2024-05-09 23:13:52 -04:00
Alice Mikhaylenko
b4890edd64 inspector: Sort GTK CSS properties between standard and custom ones 2024-05-08 19:03:45 +04:00
Alice Mikhaylenko
93b9388180 inspector: Show custom properties for css nodes 2024-05-08 19:03:45 +04:00
Alice Mikhaylenko
76b2609ad5 testsuite: Add css variables tests 2024-05-08 19:03:44 +04:00
Alice Mikhaylenko
a37a0711ad csskeyframes: Support variables 2024-05-08 19:03:44 +04:00
Alice Mikhaylenko
23dbb7122c cssanimation: Recompute values while playing
This will be necessary for supporting variables in animations.

For this we need to pass all the gtk_css_value_compute() parameters into
GtkCssAnimatedStyle: parent style and provider.
2024-05-08 19:03:44 +04:00
Alice Mikhaylenko
e04ab263f9 cssstaticstyle: Split property lists into a separate header
We'll need to use them in GtkCssAnimatedStyle too.
2024-05-08 19:03:44 +04:00
Alice Mikhaylenko
5e6e808a55 cssvalue: Pass an extra GtkCssVariableSet to compute()
We'll need this to support variables in @keyframes, since styles will
need to combine their own variables and the ones from the keyframes.

See the next commit, this one is split out to avoid a huge diff.
2024-05-08 19:03:44 +04:00
Alice Mikhaylenko
6eaf6e2f7d Implement basic support for CSS variables 2024-05-08 19:03:43 +04:00
Alice Mikhaylenko
e4a4a0f6dd cssvalue: Add contains_variables()
We'll need this to know which values to recompute for animations.

It will be used in the next commit, it's separate to avoid the diff
being too large.
2024-05-08 19:00:40 +04:00
Alice Mikhaylenko
f301ea7936 csstokenizer: Add save() and restore()
We'll need that to check if property values contain variables.
2024-05-08 19:00:40 +04:00
Alice Mikhaylenko
a3e9ecd199 cssprovider: Copy bytes when loading
We'll need to keep accessing them later to compute values with variables,
so we can't avoid this anymore.
2024-05-08 19:00:40 +04:00
98 changed files with 4148 additions and 631 deletions

View File

@@ -56,6 +56,30 @@ follows:
1 value:
: all
## Custom Properties
GTK supports custom properties as defined in the
[CSS Custom Properties for Cascading Variables](https://www.w3.org/TR/css-variables-1)
spec.
Custom properties are defined as follows:
```css
--prop: red;
```
and used via the `var` keyword:
```css
color: var(--prop);
```
Custom properties can have a fallback for when the referred property is invalid:
```css
color: var(--prop, green);
```
## Colors
GTK extends the CSS syntax with several additional ways to specify colors.

View File

@@ -26,6 +26,16 @@
#include "gtkcsserror.h"
#include "gtkcsslocationprivate.h"
static void clear_ref (GtkCssVariableValueReference *ref);
#define GDK_ARRAY_NAME gtk_css_parser_references
#define GDK_ARRAY_TYPE_NAME GtkCssParserReferences
#define GDK_ARRAY_ELEMENT_TYPE GtkCssVariableValueReference
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_NO_MEMSET 1
#define GDK_ARRAY_FREE_FUNC clear_ref
#include "gdk/gdkarrayimpl.c"
typedef struct _GtkCssParserBlock GtkCssParserBlock;
struct _GtkCssParserBlock
@@ -39,7 +49,7 @@ struct _GtkCssParserBlock
#define GDK_ARRAY_NAME gtk_css_parser_blocks
#define GDK_ARRAY_TYPE_NAME GtkCssParserBlocks
#define GDK_ARRAY_ELEMENT_TYPE GtkCssParserBlock
#define GDK_ARAY_PREALLOC 32
#define GDK_ARRAY_PREALLOC 32
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
@@ -55,11 +65,53 @@ gtk_css_parser_blocks_drop_last (GtkCssParserBlocks *blocks)
gtk_css_parser_blocks_set_size (blocks, gtk_css_parser_blocks_get_size (blocks) - 1);
}
typedef struct _GtkCssTokenizerData GtkCssTokenizerData;
struct _GtkCssTokenizerData
{
GtkCssTokenizer *tokenizer;
char *var_name;
GtkCssVariableValue *variable;
};
static void
gtk_css_tokenizer_data_clear (gpointer data)
{
GtkCssTokenizerData *td = data;
gtk_css_tokenizer_unref (td->tokenizer);
if (td->var_name)
g_free (td->var_name);
if (td->variable)
gtk_css_variable_value_unref (td->variable);
}
#define GDK_ARRAY_NAME gtk_css_tokenizers
#define GDK_ARRAY_TYPE_NAME GtkCssTokenizers
#define GDK_ARRAY_ELEMENT_TYPE GtkCssTokenizerData
#define GDK_ARRAY_FREE_FUNC gtk_css_tokenizer_data_clear
#define GDK_ARRAY_BY_VALUE 1
#define GDK_ARRAY_PREALLOC 16
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
static inline GtkCssTokenizerData *
gtk_css_tokenizers_get_last (GtkCssTokenizers *tokenizers)
{
return gtk_css_tokenizers_index (tokenizers, gtk_css_tokenizers_get_size (tokenizers) - 1);
}
static inline void
gtk_css_tokenizers_drop_last (GtkCssTokenizers *tokenizers)
{
gtk_css_tokenizers_set_size (tokenizers, gtk_css_tokenizers_get_size (tokenizers) - 1);
}
struct _GtkCssParser
{
volatile int ref_count;
GtkCssTokenizer *tokenizer;
GtkCssTokenizers tokenizers;
GFile *file;
GFile *directory;
GtkCssParserErrorFunc error_func;
@@ -69,10 +121,22 @@ struct _GtkCssParser
GtkCssParserBlocks blocks;
GtkCssLocation location;
GtkCssToken token;
GtkCssVariableValue **refs;
gsize n_refs;
gsize next_ref;
gboolean var_fallback;
};
static inline GtkCssTokenizer *
get_tokenizer (GtkCssParser *self)
{
return gtk_css_tokenizers_get_last (&self->tokenizers)->tokenizer;
}
static GtkCssParser *
gtk_css_parser_new (GtkCssTokenizer *tokenizer,
GtkCssVariableValue *value,
GFile *file,
GtkCssParserErrorFunc error_func,
gpointer user_data,
@@ -83,7 +147,14 @@ gtk_css_parser_new (GtkCssTokenizer *tokenizer,
self = g_new0 (GtkCssParser, 1);
self->ref_count = 1;
self->tokenizer = gtk_css_tokenizer_ref (tokenizer);
gtk_css_tokenizers_init (&self->tokenizers);
gtk_css_tokenizers_append (&self->tokenizers,
&(GtkCssTokenizerData) {
gtk_css_tokenizer_ref (tokenizer),
NULL,
value ? gtk_css_variable_value_ref (value) : NULL });
if (file)
self->file = g_object_ref (file);
@@ -125,21 +196,45 @@ gtk_css_parser_new_for_bytes (GBytes *bytes,
{
GtkCssTokenizer *tokenizer;
GtkCssParser *result;
tokenizer = gtk_css_tokenizer_new (bytes);
result = gtk_css_parser_new (tokenizer, file, error_func, user_data, user_destroy);
result = gtk_css_parser_new (tokenizer, NULL, file, error_func, user_data, user_destroy);
gtk_css_tokenizer_unref (tokenizer);
return result;
}
GtkCssParser *
gtk_css_parser_new_for_token_stream (GtkCssVariableValue *value,
GFile *file,
GtkCssVariableValue **refs,
gsize n_refs,
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy)
{
GtkCssTokenizer *tokenizer;
GtkCssParser *result;
tokenizer = gtk_css_tokenizer_new_for_range (value->bytes, value->offset,
value->end_offset - value->offset);
result = gtk_css_parser_new (tokenizer, value, file, error_func, user_data, user_destroy);
gtk_css_tokenizer_unref (tokenizer);
result->refs = refs;
result->n_refs = n_refs;
result->next_ref = 0;
return result;
}
static void
gtk_css_parser_finalize (GtkCssParser *self)
{
if (self->user_destroy)
self->user_destroy (self->user_data);
g_clear_pointer (&self->tokenizer, gtk_css_tokenizer_unref);
gtk_css_tokenizers_clear (&self->tokenizers);
g_clear_object (&self->file);
g_clear_object (&self->directory);
if (gtk_css_parser_blocks_get_size (&self->blocks) > 0)
@@ -179,6 +274,12 @@ gtk_css_parser_get_file (GtkCssParser *self)
return self->file;
}
GBytes *
gtk_css_parser_get_bytes (GtkCssParser *self)
{
return gtk_css_tokenizer_get_bytes (gtk_css_tokenizers_get (&self->tokenizers, 0)->tokenizer);
}
/**
* gtk_css_parser_resolve_url:
* @self: a `GtkCssParser`
@@ -260,7 +361,7 @@ gtk_css_parser_get_start_location (GtkCssParser *self)
const GtkCssLocation *
gtk_css_parser_get_end_location (GtkCssParser *self)
{
return gtk_css_tokenizer_get_location (self->tokenizer);
return gtk_css_tokenizer_get_location (get_tokenizer (self));
}
/**
@@ -294,12 +395,14 @@ static void
gtk_css_parser_ensure_token (GtkCssParser *self)
{
GError *error = NULL;
GtkCssTokenizer *tokenizer;
if (!gtk_css_token_is (&self->token, GTK_CSS_TOKEN_EOF))
return;
self->location = *gtk_css_tokenizer_get_location (self->tokenizer);
if (!gtk_css_tokenizer_read_token (self->tokenizer, &self->token, &error))
tokenizer = get_tokenizer (self);
self->location = *gtk_css_tokenizer_get_location (tokenizer);
if (!gtk_css_tokenizer_read_token (tokenizer, &self->token, &error))
{
/* We ignore the error here, because the resulting token will
* likely already trigger an error in the parsing code and
@@ -307,6 +410,49 @@ gtk_css_parser_ensure_token (GtkCssParser *self)
*/
g_clear_error (&error);
}
if (gtk_css_tokenizers_get_size (&self->tokenizers) > 1 && gtk_css_token_is (&self->token, GTK_CSS_TOKEN_EOF))
{
gtk_css_tokenizers_drop_last (&self->tokenizers);
gtk_css_parser_ensure_token (self);
return;
}
/* Resolve var(--name): skip it and insert the resolved reference instead */
if (self->n_refs > 0 && gtk_css_token_is_function (&self->token, "var") && self->var_fallback == 0)
{
GtkCssVariableValue *ref;
GtkCssTokenizer *ref_tokenizer;
gtk_css_parser_start_block (self);
g_assert (gtk_css_parser_has_token (self, GTK_CSS_TOKEN_IDENT));
char *var_name = gtk_css_parser_consume_ident (self);
g_assert (var_name[0] == '-' && var_name[1] == '-');
/* If we encounter var() in a fallback when we can already resolve the
* actual variable, skip it */
self->var_fallback++;
gtk_css_parser_skip (self);
gtk_css_parser_end_block (self);
self->var_fallback--;
g_assert (self->next_ref < self->n_refs);
ref = self->refs[self->next_ref++];
ref_tokenizer = gtk_css_tokenizer_new_for_range (ref->bytes, ref->offset,
ref->end_offset - ref->offset);
gtk_css_tokenizers_append (&self->tokenizers,
&(GtkCssTokenizerData) {
ref_tokenizer,
g_strdup (var_name),
gtk_css_variable_value_ref (ref)
});
gtk_css_parser_ensure_token (self);
g_free (var_name);
}
}
const GtkCssToken *
@@ -523,6 +669,19 @@ gtk_css_parser_skip_until (GtkCssParser *self,
}
}
void
gtk_css_parser_skip_whitespace (GtkCssParser *self)
{
const GtkCssToken *token;
for (token = gtk_css_parser_peek_token (self);
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
token = gtk_css_parser_peek_token (self))
{
gtk_css_parser_consume_token (self);
}
}
void
gtk_css_parser_emit_error (GtkCssParser *self,
const GtkCssLocation *start,
@@ -1133,3 +1292,319 @@ gtk_css_parser_consume_any (GtkCssParser *parser,
return result;
}
gboolean
gtk_css_parser_has_references (GtkCssParser *self)
{
GtkCssTokenizer *tokenizer = get_tokenizer (self);
gboolean ret = FALSE;
int inner_blocks = 0, i;
gtk_css_tokenizer_save (tokenizer);
do {
const GtkCssToken *token;
token = gtk_css_parser_get_token (self);
if (inner_blocks == 0)
{
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
break;
if (gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_SQUARE))
{
goto error;
}
}
if (gtk_css_token_is_preserved (token, NULL))
{
if (inner_blocks > 0 && gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_end_block (self);
inner_blocks--;
}
else
{
gtk_css_parser_consume_token (self);
}
}
else
{
gboolean is_var = gtk_css_token_is_function (token, "var");
inner_blocks++;
gtk_css_parser_start_block (self);
if (!ret && is_var)
{
token = gtk_css_parser_get_token (self);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
const char *var_name = gtk_css_token_get_string (token);
if (var_name[0] != '-' || var_name[1] != '-')
goto error;
gtk_css_parser_consume_token (self);
if (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_EOF) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_COMMA))
{
goto error;
}
ret = TRUE;
}
}
}
}
while (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SEMICOLON) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_CLOSE_CURLY));
if (inner_blocks > 0)
goto error;
g_assert (tokenizer == get_tokenizer (self));
gtk_css_tokenizer_restore (tokenizer);
self->location = *gtk_css_tokenizer_get_location (tokenizer);
gtk_css_tokenizer_read_token (tokenizer, &self->token, NULL);
return ret;
error:
for (i = 0; i < inner_blocks; i++)
gtk_css_parser_end_block (self);
g_assert (tokenizer == get_tokenizer (self));
gtk_css_tokenizer_restore (tokenizer);
self->location = *gtk_css_tokenizer_get_location (tokenizer);
gtk_css_tokenizer_read_token (tokenizer, &self->token, NULL);
return FALSE;
}
static void
clear_ref (GtkCssVariableValueReference *ref)
{
g_free (ref->name);
if (ref->fallback)
gtk_css_variable_value_unref (ref->fallback);
}
#define GDK_ARRAY_NAME gtk_css_parser_references
#define GDK_ARRAY_TYPE_NAME GtkCssParserReferences
#define GDK_ARRAY_ELEMENT_TYPE GtkCssVariableValueReference
GtkCssVariableValue *
gtk_css_parser_parse_value_into_token_stream (GtkCssParser *self)
{
GBytes *bytes = gtk_css_tokenizer_get_bytes (get_tokenizer (self));
const GtkCssToken *token;
gsize offset;
gsize length = 0;
GtkCssParserReferences refs;
int inner_blocks = 0, i;
gboolean is_initial = FALSE;
for (token = gtk_css_parser_peek_token (self);
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
token = gtk_css_parser_peek_token (self))
{
gtk_css_parser_consume_token (self);
}
gtk_css_parser_references_init (&refs);
offset = self->location.bytes;
do {
token = gtk_css_parser_get_token (self);
if (length == 0 && gtk_css_token_is_ident (token, "initial"))
is_initial = TRUE;
if (gtk_css_token_is (token, GTK_CSS_TOKEN_BAD_STRING) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_BAD_URL))
{
gtk_css_parser_error_syntax (self, "Invalid property value");
goto error;
}
if (inner_blocks == 0)
{
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
break;
if (gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_SQUARE))
{
gtk_css_parser_error_syntax (self, "Invalid property value");
goto error;
}
}
if (gtk_css_token_is_preserved (token, NULL))
{
if (inner_blocks > 0 && gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
length++;
gtk_css_parser_end_block (self);
inner_blocks--;
}
else
{
length++;
gtk_css_parser_consume_token (self);
}
}
else
{
gboolean is_var = gtk_css_token_is_function (token, "var");
length++;
inner_blocks++;
gtk_css_parser_start_block (self);
if (is_var)
{
token = gtk_css_parser_get_token (self);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
GtkCssVariableValueReference ref;
char *var_name = g_strdup (gtk_css_token_get_string (token));
if (var_name[0] != '-' || var_name[1] != '-')
{
gtk_css_parser_error_value (self, "Invalid variable name: %s", var_name);
g_free (var_name);
goto error;
}
length++;
gtk_css_parser_consume_token (self);
if (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_EOF) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_COMMA))
{
gtk_css_parser_error_syntax (self, "Invalid property value");
g_free (var_name);
goto error;
}
ref.name = var_name;
if (gtk_css_parser_has_token (self, GTK_CSS_TOKEN_EOF))
{
ref.length = 3;
ref.fallback = NULL;
}
else
{
length++;
gtk_css_parser_consume_token (self);
ref.fallback = gtk_css_parser_parse_value_into_token_stream (self);
if (ref.fallback == NULL)
{
gtk_css_parser_error_value (self, "Invalid fallback for: %s", var_name);
g_free (var_name);
goto error;
}
ref.length = 4 + ref.fallback->length;
length += ref.fallback->length;
}
gtk_css_parser_references_append (&refs, &ref);
}
}
}
}
while (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SEMICOLON) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_CLOSE_CURLY));
if (inner_blocks > 0)
{
gtk_css_parser_error_syntax (self, "Invalid property value");
goto error;
}
if (is_initial && length == 1)
{
gtk_css_parser_references_clear (&refs);
return gtk_css_variable_value_new_initial (bytes,
offset,
self->location.bytes);
}
else
{
GtkCssVariableValueReference *out_refs;
gsize n_refs;
n_refs = gtk_css_parser_references_get_size (&refs);
out_refs = gtk_css_parser_references_steal (&refs);
return gtk_css_variable_value_new (bytes,
offset,
self->location.bytes,
length,
out_refs,
n_refs);
}
error:
for (i = 0; i < inner_blocks; i++)
gtk_css_parser_end_block (self);
gtk_css_parser_references_clear (&refs);
return NULL;
}
void
gtk_css_parser_get_expanding_variables (GtkCssParser *self,
GtkCssVariableValue ***variables,
char ***variable_names,
gsize *n_variables)
{
gsize len = gtk_css_tokenizers_get_size (&self->tokenizers);
GtkCssVariableValue **vars = NULL;
char **names = NULL;
gsize n;
if (variables)
vars = g_new0 (GtkCssVariableValue *, len + 1);
if (variable_names)
names = g_new0 (char *, len + 1);
n = 0;
for (gsize i = 0; i < gtk_css_tokenizers_get_size (&self->tokenizers); i++)
{
GtkCssTokenizerData *data = gtk_css_tokenizers_index (&self->tokenizers, i);
if (variables && data->variable)
vars[n] = gtk_css_variable_value_ref (data->variable);
if (variable_names)
names[n] = g_strdup (data->var_name);
n++;
}
if (variables)
*variables = vars;
if (variable_names)
*variable_names = names;
if (n_variables)
*n_variables = n;
}

View File

@@ -22,6 +22,7 @@
#include "gtkcssenums.h"
#include "gtkcsstokenizerprivate.h"
#include "gtkcssvariablevalueprivate.h"
#include <gio/gio.h>
@@ -58,10 +59,18 @@ GtkCssParser * gtk_css_parser_new_for_bytes (GBytes
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy);
GtkCssParser * gtk_css_parser_new_for_token_stream (GtkCssVariableValue *value,
GFile *file,
GtkCssVariableValue **refs,
gsize n_refs,
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy);
GtkCssParser * gtk_css_parser_ref (GtkCssParser *self);
void gtk_css_parser_unref (GtkCssParser *self);
GFile * gtk_css_parser_get_file (GtkCssParser *self) G_GNUC_PURE;
GBytes * gtk_css_parser_get_bytes (GtkCssParser *self) G_GNUC_PURE;
GFile * gtk_css_parser_resolve_url (GtkCssParser *self,
const char *url);
@@ -81,6 +90,7 @@ void gtk_css_parser_end_block (GtkCssParser
void gtk_css_parser_skip (GtkCssParser *self);
void gtk_css_parser_skip_until (GtkCssParser *self,
GtkCssTokenType token_type);
void gtk_css_parser_skip_whitespace (GtkCssParser *self);
void gtk_css_parser_emit_error (GtkCssParser *self,
const GtkCssLocation *start,
@@ -150,5 +160,14 @@ gsize gtk_css_parser_consume_any (GtkCssParser
gsize n_options,
gpointer user_data);
gboolean gtk_css_parser_has_references (GtkCssParser *parser);
GtkCssVariableValue * gtk_css_parser_parse_value_into_token_stream (GtkCssParser *parser);
void gtk_css_parser_get_expanding_variables (GtkCssParser *parser,
GtkCssVariableValue ***variables,
char ***names,
gsize *n_variables);
G_END_DECLS

View File

@@ -26,6 +26,7 @@ struct _GtkCssSection
int ref_count;
GtkCssSection *parent;
GFile *file;
GBytes *bytes;
GtkCssLocation start_location;
GtkCssLocation end_location; /* end location if parser is %NULL */
};
@@ -48,6 +49,15 @@ GtkCssSection *
gtk_css_section_new (GFile *file,
const GtkCssLocation *start,
const GtkCssLocation *end)
{
return gtk_css_section_new_with_bytes (file, NULL,start, end);
}
GtkCssSection *
gtk_css_section_new_with_bytes (GFile *file,
GBytes *bytes,
const GtkCssLocation *start,
const GtkCssLocation *end)
{
GtkCssSection *result;
@@ -60,6 +70,8 @@ gtk_css_section_new (GFile *file,
result->ref_count = 1;
if (file)
result->file = g_object_ref (file);
if (bytes)
result->bytes = g_bytes_ref (bytes);
result->start_location = *start;
result->end_location = *end;
@@ -104,6 +116,8 @@ gtk_css_section_unref (GtkCssSection *section)
gtk_css_section_unref (section->parent);
if (section->file)
g_object_unref (section->file);
if (section->bytes)
g_bytes_unref (section->bytes);
g_free (section);
}
@@ -151,6 +165,14 @@ gtk_css_section_get_file (const GtkCssSection *section)
return section->file;
}
GBytes *
gtk_css_section_get_bytes (const GtkCssSection *section)
{
g_return_val_if_fail (section != NULL, NULL);
return section->bytes;
}
/**
* gtk_css_section_get_start_location:
* @section: the section

View File

@@ -46,6 +46,11 @@ GDK_AVAILABLE_IN_ALL
GtkCssSection * gtk_css_section_new (GFile *file,
const GtkCssLocation *start,
const GtkCssLocation *end);
GDK_AVAILABLE_IN_4_16
GtkCssSection * gtk_css_section_new_with_bytes (GFile *file,
GBytes *bytes,
const GtkCssLocation *start,
const GtkCssLocation *end);
GDK_AVAILABLE_IN_ALL
GtkCssSection * gtk_css_section_ref (GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
@@ -61,6 +66,8 @@ GDK_AVAILABLE_IN_ALL
GtkCssSection * gtk_css_section_get_parent (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
GFile * gtk_css_section_get_file (const GtkCssSection *section);
GDK_AVAILABLE_IN_4_16
GBytes * gtk_css_section_get_bytes (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
const GtkCssLocation *
gtk_css_section_get_start_location (const GtkCssSection *section);

View File

@@ -36,6 +36,9 @@ struct _GtkCssTokenizer
const char *end;
GtkCssLocation position;
GtkCssLocation saved_position;
const char *saved_data;
};
void
@@ -568,6 +571,14 @@ gtk_css_token_init_dimension (GtkCssToken *token,
GtkCssTokenizer *
gtk_css_tokenizer_new (GBytes *bytes)
{
return gtk_css_tokenizer_new_for_range (bytes, 0, g_bytes_get_size (bytes));
}
GtkCssTokenizer *
gtk_css_tokenizer_new_for_range (GBytes *bytes,
gsize offset,
gsize length)
{
GtkCssTokenizer *tokenizer;
@@ -576,8 +587,8 @@ gtk_css_tokenizer_new (GBytes *bytes)
tokenizer->bytes = g_bytes_ref (bytes);
tokenizer->name_buffer = g_string_new (NULL);
tokenizer->data = g_bytes_get_data (bytes, NULL);
tokenizer->end = tokenizer->data + g_bytes_get_size (bytes);
tokenizer->data = g_bytes_get_region (bytes, 1, offset, length);
tokenizer->end = tokenizer->data + length;
gtk_css_location_init (&tokenizer->position);
@@ -604,6 +615,12 @@ gtk_css_tokenizer_unref (GtkCssTokenizer *tokenizer)
g_free (tokenizer);
}
GBytes *
gtk_css_tokenizer_get_bytes (GtkCssTokenizer *tokenizer)
{
return tokenizer->bytes;
}
const GtkCssLocation *
gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer)
{
@@ -1484,3 +1501,23 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
}
}
void
gtk_css_tokenizer_save (GtkCssTokenizer *tokenizer)
{
g_assert (!tokenizer->saved_data);
tokenizer->saved_position = tokenizer->position;
tokenizer->saved_data = tokenizer->data;
}
void
gtk_css_tokenizer_restore (GtkCssTokenizer *tokenizer)
{
g_assert (tokenizer->saved_data);
tokenizer->position = tokenizer->saved_position;
tokenizer->data = tokenizer->saved_data;
gtk_css_location_init (&tokenizer->saved_position);
tokenizer->saved_data = NULL;
}

View File

@@ -138,15 +138,22 @@ void gtk_css_token_print (const GtkCssTok
char * gtk_css_token_to_string (const GtkCssToken *token);
GtkCssTokenizer * gtk_css_tokenizer_new (GBytes *bytes);
GtkCssTokenizer * gtk_css_tokenizer_new_for_range (GBytes *bytes,
gsize offset,
gsize length);
GtkCssTokenizer * gtk_css_tokenizer_ref (GtkCssTokenizer *tokenizer);
void gtk_css_tokenizer_unref (GtkCssTokenizer *tokenizer);
GBytes * gtk_css_tokenizer_get_bytes (GtkCssTokenizer *tokenizer);
const GtkCssLocation * gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer) G_GNUC_CONST;
gboolean gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
GtkCssToken *token,
GError **error);
void gtk_css_tokenizer_save (GtkCssTokenizer *tokenizer);
void gtk_css_tokenizer_restore (GtkCssTokenizer *tokenizer);
G_END_DECLS

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#include "gtkcssvariablevalueprivate.h"
GtkCssVariableValue *
gtk_css_variable_value_new (GBytes *bytes,
gsize offset,
gsize end_offset,
gsize length,
GtkCssVariableValueReference *references,
gsize n_references)
{
GtkCssVariableValue *self = g_new0 (GtkCssVariableValue, 1);
self->ref_count = 1;
self->bytes = g_bytes_ref (bytes);
self->offset = offset;
self->end_offset = end_offset;
self->length = length;
self->references = references;
self->n_references = n_references;
return self;
}
GtkCssVariableValue *
gtk_css_variable_value_new_initial (GBytes *bytes,
gsize offset,
gsize end_offset)
{
GtkCssVariableValue *self = gtk_css_variable_value_new (bytes, offset, end_offset, 1, NULL, 0);
self->is_invalid = TRUE;
return self;
}
GtkCssVariableValue *
gtk_css_variable_value_ref (GtkCssVariableValue *self)
{
self->ref_count++;
return self;
}
void
gtk_css_variable_value_unref (GtkCssVariableValue *self)
{
gsize i;
self->ref_count--;
if (self->ref_count > 0)
return;
g_bytes_unref (self->bytes);
for (i = 0; i < self->n_references; i++)
{
GtkCssVariableValueReference *ref = &self->references[i];
g_free (ref->name);
if (ref->fallback)
gtk_css_variable_value_unref (ref->fallback);
}
if (self->section)
gtk_css_section_unref (self->section);
g_free (self->references);
g_free (self);
}
void
gtk_css_variable_value_print (GtkCssVariableValue *self,
GString *string)
{
gsize len = self->end_offset - self->offset;
gconstpointer data = g_bytes_get_region (self->bytes, 1, self->offset, len);
g_assert (data != NULL);
g_string_append_len (string, (const char *) data, len);
}
char *
gtk_css_variable_value_to_string (GtkCssVariableValue *self)
{
GString *string = g_string_new (NULL);
gtk_css_variable_value_print (self, string);
return g_string_free (string, FALSE);
}
gboolean
gtk_css_variable_value_equal (const GtkCssVariableValue *value1,
const GtkCssVariableValue *value2)
{
if (value1 == value2)
return TRUE;
if (value1 == NULL || value2 == NULL)
return FALSE;
if (value1->bytes != value2->bytes)
return FALSE;
if (value1->offset != value2->offset)
return FALSE;
if (value1->end_offset != value2->end_offset)
return FALSE;
return TRUE;
}
GtkCssVariableValue *
gtk_css_variable_value_transition (GtkCssVariableValue *start,
GtkCssVariableValue *end,
double progress)
{
GtkCssVariableValue *ret = progress < 0.5 ? start : end;
if (ret == NULL)
return NULL;
return gtk_css_variable_value_ref (ret);
}
void
gtk_css_variable_value_set_section (GtkCssVariableValue *self,
GtkCssSection *section)
{
self->section = gtk_css_section_ref (section);
}
void
gtk_css_variable_value_taint (GtkCssVariableValue *self)
{
self->is_animation_tainted = TRUE;
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#pragma once
#include "gtkcss.h"
#include "gtkcsstokenizerprivate.h"
G_BEGIN_DECLS
typedef struct _GtkCssVariableValueReference GtkCssVariableValueReference;
typedef struct _GtkCssVariableValue GtkCssVariableValue;
struct _GtkCssVariableValueReference
{
char *name;
gsize length;
GtkCssVariableValue *fallback;
};
struct _GtkCssVariableValue
{
int ref_count;
GBytes *bytes;
gsize offset;
gsize end_offset;
gsize length;
GtkCssVariableValueReference *references;
gsize n_references;
GtkCssSection *section;
gboolean is_invalid;
gboolean is_animation_tainted;
};
GtkCssVariableValue *gtk_css_variable_value_new (GBytes *bytes,
gsize offset,
gsize end_offset,
gsize length,
GtkCssVariableValueReference *references,
gsize n_references);
GtkCssVariableValue *gtk_css_variable_value_new_initial (GBytes *bytes,
gsize offset,
gsize end_offset);
GtkCssVariableValue *gtk_css_variable_value_ref (GtkCssVariableValue *self);
void gtk_css_variable_value_unref (GtkCssVariableValue *self);
void gtk_css_variable_value_print (GtkCssVariableValue *self,
GString *string);
char * gtk_css_variable_value_to_string (GtkCssVariableValue *self);
gboolean gtk_css_variable_value_equal (const GtkCssVariableValue *value1,
const GtkCssVariableValue *value2) G_GNUC_PURE;
GtkCssVariableValue *gtk_css_variable_value_transition (GtkCssVariableValue *start,
GtkCssVariableValue *end,
double progress);
void gtk_css_variable_value_set_section (GtkCssVariableValue *self,
GtkCssSection *section);
void gtk_css_variable_value_taint (GtkCssVariableValue *self);
G_END_DECLS

View File

@@ -6,8 +6,9 @@ gtk_css_public_sources = files([
gtk_css_private_sources = files([
'gtkcssdataurl.c',
'gtkcssparser.c',
'gtkcsstokenizer.c',
'gtkcssserializer.c',
'gtkcsstokenizer.c',
'gtkcssvariablevalue.c',
])
gtk_css_public_headers = files([

View File

@@ -33,13 +33,59 @@
#include "gtkcssstringvalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkcsstransitionprivate.h"
#include "gtkcssvaluesprivate.h"
#include "gtkprivate.h"
#include "gtkstyleanimationprivate.h"
#include "gtkstylepropertyprivate.h"
#include "gtkstyleproviderprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
G_DEFINE_TYPE (GtkCssAnimatedStyle, gtk_css_animated_style, GTK_TYPE_CSS_STYLE)
#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 +120,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)
{
@@ -96,6 +151,9 @@ gtk_css_animated_style_finalize (GObject *object)
GtkCssAnimatedStyle *style = GTK_CSS_ANIMATED_STYLE (object);
g_object_unref (style->style);
if (style->parent_style)
g_object_unref (style->parent_style);
g_object_unref (style->provider);
G_OBJECT_CLASS (gtk_css_animated_style_parent_class)->finalize (object);
}
@@ -112,6 +170,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
@@ -546,6 +605,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,
@@ -770,7 +874,6 @@ gtk_css_animated_style_find_animation (GtkStyleAnimation **animations,
static GPtrArray *
gtk_css_animated_style_create_css_animations (GPtrArray *animations,
GtkCssStyle *base_style,
GtkCssStyle *parent_style,
gint64 timestamp,
GtkStyleProvider *provider,
GtkCssStyle *source)
@@ -832,8 +935,6 @@ gtk_css_animated_style_create_css_animations (GPtrArray *animations,
if (keyframes == NULL)
continue;
keyframes = _gtk_css_keyframes_compute (keyframes, provider, base_style, parent_style);
animation = _gtk_css_animation_new (name,
keyframes,
timestamp,
@@ -844,7 +945,6 @@ gtk_css_animated_style_create_css_animations (GPtrArray *animations,
_gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
_gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
_gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
_gtk_css_keyframes_unref (keyframes);
}
if (!animations)
@@ -893,7 +993,7 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
if (previous_style != NULL)
animations = gtk_css_animated_style_create_css_transitions (animations, base_style, timestamp, previous_style);
animations = gtk_css_animated_style_create_css_animations (animations, base_style, parent_style, timestamp, provider, previous_style);
animations = gtk_css_animated_style_create_css_animations (animations, base_style, timestamp, provider, previous_style);
animations = gtk_css_animated_style_create_dynamic (animations, base_style, timestamp);
if (animations == NULL)
@@ -902,6 +1002,9 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
result = g_object_new (GTK_TYPE_CSS_ANIMATED_STYLE, NULL);
result->style = g_object_ref (base_style);
if (parent_style)
result->parent_style = g_object_ref (parent_style);
result->provider = g_object_ref (provider);
result->current_time = timestamp;
result->n_animations = animations->len;
result->animations = g_ptr_array_free (animations, FALSE);
@@ -918,6 +1021,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);
@@ -927,7 +1032,9 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
GtkCssStyle *
gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
GtkCssStyle *base_style,
gint64 timestamp)
GtkCssStyle *parent_style,
gint64 timestamp,
GtkStyleProvider *provider)
{
GtkCssAnimatedStyle *result;
GtkCssStyle *style;
@@ -936,6 +1043,8 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (source), NULL);
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (base_style), NULL);
gtk_internal_return_val_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style), NULL);
gtk_internal_return_val_if_fail (GTK_IS_STYLE_PROVIDER (provider), NULL);
if (timestamp == 0)
return g_object_ref (source->style);
@@ -966,6 +1075,9 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
result = g_object_new (GTK_TYPE_CSS_ANIMATED_STYLE, NULL);
result->style = g_object_ref (base_style);
if (parent_style)
result->parent_style = g_object_ref (parent_style);
result->provider = g_object_ref (provider);
result->current_time = timestamp;
result->n_animations = animations->len;
result->animations = g_ptr_array_free (animations, FALSE);
@@ -982,8 +1094,34 @@ 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);
return GTK_CSS_STYLE (result);
}
GtkCssStyle *
gtk_css_animated_style_get_base_style (GtkCssAnimatedStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
return style->style;
}
GtkCssStyle *
gtk_css_animated_style_get_parent_style (GtkCssAnimatedStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
return style->parent_style;
}
GtkStyleProvider *
gtk_css_animated_style_get_provider (GtkCssAnimatedStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
return style->provider;
}

View File

@@ -38,6 +38,8 @@ struct _GtkCssAnimatedStyle
GtkCssStyle parent;
GtkCssStyle *style; /* the style if we weren't animating */
GtkCssStyle *parent_style;
GtkStyleProvider *provider;
gint64 current_time; /* the current time in our world */
gpointer *animations; /* GtkStyleAnimation**, least important one first */
@@ -57,15 +59,26 @@ GtkCssStyle * gtk_css_animated_style_new (GtkCssStyle
GtkStyleProvider *provider,
GtkCssStyle *previous_style);
GtkCssStyle * gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
GtkCssStyle *base,
gint64 timestamp);
GtkCssStyle *base_style,
GtkCssStyle *parent_style,
gint64 timestamp,
GtkStyleProvider *provider);
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);
G_END_DECLS

View File

@@ -90,6 +90,9 @@ gtk_css_animation_apply_values (GtkStyleAnimation *style_animation,
GtkCssAnimatedStyle *style)
{
GtkCssAnimation *animation = (GtkCssAnimation *)style_animation;
GtkCssStyle *base_style, *parent_style;
GtkStyleProvider *provider;
GtkCssKeyframes *resolved_keyframes;
double progress;
guint i;
@@ -99,19 +102,49 @@ gtk_css_animation_apply_values (GtkStyleAnimation *style_animation,
progress = gtk_css_animation_get_progress (animation);
progress = _gtk_css_ease_value_transform (animation->ease, progress);
for (i = 0; i < _gtk_css_keyframes_get_n_properties (animation->keyframes); i++)
base_style = gtk_css_animated_style_get_base_style (style);
parent_style = gtk_css_animated_style_get_parent_style (style);
provider = gtk_css_animated_style_get_provider (style);
resolved_keyframes = _gtk_css_keyframes_compute (animation->keyframes,
provider,
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));
if (!value)
continue;
gtk_css_animated_style_set_animated_custom_value (style, variable_id, value);
gtk_css_variable_value_unref (value);
}
for (i = 0; i < _gtk_css_keyframes_get_n_properties (resolved_keyframes); i++)
{
GtkCssValue *value;
guint property_id;
property_id = _gtk_css_keyframes_get_property_id (animation->keyframes, i);
property_id = _gtk_css_keyframes_get_property_id (resolved_keyframes, i);
value = _gtk_css_keyframes_get_value (animation->keyframes,
value = _gtk_css_keyframes_get_value (resolved_keyframes,
i,
progress,
gtk_css_animated_style_get_intrinsic_value (style, property_id));
gtk_css_animated_style_set_animated_value (style, property_id, value);
}
_gtk_css_keyframes_unref (resolved_keyframes);
}
static gboolean

View File

@@ -41,11 +41,12 @@ gtk_css_value_array_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_array_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_array_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *result;
GtkCssValue *i_value;
@@ -54,7 +55,7 @@ gtk_css_value_array_compute (GtkCssValue *value,
result = NULL;
for (i = 0; i < value->n_values; i++)
{
i_value = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style);
i_value = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style, variables);
if (result == NULL &&
i_value != value->values[i])
@@ -402,10 +403,13 @@ _gtk_css_array_value_new_from_array (GtkCssValue **values,
for (i = 0; i < n_values; i ++)
{
if (!gtk_css_value_is_computed (values[i]))
{
result->is_computed = FALSE;
break;
}
result->is_computed = FALSE;
if (gtk_css_value_contains_variables (values[i]))
result->contains_variables = TRUE;
if (!result->is_computed && result->contains_variables)
break;
}
return result;
@@ -467,3 +471,4 @@ _gtk_css_array_value_get_n_values (const GtkCssValue *value)
return value->n_values;
}

View File

@@ -41,11 +41,12 @@ gtk_css_value_bg_size_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_bg_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_bg_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *x, *y;
@@ -55,10 +56,10 @@ gtk_css_value_bg_size_compute (GtkCssValue *value,
x = y = NULL;
if (value->x)
x = _gtk_css_value_compute (value->x, property_id, provider, style, parent_style);
x = _gtk_css_value_compute (value->x, property_id, provider, style, parent_style, variables);
if (value->y)
y = _gtk_css_value_compute (value->y, property_id, provider, style, parent_style);
y = _gtk_css_value_compute (value->y, property_id, provider, style, parent_style, variables);
if (x == value->x && y == value->y)
{
@@ -163,9 +164,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_BG_SIZE = {
gtk_css_value_bg_size_print
};
static GtkCssValue auto_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, FALSE, NULL, NULL };
static GtkCssValue cover_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, TRUE, FALSE, NULL, NULL };
static GtkCssValue contain_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, TRUE, NULL, NULL };
static GtkCssValue auto_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, FALSE, FALSE, NULL, NULL };
static GtkCssValue cover_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, TRUE, FALSE, NULL, NULL };
static GtkCssValue contain_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, FALSE, TRUE, NULL, NULL };
GtkCssValue *
_gtk_css_bg_size_value_new (GtkCssValue *x,

View File

@@ -42,11 +42,12 @@ gtk_css_value_border_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_border_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_border_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *values[4];
GtkCssValue *computed;
@@ -57,7 +58,7 @@ gtk_css_value_border_compute (GtkCssValue *value,
{
if (value->values[i])
{
values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style);
values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style, variables);
changed |= (values[i] != value->values[i]);
}
else
@@ -260,3 +261,4 @@ _gtk_css_border_value_get_left (const GtkCssValue *value)
return value->values[GTK_CSS_LEFT];
}

View File

@@ -94,10 +94,11 @@ gtk_css_value_color_free (GtkCssValue *color)
}
static GtkCssValue *
gtk_css_value_color_get_fallback (guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_color_get_fallback (guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
switch (property_id)
{
@@ -120,7 +121,8 @@ gtk_css_value_color_get_fallback (guint property_id,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
case GTK_CSS_PROPERTY_ICON_PALETTE:
return _gtk_css_value_ref (style->core->color);
default:
@@ -132,11 +134,12 @@ gtk_css_value_color_get_fallback (guint property_id,
}
static GtkCssValue *
gtk_css_value_color_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_color_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *resolved;
@@ -173,7 +176,7 @@ gtk_css_value_color_compute (GtkCssValue *value,
}
if (resolved == NULL)
return gtk_css_value_color_get_fallback (property_id, provider, style, parent_style);
return gtk_css_value_color_get_fallback (property_id, provider, style, parent_style, variables);
return resolved;
}
@@ -484,9 +487,9 @@ _gtk_css_color_value_resolve (GtkCssValue *color,
return value;
}
static GtkCssValue transparent_black_singleton = { &GTK_CSS_VALUE_COLOR, 1, TRUE, COLOR_TYPE_LITERAL, NULL,
static GtkCssValue transparent_black_singleton = { &GTK_CSS_VALUE_COLOR, 1, TRUE, FALSE, COLOR_TYPE_LITERAL, NULL,
.sym_col.rgba = {0, 0, 0, 0} };
static GtkCssValue white_singleton = { &GTK_CSS_VALUE_COLOR, 1, TRUE, COLOR_TYPE_LITERAL, NULL,
static GtkCssValue white_singleton = { &GTK_CSS_VALUE_COLOR, 1, TRUE, FALSE, COLOR_TYPE_LITERAL, NULL,
.sym_col.rgba = {1, 1, 1, 1} };
@@ -620,7 +623,7 @@ _gtk_css_color_value_new_mix (GtkCssValue *color1,
GtkCssValue *
_gtk_css_color_value_new_current_color (void)
{
static GtkCssValue current_color = { &GTK_CSS_VALUE_COLOR, 1, FALSE, COLOR_TYPE_CURRENT_COLOR, NULL, };
static GtkCssValue current_color = { &GTK_CSS_VALUE_COLOR, 1, FALSE, FALSE, COLOR_TYPE_CURRENT_COLOR, NULL, };
return _gtk_css_value_ref (&current_color);
}

View File

@@ -37,16 +37,17 @@ gtk_css_value_corner_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_corner_compute (GtkCssValue *corner,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_corner_compute (GtkCssValue *corner,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *x, *y;
x = _gtk_css_value_compute (corner->x, property_id, provider, style, parent_style);
y = _gtk_css_value_compute (corner->y, property_id, provider, style, parent_style);
x = _gtk_css_value_compute (corner->x, property_id, provider, style, parent_style, variables);
y = _gtk_css_value_compute (corner->y, property_id, provider, style, parent_style, variables);
if (x == corner->x && y == corner->y)
{
_gtk_css_value_unref (x);
@@ -110,14 +111,14 @@ static const GtkCssValueClass GTK_CSS_VALUE_CORNER = {
};
static GtkCssValue corner_singletons[] = {
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, FALSE, NULL, NULL },
};
static inline void
@@ -226,3 +227,4 @@ gtk_css_corner_value_is_zero (const GtkCssValue *corner)
return gtk_css_dimension_value_is_zero (corner->x) &&
gtk_css_dimension_value_is_zero (corner->y);
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#include "gtkcsscustompropertypoolprivate.h"
struct _GtkCssCustomPropertyPool
{
GObject parent_instance;
GArray *names;
GHashTable *name_mappings;
};
struct _GtkCssCustomPropertyName
{
int ref_count;
char *name;
};
typedef struct _GtkCssCustomPropertyName GtkCssCustomPropertyName;
static GtkCssCustomPropertyPool *instance = NULL;
G_DEFINE_FINAL_TYPE (GtkCssCustomPropertyPool, gtk_css_custom_property_pool, G_TYPE_OBJECT)
static void
clear_custom_property_name (GtkCssCustomPropertyName *name)
{
g_clear_pointer (&name->name, g_free);
}
static void
gtk_css_custom_property_pool_finalize (GObject *object)
{
GtkCssCustomPropertyPool *self = (GtkCssCustomPropertyPool *)object;
g_hash_table_unref (self->name_mappings);
g_array_unref (self->names);
G_OBJECT_CLASS (gtk_css_custom_property_pool_parent_class)->finalize (object);
}
static void
gtk_css_custom_property_pool_class_init (GtkCssCustomPropertyPoolClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_css_custom_property_pool_finalize;
}
static void
gtk_css_custom_property_pool_init (GtkCssCustomPropertyPool *self)
{
self->name_mappings = g_hash_table_new (g_str_hash, g_str_equal);
self->names = g_array_new (FALSE, FALSE, sizeof (GtkCssCustomPropertyName));
g_array_set_clear_func (self->names, (GDestroyNotify) clear_custom_property_name);
}
GtkCssCustomPropertyPool *
gtk_css_custom_property_pool_get (void)
{
if (instance == NULL)
instance = g_object_new (GTK_TYPE_CSS_CUSTOM_PROPERTY_POOL, NULL);
return instance;
}
int
gtk_css_custom_property_pool_add (GtkCssCustomPropertyPool *self,
const char *str)
{
GtkCssCustomPropertyName name;
int id;
id = gtk_css_custom_property_pool_lookup (self, str);
if (id > 0)
return gtk_css_custom_property_pool_ref (self, id);
name.ref_count = 1;
name.name = g_strdup (str);
// TODO reuse slots after they're gone
g_array_append_val (self->names, name);
id = self->names->len;
g_hash_table_insert (self->name_mappings, (char *) name.name, GINT_TO_POINTER (id));
return id;
}
int
gtk_css_custom_property_pool_lookup (GtkCssCustomPropertyPool *self,
const char *str)
{
gpointer id;
id = g_hash_table_lookup (self->name_mappings, str);
return GPOINTER_TO_INT (id);
}
int
gtk_css_custom_property_pool_ref (GtkCssCustomPropertyPool *self,
int id)
{
GtkCssCustomPropertyName *name;
name = &g_array_index (self->names, GtkCssCustomPropertyName, id - 1);
name->ref_count++;
return id;
}
void
gtk_css_custom_property_pool_unref (GtkCssCustomPropertyPool *self,
int id)
{
GtkCssCustomPropertyName *name;
name = &g_array_index (self->names, GtkCssCustomPropertyName, id - 1);
g_assert (name->ref_count > 0);
name->ref_count--;
if (name->ref_count == 0)
{
g_hash_table_remove (self->name_mappings, name->name);
clear_custom_property_name (name);
}
}
const char *
gtk_css_custom_property_pool_get_name (GtkCssCustomPropertyPool *self,
int id)
{
GtkCssCustomPropertyName *name;
name = &g_array_index (self->names, GtkCssCustomPropertyName, id - 1);
return name->name;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#pragma once
#include <glib-object.h>
G_BEGIN_DECLS
#define GTK_TYPE_CSS_CUSTOM_PROPERTY_POOL (gtk_css_custom_property_pool_get_type())
G_DECLARE_FINAL_TYPE (GtkCssCustomPropertyPool, gtk_css_custom_property_pool, GTK, CSS_CUSTOM_PROPERTY_POOL, GObject)
GtkCssCustomPropertyPool *gtk_css_custom_property_pool_get (void);
int gtk_css_custom_property_pool_add (GtkCssCustomPropertyPool *self,
const char *str);
int gtk_css_custom_property_pool_lookup (GtkCssCustomPropertyPool *self,
const char *str);
const char * gtk_css_custom_property_pool_get_name (GtkCssCustomPropertyPool *self,
int id);
int gtk_css_custom_property_pool_ref (GtkCssCustomPropertyPool *self,
int id);
void gtk_css_custom_property_pool_unref (GtkCssCustomPropertyPool *self,
int id);
G_END_DECLS

View File

@@ -50,11 +50,12 @@ gtk_css_value_ease_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_ease_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_ease_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (value);
}
@@ -407,3 +408,4 @@ _gtk_css_ease_value_transform (const GtkCssValue *ease,
}

View File

@@ -41,11 +41,12 @@ gtk_css_value_enum_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_enum_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_enum_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (value);
}
@@ -87,16 +88,16 @@ static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
};
static GtkCssValue border_style_values[] = {
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_NONE, "none" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_INSET, "inset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_OUTSET, "outset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_HIDDEN, "hidden" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOTTED, "dotted" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DASHED, "dashed" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_GROOVE, "groove" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_RIDGE, "ridge" }
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_NONE, "none" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_INSET, "inset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_OUTSET, "outset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_HIDDEN, "hidden" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_DOTTED, "dotted" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_DASHED, "dashed" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_GROOVE, "groove" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, FALSE, GTK_BORDER_STYLE_RIDGE, "ridge" }
};
GtkCssValue *
@@ -145,22 +146,22 @@ static const GtkCssValueClass GTK_CSS_VALUE_BLEND_MODE = {
};
static GtkCssValue blend_mode_values[] = {
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DEFAULT, "normal" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_MULTIPLY, "multiply" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SCREEN, "screen" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_OVERLAY, "overlay" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DARKEN, "darken" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_LIGHTEN, "lighten" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_DODGE, "color-dodge" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_BURN, "color-burn" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HARD_LIGHT, "hard-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SOFT_LIGHT, "soft-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DIFFERENCE, "difference" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_EXCLUSION, "exclusion" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR, "color" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HUE, "hue" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SATURATION, "saturation" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_LUMINOSITY, "luminosity" }
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_DEFAULT, "normal" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_MULTIPLY, "multiply" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_SCREEN, "screen" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_OVERLAY, "overlay" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_DARKEN, "darken" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_LIGHTEN, "lighten" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_COLOR_DODGE, "color-dodge" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_COLOR_BURN, "color-burn" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_HARD_LIGHT, "hard-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_SOFT_LIGHT, "soft-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_DIFFERENCE, "difference" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_EXCLUSION, "exclusion" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_COLOR, "color" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_HUE, "hue" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_SATURATION, "saturation" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, FALSE, GSK_BLEND_MODE_LUMINOSITY, "luminosity" }
};
GtkCssValue *
@@ -229,11 +230,12 @@ gtk_css_font_size_get_default_px (GtkStyleProvider *provider,
}
static GtkCssValue *
gtk_css_value_font_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
double font_size;
@@ -296,15 +298,15 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_SIZE = {
};
static GtkCssValue font_size_values[] = {
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGER, "larger" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALL, "small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGE, "large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_XX_LARGE, "xx-large" }
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_LARGER, "larger" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_SMALL, "small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_LARGE, "large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, FALSE, GTK_CSS_FONT_SIZE_XX_LARGE, "xx-large" }
};
GtkCssValue *
@@ -353,9 +355,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
};
static GtkCssValue font_style_values[] = {
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_OBLIQUE, "oblique" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_ITALIC, "italic" }
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, FALSE, PANGO_STYLE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, FALSE, PANGO_STYLE_OBLIQUE, "oblique" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, FALSE, PANGO_STYLE_ITALIC, "italic" }
};
GtkCssValue *
@@ -396,11 +398,12 @@ _gtk_css_font_style_value_get (const GtkCssValue *value)
#define LIGHTER -2
static GtkCssValue *
gtk_css_value_font_weight_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_weight_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
PangoWeight new_weight;
int parent_value;
@@ -452,8 +455,8 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
};
static GtkCssValue font_weight_values[] = {
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, BOLDER, "bolder" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, LIGHTER, "lighter" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, FALSE, BOLDER, "bolder" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, FALSE, LIGHTER, "lighter" },
};
GtkCssValue *
@@ -502,15 +505,15 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_STRETCH = {
};
static GtkCssValue font_stretch_values[] = {
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_ULTRA_CONDENSED, "ultra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_CONDENSED, "extra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_CONDENSED, "condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_CONDENSED, "semi-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_EXPANDED, "semi-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXPANDED, "expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_EXPANDED, "extra-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_ULTRA_EXPANDED, "ultra-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_ULTRA_CONDENSED, "ultra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_EXTRA_CONDENSED, "extra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_CONDENSED, "condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_SEMI_CONDENSED, "semi-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_SEMI_EXPANDED, "semi-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_EXPANDED, "expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_EXTRA_EXPANDED, "extra-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, FALSE, PANGO_STRETCH_ULTRA_EXPANDED, "ultra-expanded" },
};
GtkCssValue *
@@ -559,9 +562,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
};
static GtkCssValue text_decoration_style_values[] = {
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_WAVY, "wavy" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, FALSE, GTK_CSS_TEXT_DECORATION_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, FALSE, GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, FALSE, GTK_CSS_TEXT_DECORATION_STYLE_WAVY, "wavy" },
};
GtkCssValue *
@@ -610,9 +613,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
};
static GtkCssValue area_values[] = {
{ &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_BORDER_BOX, "border-box" },
{ &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
{ &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
{ &GTK_CSS_VALUE_AREA, 1, TRUE, FALSE, GTK_CSS_AREA_BORDER_BOX, "border-box" },
{ &GTK_CSS_VALUE_AREA, 1, TRUE, FALSE, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
{ &GTK_CSS_VALUE_AREA, 1, TRUE, FALSE, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
};
GtkCssValue *
@@ -667,10 +670,10 @@ static const GtkCssValueClass GTK_CSS_VALUE_DIRECTION = {
};
static GtkCssValue direction_values[] = {
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_REVERSE, "reverse" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_ALTERNATE_REVERSE, "alternate-reverse" }
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, FALSE, GTK_CSS_DIRECTION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, FALSE, GTK_CSS_DIRECTION_REVERSE, "reverse" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, FALSE, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, FALSE, GTK_CSS_DIRECTION_ALTERNATE_REVERSE, "alternate-reverse" }
};
GtkCssValue *
@@ -728,8 +731,8 @@ static const GtkCssValueClass GTK_CSS_VALUE_PLAY_STATE = {
};
static GtkCssValue play_state_values[] = {
{ &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, GTK_CSS_PLAY_STATE_RUNNING, "running" },
{ &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, GTK_CSS_PLAY_STATE_PAUSED, "paused" }
{ &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, FALSE, GTK_CSS_PLAY_STATE_RUNNING, "running" },
{ &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, FALSE, GTK_CSS_PLAY_STATE_PAUSED, "paused" }
};
GtkCssValue *
@@ -784,10 +787,10 @@ static const GtkCssValueClass GTK_CSS_VALUE_FILL_MODE = {
};
static GtkCssValue fill_mode_values[] = {
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_NONE, "none" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_FORWARDS, "forwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_BACKWARDS, "backwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_BOTH, "both" }
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, FALSE, GTK_CSS_FILL_NONE, "none" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, FALSE, GTK_CSS_FILL_FORWARDS, "forwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, FALSE, GTK_CSS_FILL_BACKWARDS, "backwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, FALSE, GTK_CSS_FILL_BOTH, "both" }
};
GtkCssValue *
@@ -842,9 +845,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_ICON_STYLE = {
};
static GtkCssValue icon_style_values[] = {
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REQUESTED, "requested" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REGULAR, "regular" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_SYMBOLIC, "symbolic" }
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, FALSE, GTK_CSS_ICON_STYLE_REQUESTED, "requested" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, FALSE, GTK_CSS_ICON_STYLE_REGULAR, "regular" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, FALSE, GTK_CSS_ICON_STYLE_SYMBOLIC, "symbolic" }
};
GtkCssValue *
@@ -899,9 +902,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_KERNING = {
};
static GtkCssValue font_kerning_values[] = {
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_AUTO, "auto" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_NONE, "none" }
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, FALSE, GTK_CSS_FONT_KERNING_AUTO, "auto" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, FALSE, GTK_CSS_FONT_KERNING_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, FALSE, GTK_CSS_FONT_KERNING_NONE, "none" }
};
GtkCssValue *
@@ -956,9 +959,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_POSITION = {
};
static GtkCssValue font_variant_position_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_SUB, "sub" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_SUPER, "super" }
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_POSITION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_POSITION_SUB, "sub" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_POSITION_SUPER, "super" }
};
GtkCssValue *
@@ -1013,13 +1016,13 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_CAPS = {
};
static GtkCssValue font_variant_caps_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS, "small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS, "all-small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS, "petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS, "all-petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_UNICASE, "unicase" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS, "titling-caps" }
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_CAPS_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS, "small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS, "all-small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS, "petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS, "all-petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_CAPS_UNICASE, "unicase" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS, "titling-caps" }
};
GtkCssValue *
@@ -1074,8 +1077,8 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE = {
};
static GtkCssValue font_variant_alternate_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS, "historical-forms" }
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, FALSE, GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS, "historical-forms" }
};
GtkCssValue *
@@ -1583,10 +1586,10 @@ static const GtkCssValueClass GTK_CSS_VALUE_TEXT_TRANSFORM = {
};
static GtkCssValue text_transform_values[] = {
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, GTK_CSS_TEXT_TRANSFORM_NONE, "none" },
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, GTK_CSS_TEXT_TRANSFORM_LOWERCASE, "lowercase" },
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, GTK_CSS_TEXT_TRANSFORM_UPPERCASE, "uppercase" },
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, GTK_CSS_TEXT_TRANSFORM_CAPITALIZE, "capitalize" },
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, FALSE, GTK_CSS_TEXT_TRANSFORM_NONE, "none" },
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, FALSE, GTK_CSS_TEXT_TRANSFORM_LOWERCASE, "lowercase" },
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, FALSE, GTK_CSS_TEXT_TRANSFORM_UPPERCASE, "uppercase" },
{ &GTK_CSS_VALUE_TEXT_TRANSFORM, 1, TRUE, FALSE, GTK_CSS_TEXT_TRANSFORM_CAPITALIZE, "capitalize" },
};
GtkCssValue *

View File

@@ -307,55 +307,56 @@ gtk_css_value_filter_free (GtkCssValue *value)
/* returns TRUE if dest == src */
static gboolean
gtk_css_filter_compute (GtkCssFilter *dest,
GtkCssFilter *src,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_filter_compute (GtkCssFilter *dest,
GtkCssFilter *src,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
dest->type = src->type;
switch (src->type)
{
case GTK_CSS_FILTER_BRIGHTNESS:
dest->brightness.value = _gtk_css_value_compute (src->brightness.value, property_id, provider, style, parent_style);
dest->brightness.value = _gtk_css_value_compute (src->brightness.value, property_id, provider, style, parent_style, variables);
return dest->brightness.value == src->brightness.value;
case GTK_CSS_FILTER_CONTRAST:
dest->contrast.value = _gtk_css_value_compute (src->contrast.value, property_id, provider, style, parent_style);
dest->contrast.value = _gtk_css_value_compute (src->contrast.value, property_id, provider, style, parent_style, variables);
return dest->contrast.value == src->contrast.value;
case GTK_CSS_FILTER_GRAYSCALE:
dest->grayscale.value = _gtk_css_value_compute (src->grayscale.value, property_id, provider, style, parent_style);
dest->grayscale.value = _gtk_css_value_compute (src->grayscale.value, property_id, provider, style, parent_style, variables);
return dest->grayscale.value == src->grayscale.value;
case GTK_CSS_FILTER_HUE_ROTATE:
dest->hue_rotate.value = _gtk_css_value_compute (src->hue_rotate.value, property_id, provider, style, parent_style);
dest->hue_rotate.value = _gtk_css_value_compute (src->hue_rotate.value, property_id, provider, style, parent_style, variables);
return dest->hue_rotate.value == src->hue_rotate.value;
case GTK_CSS_FILTER_INVERT:
dest->invert.value = _gtk_css_value_compute (src->invert.value, property_id, provider, style, parent_style);
dest->invert.value = _gtk_css_value_compute (src->invert.value, property_id, provider, style, parent_style, variables);
return dest->invert.value == src->invert.value;
case GTK_CSS_FILTER_OPACITY:
dest->opacity.value = _gtk_css_value_compute (src->opacity.value, property_id, provider, style, parent_style);
dest->opacity.value = _gtk_css_value_compute (src->opacity.value, property_id, provider, style, parent_style, variables);
return dest->opacity.value == src->opacity.value;
case GTK_CSS_FILTER_SATURATE:
dest->saturate.value = _gtk_css_value_compute (src->saturate.value, property_id, provider, style, parent_style);
dest->saturate.value = _gtk_css_value_compute (src->saturate.value, property_id, provider, style, parent_style, variables);
return dest->saturate.value == src->saturate.value;
case GTK_CSS_FILTER_SEPIA:
dest->sepia.value = _gtk_css_value_compute (src->sepia.value, property_id, provider, style, parent_style);
dest->sepia.value = _gtk_css_value_compute (src->sepia.value, property_id, provider, style, parent_style, variables);
return dest->sepia.value == src->sepia.value;
case GTK_CSS_FILTER_BLUR:
dest->blur.value = _gtk_css_value_compute (src->blur.value, property_id, provider, style, parent_style);
dest->blur.value = _gtk_css_value_compute (src->blur.value, property_id, provider, style, parent_style, variables);
return dest->blur.value == src->blur.value;
case GTK_CSS_FILTER_DROP_SHADOW:
dest->drop_shadow.value = _gtk_css_value_compute (src->drop_shadow.value, property_id, provider, style, parent_style);
dest->drop_shadow.value = _gtk_css_value_compute (src->drop_shadow.value, property_id, provider, style, parent_style, variables);
return dest->drop_shadow.value == src->drop_shadow.value;
case GTK_CSS_FILTER_NONE:
@@ -366,11 +367,12 @@ gtk_css_filter_compute (GtkCssFilter *dest,
}
static GtkCssValue *
gtk_css_value_filter_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_filter_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *result;
gboolean changes;
@@ -390,7 +392,8 @@ gtk_css_value_filter_compute (GtkCssValue *value,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
}
if (!changes)
@@ -723,7 +726,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FILTER = {
gtk_css_value_filter_print
};
static GtkCssValue filter_none_singleton = { &GTK_CSS_VALUE_FILTER, 1, TRUE, 0, { { GTK_CSS_FILTER_NONE } } };
static GtkCssValue filter_none_singleton = { &GTK_CSS_VALUE_FILTER, 1, TRUE, FALSE, 0, { { GTK_CSS_FILTER_NONE } } };
static GtkCssValue *
gtk_css_filter_value_alloc (guint n_filters)

View File

@@ -53,11 +53,12 @@ gtk_css_value_font_features_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_font_features_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_features_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (specified);
}

View File

@@ -52,11 +52,12 @@ gtk_css_value_font_variations_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_font_variations_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_variations_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (specified);
}

View File

@@ -65,11 +65,12 @@ gtk_css_image_real_get_aspect_ratio (GtkCssImage *image)
}
static GtkCssImage *
gtk_css_image_real_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_real_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return g_object_ref (image);
}
@@ -173,11 +174,12 @@ _gtk_css_image_get_aspect_ratio (GtkCssImage *image)
}
GtkCssImage *
_gtk_css_image_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
_gtk_css_image_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageClass *klass;
@@ -187,7 +189,7 @@ _gtk_css_image_compute (GtkCssImage *image,
klass = GTK_CSS_IMAGE_GET_CLASS (image);
return klass->compute (image, property_id, provider, style, parent_style);
return klass->compute (image, property_id, provider, style, parent_style, variables);
}
GtkCssImage *

View File

@@ -313,11 +313,12 @@ gtk_css_image_conic_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_conic_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_conic_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageConic *self = GTK_CSS_IMAGE_CONIC (image);
GtkCssImageConic *copy;
@@ -325,8 +326,8 @@ gtk_css_image_conic_compute (GtkCssImage *image,
copy = g_object_new (GTK_TYPE_CSS_IMAGE_CONIC, NULL);
copy->center = _gtk_css_value_compute (self->center, property_id, provider, style, parent_style);
copy->rotation = _gtk_css_value_compute (self->rotation, property_id, provider, style, parent_style);
copy->center = _gtk_css_value_compute (self->center, property_id, provider, style, parent_style, variables);
copy->rotation = _gtk_css_value_compute (self->rotation, property_id, provider, style, parent_style, variables);
copy->n_stops = self->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageConicColorStop) * copy->n_stops);
@@ -335,11 +336,11 @@ gtk_css_image_conic_compute (GtkCssImage *image,
const GtkCssImageConicColorStop *stop = &self->color_stops[i];
GtkCssImageConicColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style, variables);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style, variables);
}
else
{

View File

@@ -399,11 +399,12 @@ gtk_css_image_cross_fade_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_cross_fade_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_cross_fade_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImageCrossFade *result;
@@ -418,7 +419,7 @@ gtk_css_image_cross_fade_compute (GtkCssImage *image,
gtk_css_image_cross_fade_add (result,
entry->has_progress,
entry->progress,
_gtk_css_image_compute (entry->image, property_id, provider, style, parent_style));
_gtk_css_image_compute (entry->image, property_id, provider, style, parent_style, variables));
}
return GTK_CSS_IMAGE (result);

View File

@@ -133,11 +133,12 @@ gtk_css_image_fallback_dispose (GObject *object)
static GtkCssImage *
gtk_css_image_fallback_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_fallback_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (image);
GtkCssImageFallback *copy;
@@ -152,7 +153,8 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
/* image($color) that didn't change */
if (computed_color && !fallback->images &&
@@ -168,7 +170,8 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
if (gtk_css_image_is_invalid (copy->images[i]))
continue;

View File

@@ -138,11 +138,12 @@ gtk_css_image_icon_theme_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_icon_theme_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_icon_theme_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image);
GtkCssImageIconTheme *copy;

View File

@@ -488,11 +488,12 @@ gtk_css_image_linear_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_linear_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_linear_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
GtkCssImageLinear *copy;
@@ -503,7 +504,7 @@ gtk_css_image_linear_compute (GtkCssImage *image,
copy->side = linear->side;
if (linear->angle)
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, style, parent_style);
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, style, parent_style, variables);
copy->n_stops = linear->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageLinearColorStop) * copy->n_stops);
@@ -512,11 +513,11 @@ gtk_css_image_linear_compute (GtkCssImage *image,
const GtkCssImageLinearColorStop *stop = &linear->color_stops[i];
GtkCssImageLinearColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style, variables);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style, variables);
}
else
{

View File

@@ -96,11 +96,12 @@ gtk_css_image_paintable_get_static_image (GtkCssImage *image)
}
static GtkCssImage *
gtk_css_image_paintable_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_paintable_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return gtk_css_image_paintable_get_static_image (image);
}

View File

@@ -26,6 +26,7 @@
#include "gtk/css/gtkcsstokenizerprivate.h"
#include "gtk/css/gtkcssparserprivate.h"
#include "gtk/gtkcsstypesprivate.h"
#include "gtk/gtkcssvariablesetprivate.h"
#include "gtk/gtksnapshot.h"
#include "gtk/gtkstyleprovider.h"
@@ -62,7 +63,8 @@ struct _GtkCssImageClass
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style);
GtkCssStyle *parent_style,
GtkCssVariableSet *variables);
/* compare two images for equality */
gboolean (* equal) (GtkCssImage *image1,
GtkCssImage *image2);
@@ -106,7 +108,8 @@ GtkCssImage * _gtk_css_image_compute (GtkCssImage *
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style);
GtkCssStyle *parent_style,
GtkCssVariableSet *variables);
gboolean _gtk_css_image_equal (GtkCssImage *image1,
GtkCssImage *image2) G_GNUC_PURE;
GtkCssImage * _gtk_css_image_transition (GtkCssImage *start,

View File

@@ -489,11 +489,12 @@ gtk_css_image_radial_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_radial_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_radial_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
GtkCssImageRadial *copy;
@@ -504,13 +505,13 @@ gtk_css_image_radial_compute (GtkCssImage *image,
copy->circle = radial->circle;
copy->size = radial->size;
copy->position = _gtk_css_value_compute (radial->position, property_id, provider, style, parent_style);
copy->position = _gtk_css_value_compute (radial->position, property_id, provider, style, parent_style, variables);
if (radial->sizes[0])
copy->sizes[0] = _gtk_css_value_compute (radial->sizes[0], property_id, provider, style, parent_style);
copy->sizes[0] = _gtk_css_value_compute (radial->sizes[0], property_id, provider, style, parent_style, variables);
if (radial->sizes[1])
copy->sizes[1] = _gtk_css_value_compute (radial->sizes[1], property_id, provider, style, parent_style);
copy->sizes[1] = _gtk_css_value_compute (radial->sizes[1], property_id, provider, style, parent_style, variables);
copy->n_stops = radial->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageRadialColorStop) * copy->n_stops);
@@ -519,11 +520,11 @@ gtk_css_image_radial_compute (GtkCssImage *image,
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
GtkCssImageRadialColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style, variables);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style, variables);
}
else
{

View File

@@ -201,11 +201,12 @@ gtk_css_image_recolor_snapshot (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_recolor_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_recolor_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image);
GtkCssValue *palette;
@@ -216,7 +217,7 @@ gtk_css_image_recolor_compute (GtkCssImage *image,
scale = gtk_style_provider_get_scale (provider);
if (recolor->palette)
palette = _gtk_css_value_compute (recolor->palette, property_id, provider, style, parent_style);
palette = _gtk_css_value_compute (recolor->palette, property_id, provider, style, parent_style, variables);
else
palette = _gtk_css_value_ref (style->core->icon_palette);

View File

@@ -97,11 +97,12 @@ gtk_css_image_scaled_dispose (GObject *object)
static GtkCssImage *
gtk_css_image_scaled_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_scaled_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
int scale;
@@ -137,7 +138,8 @@ gtk_css_image_scaled_compute (GtkCssImage *image,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
res->scales[0] = scaled->scales[best];
return GTK_CSS_IMAGE (res);

View File

@@ -112,11 +112,12 @@ gtk_css_image_url_snapshot (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_url_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_url_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
GtkCssImage *copy;

View File

@@ -34,11 +34,12 @@ gtk_css_value_image_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_image_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_image_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImage *image, *computed;
@@ -47,7 +48,7 @@ gtk_css_value_image_compute (GtkCssValue *value,
if (image == NULL)
return _gtk_css_value_ref (value);
computed = _gtk_css_image_compute (image, property_id, provider, style, parent_style);
computed = _gtk_css_image_compute (image, property_id, provider, style, parent_style, variables);
if (computed == image)
{
@@ -136,7 +137,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_IMAGE = {
GtkCssValue *
_gtk_css_image_value_new (GtkCssImage *image)
{
static GtkCssValue image_none_singleton = { &GTK_CSS_VALUE_IMAGE, 1, TRUE, NULL };
static GtkCssValue image_none_singleton = { &GTK_CSS_VALUE_IMAGE, 1, TRUE, FALSE, NULL };
GtkCssValue *value;
if (image == NULL)

View File

@@ -34,11 +34,12 @@ gtk_css_value_inherit_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_inherit_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_inherit_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
if (parent_style)
{
@@ -50,7 +51,8 @@ gtk_css_value_inherit_compute (GtkCssValue *value,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
}
}

View File

@@ -38,11 +38,12 @@ gtk_css_value_initial_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_initial_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_initial_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkSettings *settings;
@@ -75,7 +76,8 @@ gtk_css_value_initial_compute (GtkCssValue *value,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
}
static gboolean
@@ -135,5 +137,6 @@ _gtk_css_initial_value_new_compute (guint property_id,
property_id,
provider,
style,
parent_style);
parent_style,
NULL);
}

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,47 @@ 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_value_taint (var_value);
gtk_css_variable_set_add (keyframes->variables[k], id, var_value);
gtk_css_custom_property_pool_unref (pool, id);
g_free (name);
return TRUE;
}
property = _gtk_style_property_lookup (name);
if (property == NULL)
{
@@ -251,9 +325,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 +432,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;
@@ -378,12 +499,27 @@ compare_property_by_name (gconstpointer a,
_gtk_css_style_property_lookup_by_id (keyframes->property_ids[*(const guint *) b]))));
}
static int
compare_custom_property_ids (gconstpointer a, gconstpointer b, gpointer user_data)
{
GtkCssCustomPropertyPool *pool = user_data;
int id1 = GPOINTER_TO_INT (*((const int *) a));
int id2 = GPOINTER_TO_INT (*((const int *) b));
const char *name1, *name2;
name1 = gtk_css_custom_property_pool_get_name (pool, id1);
name2 = gtk_css_custom_property_pool_get_name (pool, id2);
return strcmp (name1, name2);
}
void
_gtk_css_keyframes_print (GtkCssKeyframes *keyframes,
GString *string)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
guint k, p;
guint *sorted;
guint *sorted, *sorted_variable_ids = NULL;
g_return_if_fail (keyframes != NULL);
g_return_if_fail (string != NULL);
@@ -393,6 +529,18 @@ _gtk_css_keyframes_print (GtkCssKeyframes *keyframes,
sorted[p] = p;
g_qsort_with_data (sorted, keyframes->n_properties, sizeof (guint), compare_property_by_name, keyframes);
if (keyframes->variable_ids)
{
sorted_variable_ids = g_memdup2 (keyframes->variable_ids,
sizeof (int) * keyframes->n_variables);
g_qsort_with_data (sorted_variable_ids,
keyframes->n_variables,
sizeof (int),
compare_custom_property_ids,
pool);
}
for (k = 0; k < keyframes->n_keyframes; k++)
{
/* useful for 0% and 100% which might be empty */
@@ -422,11 +570,43 @@ _gtk_css_keyframes_print (GtkCssKeyframes *keyframes,
g_string_append (string, ";\n");
}
if (keyframes->variables && keyframes->variables[k])
{
for (p = 0; p < keyframes->n_variables; p++)
{
int variable_id = sorted_variable_ids[p];
GtkCssVariableValue *value =
gtk_css_variable_set_lookup (keyframes->variables[k], variable_id, NULL);
const char *name;
if (value == NULL)
continue;
if (!opened)
{
if (keyframes->keyframe_progress[k] == 0.0)
g_string_append (string, " from {\n");
else if (keyframes->keyframe_progress[k] == 1.0)
g_string_append (string, " to {\n");
else
g_string_append_printf (string, " %g%% {\n", keyframes->keyframe_progress[k] * 100);
opened = TRUE;
}
name = gtk_css_custom_property_pool_get_name (pool, variable_id);
g_string_append_printf (string, " %s: ", name);
gtk_css_variable_value_print (value, string);
g_string_append (string, ";\n");
}
}
if (opened)
g_string_append (string, " }\n");
}
g_free (sorted);
g_free (sorted_variable_ids);
}
GtkCssKeyframes *
@@ -461,10 +641,27 @@ _gtk_css_keyframes_compute (GtkCssKeyframes *keyframes,
resolved->property_ids[p],
provider,
style,
parent_style);
parent_style,
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;
}
@@ -540,3 +737,83 @@ _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;
if (keyframes->variables[k] == NULL)
continue;
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

@@ -39,15 +39,16 @@ gtk_css_value_line_height_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_line_height_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_line_height_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *height;
height = _gtk_css_value_compute (value->height, property_id, provider, style, parent_style);
height = _gtk_css_value_compute (value->height, property_id, provider, style, parent_style, variables);
if (gtk_css_number_value_get_dimension (height) == GTK_CSS_DIMENSION_PERCENTAGE)
{

View File

@@ -19,6 +19,7 @@
#include "gtkcsslookupprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkcsstypesprivate.h"
#include "gtkprivatetypebuiltins.h"
@@ -36,6 +37,9 @@ void
_gtk_css_lookup_destroy (GtkCssLookup *lookup)
{
_gtk_bitmask_free (lookup->set_values);
if (lookup->custom_values)
g_hash_table_unref (lookup->custom_values);
}
gboolean
@@ -74,3 +78,17 @@ _gtk_css_lookup_set (GtkCssLookup *lookup,
lookup->values[id].section = section;
lookup->set_values = _gtk_bitmask_set (lookup->set_values, id, TRUE);
}
void
_gtk_css_lookup_set_custom (GtkCssLookup *lookup,
int id,
GtkCssVariableValue *value)
{
gtk_internal_return_if_fail (lookup != NULL);
if (!lookup->custom_values)
lookup->custom_values = g_hash_table_new (g_direct_hash, g_direct_equal);
if (!g_hash_table_contains (lookup->custom_values, GINT_TO_POINTER (id)))
g_hash_table_replace (lookup->custom_values, GINT_TO_POINTER (id), value);
}

View File

@@ -23,6 +23,8 @@
#include "gtk/gtkcssstaticstyleprivate.h"
#include "gtk/css/gtkcsssection.h"
#include "gtk/css/gtkcsstokenizerprivate.h"
#include "gtk/css/gtkcssvariablevalueprivate.h"
G_BEGIN_DECLS
@@ -37,6 +39,7 @@ typedef struct {
struct _GtkCssLookup {
GtkBitmask *set_values;
GtkCssLookupValue values[GTK_CSS_PROPERTY_N_PROPERTIES];
GHashTable *custom_values;
};
void _gtk_css_lookup_init (GtkCssLookup *lookup);
@@ -47,6 +50,9 @@ void _gtk_css_lookup_set (GtkCssLookup
guint id,
GtkCssSection *section,
GtkCssValue *value);
void _gtk_css_lookup_set_custom (GtkCssLookup *lookup,
int id,
GtkCssVariableValue *value);
static inline const GtkBitmask *
_gtk_css_lookup_get_set_values (const GtkCssLookup *lookup)

View File

@@ -445,9 +445,12 @@ gtk_css_node_real_update_style (GtkCssNode *cssnode,
}
else if (static_style != style && (change & GTK_CSS_CHANGE_TIMESTAMP))
{
GtkCssNode *parent = gtk_css_node_get_parent (cssnode);
new_style = gtk_css_animated_style_new_advance (GTK_CSS_ANIMATED_STYLE (style),
static_style,
timestamp);
parent ? gtk_css_node_get_style (parent) : NULL,
timestamp,
gtk_css_node_get_style_provider (cssnode));
}
else
{

View File

@@ -108,11 +108,12 @@ get_base_font_size_px (guint property_id,
}
static GtkCssValue *
gtk_css_value_number_compute (GtkCssValue *number,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_number_compute (GtkCssValue *number,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
double value;
@@ -130,7 +131,8 @@ gtk_css_value_number_compute (GtkCssValue *number,
{
GtkCssValue *computed = _gtk_css_value_compute (number->calc.terms[i],
property_id, provider, style,
parent_style);
parent_style,
variables);
changed |= computed != number->calc.terms[i];
new_values[i] = computed;
}
@@ -366,38 +368,38 @@ gtk_css_dimension_value_new (double value,
GtkCssUnit unit)
{
static GtkCssValue number_singletons[] = {
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_NUMBER, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_NUMBER, 1 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_NUMBER, 96 }} }, /* DPI default */
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_NUMBER, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_NUMBER, 1 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_NUMBER, 96 }} }, /* DPI default */
};
static GtkCssValue px_singletons[] = {
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 1 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 2 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 3 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 4 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 5 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 6 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 7 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 8 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 16 }} }, /* Icon size default */
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 32 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 64 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 1 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 2 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 3 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 4 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 5 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 6 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 7 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 8 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 16 }} }, /* Icon size default */
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 32 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PX, 64 }} },
};
static GtkCssValue percent_singletons[] = {
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PERCENT, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PERCENT, 50 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PERCENT, 100 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PERCENT, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, FALSE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PERCENT, 50 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, FALSE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_PERCENT, 100 }} },
};
static GtkCssValue second_singletons[] = {
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_S, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_S, 1 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_S, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_S, 1 }} },
};
static GtkCssValue deg_singletons[] = {
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 90 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 180 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 270 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 0 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 90 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 180 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, FALSE, TYPE_DIMENSION, {{ GTK_CSS_DEG, 270 }} },
};
GtkCssValue *result;

View File

@@ -103,11 +103,12 @@ gtk_css_value_palette_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_palette_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_palette_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *computed_color;
GtkCssValue *result;
@@ -120,7 +121,7 @@ gtk_css_value_palette_compute (GtkCssValue *specified,
{
GtkCssValue *value = specified->color_values[i];
computed_color = _gtk_css_value_compute (value, property_id, provider, style, parent_style);
computed_color = _gtk_css_value_compute (value, property_id, provider, style, parent_style, variables);
result->color_names[i] = g_strdup (specified->color_names[i]);
result->color_values[i] = computed_color;

View File

@@ -36,16 +36,17 @@ gtk_css_value_position_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_position_compute (GtkCssValue *position,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_position_compute (GtkCssValue *position,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *x, *y;
x = _gtk_css_value_compute (position->x, property_id, provider, style, parent_style);
y = _gtk_css_value_compute (position->y, property_id, provider, style, parent_style);
x = _gtk_css_value_compute (position->x, property_id, provider, style, parent_style, variables);
y = _gtk_css_value_compute (position->y, property_id, provider, style, parent_style, variables);
if (x == position->x && y == position->y)
{
_gtk_css_value_unref (x);

View File

@@ -22,10 +22,13 @@
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcsstokenizerprivate.h"
#include "gtk/css/gtkcssparserprivate.h"
#include "gtk/css/gtkcssvariablevalueprivate.h"
#include "gtkbitmaskprivate.h"
#include "gtkcssarrayvalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
#include "gtkcsskeyframesprivate.h"
#include "gtkcssreferencevalueprivate.h"
#include "gtkcssselectorprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtksettingsprivate.h"
@@ -113,6 +116,7 @@ struct GtkCssRuleset
PropertyValue *styles;
guint n_styles;
guint owns_styles : 1;
GHashTable *custom_properties;
};
struct _GtkCssScanner
@@ -133,6 +137,7 @@ struct _GtkCssProviderPrivate
GtkCssSelectorTree *tree;
GResource *resource;
char *path;
GBytes *bytes; /* *no* reference */
};
enum {
@@ -270,6 +275,8 @@ gtk_css_ruleset_clear (GtkCssRuleset *ruleset)
gtk_css_section_unref (ruleset->styles[i].section);
}
g_free (ruleset->styles);
if (ruleset->custom_properties)
g_hash_table_unref (ruleset->custom_properties);
}
if (ruleset->selector)
_gtk_css_selector_free (ruleset->selector);
@@ -285,7 +292,7 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset,
{
guint i;
g_return_if_fail (ruleset->owns_styles || ruleset->n_styles == 0);
g_return_if_fail (ruleset->owns_styles || (ruleset->n_styles == 0 && ruleset->custom_properties == NULL));
ruleset->owns_styles = TRUE;
@@ -315,6 +322,39 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset,
ruleset->styles[i].section = NULL;
}
static void
unref_custom_property_name (gpointer pointer)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
gtk_css_custom_property_pool_unref (pool, GPOINTER_TO_INT (pointer));
}
static void
gtk_css_ruleset_add_custom (GtkCssRuleset *ruleset,
const char *name,
GtkCssVariableValue *value)
{
GtkCssCustomPropertyPool *pool;
int id;
g_return_if_fail (ruleset->owns_styles || (ruleset->n_styles == 0 && ruleset->custom_properties == NULL));
ruleset->owns_styles = TRUE;
if (ruleset->custom_properties == NULL)
{
ruleset->custom_properties = g_hash_table_new_full (g_direct_hash, g_direct_equal,
unref_custom_property_name,
(GDestroyNotify) gtk_css_variable_value_unref);
}
pool = gtk_css_custom_property_pool_get ();
id = gtk_css_custom_property_pool_add (pool, name);
g_hash_table_replace (ruleset->custom_properties, GINT_TO_POINTER (id), value);
}
static void
gtk_css_scanner_destroy (GtkCssScanner *scanner)
{
@@ -342,9 +382,10 @@ gtk_css_scanner_parser_error (GtkCssParser *parser,
GtkCssScanner *scanner = user_data;
GtkCssSection *section;
section = gtk_css_section_new (gtk_css_parser_get_file (parser),
start,
end);
section = gtk_css_section_new_with_bytes (gtk_css_parser_get_file (parser),
gtk_css_parser_get_bytes (parser),
start,
end);
gtk_css_style_provider_emit_error (GTK_STYLE_PROVIDER (scanner->provider), section, error);
@@ -490,7 +531,7 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
{
ruleset = gtk_css_selector_matches_get (&tree_rules, i);
if (ruleset->styles == NULL)
if (ruleset->styles == NULL && ruleset->custom_properties == NULL)
continue;
for (j = 0; j < ruleset->n_styles; j++)
@@ -506,6 +547,18 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
ruleset->styles[j].section,
ruleset->styles[j].value);
}
if (ruleset->custom_properties)
{
GHashTableIter iter;
gpointer id;
GtkCssVariableValue *value;
g_hash_table_iter_init (&iter, ruleset->custom_properties);
while (g_hash_table_iter_next (&iter, &id, (gpointer) &value))
_gtk_css_lookup_set_custom (lookup, GPOINTER_TO_INT (id), value);
}
}
}
gtk_css_selector_matches_clear (&tree_rules);
@@ -514,6 +567,16 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
*change = gtk_css_selector_tree_get_change_all (priv->tree, filter, node);
}
static gboolean
gtk_css_style_provider_has_section (GtkStyleProvider *provider,
GtkCssSection *section)
{
GtkCssProvider *self = GTK_CSS_PROVIDER (provider);
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (self);
return priv->bytes == gtk_css_section_get_bytes (section);
}
static void
gtk_css_style_provider_iface_init (GtkStyleProviderInterface *iface)
{
@@ -521,6 +584,7 @@ gtk_css_style_provider_iface_init (GtkStyleProviderInterface *iface)
iface->get_keyframes = gtk_css_style_provider_get_keyframes;
iface->lookup = gtk_css_style_provider_lookup;
iface->emit_error = gtk_css_style_provider_emit_error;
iface->has_section = gtk_css_style_provider_has_section;
}
static void
@@ -572,7 +636,7 @@ css_provider_commit (GtkCssProvider *css_provider,
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (css_provider);
guint i;
if (ruleset->styles == NULL)
if (ruleset->styles == NULL && ruleset->custom_properties == NULL)
{
for (i = 0; i < gtk_css_selectors_get_size (selectors); i++)
_gtk_css_selector_free (gtk_css_selectors_get (selectors, i));
@@ -814,6 +878,49 @@ parse_declaration (GtkCssScanner *scanner,
if (name == NULL)
goto out;
/* This is a custom property */
if (name[0] == '-' && name[1] == '-')
{
GtkCssVariableValue *value;
GtkCssLocation start_location;
GtkCssSection *section;
if (!gtk_css_parser_try_token (scanner->parser, GTK_CSS_TOKEN_COLON))
{
gtk_css_parser_error_syntax (scanner->parser, "Expected ':'");
goto out;
}
gtk_css_parser_skip_whitespace (scanner->parser);
if (gtk_keep_css_sections)
start_location = *gtk_css_parser_get_start_location (scanner->parser);
value = gtk_css_parser_parse_value_into_token_stream (scanner->parser);
if (value == NULL)
goto out;
if (gtk_keep_css_sections)
{
section = gtk_css_section_new_with_bytes (gtk_css_parser_get_file (scanner->parser),
gtk_css_parser_get_bytes (scanner->parser),
&start_location,
gtk_css_parser_get_start_location (scanner->parser));
}
else
section = NULL;
if (section != NULL)
{
gtk_css_variable_value_set_section (value, section);
gtk_css_section_unref (section);
}
gtk_css_ruleset_add_custom (ruleset, name, value);
goto out;
}
property = _gtk_style_property_lookup (name);
if (property)
@@ -827,22 +934,88 @@ parse_declaration (GtkCssScanner *scanner,
goto out;
}
value = _gtk_style_property_parse_value (property, scanner->parser);
if (value == NULL)
goto out;
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
if (gtk_css_parser_has_references (scanner->parser))
{
gtk_css_parser_error_syntax (scanner->parser, "Junk at end of value for %s", property->name);
goto out;
GtkCssLocation start_location;
GtkCssVariableValue *var_value;
gtk_css_parser_skip_whitespace (scanner->parser);
if (gtk_keep_css_sections)
start_location = *gtk_css_parser_get_start_location (scanner->parser);
var_value = gtk_css_parser_parse_value_into_token_stream (scanner->parser);
if (var_value == NULL)
goto out;
if (gtk_keep_css_sections)
section = gtk_css_section_new_with_bytes (gtk_css_parser_get_file (scanner->parser),
gtk_css_parser_get_bytes (scanner->parser),
&start_location,
gtk_css_parser_get_start_location (scanner->parser));
else
section = NULL;
if (section != NULL)
{
gtk_css_variable_value_set_section (var_value, section);
gtk_css_section_unref (section);
}
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 (scanner->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 (scanner->parser));
}
gtk_css_variable_value_unref (var_value);
}
else
{
value = _gtk_style_property_parse_value (property, scanner->parser);
if (value == NULL)
goto out;
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_error_syntax (scanner->parser, "Junk at end of value for %s", property->name);
gtk_css_value_unref (value);
goto out;
}
}
if (gtk_keep_css_sections)
{
section = gtk_css_section_new (gtk_css_parser_get_file (scanner->parser),
gtk_css_parser_get_block_location (scanner->parser),
gtk_css_parser_get_end_location (scanner->parser));
section = gtk_css_section_new_with_bytes (gtk_css_parser_get_file (scanner->parser),
gtk_css_parser_get_bytes (scanner->parser),
gtk_css_parser_get_block_location (scanner->parser),
gtk_css_parser_get_end_location (scanner->parser));
}
else
section = NULL;
@@ -1025,6 +1198,7 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
GFile *file,
GBytes *bytes)
{
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (self);
gint64 before G_GNUC_UNUSED;
before = GDK_PROFILER_CURRENT_TIME;
@@ -1059,6 +1233,8 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
}
}
priv->bytes = bytes;
if (bytes)
{
GtkCssScanner *scanner;
@@ -1112,7 +1288,7 @@ gtk_css_provider_load_from_data (GtkCssProvider *css_provider,
if (length < 0)
length = strlen (data);
bytes = g_bytes_new_static (data, length);
bytes = g_bytes_new (data, length);
gtk_css_provider_load_from_bytes (css_provider, bytes);
@@ -1139,7 +1315,7 @@ gtk_css_provider_load_from_string (GtkCssProvider *css_provider,
g_return_if_fail (GTK_IS_CSS_PROVIDER (css_provider));
g_return_if_fail (string != NULL);
bytes = g_bytes_new_static (string, strlen (string));
bytes = g_bytes_new (string, strlen (string));
gtk_css_provider_load_from_bytes (css_provider, bytes);
@@ -1473,6 +1649,20 @@ compare_properties (gconstpointer a, gconstpointer b, gpointer style)
_gtk_style_property_get_name (GTK_STYLE_PROPERTY (styles[*ub].property)));
}
static int
compare_custom_properties (gconstpointer a, gconstpointer b, gpointer user_data)
{
GtkCssCustomPropertyPool *pool = user_data;
int id1 = GPOINTER_TO_INT (*((const int *) a));
int id2 = GPOINTER_TO_INT (*((const int *) b));
const char *name1, *name2;
name1 = gtk_css_custom_property_pool_get_name (pool, id1);
name2 = gtk_css_custom_property_pool_get_name (pool, id2);
return strcmp (name1, name2);
}
static void
gtk_css_ruleset_print (const GtkCssRuleset *ruleset,
GString *str)
@@ -1506,6 +1696,31 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset,
g_free (sorted);
}
if (ruleset->custom_properties)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
GPtrArray *keys;
keys = g_hash_table_get_keys_as_ptr_array (ruleset->custom_properties);
g_ptr_array_sort_with_data (keys, compare_custom_properties, pool);
for (i = 0; i < keys->len; i++)
{
int id = GPOINTER_TO_INT (g_ptr_array_index (keys, i));
const char *name = gtk_css_custom_property_pool_get_name (pool, id);
GtkCssVariableValue *value = g_hash_table_lookup (ruleset->custom_properties,
GINT_TO_POINTER (id));
g_string_append (str, " ");
g_string_append (str, name);
g_string_append (str, ": ");
gtk_css_variable_value_print (value, str);
g_string_append (str, ";\n");
}
g_ptr_array_unref (keys);
}
g_string_append (str, "}\n");
}
@@ -1598,4 +1813,3 @@ gtk_css_provider_to_string (GtkCssProvider *provider)
return g_string_free (str, FALSE);
}

377
gtk/gtkcssreferencevalue.c Normal file
View File

@@ -0,0 +1,377 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#include "config.h"
#include "gtkcssreferencevalueprivate.h"
#include "gtkcssarrayvalueprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtkcssstyleprivate.h"
#include "gtkcssunsetvalueprivate.h"
#include "gtkcssvalueprivate.h"
#include "gtkstyleproviderprivate.h"
#define GDK_ARRAY_NAME gtk_css_refs
#define GDK_ARRAY_TYPE_NAME GtkCssRefs
#define GDK_ARRAY_ELEMENT_TYPE gpointer
#define GDK_ARAY_PREALLOC 32
#define GDK_ARRAY_NO_MEMSET 1
#include "gdk/gdkarrayimpl.c"
#define MAX_TOKEN_LENGTH 65536
typedef enum {
RESOLVE_SUCCESS,
RESOLVE_INVALID,
RESOLVE_ANIMATION_TAINTED,
} ResolveResult;
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
GtkStyleProperty *property;
GtkCssVariableValue *value;
GFile *file;
guint subproperty;
};
static void
gtk_css_value_reference_free (GtkCssValue *value)
{
gtk_css_variable_value_unref (value->value);
if (value->file)
g_object_unref (value->file);
}
static ResolveResult
resolve_references_do (GtkCssVariableValue *value,
guint property_id,
GtkCssVariableSet *style_variables,
GtkCssVariableSet *keyframes_variables,
gboolean root,
GtkCssRefs *refs,
gsize *out_length,
gsize *out_n_refs)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
gsize i;
gsize length = value->length;
gsize n_refs = 0;
ResolveResult ret = RESOLVE_SUCCESS;
if (value->is_animation_tainted)
{
GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (property_id);
if (!_gtk_css_style_property_is_animated (prop))
{
/* Animation-tainted variables make other variables that reference
* them animation-tainted too, so unlike regular invalid variables it
* propagates to the root. For example, if --test is animation-tainted,
* --test2: var(--test, fallback1); prop: var(--test2, fallback2); will\
* resolve to fallback2 and _not_ to fallback1. So we'll propagate it
* up until the root, and treat it same as invalid there instead. */
ret = RESOLVE_ANIMATION_TAINTED;
goto error;
}
}
if (value->is_invalid)
{
ret = RESOLVE_INVALID;
goto error;
}
if (!root)
{
n_refs += 1;
gtk_css_refs_append (refs, value);
}
for (i = 0; i < value->n_references; i++)
{
GtkCssVariableValueReference *ref = &value->references[i];
int id = gtk_css_custom_property_pool_lookup (pool, ref->name);
GtkCssVariableValue *var_value = NULL;
gsize var_length, var_refs;
GtkCssVariableSet *source = style_variables;
ResolveResult result = RESOLVE_INVALID;
if (keyframes_variables)
var_value = gtk_css_variable_set_lookup (keyframes_variables, id, NULL);
if (!var_value && style_variables)
var_value = gtk_css_variable_set_lookup (style_variables, id, &source);
if (var_value)
{
result = resolve_references_do (var_value, property_id, source,
keyframes_variables, FALSE,
refs, &var_length, &var_refs);
if (root && result == RESOLVE_ANIMATION_TAINTED)
result = RESOLVE_INVALID;
}
if (result == RESOLVE_INVALID)
{
if (ref->fallback)
{
result = resolve_references_do (ref->fallback, property_id,
style_variables, keyframes_variables,
FALSE, refs, &var_length, &var_refs);
if (root && result == RESOLVE_ANIMATION_TAINTED)
result = RESOLVE_INVALID;
}
if (result != RESOLVE_SUCCESS)
{
ret = result;
goto error;
}
}
else if (result == RESOLVE_ANIMATION_TAINTED)
{
ret = RESOLVE_ANIMATION_TAINTED;
goto error;
}
length += var_length - ref->length;
n_refs += var_refs;
if (length > MAX_TOKEN_LENGTH)
{
ret = RESOLVE_INVALID;
goto error;
}
}
if (out_length)
*out_length = length;
if (out_n_refs)
*out_n_refs = n_refs;
return ret;
error:
/* Remove the references we added as if nothing happened */
gtk_css_refs_splice (refs, gtk_css_refs_get_size (refs) - n_refs, n_refs, TRUE, NULL, 0);
if (out_length)
*out_length = 0;
if (out_n_refs)
*out_n_refs = 0;
return ret;
}
static void
resolve_references (GtkCssVariableValue *input,
guint property_id,
GtkCssStyle *style,
GtkCssVariableSet *keyframes_variables,
GtkCssRefs *refs)
{
if (resolve_references_do (input, property_id, style->variables,
keyframes_variables, TRUE, refs,
NULL, NULL) != RESOLVE_SUCCESS)
{
gtk_css_refs_clear (refs);
}
}
static void
parser_error (GtkCssParser *parser,
const GtkCssLocation *start,
const GtkCssLocation *end,
const GError *error,
gpointer user_data)
{
GtkStyleProvider *provider = user_data;
GError *new_error = NULL;
GtkCssVariableValue **vars;
char **names;
gsize n_vars;
gtk_css_parser_get_expanding_variables (parser, &vars, &names, &n_vars);
if (n_vars > 0)
{
for (int i = 0; i < n_vars; i++)
{
if (names[i + 1])
g_set_error (&new_error,
GTK_CSS_PARSER_ERROR, GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE,
"While expanding %s: %s", names[i + 1], error->message);
else
g_set_error_literal (&new_error,
GTK_CSS_PARSER_ERROR, GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE,
error->message);
gtk_style_provider_emit_error (provider, vars[i]->section, new_error);
g_clear_error (&new_error);
}
for (int i = 0; i < n_vars; i++)
{
if (vars[i])
gtk_css_variable_value_unref (vars[i]);
g_free (names[i]);
}
g_free (vars);
g_free (names);
}
}
static GtkCssValue *
gtk_css_value_reference_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *result = NULL, *computed;
GtkCssRefs refs;
gtk_css_refs_init (&refs);
resolve_references (value->value, property_id, style, variables, &refs);
if (gtk_css_refs_get_size (&refs) > 0)
{
const GtkCssToken *token;
GtkCssParser *value_parser =
gtk_css_parser_new_for_token_stream (value->value,
value->file,
(GtkCssVariableValue **) refs.start,
gtk_css_refs_get_size (&refs),
parser_error, provider, NULL);
result = _gtk_style_property_parse_value (value->property, value_parser);
token = gtk_css_parser_peek_token (value_parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
char *junk;
junk = gtk_css_token_to_string (token);
gtk_css_parser_error_syntax (value_parser,
"Junk at end of %s value: %s",
value->property->name, junk);
g_free (junk);
g_clear_pointer (&result, gtk_css_value_unref);
}
gtk_css_parser_unref (value_parser);
}
gtk_css_refs_clear (&refs);
if (result == NULL)
result = _gtk_css_unset_value_new ();
if (GTK_IS_CSS_SHORTHAND_PROPERTY (value->property))
{
GtkCssValue *sub = gtk_css_value_ref (_gtk_css_array_value_get_nth (result, value->subproperty));
gtk_css_value_unref (result);
result = sub;
}
computed = _gtk_css_value_compute (result,
property_id,
provider,
style,
parent_style,
variables);
computed->is_computed = TRUE;
gtk_css_value_unref (result);
return computed;
}
static gboolean
gtk_css_value_reference_equal (const GtkCssValue *value1,
const GtkCssValue *value2)
{
return FALSE;
}
static GtkCssValue *
gtk_css_value_reference_transition (GtkCssValue *start,
GtkCssValue *end,
guint property_id,
double progress)
{
return NULL;
}
static void
gtk_css_value_reference_print (const GtkCssValue *value,
GString *string)
{
gtk_css_variable_value_print (value->value, string);
}
static const GtkCssValueClass GTK_CSS_VALUE_REFERENCE = {
"GtkCssReferenceValue",
gtk_css_value_reference_free,
gtk_css_value_reference_compute,
gtk_css_value_reference_equal,
gtk_css_value_reference_transition,
NULL,
NULL,
gtk_css_value_reference_print
};
GtkCssValue *
_gtk_css_reference_value_new (GtkStyleProperty *property,
GtkCssVariableValue *value,
GFile *file)
{
GtkCssValue *result;
result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_REFERENCE);
result->property = property;
result->value = gtk_css_variable_value_ref (value);
result->contains_variables = TRUE;
if (file)
result->file = g_object_ref (file);
else
result->file = NULL;
return result;
}
void
_gtk_css_reference_value_set_subproperty (GtkCssValue *value,
guint property)
{
g_assert (GTK_IS_CSS_SHORTHAND_PROPERTY (value->property));
value->subproperty = property;
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#pragma once
#include <gtk/css/gtkcss.h>
#include "gtkcssvalueprivate.h"
#include "gtkstylepropertyprivate.h"
#include "css/gtkcssvariablevalueprivate.h"
G_BEGIN_DECLS
GtkCssValue *_gtk_css_reference_value_new (GtkStyleProperty *property,
GtkCssVariableValue *value,
GFile *file);
void _gtk_css_reference_value_set_subproperty (GtkCssValue *value,
guint property);
G_END_DECLS

View File

@@ -34,11 +34,12 @@ gtk_css_value_repeat_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_repeat_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_repeat_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (value);
}
@@ -140,28 +141,28 @@ static struct {
GtkCssValue values[4];
} background_repeat_values[4] = {
{ "no-repeat",
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
} },
{ "repeat",
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
} },
{ "round",
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
} },
{ "space",
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_NO_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BACKGROUND_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
} }
};
@@ -234,28 +235,28 @@ static struct {
GtkCssValue values[4];
} border_repeat_values[4] = {
{ "stretch",
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_SPACE }
} },
{ "repeat",
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_SPACE }
} },
{ "round",
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_ROUND, GTK_CSS_REPEAT_STYLE_SPACE }
} },
{ "space",
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
{ { &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_STRETCH },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_REPEAT },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_ROUND },
{ &GTK_CSS_VALUE_BORDER_REPEAT, 1, TRUE, FALSE, GTK_CSS_REPEAT_STYLE_SPACE, GTK_CSS_REPEAT_STYLE_SPACE }
} }
};

View File

@@ -113,11 +113,12 @@ gtk_css_value_shadow_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_shadow_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_shadow_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
guint i;
ShadowValue *shadows;
@@ -128,11 +129,11 @@ gtk_css_value_shadow_compute (GtkCssValue *value,
{
const ShadowValue *shadow = &value->shadows[i];
shadows[i].hoffset = _gtk_css_value_compute (shadow->hoffset, property_id, provider, style, parent_style);
shadows[i].voffset = _gtk_css_value_compute (shadow->voffset, property_id, provider, style, parent_style);
shadows[i].radius = _gtk_css_value_compute (shadow->radius, property_id, provider, style, parent_style);
shadows[i].spread = _gtk_css_value_compute (shadow->spread, property_id, provider, style, parent_style),
shadows[i].color = _gtk_css_value_compute (shadow->color, property_id, provider, style, parent_style);
shadows[i].hoffset = _gtk_css_value_compute (shadow->hoffset, property_id, provider, style, parent_style, variables);
shadows[i].voffset = _gtk_css_value_compute (shadow->voffset, property_id, provider, style, parent_style, variables);
shadows[i].radius = _gtk_css_value_compute (shadow->radius, property_id, provider, style, parent_style, variables);
shadows[i].spread = _gtk_css_value_compute (shadow->spread, property_id, provider, style, parent_style, variables),
shadows[i].color = _gtk_css_value_compute (shadow->color, property_id, provider, style, parent_style, variables);
shadows[i].inset = shadow->inset;
}

View File

@@ -31,6 +31,7 @@
#include "gtkcssstringvalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkcsstransitionprivate.h"
#include "gtkcssvaluesprivate.h"
#include "gtkprivate.h"
#include "gtksettings.h"
#include "gtkstyleanimationprivate.h"
@@ -45,130 +46,6 @@ static void gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
GtkCssValue *specified,
GtkCssSection *section);
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 GET_VALUES(v) (GtkCssValue **)((guint8*)(v) + sizeof (GtkCssValues))
#define DEFINE_VALUES(ENUM, TYPE, NAME) \
@@ -322,6 +199,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 +214,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 +237,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 +266,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 +286,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 +589,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;
@@ -912,6 +833,32 @@ gtk_css_lookup_resolve (GtkCssLookup *lookup,
gtk_internal_return_if_fail (GTK_IS_CSS_STATIC_STYLE (style));
gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
if (lookup->custom_values)
{
GHashTableIter iter;
gpointer id;
GtkCssVariableValue *value;
style->variables = gtk_css_variable_set_new ();
g_hash_table_iter_init (&iter, lookup->custom_values);
while (g_hash_table_iter_next (&iter, &id, (gpointer) &value))
gtk_css_variable_set_add (style->variables, GPOINTER_TO_INT (id), value);
gtk_css_variable_set_resolve_cycles (style->variables);
if (parent_style)
{
gtk_css_variable_set_set_parent (style->variables,
parent_style->variables);
}
}
else if (parent_style && parent_style->variables)
{
style->variables = gtk_css_variable_set_ref (parent_style->variables);
}
if (_gtk_bitmask_is_empty (_gtk_css_lookup_get_set_values (lookup)))
{
style->background = (GtkCssBackgroundValues *)gtk_css_values_ref (gtk_css_background_initial_values);
@@ -1047,7 +994,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);
@@ -1068,7 +1015,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;
@@ -1085,19 +1032,34 @@ gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
*/
if (specified)
{
value = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, parent_style);
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
@@ -1107,3 +1069,15 @@ gtk_css_static_style_get_change (GtkCssStaticStyle *style)
return style->change;
}
void
gtk_css_custom_values_compute_changes_and_affects (GtkCssStyle *style1,
GtkCssStyle *style2,
GtkBitmask **changes,
GtkCssAffects *affects)
{
if (gtk_css_variable_set_equal (style1->variables, style2->variables))
return;
*changes = _gtk_bitmask_set (*changes, GTK_CSS_PROPERTY_CUSTOM, TRUE);
}

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

@@ -35,11 +35,12 @@ gtk_css_value_string_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_string_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_string_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (value);
}
@@ -226,3 +227,4 @@ _gtk_css_ident_value_get (const GtkCssValue *value)
return value->string;
}

View File

@@ -24,6 +24,7 @@
#include "gtkcssanimationprivate.h"
#include "gtkcssarrayvalueprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
#include "gtkcssenumvalueprivate.h"
#include "gtkcssinheritvalueprivate.h"
#include "gtkcssinitialvalueprivate.h"
@@ -74,6 +75,9 @@ gtk_css_style_finalize (GObject *object)
gtk_css_values_unref ((GtkCssValues *)style->size);
gtk_css_values_unref ((GtkCssValues *)style->other);
if (style->variables)
gtk_css_variable_set_unref (style->variables);
G_OBJECT_CLASS (gtk_css_style_parent_class)->finalize (object);
}
@@ -312,6 +316,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`
@@ -369,6 +382,43 @@ gtk_css_style_print (GtkCssStyle *style,
retval = TRUE;
}
if (style->variables)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
GArray *ids = gtk_css_variable_set_list_ids (style->variables);
for (i = 0; i < ids->len; i++)
{
int id = g_array_index (ids, int, i);
const char *name = gtk_css_custom_property_pool_get_name (pool, id);
GtkCssVariableSet *source;
GtkCssVariableValue *value = gtk_css_variable_set_lookup (style->variables, id, &source);
if (!value)
continue;
if (source != style->variables && skip_initial)
continue;
g_string_append_printf (string, "%*s%s: ", indent, "", name);
gtk_css_variable_value_print (value, string);
g_string_append_c (string, ';');
if (value->section)
{
g_string_append (string, " /* ");
gtk_css_section_print (value->section, string);
g_string_append (string, " */");
}
g_string_append_c (string, '\n');
}
retval = TRUE;
g_array_unref (ids);
}
return retval;
}
@@ -865,3 +915,22 @@ gtk_css_values_new (GtkCssValuesType type)
return values;
}
GtkCssVariableValue *
gtk_css_style_get_custom_property (GtkCssStyle *style,
int id)
{
if (style->variables)
return gtk_css_variable_set_lookup (style->variables, id, NULL);
return NULL;
}
GArray *
gtk_css_style_list_custom_properties (GtkCssStyle *style)
{
if (style->variables)
return gtk_css_variable_set_list_ids (style->variables);
return NULL;
}

View File

@@ -102,6 +102,12 @@ compute_change (GtkCssStyleChange *change)
change->new_style,
&change->changes,
&change->affects);
if (change->old_style->variables != change->new_style->variables)
gtk_css_custom_values_compute_changes_and_affects (change->old_style,
change->new_style,
&change->changes,
&change->affects);
}
void

View File

@@ -24,6 +24,8 @@
#include "gtk/gtkbitmaskprivate.h"
#include "gtk/gtkcssvalueprivate.h"
#include "gtk/gtkcssvariablesetprivate.h"
#include "gtk/css/gtkcssvariablevalueprivate.h"
G_BEGIN_DECLS
@@ -232,6 +234,10 @@ struct _GtkCssStyle
GtkCssTransitionValues *transition;
GtkCssSizeValues *size;
GtkCssOtherValues *other;
GtkCssVariableSet *variables;
GtkCssValue *variable_values;
int n_variable_values;
};
struct _GtkCssStyleClass
@@ -246,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;
@@ -257,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,
@@ -271,6 +283,10 @@ PangoFontDescription * gtk_css_style_get_pango_font (GtkCssStyle
void gtk_css_style_lookup_symbolic_colors (GtkCssStyle *style,
GdkRGBA color_out[4]);
GtkCssVariableValue * gtk_css_style_get_custom_property (GtkCssStyle *style,
int id);
GArray * gtk_css_style_list_custom_properties (GtkCssStyle *style);
GtkCssValues *gtk_css_values_new (GtkCssValuesType type);
GtkCssValues *gtk_css_values_ref (GtkCssValues *values);
void gtk_css_values_unref (GtkCssValues *values);
@@ -320,6 +336,10 @@ void gtk_css_other_values_compute_changes_and_affects (GtkCssStyle *style1,
GtkCssStyle *style2,
GtkBitmask **changes,
GtkCssAffects *affects);
void gtk_css_custom_values_compute_changes_and_affects (GtkCssStyle *style1,
GtkCssStyle *style2,
GtkBitmask **changes,
GtkCssAffects *affects);
G_END_DECLS

View File

@@ -273,12 +273,13 @@ gtk_css_value_transform_free (GtkCssValue *value)
/* returns TRUE if dest == src */
static gboolean
gtk_css_transform_compute (GtkCssTransform *dest,
GtkCssTransform *src,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_transform_compute (GtkCssTransform *dest,
GtkCssTransform *src,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
dest->type = src->type;
@@ -288,41 +289,41 @@ gtk_css_transform_compute (GtkCssTransform *dest,
memcpy (dest, src, sizeof (GtkCssTransform));
return TRUE;
case GTK_CSS_TRANSFORM_TRANSLATE:
dest->translate.x = _gtk_css_value_compute (src->translate.x, property_id, provider, style, parent_style);
dest->translate.y = _gtk_css_value_compute (src->translate.y, property_id, provider, style, parent_style);
dest->translate.z = _gtk_css_value_compute (src->translate.z, property_id, provider, style, parent_style);
dest->translate.x = _gtk_css_value_compute (src->translate.x, property_id, provider, style, parent_style, variables);
dest->translate.y = _gtk_css_value_compute (src->translate.y, property_id, provider, style, parent_style, variables);
dest->translate.z = _gtk_css_value_compute (src->translate.z, property_id, provider, style, parent_style, variables);
return dest->translate.x == src->translate.x
&& dest->translate.y == src->translate.y
&& dest->translate.z == src->translate.z;
case GTK_CSS_TRANSFORM_ROTATE:
dest->rotate.x = _gtk_css_value_compute (src->rotate.x, property_id, provider, style, parent_style);
dest->rotate.y = _gtk_css_value_compute (src->rotate.y, property_id, provider, style, parent_style);
dest->rotate.z = _gtk_css_value_compute (src->rotate.z, property_id, provider, style, parent_style);
dest->rotate.angle = _gtk_css_value_compute (src->rotate.angle, property_id, provider, style, parent_style);
dest->rotate.x = _gtk_css_value_compute (src->rotate.x, property_id, provider, style, parent_style, variables);
dest->rotate.y = _gtk_css_value_compute (src->rotate.y, property_id, provider, style, parent_style, variables);
dest->rotate.z = _gtk_css_value_compute (src->rotate.z, property_id, provider, style, parent_style, variables);
dest->rotate.angle = _gtk_css_value_compute (src->rotate.angle, property_id, provider, style, parent_style, variables);
return dest->rotate.x == src->rotate.x
&& dest->rotate.y == src->rotate.y
&& dest->rotate.z == src->rotate.z
&& dest->rotate.angle == src->rotate.angle;
case GTK_CSS_TRANSFORM_SCALE:
dest->scale.x = _gtk_css_value_compute (src->scale.x, property_id, provider, style, parent_style);
dest->scale.y = _gtk_css_value_compute (src->scale.y, property_id, provider, style, parent_style);
dest->scale.z = _gtk_css_value_compute (src->scale.z, property_id, provider, style, parent_style);
dest->scale.x = _gtk_css_value_compute (src->scale.x, property_id, provider, style, parent_style, variables);
dest->scale.y = _gtk_css_value_compute (src->scale.y, property_id, provider, style, parent_style, variables);
dest->scale.z = _gtk_css_value_compute (src->scale.z, property_id, provider, style, parent_style, variables);
return dest->scale.x == src->scale.x
&& dest->scale.y == src->scale.y
&& dest->scale.z == src->scale.z;
case GTK_CSS_TRANSFORM_SKEW:
dest->skew.x = _gtk_css_value_compute (src->skew.x, property_id, provider, style, parent_style);
dest->skew.y = _gtk_css_value_compute (src->skew.y, property_id, provider, style, parent_style);
dest->skew.x = _gtk_css_value_compute (src->skew.x, property_id, provider, style, parent_style, variables);
dest->skew.y = _gtk_css_value_compute (src->skew.y, property_id, provider, style, parent_style, variables);
return dest->skew.x == src->skew.x
&& dest->skew.y == src->skew.y;
case GTK_CSS_TRANSFORM_SKEW_X:
dest->skew_x.skew = _gtk_css_value_compute (src->skew_x.skew, property_id, provider, style, parent_style);
dest->skew_x.skew = _gtk_css_value_compute (src->skew_x.skew, property_id, provider, style, parent_style, variables);
return dest->skew_x.skew == src->skew_x.skew;
case GTK_CSS_TRANSFORM_SKEW_Y:
dest->skew_y.skew = _gtk_css_value_compute (src->skew_y.skew, property_id, provider, style, parent_style);
dest->skew_y.skew = _gtk_css_value_compute (src->skew_y.skew, property_id, provider, style, parent_style, variables);
return dest->skew_y.skew == src->skew_y.skew;
case GTK_CSS_TRANSFORM_PERSPECTIVE:
dest->perspective.depth = _gtk_css_value_compute (src->perspective.depth, property_id, provider, style, parent_style);
dest->perspective.depth = _gtk_css_value_compute (src->perspective.depth, property_id, provider, style, parent_style, variables);
return dest->perspective.depth == src->perspective.depth;
case GTK_CSS_TRANSFORM_NONE:
default:
@@ -332,11 +333,12 @@ gtk_css_transform_compute (GtkCssTransform *dest,
}
static GtkCssValue *
gtk_css_value_transform_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_transform_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *result;
gboolean changes;
@@ -356,7 +358,8 @@ gtk_css_value_transform_compute (GtkCssValue *value,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
}
if (!changes)
@@ -801,7 +804,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_TRANSFORM = {
gtk_css_value_transform_print
};
static GtkCssValue transform_none_singleton = { &GTK_CSS_VALUE_TRANSFORM, 1, TRUE, 0, { { GTK_CSS_TRANSFORM_NONE } } };
static GtkCssValue transform_none_singleton = { &GTK_CSS_VALUE_TRANSFORM, 1, TRUE, FALSE, 0, { { GTK_CSS_TRANSFORM_NONE } } };
static GtkCssValue *
gtk_css_transform_value_alloc (guint n_transforms)

View File

@@ -277,7 +277,8 @@ enum { /*< skip >*/
GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS,
GTK_CSS_PROPERTY_LINE_HEIGHT,
/* add more */
GTK_CSS_PROPERTY_N_PROPERTIES
GTK_CSS_PROPERTY_N_PROPERTIES,
GTK_CSS_PROPERTY_CUSTOM,
};
typedef enum /*< skip >*/ {

View File

@@ -35,11 +35,12 @@ gtk_css_value_unset_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_unset_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_unset_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssStyleProperty *property;
GtkCssValue *unset_value;
@@ -55,7 +56,8 @@ gtk_css_value_unset_compute (GtkCssValue *value,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
}
static gboolean

View File

@@ -199,6 +199,7 @@ gtk_css_value_unref (GtkCssValue *value)
* @provider: Style provider for looking up extra information
* @style: Style to compute for
* @parent_style: parent style to use for inherited values
* @variables: an additional set of variables to use along with @style
*
* Converts the specified @value into the computed value for the CSS
* property given by @property_id using the information in @context.
@@ -208,11 +209,12 @@ gtk_css_value_unref (GtkCssValue *value)
* Returns: the computed value
**/
GtkCssValue *
_gtk_css_value_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
_gtk_css_value_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
if (gtk_css_value_is_computed (value))
return _gtk_css_value_ref (value);
@@ -221,7 +223,7 @@ _gtk_css_value_compute (GtkCssValue *value,
get_accounting_data (value->class->type_name)->computed++;
#endif
return value->class->compute (value, property_id, provider, style, parent_style);
return value->class->compute (value, property_id, provider, style, parent_style, variables);
}
gboolean
@@ -367,3 +369,9 @@ gtk_css_value_is_computed (const GtkCssValue *value)
{
return value->is_computed;
}
gboolean
gtk_css_value_contains_variables (const GtkCssValue *value)
{
return value->contains_variables;
}

View File

@@ -22,6 +22,7 @@
#include <glib-object.h>
#include "gtkcsstypesprivate.h"
#include "gtkcssvariablesetprivate.h"
#include "gtkstyleprovider.h"
G_BEGIN_DECLS
@@ -37,7 +38,8 @@ typedef struct _GtkCssValueClass GtkCssValueClass;
#define GTK_CSS_VALUE_BASE \
const GtkCssValueClass *class; \
int ref_count; \
guint is_computed: 1;
guint is_computed: 1; \
guint contains_variables: 1;
struct _GtkCssValueClass {
const char *type_name;
@@ -47,7 +49,8 @@ struct _GtkCssValueClass {
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style);
GtkCssStyle *parent_style,
GtkCssVariableSet *variables);
gboolean (* equal) (const GtkCssValue *value1,
const GtkCssValue *value2);
GtkCssValue * (* transition) (GtkCssValue *start,
@@ -76,7 +79,8 @@ GtkCssValue *_gtk_css_value_compute (GtkCssValue
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style) G_GNUC_PURE;
GtkCssStyle *parent_style,
GtkCssVariableSet *variables) G_GNUC_PURE;
gboolean _gtk_css_value_equal (const GtkCssValue *value1,
const GtkCssValue *value2) G_GNUC_PURE;
gboolean _gtk_css_value_equal0 (const GtkCssValue *value1,
@@ -93,6 +97,7 @@ char * _gtk_css_value_to_string (const GtkCssValue
void _gtk_css_value_print (const GtkCssValue *value,
GString *string);
gboolean gtk_css_value_is_computed (const GtkCssValue *value) G_GNUC_PURE;
gboolean gtk_css_value_contains_variables (const GtkCssValue *value) G_GNUC_PURE;
G_END_DECLS

151
gtk/gtkcssvaluesprivate.h Normal file
View File

@@ -0,0 +1,151 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#pragma once
#include <glib-object.h>
G_BEGIN_DECLS
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,
};
G_END_DECLS

359
gtk/gtkcssvariableset.c Normal file
View File

@@ -0,0 +1,359 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#include "gtkcssvariablesetprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
static void
unref_custom_property_name (gpointer pointer)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
gtk_css_custom_property_pool_unref (pool, GPOINTER_TO_INT (pointer));
}
static void
maybe_unref_variable (gpointer pointer)
{
if (pointer != NULL)
gtk_css_variable_value_unref (pointer);
}
GtkCssVariableSet *
gtk_css_variable_set_new (void)
{
GtkCssVariableSet *self = g_new0 (GtkCssVariableSet, 1);
self->ref_count = 1;
self->variables = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
unref_custom_property_name,
maybe_unref_variable);
return self;
}
GtkCssVariableSet *
gtk_css_variable_set_ref (GtkCssVariableSet *self)
{
self->ref_count++;
return self;
}
void
gtk_css_variable_set_unref (GtkCssVariableSet *self)
{
self->ref_count--;
if (self->ref_count > 0)
return;
g_hash_table_unref (self->variables);
g_clear_pointer (&self->parent, gtk_css_variable_set_unref);
g_free (self);
}
GtkCssVariableSet *
gtk_css_variable_set_copy (GtkCssVariableSet *self)
{
GtkCssVariableSet *ret = gtk_css_variable_set_new ();
GHashTableIter iter;
gpointer id;
GtkCssVariableValue *value;
g_hash_table_iter_init (&iter, self->variables);
while (g_hash_table_iter_next (&iter, &id, (gpointer) &value))
gtk_css_variable_set_add (ret, GPOINTER_TO_INT (id), value);
gtk_css_variable_set_set_parent (ret, self->parent);
return ret;
}
void
gtk_css_variable_set_set_parent (GtkCssVariableSet *self,
GtkCssVariableSet *parent)
{
if (self->parent)
gtk_css_variable_set_unref (self->parent);
self->parent = parent;
if (self->parent)
gtk_css_variable_set_ref (self->parent);
}
void
gtk_css_variable_set_add (GtkCssVariableSet *self,
int id,
GtkCssVariableValue *value)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
g_hash_table_insert (self->variables,
GINT_TO_POINTER (gtk_css_custom_property_pool_ref (pool, id)),
value ? gtk_css_variable_value_ref (value) : NULL);
}
static gboolean check_variable (GtkCssVariableSet *self,
GHashTable *unvisited_variables,
GArray *stack,
int id,
GtkCssVariableValue *value);
static gboolean
check_references (GtkCssVariableSet *self,
GHashTable *unvisited_variables,
GArray *stack,
GtkCssVariableValue *value)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
int i;
for (i = 0; i < value->n_references; i++)
{
GtkCssVariableValueReference *ref = &value->references[i];
int ref_id = gtk_css_custom_property_pool_lookup (pool, ref->name);
if (g_hash_table_contains (unvisited_variables, GINT_TO_POINTER (ref_id)))
{
GtkCssVariableValue *ref_value;
ref_value = g_hash_table_lookup (self->variables, GINT_TO_POINTER (ref_id));
if (check_variable (self, unvisited_variables, stack, ref_id, ref_value))
return TRUE;
}
if (ref->fallback)
{
if (check_references (self, unvisited_variables, stack, ref->fallback))
return TRUE;
}
}
return FALSE;
}
static gboolean
check_variable (GtkCssVariableSet *self,
GHashTable *unvisited_variables,
GArray *stack,
int id,
GtkCssVariableValue *value)
{
int i;
g_array_append_val (stack, id);
for (i = stack->len - 2; i >= 0; i--)
{
/* Found a cycle, stop checking */
if (id == g_array_index (stack, int, i))
return TRUE;
}
if (check_references (self, unvisited_variables, stack, value))
return TRUE;
g_array_remove_index_fast (stack, stack->len - 1);
g_hash_table_remove (unvisited_variables, GINT_TO_POINTER (id));
return FALSE;
}
void
gtk_css_variable_set_resolve_cycles (GtkCssVariableSet *self)
{
GHashTable *variables = g_hash_table_new (g_direct_hash, g_direct_equal);
GHashTable *unvisited_variables = g_hash_table_new (g_direct_hash, g_direct_equal);
GArray *stack;
GHashTableIter iter;
gpointer id;
GtkCssVariableValue *value;
stack = g_array_new (FALSE, FALSE, sizeof (int));
g_hash_table_iter_init (&iter, self->variables);
while (g_hash_table_iter_next (&iter, &id, (gpointer) &value))
{
/* Have 2 copies of self->variables: "variables" can be iterated safely as
* we remove values, and "unvisited_variables" as a visited node marker
* for DFS */
g_hash_table_insert (variables, id, value);
g_hash_table_add (unvisited_variables, id);
}
g_hash_table_iter_init (&iter, variables);
while (g_hash_table_iter_next (&iter, &id, (gpointer) &value))
{
if (!g_hash_table_contains (unvisited_variables, id))
continue;
if (!g_hash_table_contains (self->variables, id))
continue;
if (check_variable (self, unvisited_variables, stack, GPOINTER_TO_INT (id), value))
{
int i;
/* Found a cycle, remove the offending variables */
for (i = stack->len - 2; i >= 0; i--)
{
int id_to_remove = g_array_index (stack, int, i);
g_hash_table_remove (self->variables, GINT_TO_POINTER (id_to_remove));
if (g_array_index (stack, int, i) == g_array_index (stack, int, stack->len - 1))
break;
}
g_array_remove_range (stack, 0, stack->len);
}
}
g_array_unref (stack);
g_hash_table_unref (variables);
g_hash_table_unref (unvisited_variables);
}
GtkCssVariableValue *
gtk_css_variable_set_lookup (GtkCssVariableSet *self,
int id,
GtkCssVariableSet **source)
{
GtkCssVariableValue *ret = g_hash_table_lookup (self->variables, GINT_TO_POINTER (id));
if (ret)
{
if (source)
*source = self;
return ret;
}
if (self->parent)
return gtk_css_variable_set_lookup (self->parent, id, source);
if (source)
*source = NULL;
return NULL;
}
static void
list_ids_recursive (GtkCssVariableSet *self,
GHashTable *table)
{
GHashTableIter iter;
gpointer id;
if (self->parent)
list_ids_recursive (self->parent, table);
g_hash_table_iter_init (&iter, self->variables);
while (g_hash_table_iter_next (&iter, &id, NULL))
g_hash_table_add (table, id);
}
static int
compare_ids (gconstpointer a, gconstpointer b, gpointer user_data)
{
GtkCssCustomPropertyPool *pool = user_data;
int id1 = GPOINTER_TO_INT (*((const int *) a));
int id2 = GPOINTER_TO_INT (*((const int *) b));
const char *name1, *name2;
name1 = gtk_css_custom_property_pool_get_name (pool, id1);
name2 = gtk_css_custom_property_pool_get_name (pool, id2);
return strcmp (name1, name2);
}
GArray *
gtk_css_variable_set_list_ids (GtkCssVariableSet *self)
{
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
GArray *ret = g_array_new (FALSE, FALSE, sizeof (int));
GHashTable *all_ids;
GHashTableIter iter;
gpointer id;
all_ids = g_hash_table_new (g_direct_hash, g_direct_equal);
list_ids_recursive (self, all_ids);
g_hash_table_iter_init (&iter, all_ids);
while (g_hash_table_iter_next (&iter, &id, NULL))
g_array_append_val (ret, id);
g_hash_table_unref (all_ids);
g_array_sort_with_data (ret, compare_ids, pool);
return ret;
}
gboolean
gtk_css_variable_set_equal (GtkCssVariableSet *set1,
GtkCssVariableSet *set2)
{
GHashTableIter iter;
gpointer id;
GtkCssVariableValue *value1;
if (set1 == set2)
return TRUE;
if (set1 == NULL || set2 == NULL)
return FALSE;
if (g_hash_table_size (set1->variables) != g_hash_table_size (set2->variables))
return FALSE;
if (set1->parent != set2->parent)
return FALSE;
g_hash_table_iter_init (&iter, set2->variables);
while (g_hash_table_iter_next (&iter, &id, NULL))
{
if (!g_hash_table_contains (set1->variables, id))
return FALSE;
}
g_hash_table_iter_init (&iter, set1->variables);
while (g_hash_table_iter_next (&iter, &id, (gpointer) &value1))
{
GtkCssVariableValue *value2 = g_hash_table_lookup (set2->variables, id);
if (value2 == NULL)
return FALSE;
if (!gtk_css_variable_value_equal (value1, value2))
return FALSE;
}
return TRUE;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#pragma once
#include "gtk/css/gtkcssvariablevalueprivate.h"
G_BEGIN_DECLS
typedef struct _GtkCssVariableSet GtkCssVariableSet;
struct _GtkCssVariableSet
{
int ref_count;
GHashTable *variables;
GtkCssVariableSet *parent;
};
GtkCssVariableSet * gtk_css_variable_set_new (void);
GtkCssVariableSet * gtk_css_variable_set_ref (GtkCssVariableSet *self);
void gtk_css_variable_set_unref (GtkCssVariableSet *self);
GtkCssVariableSet * gtk_css_variable_set_copy (GtkCssVariableSet *self);
void gtk_css_variable_set_set_parent (GtkCssVariableSet *self,
GtkCssVariableSet *parent);
void gtk_css_variable_set_add (GtkCssVariableSet *self,
int id,
GtkCssVariableValue *value);
void gtk_css_variable_set_resolve_cycles (GtkCssVariableSet *self);
GtkCssVariableValue *gtk_css_variable_set_lookup (GtkCssVariableSet *self,
int id,
GtkCssVariableSet **source);
GArray * gtk_css_variable_set_list_ids (GtkCssVariableSet *self);
gboolean gtk_css_variable_set_equal (GtkCssVariableSet *set1,
GtkCssVariableSet *set2);
G_END_DECLS

View File

@@ -208,6 +208,29 @@ gtk_style_cascade_lookup (GtkStyleProvider *provider,
gtk_style_cascade_iter_clear (&iter);
}
static void
gtk_style_cascade_emit_error (GtkStyleProvider *provider,
GtkCssSection *section,
const GError *error)
{
GtkStyleCascade *cascade = GTK_STYLE_CASCADE (provider);
GtkStyleCascadeIter iter;
GtkStyleProvider *item;
for (item = gtk_style_cascade_iter_init (cascade, &iter);
item;
item = gtk_style_cascade_iter_next (cascade, &iter))
{
if (gtk_style_provider_has_section (item, section))
{
gtk_style_provider_emit_error (item, section, (GError *) error);
break;
}
}
gtk_style_cascade_iter_clear (&iter);
}
static void
gtk_style_cascade_provider_iface_init (GtkStyleProviderInterface *iface)
{
@@ -216,6 +239,7 @@ gtk_style_cascade_provider_iface_init (GtkStyleProviderInterface *iface)
iface->get_scale = gtk_style_cascade_get_scale;
iface->get_keyframes = gtk_style_cascade_get_keyframes;
iface->lookup = gtk_style_cascade_lookup;
iface->emit_error = gtk_style_cascade_emit_error;
}
G_DEFINE_TYPE_EXTENDED (GtkStyleCascade, _gtk_style_cascade, G_TYPE_OBJECT, 0,

View File

@@ -170,6 +170,19 @@ gtk_style_provider_emit_error (GtkStyleProvider *provider,
iface->emit_error (provider, section, error);
}
gboolean
gtk_style_provider_has_section (GtkStyleProvider *provider,
GtkCssSection *section)
{
GtkStyleProviderInterface *iface;
iface = GTK_STYLE_PROVIDER_GET_INTERFACE (provider);
if (iface->has_section)
return iface->has_section (provider, section);
return FALSE;
}
/* These apis are misnamed, and the rest of GtkStyleContext is deprecated,
* so put them here for now
@@ -230,4 +243,3 @@ gtk_style_context_remove_provider_for_display (GdkDisplay *display,
cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_display (display), 1);
_gtk_style_cascade_remove_provider (cascade, provider);
}

View File

@@ -52,6 +52,8 @@ struct _GtkStyleProviderInterface
const GError *error);
/* signal */
void (* changed) (GtkStyleProvider *provider);
gboolean (* has_section) (GtkStyleProvider *provider,
GtkCssSection *section);
};
GtkSettings * gtk_style_provider_get_settings (GtkStyleProvider *provider);
@@ -71,6 +73,8 @@ void gtk_style_provider_changed (GtkStyleProvid
void gtk_style_provider_emit_error (GtkStyleProvider *provider,
GtkCssSection *section,
GError *error);
gboolean gtk_style_provider_has_section (GtkStyleProvider *provider,
GtkCssSection *section);
G_END_DECLS

View File

@@ -28,6 +28,7 @@
#include "gtklabel.h"
#include "gtk/gtkwidgetprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
#include "gtkcssproviderprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkcssstyleprivate.h"
@@ -600,6 +601,33 @@ bind_node_state (GtkSignalListItemFactory *factory,
g_free (text);
}
static int
compare_name_cb (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
const CssProperty *prop_a = a;
const CssProperty *prop_b = b;
gboolean a_var = prop_a->name[0] == '-' && prop_a->name[1] == '-';
gboolean b_var = prop_b->name[0] == '-' && prop_b->name[1] == '-';
gboolean a_gtk = prop_a->name[0] == '-' && prop_a->name[1] != '-';
gboolean b_gtk = prop_b->name[0] == '-' && prop_b->name[1] != '-';
int ret;
if (a_var && !b_var)
ret = 1;
else if (b_var && !a_var)
ret = -1;
else if (a_gtk && !b_gtk)
ret = 1;
else if (b_gtk && !a_gtk)
ret = -1;
else
ret = g_utf8_collate (prop_a->name, prop_b->name);
return gtk_ordering_from_cmpfunc (ret);
}
static void
gtk_inspector_css_node_tree_init (GtkInspectorCssNodeTree *cnt)
{
@@ -676,7 +704,7 @@ gtk_inspector_css_node_tree_init (GtkInspectorCssNodeTree *cnt)
g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_name), NULL);
gtk_column_view_column_set_factory (column, factory);
sorter = GTK_SORTER (gtk_string_sorter_new (gtk_property_expression_new (css_property_get_type (), NULL, "name")));
sorter = GTK_SORTER (gtk_custom_sorter_new ((GCompareDataFunc) compare_name_cb, NULL, NULL));
gtk_column_view_column_set_sorter (column, sorter);
gtk_column_view_sort_by_column (GTK_COLUMN_VIEW (priv->prop_tree), column, GTK_SORT_ASCENDING);
g_object_unref (sorter);
@@ -773,9 +801,14 @@ gtk_inspector_css_node_tree_update_style (GtkInspectorCssNodeTree *cnt,
GtkCssStyle *new_style)
{
GtkInspectorCssNodeTreePrivate *priv = cnt->priv;
int i;
GtkCssCustomPropertyPool *pool = gtk_css_custom_property_pool_get ();
GArray *custom_props;
int i, n, n_props;
for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
n_props = _gtk_css_style_property_get_n_properties ();
n = g_list_model_get_n_items (G_LIST_MODEL (priv->prop_model));
for (i = 0; i < n_props; i++)
{
GtkCssStyleProperty *prop;
const char *name;
@@ -809,6 +842,47 @@ gtk_inspector_css_node_tree_update_style (GtkInspectorCssNodeTree *cnt,
g_free (location);
g_free (value);
}
g_list_store_splice (priv->prop_model, n_props, n - n_props, NULL, 0);
if (new_style)
{
custom_props = gtk_css_style_list_custom_properties (new_style);
if (custom_props)
{
for (i = 0; i < custom_props->len; i++)
{
GtkCssVariableValue *var_value;
int id;
const char *name;
GtkCssSection *section;
char *location;
char *value;
CssProperty *property;
id = g_array_index (custom_props, int, i);
name = gtk_css_custom_property_pool_get_name (pool, id);
var_value = gtk_css_style_get_custom_property (new_style, id);
value = gtk_css_variable_value_to_string (var_value);
section = var_value->section;
if (section)
location = gtk_css_section_to_string (section);
else
location = NULL;
property = css_property_new (name, value, location);
g_list_store_append (priv->prop_model, property);
g_free (location);
g_free (value);
}
g_array_unref (custom_props);
}
}
}
static void

View File

@@ -53,6 +53,7 @@ gtk_private_sources = files([
'gtkcsscalcvalue.c',
'gtkcsscolorvalue.c',
'gtkcsscornervalue.c',
'gtkcsscustompropertypool.c',
'gtkcssdimensionvalue.c',
'gtkcssdynamic.c',
'gtkcsseasevalue.c',
@@ -84,6 +85,7 @@ gtk_private_sources = files([
'gtkcssnumbervalue.c',
'gtkcsspalettevalue.c',
'gtkcsspositionvalue.c',
'gtkcssreferencevalue.c',
'gtkcssrepeatvalue.c',
'gtkcssselector.c',
'gtkcssshadowvalue.c',
@@ -101,6 +103,7 @@ gtk_private_sources = files([
'gtkcsstypes.c',
'gtkcssunsetvalue.c',
'gtkcssvalue.c',
'gtkcssvariableset.c',
'gtkcsswidgetnode.c',
'gtkdrop.c',
'gtkfilechooserentry.c',

View File

@@ -0,0 +1,14 @@
/* test variable changes */
box {
--test: red;
color: var(--test, green);
}
label:hover {
--test: blue;
}
label:active {
--test: initial;
}

View File

@@ -0,0 +1,3 @@
window.background:dir(ltr)
box.horizontal:dir(ltr) name
label.a:dir(ltr) name|state|hover

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="decorated">0</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<child>
<object class="GtkLabel">
<style><class name="a"/></style>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -606,6 +606,23 @@ test_data = [
'value-none.css',
'value-none.errors',
'value-none.ref.css',
'variables.css',
'variables.ref.css',
'variables-invalid-01.css',
'variables-invalid-01.errors',
'variables-invalid-01.ref.css',
'variables-invalid-02.css',
'variables-invalid-02.errors',
'variables-invalid-02.ref.css',
'variables-invalid-03.css',
'variables-invalid-03.errors',
'variables-invalid-03.ref.css',
'variables-invalid-04.css',
'variables-invalid-04.errors',
'variables-invalid-04.ref.css',
'variables-invalid-05.css',
'variables-invalid-05.errors',
'variables-invalid-05.ref.css',
]
foreach testname : test_data

View File

@@ -0,0 +1,3 @@
label {
color: var(
}

View File

@@ -0,0 +1,5 @@
variables-invalid-01.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-01.css:2:10-14: error: GTK_CSS_PARSER_ERROR_SYNTAX
variables-invalid-01.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-01.css:2:3-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-01.css:1:7-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX

View File

@@ -0,0 +1,3 @@
label {
color: var(color);
}

View File

@@ -0,0 +1 @@
variables-invalid-02.css:2:10-14: error: GTK_CSS_PARSER_ERROR_SYNTAX

View File

@@ -0,0 +1,3 @@
label {
color: var(color
}

View File

@@ -0,0 +1,5 @@
variables-invalid-03.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-03.css:2:10-14: error: GTK_CSS_PARSER_ERROR_SYNTAX
variables-invalid-03.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-03.css:2:3-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-03.css:1:7-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX

View File

@@ -0,0 +1,3 @@
label {
color: var(color,
}

View File

@@ -0,0 +1,5 @@
variables-invalid-04.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-04.css:2:10-14: error: GTK_CSS_PARSER_ERROR_SYNTAX
variables-invalid-04.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-04.css:2:3-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-04.css:1:7-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX

View File

@@ -0,0 +1,3 @@
label {
color: var(color, var()
}

View File

@@ -0,0 +1,5 @@
variables-invalid-05.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-05.css:2:10-14: error: GTK_CSS_PARSER_ERROR_SYNTAX
variables-invalid-05.css:2:10-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-05.css:2:3-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX
variables-invalid-05.css:1:7-4:1: error: GTK_CSS_PARSER_WARNING_SYNTAX

View File

@@ -0,0 +1,14 @@
:root {
--color1: red;
--color2: initial;
}
label {
color: var(--color1);
background-color: var(--color2, green);
}
@keyframes aaaa {
from { --test: red; --test2: green; }
to { --test: blue; --test3: cyan; }
}

View File

@@ -0,0 +1,20 @@
@keyframes aaaa {
from {
--test: red;
--test2: green;
}
to {
--test: blue;
--test3: cyan;
}
}
label {
background-color: var(--color2, green);
color: var(--color1);
}
:root {
--color1: red;
--color2: initial;
}

View File

@@ -0,0 +1,147 @@
:root {
--color1: red;
--not-a-color: 20px;
/* A dependency cycle */
--test1: var(--test2);
--test2: var(--test1);
}
.label-1 {
color: var(--color1);
/* Fallback is unused when the variable resolves */
background-color: var(--color1, green);
/* Nested fallbacks */
box-shadow: inset 0 0 3px var(--color2, var(--color3, green));
}
.label-2 {
/* Overriding variables */
--color1: yellow;
color: var(--color1);
/* Nonexistent variable, so the fallback is used */
background-color: var(--color2, green);
/* Variables are case-sensitive */
box-shadow: inset 0 0 3px var(--Color1, green);
}
.label-3 {
/* Unsetting variables */
--color1: initial;
color: var(--color1, green);
/* Shorthand properties */
--border1: 3px;
--border2: solid red;
border: var(--border1, 4px) var(--border2);
}
.label-4 {
/* --test1 is a part of a dependency cycle */
/* See https://www.w3.org/TR/css-variables-1/#cycles */
color: var(--test1, green);
/* A dependency cycle with a fallback, the variable is invalid anyway */
--test3: var(--test3, green);
background-color: var(--test3, purple);
}
.label-5 {
/* Not a dependency cycle since we've overridden --test1. --test2 is still bad */
--test1: red;
color: var(--test1, green);
background-color: var(--test2, green);
--prop1: lol;
--prop2: var(--prop1) var(--prop1);
--prop3: var(--prop2) var(--prop2);
--prop4: var(--prop3) var(--prop3);
--prop5: var(--prop4) var(--prop4);
--prop6: var(--prop5) var(--prop5);
--prop7: var(--prop6) var(--prop6);
--prop8: var(--prop7) var(--prop7);
--prop9: var(--prop8) var(--prop8);
--prop10: var(--prop9) var(--prop9);
--prop11: var(--prop10) var(--prop10);
--prop12: var(--prop11) var(--prop11);
--prop13: var(--prop12) var(--prop12);
--prop14: var(--prop13) var(--prop13);
--prop15: var(--prop14) var(--prop14);
--prop16: var(--prop15) var(--prop15);
--prop17: var(--prop16) var(--prop16);
--prop18: var(--prop17) var(--prop17);
--prop19: var(--prop18) var(--prop18);
--prop20: var(--prop19) var(--prop19);
/* Fallback is used since --prop20 is too long */
/* See https://www.w3.org/TR/css-variables-1/#long-variables */
box-shadow: inset 0 0 3px var(--prop20, green);
}
.label-6 {
all: unset;
/* Should still be red, since variables are not unset by that */
color: var(--color1, green);
}
.label-7 {
/* Empty fallback */
color: var(--color2,) var(--color1);
background-color: red;
}
.label-7 {
/* Invalid variable, but this declaration still wins over the one above */
background-color: var(--not-a-color);
}
@keyframes test {
from {
--test1: red;
--test2: blue;
--duration: 2s;
--padding-right: 10px;
padding-left: var(--padding1, 10px);
padding-right: var(--padding-right);
}
to {
--test1: blue;
--test3: red;
--duration: 3s;
padding-left: var(--padding2, 20px);
}
}
.label-8 {
/* FIXME: this is only there because properties that are only in keyframes */
/* won't get printed otherwise */
padding-left: 0;
padding-right: 0;
--padding1: 1px;
--padding2: 2px;
/* We're testing the initial state */
animation: test 10s infinite linear;
/* This gets overridden by the animation */
--test1: pink;
color: var(--test1, yellow);
/* Only defined in the initial state, still fine */
background-color: var(--test2, yellow);
/* Variables only defined later in the animation -> invalid */
box-shadow: inset 0 0 3px var(--test3, yellow);
/* --duration is animation-tainted and so is --duration2, this should be 5s */
--duration2: var(--duration, 4s);
transition-duration: var(--duration2, 5s);
}

View File

@@ -0,0 +1,189 @@
window.background:dir(ltr)
--color1: red; /* variables.css:2:3-17 */
--not-a-color: 20px; /* variables.css:3:3-23 */
box.horizontal:dir(ltr)
--color1: red; /* variables.css:2:3-17 */
--not-a-color: 20px; /* variables.css:3:3-23 */
label.label-1:dir(ltr)
color: rgb(255,0,0); /* variables.css:11:3-24 */
background-color: rgb(255,0,0); /* variables.css:14:3-42 */
box-shadow: 0 0 3px rgb(0,128,0) inset; /* variables.css:17:3-65 */
--color1: red; /* variables.css:2:3-17 */
--not-a-color: 20px; /* variables.css:3:3-23 */
label.label-2:dir(ltr)
color: rgb(255,255,0); /* variables.css:23:3-24 */
background-color: rgb(0,128,0); /* variables.css:26:3-42 */
box-shadow: 0 0 3px rgb(0,128,0) inset; /* variables.css:29:3-50 */
--color1: yellow; /* variables.css:22:3-20 */
label.label-3:dir(ltr)
color: rgb(0,128,0); /* variables.css:35:3-31 */
border-top-style: solid; /* variables.css:40:3-46 */
border-top-width: 3px; /* variables.css:40:3-46 */
border-left-style: solid; /* variables.css:40:3-46 */
border-left-width: 3px; /* variables.css:40:3-46 */
border-bottom-style: solid; /* variables.css:40:3-46 */
border-bottom-width: 3px; /* variables.css:40:3-46 */
border-right-style: solid; /* variables.css:40:3-46 */
border-right-width: 3px; /* variables.css:40:3-46 */
border-top-color: rgb(255,0,0); /* variables.css:40:3-46 */
border-right-color: rgb(255,0,0); /* variables.css:40:3-46 */
border-bottom-color: rgb(255,0,0); /* variables.css:40:3-46 */
border-left-color: rgb(255,0,0); /* variables.css:40:3-46 */
border-image-source: none; /* variables.css:40:3-46 */
border-image-repeat: stretch; /* variables.css:40:3-46 */
border-image-slice: 100%; /* variables.css:40:3-46 */
border-image-width: 1; /* variables.css:40:3-46 */
--border1: 3px; /* variables.css:38:3-18 */
--border2: solid red; /* variables.css:39:3-24 */
--color1: initial; /* variables.css:34:3-21 */
label.label-4:dir(ltr)
color: rgb(0,128,0); /* variables.css:46:3-30 */
background-color: rgb(128,0,128); /* variables.css:50:3-42 */
label.label-5:dir(ltr)
color: rgb(255,0,0); /* variables.css:56:3-30 */
background-color: rgb(0,128,0); /* variables.css:57:3-41 */
box-shadow: 0 0 3px rgb(0,128,0) inset; /* variables.css:82:3-50 */
--prop1: lol; /* variables.css:59:3-16 */
--prop10: var(--prop9) var(--prop9); /* variables.css:68:3-39 */
--prop11: var(--prop10) var(--prop10); /* variables.css:69:3-41 */
--prop12: var(--prop11) var(--prop11); /* variables.css:70:3-41 */
--prop13: var(--prop12) var(--prop12); /* variables.css:71:3-41 */
--prop14: var(--prop13) var(--prop13); /* variables.css:72:3-41 */
--prop15: var(--prop14) var(--prop14); /* variables.css:73:3-41 */
--prop16: var(--prop15) var(--prop15); /* variables.css:74:3-41 */
--prop17: var(--prop16) var(--prop16); /* variables.css:75:3-41 */
--prop18: var(--prop17) var(--prop17); /* variables.css:76:3-41 */
--prop19: var(--prop18) var(--prop18); /* variables.css:77:3-41 */
--prop2: var(--prop1) var(--prop1); /* variables.css:60:3-38 */
--prop20: var(--prop19) var(--prop19); /* variables.css:78:3-41 */
--prop3: var(--prop2) var(--prop2); /* variables.css:61:3-38 */
--prop4: var(--prop3) var(--prop3); /* variables.css:62:3-38 */
--prop5: var(--prop4) var(--prop4); /* variables.css:63:3-38 */
--prop6: var(--prop5) var(--prop5); /* variables.css:64:3-38 */
--prop7: var(--prop6) var(--prop6); /* variables.css:65:3-38 */
--prop8: var(--prop7) var(--prop7); /* variables.css:66:3-38 */
--prop9: var(--prop8) var(--prop8); /* variables.css:67:3-38 */
--test1: red; /* variables.css:55:3-16 */
label.label-6:dir(ltr)
color: rgb(255,0,0); /* variables.css:89:3-31 */
-gtk-dpi: 96; /* variables.css:86:3-14 */
font-size: 13.333333333333334px; /* variables.css:86:3-14 */
-gtk-icon-palette: error rgb(255,255,255), success rgb(255,255,255), warning rgb(255,255,255); /* variables.css:86:3-14 */
background-color: rgba(0,0,0,0); /* variables.css:86:3-14 */
font-family: "Sans"; /* variables.css:86:3-14 */
font-style: normal; /* variables.css:86:3-14 */
font-weight: 400; /* variables.css:86:3-14 */
font-stretch: normal; /* variables.css:86:3-14 */
letter-spacing: 0; /* variables.css:86:3-14 */
text-decoration-line: none; /* variables.css:86:3-14 */
text-decoration-color: rgb(255,0,0); /* variables.css:86:3-14 */
text-decoration-style: solid; /* variables.css:86:3-14 */
text-transform: none; /* variables.css:86:3-14 */
font-kerning: auto; /* variables.css:86:3-14 */
font-variant-ligatures: normal; /* variables.css:86:3-14 */
font-variant-position: normal; /* variables.css:86:3-14 */
font-variant-caps: normal; /* variables.css:86:3-14 */
font-variant-numeric: normal; /* variables.css:86:3-14 */
font-variant-alternates: normal; /* variables.css:86:3-14 */
font-variant-east-asian: normal; /* variables.css:86:3-14 */
text-shadow: none; /* variables.css:86:3-14 */
box-shadow: none; /* variables.css:86:3-14 */
margin-top: 0; /* variables.css:86:3-14 */
margin-left: 0; /* variables.css:86:3-14 */
margin-bottom: 0; /* variables.css:86:3-14 */
margin-right: 0; /* variables.css:86:3-14 */
padding-top: 0; /* variables.css:86:3-14 */
padding-left: 0; /* variables.css:86:3-14 */
padding-bottom: 0; /* variables.css:86:3-14 */
padding-right: 0; /* variables.css:86:3-14 */
border-top-style: none; /* variables.css:86:3-14 */
border-top-width: 0; /* variables.css:86:3-14 */
border-left-style: none; /* variables.css:86:3-14 */
border-left-width: 0; /* variables.css:86:3-14 */
border-bottom-style: none; /* variables.css:86:3-14 */
border-bottom-width: 0; /* variables.css:86:3-14 */
border-right-style: none; /* variables.css:86:3-14 */
border-right-width: 0; /* variables.css:86:3-14 */
border-top-left-radius: 0; /* variables.css:86:3-14 */
border-top-right-radius: 0; /* variables.css:86:3-14 */
border-bottom-right-radius: 0; /* variables.css:86:3-14 */
border-bottom-left-radius: 0; /* variables.css:86:3-14 */
outline-style: none; /* variables.css:86:3-14 */
outline-width: 0; /* variables.css:86:3-14 */
outline-offset: 0; /* variables.css:86:3-14 */
background-clip: border-box; /* variables.css:86:3-14 */
background-origin: padding-box; /* variables.css:86:3-14 */
background-size: auto; /* variables.css:86:3-14 */
background-position: left top; /* variables.css:86:3-14 */
border-top-color: rgb(255,0,0); /* variables.css:86:3-14 */
border-right-color: rgb(255,0,0); /* variables.css:86:3-14 */
border-bottom-color: rgb(255,0,0); /* variables.css:86:3-14 */
border-left-color: rgb(255,0,0); /* variables.css:86:3-14 */
outline-color: rgb(255,0,0); /* variables.css:86:3-14 */
background-repeat: repeat; /* variables.css:86:3-14 */
background-image: none; /* variables.css:86:3-14 */
background-blend-mode: normal; /* variables.css:86:3-14 */
border-image-source: none; /* variables.css:86:3-14 */
border-image-repeat: stretch; /* variables.css:86:3-14 */
border-image-slice: 100%; /* variables.css:86:3-14 */
border-image-width: 1; /* variables.css:86:3-14 */
-gtk-icon-source: none; /* variables.css:86:3-14 */
-gtk-icon-size: 16px; /* variables.css:86:3-14 */
-gtk-icon-shadow: none; /* variables.css:86:3-14 */
-gtk-icon-style: requested; /* variables.css:86:3-14 */
-gtk-icon-transform: none; /* variables.css:86:3-14 */
-gtk-icon-filter: none; /* variables.css:86:3-14 */
border-spacing: 0 0; /* variables.css:86:3-14 */
transform: none; /* variables.css:86:3-14 */
transform-origin: center; /* variables.css:86:3-14 */
min-width: 0; /* variables.css:86:3-14 */
min-height: 0; /* variables.css:86:3-14 */
transition-property: all; /* variables.css:86:3-14 */
transition-duration: 0; /* variables.css:86:3-14 */
transition-timing-function: ease; /* variables.css:86:3-14 */
transition-delay: 0; /* variables.css:86:3-14 */
animation-name: none; /* variables.css:86:3-14 */
animation-duration: 0; /* variables.css:86:3-14 */
animation-timing-function: ease; /* variables.css:86:3-14 */
animation-iteration-count: 1; /* variables.css:86:3-14 */
animation-direction: normal; /* variables.css:86:3-14 */
animation-play-state: running; /* variables.css:86:3-14 */
animation-delay: 0; /* variables.css:86:3-14 */
animation-fill-mode: none; /* variables.css:86:3-14 */
opacity: 1; /* variables.css:86:3-14 */
filter: none; /* variables.css:86:3-14 */
caret-color: rgb(255,255,255); /* variables.css:86:3-14 */
-gtk-secondary-caret-color: rgb(255,255,255); /* variables.css:86:3-14 */
font-feature-settings: normal; /* variables.css:86:3-14 */
font-variation-settings: normal; /* variables.css:86:3-14 */
line-height: normal; /* variables.css:86:3-14 */
--color1: red; /* variables.css:2:3-17 */
--not-a-color: 20px; /* variables.css:3:3-23 */
label.label-7:dir(ltr)
color: rgb(255,0,0); /* variables.css:94:3-39 */
background-color: rgba(0,0,0,0); /* variables.css:101:3-40 */
--color1: red; /* variables.css:2:3-17 */
--not-a-color: 20px; /* variables.css:3:3-23 */
label.label-8:dir(ltr)
color: rgb(255,0,0); /* variables.css:136:3-31 */
background-color: rgb(0,0,255); /* variables.css:139:3-42 */
box-shadow: 0 0 3px rgb(255,255,0) inset; /* variables.css:142:3-50 */
padding-left: 1px; /* variables.css:124:3-19 */
padding-right: 10px; /* variables.css:125:3-20 */
transition-duration: 5s; /* variables.css:146:3-45 */
animation-name: test; /* variables.css:131:3-39 */
animation-duration: 10s; /* variables.css:131:3-39 */
animation-timing-function: linear; /* variables.css:131:3-39 */
animation-iteration-count: infinite; /* variables.css:131:3-39 */
animation-direction: normal; /* variables.css:131:3-39 */
animation-delay: 0; /* variables.css:131:3-39 */
animation-fill-mode: none; /* variables.css:131:3-39 */
--duration: 2s;
--duration2: var(--duration, 4s); /* variables.css:145:3-36 */
--padding-right: 10px;
--padding1: 1px; /* variables.css:127:3-19 */
--padding2: 2px; /* variables.css:128:3-19 */
--test1: red;
--test2: blue;

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="decorated">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-2"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-3"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-4"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-5"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-6"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-7"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Hello World!</property>
<style>
<class name="label-8"/>
</style>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -223,16 +223,16 @@ test_transition (gconstpointer data)
value1 = value_from_string (prop, test->value1);
g_assert_nonnull (value1);
computed1 = _gtk_css_value_compute (value1, test->prop, provider, style, NULL);
computed1 = _gtk_css_value_compute (value1, test->prop, provider, style, NULL, NULL);
value2 = value_from_string (prop, test->value2);
g_assert_nonnull (value2);
computed2 = _gtk_css_value_compute (value2, test->prop, provider, style, NULL);
computed2 = _gtk_css_value_compute (value2, test->prop, provider, style, NULL, NULL);
if (test->value3)
{
value3 = value_from_string (prop, test->value3);
computed3 = _gtk_css_value_compute (value3, test->prop, provider, style, NULL);
computed3 = _gtk_css_value_compute (value3, test->prop, provider, style, NULL, NULL);
}
else
{