GtkCssValue *specified)
{
GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified);
- GdkRGBA rgba;
+ GtkCssValue *resolved;
if (symbolic == _gtk_symbolic_color_get_current_color ())
{
return _gtk_css_value_ref (_gtk_style_context_peek_property (context, "color"));
}
}
- else if (_gtk_style_context_resolve_color (context,
- symbolic,
- &rgba))
+ else if ((resolved = _gtk_style_context_resolve_color_value (context,
+ symbolic)) != NULL)
{
- return _gtk_css_value_new_from_rgba (&rgba);
+ return resolved;
}
else
{
GtkStyleContext *context,
GtkCssValue *specified)
{
- GtkCssImage *image = _gtk_css_value_get_image (specified);
+ GtkCssImage *image, *computed;
+
+ image = _gtk_css_value_get_image (specified);
- if (image)
- image = _gtk_css_image_compute (image, context);
+ if (image == NULL)
+ return _gtk_css_value_ref (specified);
+
+ computed = _gtk_css_image_compute (image, context);
+
+ if (computed == image)
+ {
+ g_object_unref (computed);
+ return _gtk_css_value_ref (specified);
+ }
- return _gtk_css_value_new_take_image (image);
+ return _gtk_css_value_new_take_image (computed);
}
static gboolean
GtkStyleContext *context,
GtkCssValue *specified)
{
- GtkCssBackgroundSize *ssize = _gtk_css_value_get_background_size (specified);
+ const GtkCssBackgroundSize *ssize = _gtk_css_value_get_background_size (specified);
GtkCssBackgroundSize csize;
gboolean changed;
return _gtk_css_value_ref (specified);
}
+static gboolean
+background_position_parse (GtkCssStyleProperty *property,
+ GValue *value,
+ GtkCssParser *parser,
+ GFile *base)
+{
+ static const struct {
+ const char *name;
+ guint percentage;
+ gboolean horizontal;
+ gboolean vertical;
+ } names[] = {
+ { "left", 0, TRUE, FALSE },
+ { "right", 100, TRUE, FALSE },
+ { "center", 50, TRUE, TRUE },
+ { "top", 0, FALSE, TRUE },
+ { "bottom", 100, FALSE, TRUE },
+ { NULL , 0, TRUE, FALSE }, /* used for numbers */
+ { NULL , 50, TRUE, TRUE } /* used for no value */
+ };
+ GtkCssBackgroundPosition pos;
+ GtkCssNumber *missing;
+ guint first, second;
+
+ for (first = 0; names[first].name != NULL; first++)
+ {
+ if (_gtk_css_parser_try (parser, names[first].name, TRUE))
+ {
+ if (names[first].horizontal)
+ {
+ _gtk_css_number_init (&pos.x, names[first].percentage, GTK_CSS_PERCENT);
+ missing = &pos.y;
+ }
+ else
+ {
+ _gtk_css_number_init (&pos.y, names[first].percentage, GTK_CSS_PERCENT);
+ missing = &pos.x;
+ }
+ break;
+ }
+ }
+ if (names[first].name == NULL)
+ {
+ missing = &pos.y;
+ if (!_gtk_css_parser_read_number (parser,
+ &pos.x,
+ GTK_CSS_PARSE_PERCENT
+ | GTK_CSS_PARSE_LENGTH))
+ return FALSE;
+ }
+
+ for (second = 0; names[second].name != NULL; second++)
+ {
+ if (_gtk_css_parser_try (parser, names[second].name, TRUE))
+ {
+ _gtk_css_number_init (missing, names[second].percentage, GTK_CSS_PERCENT);
+ break;
+ }
+ }
+
+ if (names[second].name == NULL)
+ {
+ if (_gtk_css_parser_has_number (parser))
+ {
+ if (missing != &pos.y)
+ {
+ _gtk_css_parser_error (parser, "Invalid combination of values");
+ return FALSE;
+ }
+ if (!_gtk_css_parser_read_number (parser,
+ missing,
+ GTK_CSS_PARSE_PERCENT
+ | GTK_CSS_PARSE_LENGTH))
+ return FALSE;
+ }
+ else
+ {
+ second++;
+ _gtk_css_number_init (missing, 50, GTK_CSS_PERCENT);
+ }
+ }
+ else
+ {
+ if ((names[first].horizontal && !names[second].vertical) ||
+ (!names[first].horizontal && !names[second].horizontal))
+ {
+ _gtk_css_parser_error (parser, "Invalid combination of values");
+ return FALSE;
+ }
+ }
+
+ g_value_set_boxed (value, &pos);
+ return TRUE;
+}
+
+static void
+background_position_print (GtkCssStyleProperty *property,
+ const GValue *value,
+ GString *string)
+{
+ GtkCssBackgroundPosition *pos = g_value_get_boxed (value);
+ static const GtkCssNumber center = GTK_CSS_NUMBER_INIT (50, GTK_CSS_PERCENT);
+ static const struct {
+ const char *x_name;
+ const char *y_name;
+ GtkCssNumber number;
+ } values[] = {
+ { "left", "top", GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT) },
+ { "right", "bottom", GTK_CSS_NUMBER_INIT (100, GTK_CSS_PERCENT) }
+ };
+ guint i;
+
+ if (_gtk_css_number_equal (&pos->x, ¢er))
+ {
+ if (_gtk_css_number_equal (&pos->y, ¢er))
+ {
+ g_string_append (string, "center");
+ return;
+ }
+ }
+ else
+ {
+ for (i = 0; i < G_N_ELEMENTS (values); i++)
+ {
+ if (_gtk_css_number_equal (&pos->x, &values[i].number))
+ {
+ g_string_append (string, values[i].x_name);
+ break;
+ }
+ }
+ if (i == G_N_ELEMENTS (values))
+ _gtk_css_number_print (&pos->x, string);
+
+ if (_gtk_css_number_equal (&pos->y, ¢er))
+ return;
+
+ g_string_append_c (string, ' ');
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (values); i++)
+ {
+ if (_gtk_css_number_equal (&pos->y, &values[i].number))
+ {
+ g_string_append (string, values[i].y_name);
+ break;
+ }
+ }
+ if (i == G_N_ELEMENTS (values))
+ {
+ if (_gtk_css_number_equal (&pos->x, ¢er))
+ g_string_append (string, "center ");
+ _gtk_css_number_print (&pos->y, string);
+ }
+}
+
+static GtkCssValue *
+background_position_compute (GtkCssStyleProperty *property,
+ GtkStyleContext *context,
+ GtkCssValue *specified)
+{
+ const GtkCssBackgroundPosition *spos = _gtk_css_value_get_background_position (specified);
+ GtkCssBackgroundPosition cpos;
+ gboolean changed;
+
+ changed = _gtk_css_number_compute (&cpos.x,
+ &spos->x,
+ context);
+ changed |= _gtk_css_number_compute (&cpos.y,
+ &spos->y,
+ context);
+ if (changed)
+ return _gtk_css_value_new_from_background_position (&cpos);
+ return _gtk_css_value_ref (specified);
+}
+
/*** REGISTRATION ***/
static GtkSymbolicColor *
GtkCssNumber number;
GtkSymbolicColor *symbolic;
GtkCssBackgroundSize default_background_size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE };
+ GtkCssBackgroundPosition default_background_position = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT)};
GtkCssBorderCornerRadius no_corner_radius = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX) };
GtkBorder border_of_ones = { 1, 1, 1, 1 };
GtkCssBorderImageRepeat border_image_repeat = { GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH };
background_size_print,
background_size_compute,
&default_background_size);
+ gtk_css_style_property_register ("background-position",
+ GTK_TYPE_CSS_BACKGROUND_POSITION,
+ GTK_TYPE_CSS_BACKGROUND_POSITION,
+ G_TYPE_NONE,
+ 0,
+ background_position_parse,
+ background_position_print,
+ background_position_compute,
+ &default_background_position);
gtk_css_style_property_register ("border-top-color",
GTK_TYPE_SYMBOLIC_COLOR,