app, libgimp, pdb: new PDB function gimp_fonts_get_by_name().

It returns all the fonts (possibly more than 1) with a given name. I left the
function gimp_font_get_by_name() as a utility when one don't want to choose (or
is not able anyway, e.g. a script with minimal information), though I wondered
if we should not simplify with a single function (the new one, which is the
correct one now that it is possible to have several fonts with a given name).

It is easy to test with fonts named the same. For instance I could find 2
different fonts, both named 'Holiday'. This call in the Python console returns
both:

> Gimp.fonts_get_by_name('Holiday')

As part of this commit, I also implemented resource arrays (or subtype arrays)
as PDB arguments and return types.
This commit is contained in:
Jehan 2023-10-02 23:22:49 +02:00
parent 66488ed958
commit eab9d8da28
14 changed files with 506 additions and 24 deletions

View File

@ -198,6 +198,7 @@ gimp_container_class_init (GimpContainerClass *klass)
klass->search = NULL;
klass->get_unique_names = NULL;
klass->get_child_by_name = NULL;
klass->get_children_by_name = NULL;
klass->get_child_by_index = NULL;
klass->get_child_index = NULL;
@ -881,6 +882,34 @@ gimp_container_get_unique_names (GimpContainer *container)
return FALSE;
}
GList *
gimp_container_get_children_by_name (GimpContainer *container,
const gchar *name)
{
g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
if (!name)
return NULL;
if (GIMP_CONTAINER_GET_CLASS (container)->get_children_by_name != NULL &&
! gimp_container_get_unique_names (container))
{
return GIMP_CONTAINER_GET_CLASS (container)->get_children_by_name (container,
name);
}
else
{
GimpObject *child;
child = GIMP_CONTAINER_GET_CLASS (container)->get_child_by_name (container, name);
if (child != NULL)
return g_list_prepend (NULL, child);
else
return NULL;
}
}
GimpObject *
gimp_container_get_child_by_name (GimpContainer *container,
const gchar *name)

View File

@ -75,6 +75,8 @@ struct _GimpContainerClass
gboolean (* get_unique_names) (GimpContainer *container);
GimpObject * (* get_child_by_name) (GimpContainer *container,
const gchar *name);
GList * (* get_children_by_name) (GimpContainer *container,
const gchar *name);
GimpObject * (* get_child_by_index) (GimpContainer *container,
gint index);
gint (* get_child_index) (GimpContainer *container,
@ -117,6 +119,8 @@ GimpObject * gimp_container_search (GimpContainer *contain
gboolean gimp_container_get_unique_names (GimpContainer *container);
GList * gimp_container_get_children_by_name (GimpContainer *container,
const gchar *name);
GimpObject * gimp_container_get_child_by_name (GimpContainer *container,
const gchar *name);
GimpObject * gimp_container_get_child_by_index (GimpContainer *container,

View File

@ -72,6 +72,8 @@ static GimpObject * gimp_list_search (GimpContainer *conta
GimpContainerSearchFunc func,
gpointer user_data);
static gboolean gimp_list_get_unique_names (GimpContainer *container);
static GList * gimp_list_get_children_by_name (GimpContainer *container,
const gchar *name);
static GimpObject * gimp_list_get_child_by_name (GimpContainer *container,
const gchar *name);
static GimpObject * gimp_list_get_child_by_index (GimpContainer *container,
@ -97,23 +99,24 @@ gimp_list_class_init (GimpListClass *klass)
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
GimpContainerClass *container_class = GIMP_CONTAINER_CLASS (klass);
object_class->finalize = gimp_list_finalize;
object_class->set_property = gimp_list_set_property;
object_class->get_property = gimp_list_get_property;
object_class->finalize = gimp_list_finalize;
object_class->set_property = gimp_list_set_property;
object_class->get_property = gimp_list_get_property;
gimp_object_class->get_memsize = gimp_list_get_memsize;
gimp_object_class->get_memsize = gimp_list_get_memsize;
container_class->add = gimp_list_add;
container_class->remove = gimp_list_remove;
container_class->reorder = gimp_list_reorder;
container_class->clear = gimp_list_clear;
container_class->have = gimp_list_have;
container_class->foreach = gimp_list_foreach;
container_class->search = gimp_list_search;
container_class->get_unique_names = gimp_list_get_unique_names;
container_class->get_child_by_name = gimp_list_get_child_by_name;
container_class->get_child_by_index = gimp_list_get_child_by_index;
container_class->get_child_index = gimp_list_get_child_index;
container_class->add = gimp_list_add;
container_class->remove = gimp_list_remove;
container_class->reorder = gimp_list_reorder;
container_class->clear = gimp_list_clear;
container_class->have = gimp_list_have;
container_class->foreach = gimp_list_foreach;
container_class->search = gimp_list_search;
container_class->get_unique_names = gimp_list_get_unique_names;
container_class->get_children_by_name = gimp_list_get_children_by_name;
container_class->get_child_by_name = gimp_list_get_child_by_name;
container_class->get_child_by_index = gimp_list_get_child_by_index;
container_class->get_child_index = gimp_list_get_child_index;
g_object_class_install_property (object_class, PROP_UNIQUE_NAMES,
g_param_spec_boolean ("unique-names",
@ -365,6 +368,29 @@ gimp_list_get_unique_names (GimpContainer *container)
return list->unique_names;
}
static GList *
gimp_list_get_children_by_name (GimpContainer *container,
const gchar *name)
{
GimpList *list = GIMP_LIST (container);
GList *children = NULL;
GList *iter;
for (iter = list->queue->head; iter; iter = g_list_next (iter))
{
GimpObject *object = iter->data;
if (! strcmp (gimp_object_get_name (object), name))
{
children = g_list_prepend (children, object);
if (list->unique_names)
return children;
}
}
return children;
}
static GimpObject *
gimp_list_get_child_by_name (GimpContainer *container,
const gchar *name)

View File

@ -71,6 +71,57 @@ font_get_by_name_invoker (GimpProcedure *procedure,
return return_vals;
}
static GimpValueArray *
fonts_get_by_name_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpValueArray *return_vals;
const gchar *name;
gint num_fonts = 0;
GimpFont **fonts = NULL;
name = g_value_get_string (gimp_value_array_index (args, 0));
if (success)
{
GList *list;
list = gimp_pdb_get_resources (gimp, GIMP_TYPE_FONT, name, GIMP_PDB_DATA_ACCESS_READ, error);
if (list == NULL)
success = FALSE;
num_fonts = g_list_length (list);
if (num_fonts > 0)
{
gint i = 0;
fonts = g_new (GimpFont *, num_fonts);
for (GList *iter = list; i < num_fonts; i++, iter = g_list_next (iter))
fonts[i] = g_object_ref (iter->data);
}
g_list_free (list);
}
return_vals = gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
if (success)
{
g_value_set_int (gimp_value_array_index (return_vals, 1), num_fonts);
gimp_value_take_object_array (gimp_value_array_index (return_vals, 2), GIMP_TYPE_FONT, (GObject **) fonts, num_fonts);
}
return return_vals;
}
void
register_font_procs (GimpPDB *pdb)
{
@ -83,8 +134,9 @@ register_font_procs (GimpPDB *pdb)
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-font-get-by-name");
gimp_procedure_set_static_help (procedure,
"Returns the font with the given name.",
"Returns the font with the given name.",
"Returns a font with the given name.",
"If several fonts are named identically, the one which is returned by this function should be considered random. This can be used when you know you won't have multiple fonts of this name or that you don't want to choose (non-interactive scripts, etc.).\n"
"If you need more control, you should use 'gimp-fonts-get-by-name' instead.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Michael Natterer <mitch@gimp.org>",
@ -105,4 +157,40 @@ register_font_procs (GimpPDB *pdb)
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-fonts-get-by-name
*/
procedure = gimp_procedure_new (fonts_get_by_name_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-fonts-get-by-name");
gimp_procedure_set_static_help (procedure,
"Returns the fonts with the given name.",
"Returns the fonts with the given name. There may be more than one.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Jehan",
"Jehan",
"2023");
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("name",
"name",
"The name of the font",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_int ("num-fonts",
"num fonts",
"The number of fonts with the given name",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_object_array ("fonts",
"fonts",
"The fonts with the given name",
GIMP_TYPE_FONT,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
}

View File

@ -101,6 +101,91 @@ gimp_pdb_get_data_factory (Gimp *gimp,
g_return_val_if_reached (NULL);
}
GList *
gimp_pdb_get_resources (Gimp *gimp,
GType data_type,
const gchar *name,
GimpPDBDataAccess access,
GError **error)
{
GList *resources;
GimpDataFactory *factory;
GimpContainer *container;
const gchar *label;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
label = gimp_pdb_get_data_label (data_type);
if (! name || ! strlen (name))
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
/* TRANSLATOR: %s is a data label from the
* PDB-error-data-label context.
*/
C_("PDB-error-message", "%s name cannot be empty"),
g_type_name (data_type));
return NULL;
}
factory = gimp_pdb_get_data_factory (gimp, data_type);
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
container = gimp_data_factory_get_container (factory);
resources = gimp_container_get_children_by_name (container, name);
if (! resources && ! strcmp (name, "Standard"))
{
GimpData *resource;
resource = gimp_data_factory_data_get_standard (factory, gimp_get_user_context (gimp));
g_return_val_if_fail (resource != NULL, NULL);
resources = g_list_prepend (NULL, resource);
}
if (! resources)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
/* TRANSLATOR: the first %s is a data label from the
* PDB-error-data-label context. The second %s is a data
* name.
*/
C_("PDB-error-message", "%s '%s' not found"), label, name);
}
else if ((access & GIMP_PDB_DATA_ACCESS_WRITE) ||
(access & GIMP_PDB_DATA_ACCESS_RENAME))
{
for (GList *iter = resources; iter; iter = iter->next)
{
if ((access & GIMP_PDB_DATA_ACCESS_WRITE) &&
! gimp_data_is_writable (GIMP_DATA (iter->data)))
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
/* TRANSLATOR: the first %s is a data label from the
* PDB-error-data-label context. The second %s is a data
* name.
*/
C_("PDB-error-message", "%s '%s' is not editable"), label, name);
return NULL;
}
else if ((access & GIMP_PDB_DATA_ACCESS_RENAME) &&
! gimp_viewable_is_name_editable (GIMP_VIEWABLE (iter->data)))
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
/* TRANSLATOR: the first %s is a data label from the
* PDB-error-data-label context. The second %s is a data
* name.
*/
C_("PDB-error-message", "%s '%s' is not renamable"), label, name);
return NULL;
}
}
}
return resources;
}
GimpResource *
gimp_pdb_get_resource (Gimp *gimp,
GType data_type,

View File

@ -22,6 +22,11 @@
GimpDataFactory * gimp_pdb_get_data_factory (Gimp *gimp,
GType data_type);
GList * gimp_pdb_get_resources (Gimp *gimp,
GType data_type,
const gchar *name,
GimpPDBDataAccess access,
GError **error);
GimpResource * gimp_pdb_get_resource (Gimp *gimp,
GType data_type,
const gchar *name,

View File

@ -30,7 +30,7 @@
#include "internal-procs.h"
/* 778 procedures registered total */
/* 779 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)

View File

@ -297,6 +297,7 @@ EXPORTS
gimp_font_get_pango_font_description
gimp_font_get_type
gimp_fonts_close_popup
gimp_fonts_get_by_name
gimp_fonts_get_list
gimp_fonts_popup
gimp_fonts_refresh

View File

@ -40,9 +40,14 @@
* gimp_font_get_by_name:
* @name: The name of the font.
*
* Returns the font with the given name.
* Returns a font with the given name.
*
* Returns the font with the given name.
* If several fonts are named identically, the one which is returned by
* this function should be considered random. This can be used when you
* know you won't have multiple fonts of this name or that you don't
* want to choose (non-interactive scripts, etc.).
* If you need more control, you should use gimp_fonts_get_by_name()
* instead.
*
* Returns: (transfer none): The font.
*
@ -71,3 +76,48 @@ gimp_font_get_by_name (const gchar *name)
return font;
}
/**
* gimp_fonts_get_by_name:
* @name: The name of the font.
* @num_fonts: (out): The number of fonts with the given name.
*
* Returns the fonts with the given name.
*
* Returns the fonts with the given name. There may be more than one.
*
* Returns: (array length=num_fonts) (element-type GimpFont) (transfer container):
* The fonts with the given name.
* The returned value must be freed with g_free().
*
* Since: 3.0
**/
GimpFont **
gimp_fonts_get_by_name (const gchar *name,
gint *num_fonts)
{
GimpValueArray *args;
GimpValueArray *return_vals;
GimpFont **fonts = NULL;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, name,
G_TYPE_NONE);
return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-fonts-get-by-name",
args);
gimp_value_array_unref (args);
*num_fonts = 0;
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
{
*num_fonts = GIMP_VALUES_GET_INT (return_vals, 1);
{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index (return_vals, 2)); if (a) fonts = g_memdup2 (a->data, a->length * sizeof (gpointer)); };
}
gimp_value_array_unref (return_vals);
return fonts;
}

View File

@ -32,7 +32,9 @@ G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
GimpFont* gimp_font_get_by_name (const gchar *name);
GimpFont* gimp_font_get_by_name (const gchar *name);
GimpFont** gimp_fonts_get_by_name (const gchar *name,
gint *num_fonts);
G_END_DECLS

View File

@ -672,6 +672,10 @@ gimp_gp_param_to_value (gpointer gimp,
{
objects[i] = (GObject *) get_display_by_id (gimp, id);
}
else if (g_type_is_a (object_type, GIMP_TYPE_RESOURCE))
{
objects[i] = (GObject *) get_resource_by_id (id);
}
if (objects[i])
g_object_ref (objects[i]);
@ -993,6 +997,10 @@ gimp_value_to_gp_param (const GValue *value,
param->data.d_id_array.data[i] =
gimp_display_get_id (GIMP_DISPLAY (array->data[i]));
}
else if (GIMP_IS_RESOURCE (array->data[i]))
{
param->data.d_id_array.data[i] = get_resource_id (array->data[i]);
}
else
{
param->data.d_id_array.data[i] = -1;

View File

@ -693,6 +693,60 @@ gimp_param_spec_object_array ("$name",
"$blurb",
GIMP_TYPE_VECTORS,
$flags)
CODE
}
elsif ($pdbtype eq 'resourcearray') {
$pspec = <<CODE;
gimp_param_spec_object_array ("$name",
"$nick",
"$blurb",
GIMP_TYPE_RESOURCE,
$flags)
CODE
}
elsif ($pdbtype eq 'brusharray') {
$pspec = <<CODE;
gimp_param_spec_object_array ("$name",
"$nick",
"$blurb",
GIMP_TYPE_BRUSH,
$flags)
CODE
}
elsif ($pdbtype eq 'fontarray') {
$pspec = <<CODE;
gimp_param_spec_object_array ("$name",
"$nick",
"$blurb",
GIMP_TYPE_FONT,
$flags)
CODE
}
elsif ($pdbtype eq 'gradientarray') {
$pspec = <<CODE;
gimp_param_spec_object_array ("$name",
"$nick",
"$blurb",
GIMP_TYPE_GRADIENT,
$flags)
CODE
}
elsif ($pdbtype eq 'palettearray') {
$pspec = <<CODE;
gimp_param_spec_object_array ("$name",
"$nick",
"$blurb",
GIMP_TYPE_PALETTE,
$flags)
CODE
}
elsif ($pdbtype eq 'patternarray') {
$pspec = <<CODE;
gimp_param_spec_object_array ("$name",
"$nick",
"$blurb",
GIMP_TYPE_PATTERN,
$flags)
CODE
}
else {

View File

@ -19,9 +19,61 @@
# The invoke code is compiled on the app side.
# The invoke code must assign to each result var
sub fonts_get_by_name {
$blurb = "Returns the fonts with the given name.";
$help = "Returns the fonts with the given name. There may be more than one.";
&jehan_pdb_misc('2023', '3.0');
@inargs = (
{ name => 'name', type => 'string', non_empty => 1,
desc => 'The name of the font' }
);
@outargs = (
{ name => 'fonts', type => 'fontarray', non_empty => 0,
desc => 'The fonts with the given name',
array => { name => 'num_fonts',
desc => 'The number of fonts with the given name' } }
);
%invoke = (
code => <<'CODE'
{
GList *list;
list = gimp_pdb_get_resources (gimp, GIMP_TYPE_FONT, name, GIMP_PDB_DATA_ACCESS_READ, error);
if (list == NULL)
success = FALSE;
num_fonts = g_list_length (list);
if (num_fonts > 0)
{
gint i = 0;
fonts = g_new (GimpFont *, num_fonts);
for (GList *iter = list; i < num_fonts; i++, iter = g_list_next (iter))
fonts[i] = g_object_ref (iter->data);
}
g_list_free (list);
}
CODE
);
}
sub font_get_by_name {
$blurb = "Returns the font with the given name.";
$help = "Returns the font with the given name.";
$blurb = "Returns a font with the given name.";
$help = <<HELP;
If several fonts are named identically, the one which is returned by this
function should be considered random. This can be used when you know you won't
have multiple fonts of this name or that you don't want to choose
(non-interactive scripts, etc.).
If you need more control, you should use gimp_fonts_get_by_name() instead.
HELP
&mitch_pdb_misc('2023', '3.0');
@ -50,7 +102,7 @@ CODE
@headers = qw("core/gimp.h"
"gimppdb-utils.h");
@procs = qw(font_get_by_name);
@procs = qw(font_get_by_name fonts_get_by_name);
%exports = (app => [@procs], lib => [@procs]);

View File

@ -185,6 +185,84 @@ package Gimp::CodeGen::pdb;
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_VECTORS, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_VECTORS, (GObject **) $var, $var_len)' },
resourcearray => { name => 'RESOURCEARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',
type => 'GimpResource **',
const_type => 'const GimpResource **',
array => 1,
init_value => 'NULL',
in_annotate => '(element-type GimpResource)',
out_annotate => '(element-type GimpResource) (transfer container)',
get_value_func => '$var = (const GimpResource **) gimp_value_get_object_array ($value)',
dup_value_func => '{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index ($value)); if (a) $var = g_memdup2 (a->data, a->length * sizeof (gpointer)); }',
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_RESOURCE, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_RESOURCE, (GObject **) $var, $var_len)' },
brusharray => { name => 'BRUSHARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',
type => 'GimpBrush **',
const_type => 'const GimpBrush **',
array => 1,
init_value => 'NULL',
in_annotate => '(element-type GimpBrush)',
out_annotate => '(element-type GimpBrush) (transfer container)',
get_value_func => '$var = (const GimpBrush **) gimp_value_get_object_array ($value)',
dup_value_func => '{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index ($value)); if (a) $var = g_memdup2 (a->data, a->length * sizeof (gpointer)); }',
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_BRUSH, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_BRUSH, (GObject **) $var, $var_len)' },
fontarray => { name => 'FONTARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',
type => 'GimpFont **',
const_type => 'const GimpFont **',
array => 1,
init_value => 'NULL',
in_annotate => '(element-type GimpFont)',
out_annotate => '(element-type GimpFont) (transfer container)',
get_value_func => '$var = (const GimpFont **) gimp_value_get_object_array ($value)',
dup_value_func => '{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index ($value)); if (a) $var = g_memdup2 (a->data, a->length * sizeof (gpointer)); }',
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_FONT, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_FONT, (GObject **) $var, $var_len)' },
gradientarray => { name => 'GRADIENTARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',
type => 'GimpGradient **',
const_type => 'const GimpGradient **',
array => 1,
init_value => 'NULL',
in_annotate => '(element-type GimpGradient)',
out_annotate => '(element-type GimpGradient) (transfer container)',
get_value_func => '$var = (const GimpGradient **) gimp_value_get_object_array ($value)',
dup_value_func => '{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index ($value)); if (a) $var = g_memdup2 (a->data, a->length * sizeof (gpointer)); }',
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_GRADIENT, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_GRADIENT, (GObject **) $var, $var_len)' },
palettearray => { name => 'PALETTEARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',
type => 'GimpPalette **',
const_type => 'const GimpPalette **',
array => 1,
init_value => 'NULL',
in_annotate => '(element-type GimpPalette)',
out_annotate => '(element-type GimpPalette) (transfer container)',
get_value_func => '$var = (const GimpPalette **) gimp_value_get_object_array ($value)',
dup_value_func => '{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index ($value)); if (a) $var = g_memdup2 (a->data, a->length * sizeof (gpointer)); }',
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_PALETTE, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_PALETTE, (GObject **) $var, $var_len)' },
patternarray => { name => 'PATTERNARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',
type => 'GimpPattern **',
const_type => 'const GimpPattern **',
array => 1,
init_value => 'NULL',
in_annotate => '(element-type GimpPattern)',
out_annotate => '(element-type GimpPattern) (transfer container)',
get_value_func => '$var = (const GimpPattern **) gimp_value_get_object_array ($value)',
dup_value_func => '{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index ($value)); if (a) $var = g_memdup2 (a->data, a->length * sizeof (gpointer)); }',
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_PATTERN, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_PATTERN, (GObject **) $var, $var_len)' },
color => { name => 'COLOR',
gtype => 'GIMP_TYPE_RGB',
type => 'GimpRGB ',