From d533104de7304bd19379194ac639da59e181211b Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Sun, 26 Oct 2003 00:03:16 +0000 Subject: [PATCH] handle negative float and double values similar to how this is done for 2003-10-26 Sven Neumann * app/config/gimpconfig-deserialize.c (gimp_config_deserialize_fundamental): handle negative float and double values similar to how this is done for integers and the like. * app/config/gimpconfig-params.h: added two new param flags and documented all flags in the header file (for now). * app/config/gimpconfig-serialize.h: handle the new param flags GIMP_PARAM_DEFAULTS and GIMP_PARAM_IGNORE. * app/text/text-enums.[ch] * app/text/gimptext.[ch]: added some properties that we will need sooner or later. Mark the new properties and a lot of the existing ones as GIMP_PARAM_DEFAULTS so that their values are not serialized unless changed from the default value. * app/text/gimptextlayout.c * app/tools/gimptextoptions.c: made all length properties in GimpText depend on a single unit. --- ChangeLog | 23 +++++++ app/config/gimpconfig-deserialize.c | 11 +++- app/config/gimpconfig-params.h | 19 +++++- app/config/gimpconfig-serialize.c | 12 +++- app/text/gimptext.c | 91 +++++++++++++++++++------- app/text/gimptext.h | 10 +-- app/text/gimptextlayout.c | 20 ++++-- app/text/text-enums.c | 20 ++++++ app/text/text-enums.h | 12 ++++ app/tools/gimptextoptions.c | 2 +- libgimpconfig/gimpconfig-deserialize.c | 11 +++- libgimpconfig/gimpconfig-params.h | 19 +++++- libgimpconfig/gimpconfig-serialize.c | 12 +++- 13 files changed, 217 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75052dbde8..0b3bd5c9ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2003-10-26 Sven Neumann + + * app/config/gimpconfig-deserialize.c + (gimp_config_deserialize_fundamental): handle negative float and + double values similar to how this is done for integers and the + like. + + * app/config/gimpconfig-params.h: added two new param flags and + documented all flags in the header file (for now). + + * app/config/gimpconfig-serialize.h: handle the new param flags + GIMP_PARAM_DEFAULTS and GIMP_PARAM_IGNORE. + + * app/text/text-enums.[ch] + * app/text/gimptext.[ch]: added some properties that we will need + sooner or later. Mark the new properties and a lot of the existing + ones as GIMP_PARAM_DEFAULTS so that their values are not + serialized unless changed from the default value. + + * app/text/gimptextlayout.c + * app/tools/gimptextoptions.c: made all length properties in + GimpText depend on a single unit. + 2003-10-26 Simon Budig * tools/authorsgen/contributors: Fixed/Added some UTF-8 encoded diff --git a/app/config/gimpconfig-deserialize.c b/app/config/gimpconfig-deserialize.c index 8460c7c4ee..de234095e7 100644 --- a/app/config/gimpconfig-deserialize.c +++ b/app/config/gimpconfig-deserialize.c @@ -404,6 +404,11 @@ gimp_config_deserialize_fundamental (GValue *value, case G_TYPE_FLOAT: case G_TYPE_DOUBLE: + if (g_scanner_peek_next_token (scanner) == '-') + { + negate = TRUE; + g_scanner_get_next_token (scanner); + } token = G_TOKEN_FLOAT; break; @@ -462,10 +467,12 @@ gimp_config_deserialize_fundamental (GValue *value, g_value_set_ulong (value, scanner->value.v_int); break; case G_TYPE_FLOAT: - g_value_set_float (value, scanner->value.v_float); + g_value_set_float (value, negate ? + - scanner->value.v_float : scanner->value.v_float); break; case G_TYPE_DOUBLE: - g_value_set_double (value, scanner->value.v_float); + g_value_set_double (value, negate ? + - scanner->value.v_float: scanner->value.v_float); break; default: diff --git a/app/config/gimpconfig-params.h b/app/config/gimpconfig-params.h index e8befe1cbd..2ff7832062 100644 --- a/app/config/gimpconfig-params.h +++ b/app/config/gimpconfig-params.h @@ -23,11 +23,28 @@ #define __GIMP_CONFIG_PARAMS_H__ +/* + * GIMP_PARAM_SERIALIZE - A property that can and should be + * serialized and deserialized. + * GIMP_PARAM_AGGREGATE - The object property is to be treated as + * part of the parent object. + * GIMP_PARAM_RESTART - Changes to this property take effect only + * after a restart. + * GIMP_PARAM_CONFIRM - Changes to this property should be + * confirmed by the user before being applied. + * GIMP_PARAM_DEFAULTS - Don't serialize this property if it has the + * default value. + * GIMP_PARAM_IGNORE - This property exists for obscure reasons + * and is needed for backward compatibility. + * Ignore the value read and don't serialize it. + */ + #define GIMP_PARAM_SERIALIZE (1 << (0 + G_PARAM_USER_SHIFT)) #define GIMP_PARAM_AGGREGATE (1 << (1 + G_PARAM_USER_SHIFT)) #define GIMP_PARAM_RESTART (1 << (2 + G_PARAM_USER_SHIFT)) #define GIMP_PARAM_CONFIRM (1 << (3 + G_PARAM_USER_SHIFT)) - +#define GIMP_PARAM_DEFAULTS (1 << (4 + G_PARAM_USER_SHIFT)) +#define GIMP_PARAM_IGNORE (1 << (5 + G_PARAM_USER_SHIFT)) #define GIMP_CONFIG_PARAM_FLAGS (G_PARAM_READWRITE | \ G_PARAM_CONSTRUCT | \ diff --git a/app/config/gimpconfig-serialize.c b/app/config/gimpconfig-serialize.c index 263d23786c..24f96f5016 100644 --- a/app/config/gimpconfig-serialize.c +++ b/app/config/gimpconfig-serialize.c @@ -212,14 +212,24 @@ gimp_config_serialize_property (GimpConfig *config, if (! (param_spec->flags & GIMP_PARAM_SERIALIZE)) return FALSE; + if (param_spec->flags & GIMP_PARAM_IGNORE) + return TRUE; + g_value_init (&value, param_spec->value_type); g_object_get_property (G_OBJECT (config), param_spec->name, &value); + if (param_spec->flags & GIMP_PARAM_DEFAULTS && + g_param_value_defaults (param_spec, &value)) + { + g_value_unset (&value); + return TRUE; + } + owner_class = g_type_class_peek (param_spec->owner_type); config_iface = g_type_interface_peek (owner_class, GIMP_TYPE_CONFIG); - /* We must call deserialize_property() *only* if the *exact* class + /* We must call serialize_property() *only* if the *exact* class * which implements it is param_spec->owner_type's class. * * Therefore, we ask param_spec->owner_type's immediate parent class diff --git a/app/text/gimptext.c b/app/text/gimptext.c index 161baa40ef..cd2d29bd2d 100644 --- a/app/text/gimptext.c +++ b/app/text/gimptext.c @@ -37,6 +37,8 @@ #include "config/gimpconfig.h" #include "config/gimpconfig-params.h" +#include "core/gimpstrokeoptions.h" + #include "gimptext.h" #include "gimp-intl.h" @@ -48,7 +50,7 @@ enum PROP_TEXT, PROP_FONT, PROP_FONT_SIZE, - PROP_FONT_SIZE_UNIT, + PROP_UNIT, PROP_HINTING, PROP_AUTOHINT, PROP_ANTIALIAS, @@ -56,6 +58,7 @@ enum PROP_LANGUAGE, PROP_BASE_DIR, PROP_COLOR, + PROP_OUTLINE, PROP_JUSTIFICATION, PROP_INDENTATION, PROP_LINE_SPACING, @@ -65,6 +68,8 @@ enum PROP_BOX_HEIGHT, PROP_BOX_UNIT, PROP_TRANSFORMATION, + PROP_OFFSET_X, + PROP_OFFSET_Y, PROP_BORDER }; @@ -160,7 +165,11 @@ gimp_text_class_init (GimpTextClass *klass) "font-size", NULL, 0.0, 8192.0, 18.0, 0); - GIMP_CONFIG_INSTALL_PROP_UNIT (object_class, PROP_FONT_SIZE_UNIT, + /* + * We use the name "font-size-unit" for backward compatibility. + * The unit is used for all lengths in the text object. + */ + GIMP_CONFIG_INSTALL_PROP_UNIT (object_class, PROP_UNIT, "font-size-unit", NULL, TRUE, FALSE, GIMP_UNIT_PIXEL, 0); @@ -177,7 +186,7 @@ gimp_text_class_init (GimpTextClass *klass) "used but you may prefer to always use " "the automatic hinter"), FALSE, - 0); + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_ANTIALIAS, "antialias", NULL, TRUE, @@ -185,7 +194,7 @@ gimp_text_class_init (GimpTextClass *klass) GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_KERNING, "kerning", NULL, FALSE, - 0); + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_STRING (object_class, PROP_LANGUAGE, "language", NULL, language, @@ -200,6 +209,11 @@ gimp_text_class_init (GimpTextClass *klass) "color", NULL, &black, 0); + GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_OUTLINE, + "outline", NULL, + GIMP_TYPE_TEXT_OUTLINE, + GIMP_TEXT_OUTLINE_NONE, + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_JUSTIFICATION, "justify", NULL, @@ -208,20 +222,19 @@ gimp_text_class_init (GimpTextClass *klass) 0); GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_INDENTATION, "indent", - N_("How many pixels the " - "first line should be shorter"), + N_("Indentation of the first line"), -8192.0, 8192.0, 0.0, - 0); + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_LINE_SPACING, "line-spacing", - N_("Additional line spacing (in pixels)"), + N_("Modify line spacing"), -8192.0, 8192.0, 0.0, - 0); + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_LETTER_SPACING, "letter-spacing", - N_("Additional letter spacing (in pixels)"), + N_("Modify letter spacing"), -8192.0, 8192.0, 0.0, - 0); + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_BOX_MODE, "box-mode", NULL, @@ -231,19 +244,29 @@ gimp_text_class_init (GimpTextClass *klass) GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BOX_WIDTH, "box-width", NULL, 0.0, GIMP_MAX_IMAGE_SIZE, 0.0, - 0); + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_BOX_HEIGHT, "box-height", NULL, 0.0, GIMP_MAX_IMAGE_SIZE, 0.0, - 0); - GIMP_CONFIG_INSTALL_PROP_UNIT (object_class, PROP_BOX_UNIT, - "box-unit", NULL, - TRUE, FALSE, GIMP_UNIT_PIXEL, - 0); + GIMP_PARAM_DEFAULTS); GIMP_CONFIG_INSTALL_PROP_MATRIX2 (object_class, PROP_TRANSFORMATION, "transformation", NULL, &identity, - 0); + GIMP_PARAM_DEFAULTS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_OFFSET_X, + "offset-x", NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + GIMP_PARAM_DEFAULTS); + GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_OFFSET_Y, + "offset-y", NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + GIMP_PARAM_DEFAULTS); + + /* "box-unit" existed for a while but was never used; ignore it */ + GIMP_CONFIG_INSTALL_PROP_UNIT (object_class, PROP_BOX_UNIT, + "box-unit", NULL, + TRUE, FALSE, GIMP_UNIT_PIXEL, + GIMP_PARAM_IGNORE); /* border does only exist to implement the old text API */ param_spec = g_param_spec_int ("border", NULL, NULL, @@ -297,8 +320,8 @@ gimp_text_get_property (GObject *object, case PROP_FONT_SIZE: g_value_set_double (value, text->font_size); break; - case PROP_FONT_SIZE_UNIT: - g_value_set_int (value, text->font_size_unit); + case PROP_UNIT: + g_value_set_int (value, text->unit); break; case PROP_HINTING: g_value_set_boolean (value, text->hinting); @@ -321,6 +344,9 @@ gimp_text_get_property (GObject *object, case PROP_COLOR: g_value_set_boxed (value, &text->color); break; + case PROP_OUTLINE: + g_value_set_enum (value, text->outline); + break; case PROP_JUSTIFICATION: g_value_set_enum (value, text->justify); break; @@ -342,12 +368,18 @@ gimp_text_get_property (GObject *object, case PROP_BOX_HEIGHT: g_value_set_double (value, text->box_height); break; - case PROP_BOX_UNIT: - g_value_set_int (value, text->box_unit); + case PROP_BOX_UNIT: /* GIMP_PARAM_IGNORE */ + g_value_set_int (value, text->unit); break; case PROP_TRANSFORMATION: g_value_set_boxed (value, &text->transformation); break; + case PROP_OFFSET_X: + g_value_set_double (value, text->offset_x); + break; + case PROP_OFFSET_Y: + g_value_set_double (value, text->offset_y); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -377,8 +409,8 @@ gimp_text_set_property (GObject *object, case PROP_FONT_SIZE: text->font_size = g_value_get_double (value); break; - case PROP_FONT_SIZE_UNIT: - text->font_size_unit = g_value_get_int (value); + case PROP_UNIT: + text->unit = g_value_get_int (value); break; case PROP_HINTING: text->hinting = g_value_get_boolean (value); @@ -403,6 +435,9 @@ gimp_text_set_property (GObject *object, color = g_value_get_boxed (value); text->color = *color; break; + case PROP_OUTLINE: + text->outline = g_value_get_enum (value); + break; case PROP_JUSTIFICATION: text->justify = g_value_get_enum (value); break; @@ -425,12 +460,18 @@ gimp_text_set_property (GObject *object, text->box_height = g_value_get_double (value); break; case PROP_BOX_UNIT: - text->box_unit = g_value_get_int (value); + /* ignore */ break; case PROP_TRANSFORMATION: matrix = g_value_get_boxed (value); text->transformation = *matrix; break; + case PROP_OFFSET_X: + text->offset_x = g_value_get_double (value); + break; + case PROP_OFFSET_Y: + text->offset_y = g_value_get_double (value); + break; case PROP_BORDER: text->border = g_value_get_int (value); break; diff --git a/app/text/gimptext.h b/app/text/gimptext.h index f304266c75..88c053093d 100644 --- a/app/text/gimptext.h +++ b/app/text/gimptext.h @@ -42,8 +42,8 @@ struct _GimpText gchar *text; gchar *font; + GimpUnit unit; gdouble font_size; - GimpUnit font_size_unit; gboolean hinting; gboolean autohint; gboolean antialias; @@ -51,6 +51,7 @@ struct _GimpText gchar *language; GimpTextDirection base_dir; GimpRGB color; + GimpTextOutline outline; GimpTextJustification justify; gdouble indent; gdouble line_spacing; @@ -58,10 +59,11 @@ struct _GimpText GimpTextBoxMode box_mode; gdouble box_width; gdouble box_height; - GimpUnit box_unit; GimpMatrix2 transformation; - /* for historical reasons, don't use */ - gint border; + gdouble offset_x; + gdouble offset_y; + + gdouble border; }; struct _GimpTextClass diff --git a/app/text/gimptextlayout.c b/app/text/gimptextlayout.c index afd8ca3a5e..6ee013a4db 100644 --- a/app/text/gimptextlayout.c +++ b/app/text/gimptextlayout.c @@ -149,7 +149,7 @@ gimp_text_layout_new (GimpText *text, size = gimp_text_layout_point_size (image->gimp, text->font_size, - text->font_size_unit, + text->unit, yres); pango_font_description_set_size (font_desc, MAX (1, size)); @@ -197,14 +197,21 @@ gimp_text_layout_new (GimpText *text, pango_layout_set_width (layout->layout, gimp_text_layout_pixel_size (image->gimp, text->box_width, - text->box_unit, + text->unit, xres)); break; } - pango_layout_set_indent (layout->layout, text->indent * PANGO_SCALE); - pango_layout_set_spacing (layout->layout, text->line_spacing * PANGO_SCALE); - + pango_layout_set_indent (layout->layout, + gimp_text_layout_pixel_size (image->gimp, + text->indent, + text->unit, + xres)); + pango_layout_set_spacing (layout->layout, + gimp_text_layout_pixel_size (image->gimp, + text->line_spacing, + text->unit, + yres)); gimp_text_layout_position (layout); switch (text->box_mode) @@ -215,7 +222,7 @@ gimp_text_layout_new (GimpText *text, layout->extents.height = PANGO_PIXELS (gimp_text_layout_pixel_size (image->gimp, text->box_height, - text->box_unit, + text->unit, yres)); break; } @@ -285,7 +292,6 @@ gimp_text_layout_position (GimpTextLayout *layout) layout->extents.width = x2 - x1; layout->extents.height = y2 - y1; - /* border should only be used by the compatibility API */ if (layout->text->border > 0) { gint border = layout->text->border; diff --git a/app/text/text-enums.c b/app/text/text-enums.c index 35ebd80bbc..ca70d5839b 100644 --- a/app/text/text-enums.c +++ b/app/text/text-enums.c @@ -67,5 +67,25 @@ gimp_text_justification_get_type (void) } +static const GEnumValue gimp_text_outline_enum_values[] = +{ + { GIMP_TEXT_OUTLINE_NONE, "GIMP_TEXT_OUTLINE_NONE", "none" }, + { GIMP_TEXT_OUTLINE_STROKE_ONLY, "GIMP_TEXT_OUTLINE_STROKE_ONLY", "stroke-only" }, + { GIMP_TEXT_OUTLINE_STROKE_FILL, "GIMP_TEXT_OUTLINE_STROKE_FILL", "stroke-fill" }, + { 0, NULL, NULL } +}; + +GType +gimp_text_outline_get_type (void) +{ + static GType enum_type = 0; + + if (!enum_type) + enum_type = g_enum_register_static ("GimpTextOutline", gimp_text_outline_enum_values); + + return enum_type; +} + + /* Generated data ends here */ diff --git a/app/text/text-enums.h b/app/text/text-enums.h index 9240a22f55..443f647819 100644 --- a/app/text/text-enums.h +++ b/app/text/text-enums.h @@ -55,4 +55,16 @@ typedef enum } GimpTextJustification; +#define GIMP_TYPE_TEXT_OUTLINE (gimp_text_outline_get_type ()) + +GType gimp_text_outline_get_type (void) G_GNUC_CONST; + +typedef enum +{ + GIMP_TEXT_OUTLINE_NONE, + GIMP_TEXT_OUTLINE_STROKE_ONLY, + GIMP_TEXT_OUTLINE_STROKE_FILL +} GimpTextOutline; + + #endif /* __TEXT_ENUMS_H__ */ diff --git a/app/tools/gimptextoptions.c b/app/tools/gimptextoptions.c index 935dfc07d9..87624e4302 100644 --- a/app/tools/gimptextoptions.c +++ b/app/tools/gimptextoptions.c @@ -298,7 +298,7 @@ gimp_text_options_gui (GimpToolOptions *tool_options) _("Font:"), 1.0, 0.5, font_selection, 2, FALSE); - digits = gimp_unit_get_digits (options->text->font_size_unit); + digits = gimp_unit_get_digits (options->text->unit); spinbutton = gimp_prop_spin_button_new (config, "font-size", 1.0, 10.0, digits); gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, diff --git a/libgimpconfig/gimpconfig-deserialize.c b/libgimpconfig/gimpconfig-deserialize.c index 8460c7c4ee..de234095e7 100644 --- a/libgimpconfig/gimpconfig-deserialize.c +++ b/libgimpconfig/gimpconfig-deserialize.c @@ -404,6 +404,11 @@ gimp_config_deserialize_fundamental (GValue *value, case G_TYPE_FLOAT: case G_TYPE_DOUBLE: + if (g_scanner_peek_next_token (scanner) == '-') + { + negate = TRUE; + g_scanner_get_next_token (scanner); + } token = G_TOKEN_FLOAT; break; @@ -462,10 +467,12 @@ gimp_config_deserialize_fundamental (GValue *value, g_value_set_ulong (value, scanner->value.v_int); break; case G_TYPE_FLOAT: - g_value_set_float (value, scanner->value.v_float); + g_value_set_float (value, negate ? + - scanner->value.v_float : scanner->value.v_float); break; case G_TYPE_DOUBLE: - g_value_set_double (value, scanner->value.v_float); + g_value_set_double (value, negate ? + - scanner->value.v_float: scanner->value.v_float); break; default: diff --git a/libgimpconfig/gimpconfig-params.h b/libgimpconfig/gimpconfig-params.h index e8befe1cbd..2ff7832062 100644 --- a/libgimpconfig/gimpconfig-params.h +++ b/libgimpconfig/gimpconfig-params.h @@ -23,11 +23,28 @@ #define __GIMP_CONFIG_PARAMS_H__ +/* + * GIMP_PARAM_SERIALIZE - A property that can and should be + * serialized and deserialized. + * GIMP_PARAM_AGGREGATE - The object property is to be treated as + * part of the parent object. + * GIMP_PARAM_RESTART - Changes to this property take effect only + * after a restart. + * GIMP_PARAM_CONFIRM - Changes to this property should be + * confirmed by the user before being applied. + * GIMP_PARAM_DEFAULTS - Don't serialize this property if it has the + * default value. + * GIMP_PARAM_IGNORE - This property exists for obscure reasons + * and is needed for backward compatibility. + * Ignore the value read and don't serialize it. + */ + #define GIMP_PARAM_SERIALIZE (1 << (0 + G_PARAM_USER_SHIFT)) #define GIMP_PARAM_AGGREGATE (1 << (1 + G_PARAM_USER_SHIFT)) #define GIMP_PARAM_RESTART (1 << (2 + G_PARAM_USER_SHIFT)) #define GIMP_PARAM_CONFIRM (1 << (3 + G_PARAM_USER_SHIFT)) - +#define GIMP_PARAM_DEFAULTS (1 << (4 + G_PARAM_USER_SHIFT)) +#define GIMP_PARAM_IGNORE (1 << (5 + G_PARAM_USER_SHIFT)) #define GIMP_CONFIG_PARAM_FLAGS (G_PARAM_READWRITE | \ G_PARAM_CONSTRUCT | \ diff --git a/libgimpconfig/gimpconfig-serialize.c b/libgimpconfig/gimpconfig-serialize.c index 263d23786c..24f96f5016 100644 --- a/libgimpconfig/gimpconfig-serialize.c +++ b/libgimpconfig/gimpconfig-serialize.c @@ -212,14 +212,24 @@ gimp_config_serialize_property (GimpConfig *config, if (! (param_spec->flags & GIMP_PARAM_SERIALIZE)) return FALSE; + if (param_spec->flags & GIMP_PARAM_IGNORE) + return TRUE; + g_value_init (&value, param_spec->value_type); g_object_get_property (G_OBJECT (config), param_spec->name, &value); + if (param_spec->flags & GIMP_PARAM_DEFAULTS && + g_param_value_defaults (param_spec, &value)) + { + g_value_unset (&value); + return TRUE; + } + owner_class = g_type_class_peek (param_spec->owner_type); config_iface = g_type_interface_peek (owner_class, GIMP_TYPE_CONFIG); - /* We must call deserialize_property() *only* if the *exact* class + /* We must call serialize_property() *only* if the *exact* class * which implements it is param_spec->owner_type's class. * * Therefore, we ask param_spec->owner_type's immediate parent class