]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcssstylepropertyimpl.c
cssvalue: Constify a bunch of APIs
[~andy/gtk] / gtk / gtkcssstylepropertyimpl.c
index 5d206e3be3d6dceb524e6464b4577c6e78cfa98e..3edcb94669d48adbc7e80e65238b425328aa9ce0 100644 (file)
@@ -146,7 +146,7 @@ color_compute (GtkCssStyleProperty    *property,
                GtkCssValue            *specified)
 {
   GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified);
-  GdkRGBA rgba;
+  GtkCssValue *resolved;
 
   if (symbolic == _gtk_symbolic_color_get_current_color ())
     {
@@ -170,11 +170,10 @@ color_compute (GtkCssStyleProperty    *property,
           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
     {
@@ -401,12 +400,22 @@ css_image_value_compute (GtkCssStyleProperty    *property,
                          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 
@@ -666,7 +675,7 @@ background_size_compute (GtkCssStyleProperty    *property,
                          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;
 
@@ -683,6 +692,181 @@ background_size_compute (GtkCssStyleProperty    *property,
   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, &center))
+    {
+      if (_gtk_css_number_equal (&pos->y, &center))
+        {
+          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, &center))
+        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, &center))
+        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 *
@@ -703,6 +887,7 @@ _gtk_css_style_property_init_properties (void)
   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 };
@@ -1055,6 +1240,15 @@ _gtk_css_style_property_init_properties (void)
                                           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,