Don't use GValue in GtkCssValue

We now have complete coverage in the GtkCssValue API for type
handling, so drop the GValue from internal storage and just create
new ones when needed.
This commit is contained in:
Alexander Larsson 2012-03-08 16:20:03 +01:00
parent 616cc5b96d
commit 1ceed037b2

View File

@ -28,19 +28,25 @@
struct _GtkCssValue
{
volatile gint ref_count;
GValue g_value;
GType type;
union {
gpointer ptr;
gint gint;
double dbl;
} u;
};
G_DEFINE_BOXED_TYPE (GtkCssValue, _gtk_css_value, _gtk_css_value_ref, _gtk_css_value_unref)
static GtkCssValue *
_gtk_css_value_new (void)
_gtk_css_value_new (GType type)
{
GtkCssValue *value;
value = g_slice_new0 (GtkCssValue);
value->ref_count = 1;
value->type = type;
return value;
}
@ -62,9 +68,24 @@ _gtk_css_value_new_from_gvalue (const GValue *g_value)
value = _gtk_css_value_new_from_number (g_value_get_boxed (g_value));
else
{
value = _gtk_css_value_new ();
g_value_init (&value->g_value, type);
g_value_copy (g_value, &value->g_value);
value = _gtk_css_value_new (type);
if (g_type_is_a (type, G_TYPE_OBJECT))
value->u.ptr = g_value_dup_object (g_value);
else if (g_type_is_a (type, G_TYPE_BOXED))
value->u.ptr = g_value_dup_boxed (g_value);
else if (g_type_is_a (type, G_TYPE_INT))
value->u.gint = g_value_get_int (g_value);
else if (g_type_is_a (type, G_TYPE_BOOLEAN))
value->u.gint = g_value_get_boolean (g_value);
else if (g_type_is_a (type, G_TYPE_ENUM))
value->u.gint = g_value_get_enum (g_value);
else if (g_type_is_a (type, G_TYPE_STRING))
value->u.ptr = g_value_dup_string (g_value);
else if (g_type_is_a (type, G_TYPE_DOUBLE))
value->u.dbl = g_value_get_double (g_value);
else
g_assert_not_reached ();
}
return value;
@ -93,8 +114,24 @@ _gtk_css_value_new_take_gvalue (GValue *g_value)
}
else
{
value = _gtk_css_value_new ();
value->g_value = *g_value;
value = _gtk_css_value_new (type);
if (g_type_is_a (type, G_TYPE_OBJECT))
value->u.ptr = g_value_get_object (g_value);
else if (g_type_is_a (type, G_TYPE_BOXED))
value->u.ptr = g_value_get_boxed (g_value);
else if (g_type_is_a (type, G_TYPE_INT))
value->u.gint = g_value_get_int (g_value);
else if (g_type_is_a (type, G_TYPE_BOOLEAN))
value->u.gint = g_value_get_boolean (g_value);
else if (g_type_is_a (type, G_TYPE_ENUM))
value->u.gint = g_value_get_enum (g_value);
else if (g_type_is_a (type, G_TYPE_STRING))
value->u.ptr = g_value_dup_string (g_value);
else if (g_type_is_a (type, G_TYPE_DOUBLE))
value->u.dbl = g_value_get_double (g_value);
else
g_assert_not_reached ();
}
return value;
@ -110,17 +147,15 @@ _gtk_css_value_new_from_int (gint val)
{
if (singletons[val] == NULL)
{
value = _gtk_css_value_new ();
g_value_init (&value->g_value, G_TYPE_INT);
g_value_set_int (&value->g_value, val);
value = _gtk_css_value_new (G_TYPE_INT);
value->u.gint = val;
singletons[val] = value;
}
return _gtk_css_value_ref (singletons[val]);
}
value = _gtk_css_value_new ();
g_value_init (&value->g_value, G_TYPE_INT);
g_value_set_int (&value->g_value, val);
value = _gtk_css_value_new (G_TYPE_INT);
value->u.gint = val;
return value;
}
@ -130,9 +165,8 @@ _gtk_css_value_new_take_string (char *string)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, G_TYPE_STRING);
g_value_take_string (&value->g_value, string);
value = _gtk_css_value_new (G_TYPE_STRING);
value->u.ptr = string;
return value;
}
@ -142,21 +176,28 @@ _gtk_css_value_new_from_string (const char *string)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, G_TYPE_STRING);
g_value_set_string (&value->g_value, string);
value = _gtk_css_value_new (G_TYPE_STRING);
value->u.ptr = g_strdup (string);
return value;
}
static gpointer
g_boxed_copy0 (GType boxed_type,
gconstpointer src_boxed)
{
if (src_boxed == NULL)
return NULL;
return g_boxed_copy (boxed_type, src_boxed);
}
GtkCssValue *
_gtk_css_value_new_from_border (const GtkBorder *border)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_BORDER);
g_value_set_boxed (&value->g_value, border);
value = _gtk_css_value_new (GTK_TYPE_BORDER);
value->u.ptr = g_boxed_copy0 (GTK_TYPE_BORDER, border);
return value;
}
@ -166,9 +207,8 @@ _gtk_css_value_new_take_pattern (cairo_pattern_t *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
g_value_take_boxed (&value->g_value, v);
value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN);
value->u.ptr = v;
return value;
}
@ -178,9 +218,8 @@ _gtk_css_value_new_from_pattern (const cairo_pattern_t *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
g_value_set_boxed (&value->g_value, v);
value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN);
value->u.ptr = g_boxed_copy0 (CAIRO_GOBJECT_TYPE_PATTERN, v);
return value;
}
@ -190,9 +229,8 @@ _gtk_css_value_new_take_shadow (GtkShadow *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_SHADOW);
g_value_take_boxed (&value->g_value, v);
value = _gtk_css_value_new (GTK_TYPE_SHADOW);
value->u.ptr = v;
return value;
}
@ -202,9 +240,8 @@ _gtk_css_value_new_take_font_description (PangoFontDescription *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, PANGO_TYPE_FONT_DESCRIPTION);
g_value_take_boxed (&value->g_value, v);
value = _gtk_css_value_new (PANGO_TYPE_FONT_DESCRIPTION);
value->u.ptr = v;
return value;
}
@ -214,9 +251,8 @@ _gtk_css_value_new_take_image (GtkCssImage *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_CSS_IMAGE);
g_value_take_object (&value->g_value, v);
value = _gtk_css_value_new (GTK_TYPE_CSS_IMAGE);
value->u.ptr = v;
return value;
}
@ -233,9 +269,8 @@ _gtk_css_value_new_from_number (const GtkCssNumber *v)
{
if (zero_singleton == NULL)
{
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
g_value_set_boxed (&value->g_value, v);
value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
zero_singleton = value;
}
return _gtk_css_value_ref (zero_singleton);
@ -251,18 +286,16 @@ _gtk_css_value_new_from_number (const GtkCssNumber *v)
int i = round (v->value);
if (px_singletons[i] == NULL)
{
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
g_value_set_boxed (&value->g_value, v);
value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
px_singletons[i] = value;
}
return _gtk_css_value_ref (px_singletons[i]);
}
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
g_value_set_boxed (&value->g_value, v);
value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
return value;
}
@ -272,9 +305,8 @@ _gtk_css_value_new_from_rgba (const GdkRGBA *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GDK_TYPE_RGBA);
g_value_set_boxed (&value->g_value, v);
value = _gtk_css_value_new (GDK_TYPE_RGBA);
value->u.ptr = g_boxed_copy0 (GDK_TYPE_RGBA, v);
return value;
}
@ -284,9 +316,8 @@ _gtk_css_value_new_from_color (const GdkColor *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GDK_TYPE_COLOR);
g_value_set_boxed (&value->g_value, v);
value = _gtk_css_value_new (GDK_TYPE_COLOR);
value->u.ptr = g_boxed_copy0 (GDK_TYPE_COLOR, v);
return value;
}
@ -296,9 +327,8 @@ _gtk_css_value_new_from_background_size (const GtkCssBackgroundSize *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_CSS_BACKGROUND_SIZE);
g_value_set_boxed (&value->g_value, v);
value = _gtk_css_value_new (GTK_TYPE_CSS_BACKGROUND_SIZE);
value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_BACKGROUND_SIZE, v);
return value;
}
@ -308,9 +338,8 @@ _gtk_css_value_new_take_symbolic_color (GtkSymbolicColor *v)
{
GtkCssValue *value;
value = _gtk_css_value_new ();
g_value_init (&value->g_value, GTK_TYPE_SYMBOLIC_COLOR);
g_value_take_boxed (&value->g_value, v);
value = _gtk_css_value_new (GTK_TYPE_SYMBOLIC_COLOR);
value->u.ptr = v;
return value;
}
@ -328,26 +357,62 @@ _gtk_css_value_ref (GtkCssValue *value)
void
_gtk_css_value_unref (GtkCssValue *value)
{
GType type;
if (value == NULL)
return;
if (!g_atomic_int_dec_and_test (&value->ref_count))
return;
g_value_unset (&value->g_value);
type = value->type;
if (g_type_is_a (type, G_TYPE_OBJECT) && value->u.ptr != NULL)
g_object_unref (value->u.ptr);
else if (g_type_is_a (type, G_TYPE_BOXED) && value->u.ptr != NULL)
g_boxed_free (type, value->u.ptr);
else if (g_type_is_a (type, G_TYPE_STRING))
g_free (value->u.ptr);
g_slice_free (GtkCssValue, value);
}
GType
_gtk_css_value_get_content_type (GtkCssValue *value)
{
return G_VALUE_TYPE (&value->g_value);
return value->type;
}
gboolean
_gtk_css_value_holds (GtkCssValue *value, GType type)
{
return G_VALUE_HOLDS (&value->g_value, type);
return g_type_is_a (value->type, type);
}
static void
fill_gvalue (GtkCssValue *value,
GValue *g_value)
{
GType type;
type = value->type;
if (g_type_is_a (type, G_TYPE_OBJECT))
g_value_set_object (g_value, value->u.ptr);
else if (g_type_is_a (type, G_TYPE_BOXED))
g_value_set_boxed (g_value, value->u.ptr);
else if (g_type_is_a (type, G_TYPE_INT))
g_value_set_int (g_value, value->u.gint);
else if (g_type_is_a (type, G_TYPE_BOOLEAN))
g_value_set_boolean (g_value, value->u.gint);
else if (g_type_is_a (type, G_TYPE_ENUM))
g_value_set_enum (g_value, value->u.gint);
else if (g_type_is_a (type, G_TYPE_STRING))
g_value_set_string (g_value, value->u.ptr);
else if (g_type_is_a (type, G_TYPE_DOUBLE))
g_value_set_double (g_value, value->u.dbl);
else
g_assert_not_reached ();
}
void
@ -356,8 +421,8 @@ _gtk_css_value_init_gvalue (GtkCssValue *value,
{
if (value != NULL)
{
g_value_init (g_value, G_VALUE_TYPE (&value->g_value));
g_value_copy (&value->g_value, g_value);
g_value_init (g_value, value->type);
fill_gvalue (value, g_value);
}
}
@ -365,13 +430,18 @@ void
_gtk_css_value_to_gvalue (GtkCssValue *value,
GValue *g_value)
{
if (G_VALUE_TYPE (&value->g_value) == G_VALUE_TYPE (g_value))
g_value_copy (&value->g_value, g_value);
else if (g_value_type_transformable (G_VALUE_TYPE (&value->g_value), G_VALUE_TYPE (g_value)))
g_value_transform (&value->g_value, g_value);
if (value->type == G_VALUE_TYPE (g_value))
fill_gvalue (value, g_value);
else if (g_value_type_transformable (value->type, G_VALUE_TYPE (g_value)))
{
GValue v = G_VALUE_INIT;
_gtk_css_value_init_gvalue (value, &v);
g_value_transform (&v, g_value);
g_value_unset (&v);
}
else
g_warning ("can't convert css value of type `%s' as value of type `%s'",
G_VALUE_TYPE_NAME (&value->g_value),
g_type_name (value->type),
G_VALUE_TYPE_NAME (g_value));
}
@ -385,159 +455,161 @@ GtkCssSpecialValue
_gtk_css_value_get_special_kind (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE), 0);
return g_value_get_enum (&value->g_value);
return value->u.gint;
}
GtkCssNumber *
_gtk_css_value_get_number (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_NUMBER), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
GtkSymbolicColor *
_gtk_css_value_get_symbolic_color (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SYMBOLIC_COLOR), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
int
_gtk_css_value_get_int (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_INT), 0);
return g_value_get_int (&value->g_value);
return value->u.gint;
}
double
_gtk_css_value_get_double (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_DOUBLE), 0);
return g_value_get_double (&value->g_value);
return value->u.dbl;
}
const char *
_gtk_css_value_get_string (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRING), 0);
return g_value_get_string (&value->g_value);
return value->u.ptr;
}
gpointer
_gtk_css_value_dup_object (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
return g_value_dup_object (&value->g_value);
if (value->u.ptr)
return g_object_ref (value->u.ptr);
return NULL;
}
gpointer
_gtk_css_value_get_object (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
return g_value_get_object (&value->g_value);
return value->u.ptr;
}
gpointer
_gtk_css_value_get_boxed (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_BOXED), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
const char **
_gtk_css_value_get_strv (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRV), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
GtkCssImage *
_gtk_css_value_get_image (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_IMAGE), NULL);
return g_value_get_object (&value->g_value);
return value->u.ptr;
}
GtkBorderStyle
_gtk_css_value_get_border_style (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_BORDER_STYLE), 0);
return g_value_get_enum (&value->g_value);
return value->u.gint;
}
GtkCssBackgroundSize *
_gtk_css_value_get_background_size (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BACKGROUND_SIZE), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
GtkCssBorderImageRepeat *
_gtk_css_value_get_border_image_repeat (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
GtkCssBorderCornerRadius *
_gtk_css_value_get_border_corner_radius (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
PangoFontDescription *
_gtk_css_value_get_font_description (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_FONT_DESCRIPTION), 0);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
PangoStyle
_gtk_css_value_get_pango_style (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_STYLE), 0);
return g_value_get_enum (&value->g_value);
return value->u.gint;
}
PangoVariant
_gtk_css_value_get_pango_variant (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_VARIANT), 0);
return g_value_get_enum (&value->g_value);
return value->u.gint;
}
PangoWeight
_gtk_css_value_get_pango_weight (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_WEIGHT), 0);
return g_value_get_enum (&value->g_value);
return value->u.gint;
}
GdkRGBA *
_gtk_css_value_get_rgba (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GDK_TYPE_RGBA), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
cairo_pattern_t *
_gtk_css_value_get_pattern (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, CAIRO_GOBJECT_TYPE_PATTERN), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
GtkGradient *
_gtk_css_value_get_gradient (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_GRADIENT), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}
GtkShadow *
_gtk_css_value_get_shadow (GtkCssValue *value)
{
g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SHADOW), NULL);
return g_value_get_boxed (&value->g_value);
return value->u.ptr;
}