app, libgimp, pdb, plug-ins: new GimpCoreObjectArray type and drawablearray…

… PDB type.

This is a first step for #7369. Clearly our GimpObjectArray was meant to
be used with C arrays, hence the wrapper function
gimp_value_set_object_array() which was taking a C array and actually
creating and setting a GimpObjectArray.

This is why our new type is actually a C array aliased as a boxed type
and containing its own size (thanks to NULL-termination).

Eventually GimpCoreObjectArray is meant to replace GimpObjectArray.

The only issue is that such a type does not allow NULL as a valid
element in such an array, but fact is that I don't think we currently
have any use case where this matters. If ever such a case arise in the
future, we may introduce back GimpObjectArray.

In this first commit, I replaced all itemarray PDB types with a new
drawablearray using this new boxed type when relevant.
This commit is contained in:
Jehan 2024-10-21 21:59:26 +02:00
parent cb4687633c
commit 38c2cd3b15
28 changed files with 739 additions and 437 deletions

View file

@ -60,12 +60,10 @@ edit_cut_invoker (GimpProcedure *procedure,
{
gboolean success = TRUE;
GimpValueArray *return_vals;
gint num_drawables;
const GimpItem **drawables;
const GimpDrawable **drawables;
gboolean non_empty = FALSE;
num_drawables = g_value_get_int (gimp_value_array_index (args, 0));
drawables = (const GimpItem **) gimp_value_get_object_array (gimp_value_array_index (args, 1));
drawables = g_value_get_boxed (gimp_value_array_index (args, 0));
if (success)
{
@ -73,7 +71,7 @@ edit_cut_invoker (GimpProcedure *procedure,
GList *drawable_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
GIMP_PDB_ITEM_CONTENT, error) ||
@ -139,12 +137,10 @@ edit_copy_invoker (GimpProcedure *procedure,
{
gboolean success = TRUE;
GimpValueArray *return_vals;
gint num_drawables;
const GimpItem **drawables;
const GimpDrawable **drawables;
gboolean non_empty = FALSE;
num_drawables = g_value_get_int (gimp_value_array_index (args, 0));
drawables = (const GimpItem **) gimp_value_get_object_array (gimp_value_array_index (args, 1));
drawables = g_value_get_boxed (gimp_value_array_index (args, 0));
if (success)
{
@ -152,7 +148,7 @@ edit_copy_invoker (GimpProcedure *procedure,
GList *drawables_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL, 0, error))
{
@ -171,7 +167,7 @@ edit_copy_invoker (GimpProcedure *procedure,
drawables_list = g_list_prepend (drawables_list, (gpointer) drawables[i]);
}
if (success && num_drawables > 0)
if (success && g_list_length (drawables_list) > 0)
{
GError *my_error = NULL;
@ -251,8 +247,7 @@ edit_paste_invoker (GimpProcedure *procedure,
GimpValueArray *return_vals;
GimpDrawable *drawable;
gboolean paste_into;
gint num_layers = 0;
GimpLayer **layers = NULL;
GimpDrawable **new_drawables = NULL;
drawable = g_value_get_object (gimp_value_array_index (args, 0));
paste_into = g_value_get_boolean (gimp_value_array_index (args, 1));
@ -268,6 +263,7 @@ edit_paste_invoker (GimpProcedure *procedure,
{
GList *drawables = NULL;
GList *list;
gint num_drawables;
gint i;
if (drawable != NULL)
@ -285,11 +281,11 @@ edit_paste_invoker (GimpProcedure *procedure,
if (! list)
success = FALSE;
num_layers = g_list_length (list);
layers = g_new (GimpLayer *, num_layers);
num_drawables = g_list_length (list);
new_drawables = g_new0 (GimpDrawable *, num_drawables + 1);
for (i = 0; i < num_layers; i++, list = g_list_next (list))
layers[i] = g_object_ref (list->data);
for (i = 0; i < num_drawables; i++, list = g_list_next (list))
new_drawables[i] = g_object_ref (list->data);
g_list_free (list);
}
@ -301,10 +297,7 @@ edit_paste_invoker (GimpProcedure *procedure,
error ? *error : NULL);
if (success)
{
g_value_set_int (gimp_value_array_index (return_vals, 1), num_layers);
gimp_value_take_object_array (gimp_value_array_index (return_vals, 2), GIMP_TYPE_LAYER, (GObject **) layers, num_layers);
}
g_value_take_boxed (gimp_value_array_index (return_vals, 1), new_drawables);
return return_vals;
}
@ -350,14 +343,12 @@ edit_named_cut_invoker (GimpProcedure *procedure,
{
gboolean success = TRUE;
GimpValueArray *return_vals;
gint num_drawables;
const GimpItem **drawables;
const GimpDrawable **drawables;
const gchar *buffer_name;
gchar *real_name = NULL;
num_drawables = g_value_get_int (gimp_value_array_index (args, 0));
drawables = (const GimpItem **) gimp_value_get_object_array (gimp_value_array_index (args, 1));
buffer_name = g_value_get_string (gimp_value_array_index (args, 2));
drawables = g_value_get_boxed (gimp_value_array_index (args, 0));
buffer_name = g_value_get_string (gimp_value_array_index (args, 1));
if (success)
{
@ -365,7 +356,7 @@ edit_named_cut_invoker (GimpProcedure *procedure,
GList *drawable_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
GIMP_PDB_ITEM_CONTENT, error) ||
@ -436,14 +427,12 @@ edit_named_copy_invoker (GimpProcedure *procedure,
{
gboolean success = TRUE;
GimpValueArray *return_vals;
gint num_drawables;
const GimpItem **drawables;
const GimpDrawable **drawables;
const gchar *buffer_name;
gchar *real_name = NULL;
num_drawables = g_value_get_int (gimp_value_array_index (args, 0));
drawables = (const GimpItem **) gimp_value_get_object_array (gimp_value_array_index (args, 1));
buffer_name = g_value_get_string (gimp_value_array_index (args, 2));
drawables = g_value_get_boxed (gimp_value_array_index (args, 0));
buffer_name = g_value_get_string (gimp_value_array_index (args, 1));
if (success)
{
@ -451,7 +440,7 @@ edit_named_copy_invoker (GimpProcedure *procedure,
GList *drawable_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
0, error))
@ -680,17 +669,11 @@ register_edit_procs (GimpPDB *pdb)
"Spencer Kimball & Peter Mattis",
"1995-1996");
gimp_procedure_add_argument (procedure,
g_param_spec_int ("num-drawables",
"num drawables",
"The number of drawables",
1, G_MAXINT32, 1,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_object_array ("drawables",
gimp_param_spec_core_object_array ("drawables",
"drawables",
"The drawables to cut from",
GIMP_TYPE_ITEM,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_boolean ("non-empty",
"non empty",
@ -717,17 +700,11 @@ register_edit_procs (GimpPDB *pdb)
"Spencer Kimball & Peter Mattis",
"1995-1996");
gimp_procedure_add_argument (procedure,
g_param_spec_int ("num-drawables",
"num drawables",
"The number of drawables to save",
1, G_MAXINT32, 1,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_object_array ("drawables",
gimp_param_spec_core_object_array ("drawables",
"drawables",
"Drawables to copy from",
GIMP_TYPE_ITEM,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_boolean ("non-empty",
"non empty",
@ -774,8 +751,8 @@ register_edit_procs (GimpPDB *pdb)
"gimp-edit-paste");
gimp_procedure_set_static_help (procedure,
"Paste buffer to the specified drawable.",
"This procedure pastes a copy of the internal GIMP edit buffer to the specified drawable. The GIMP edit buffer will be empty unless a call was previously made to either 'gimp-edit-cut' or 'gimp-edit-copy'. The \"paste_into\" option specifies whether to clear the current image selection, or to paste the buffer \"behind\" the selection. This allows the selection to act as a mask for the pasted buffer. Anywhere that the selection mask is non-zero, the pasted buffer will show through. The pasted data may be a floating selection when relevant, layers otherwise. If the image has a floating selection at the time of pasting, the old floating selection will be anchored to its drawable before the new floating selection is added.\n"
"This procedure returns the new layers (floating or not). If the result is a floating selection, it will already be attached to the specified drawable, and a subsequent call to floating_sel_attach is not needed.",
"This procedure pastes a copy of the internal GIMP edit buffer to the specified drawable. The GIMP edit buffer will be empty unless a call was previously made to either [func@Gimp.edit_cut] or [func@Gimp.edit_copy]. The \"paste_into\" option specifies whether to clear the current image selection, or to paste the buffer \"behind\" the selection. This allows the selection to act as a mask for the pasted buffer. Anywhere that the selection mask is non-zero, the pasted buffer will show through. The pasted data may be a floating selection when relevant, layers otherwise. If the image has a floating selection at the time of pasting, the old floating selection will be anchored to its drawable before the new floating selection is added.\n"
"This procedure returns the new drawables (floating or not). If the result is a floating selection, it will already be attached to the specified drawable, and a subsequent call to [func@Gimp.floating_sel_attach] is not needed.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Spencer Kimball & Peter Mattis",
@ -794,16 +771,10 @@ register_edit_procs (GimpPDB *pdb)
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_int ("num-layers",
"num layers",
"The newly pasted layers",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_object_array ("layers",
"layers",
gimp_param_spec_core_object_array ("new-drawables",
"new drawables",
"The list of pasted layers.",
GIMP_TYPE_LAYER,
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
@ -846,17 +817,11 @@ register_edit_procs (GimpPDB *pdb)
"Michael Natterer",
"2005");
gimp_procedure_add_argument (procedure,
g_param_spec_int ("num-drawables",
"num drawables",
"The number of drawables",
1, G_MAXINT32, 1,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_object_array ("drawables",
gimp_param_spec_core_object_array ("drawables",
"drawables",
"The drawables to cut from",
GIMP_TYPE_ITEM,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("buffer-name",
"buffer name",
@ -889,17 +854,11 @@ register_edit_procs (GimpPDB *pdb)
"Michael Natterer",
"2005");
gimp_procedure_add_argument (procedure,
g_param_spec_int ("num-drawables",
"num drawables",
"The number of drawables",
1, G_MAXINT32, 1,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_object_array ("drawables",
gimp_param_spec_core_object_array ("drawables",
"drawables",
"The drawables to copy from",
GIMP_TYPE_ITEM,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("buffer-name",
"buffer name",

View file

@ -651,8 +651,7 @@ image_pick_color_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
GimpValueArray *return_vals;
GimpImage *image;
gint num_drawables;
const GimpItem **drawables;
const GimpDrawable **drawables;
gdouble x;
gdouble y;
gboolean sample_merged;
@ -661,13 +660,12 @@ image_pick_color_invoker (GimpProcedure *procedure,
GeglColor *color = NULL;
image = g_value_get_object (gimp_value_array_index (args, 0));
num_drawables = g_value_get_int (gimp_value_array_index (args, 1));
drawables = (const GimpItem **) gimp_value_get_object_array (gimp_value_array_index (args, 2));
x = g_value_get_double (gimp_value_array_index (args, 3));
y = g_value_get_double (gimp_value_array_index (args, 4));
sample_merged = g_value_get_boolean (gimp_value_array_index (args, 5));
sample_average = g_value_get_boolean (gimp_value_array_index (args, 6));
average_radius = g_value_get_double (gimp_value_array_index (args, 7));
drawables = g_value_get_boxed (gimp_value_array_index (args, 1));
x = g_value_get_double (gimp_value_array_index (args, 2));
y = g_value_get_double (gimp_value_array_index (args, 3));
sample_merged = g_value_get_boolean (gimp_value_array_index (args, 4));
sample_average = g_value_get_boolean (gimp_value_array_index (args, 5));
average_radius = g_value_get_double (gimp_value_array_index (args, 6));
if (success)
{
@ -675,13 +673,13 @@ image_pick_color_invoker (GimpProcedure *procedure,
if (! sample_merged)
{
if (num_drawables == 0)
if (drawables == NULL || drawables[0] == NULL)
{
success = FALSE;
}
else
{
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
if (gimp_item_get_image (GIMP_ITEM (drawables[i])) != image)
{
success = FALSE;
@ -700,7 +698,7 @@ image_pick_color_invoker (GimpProcedure *procedure,
{
GList *drawable_list = NULL;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
GimpPickable *pickable = (GimpPickable *) drawables[i];
@ -2175,14 +2173,14 @@ image_get_selected_drawables_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
GimpValueArray *return_vals;
GimpImage *image;
gint num_drawables = 0;
GimpItem **drawables = NULL;
GimpDrawable **drawables = NULL;
image = g_value_get_object (gimp_value_array_index (args, 0));
if (success)
{
GList *list = gimp_image_get_selected_drawables (image);
gsize num_drawables;
num_drawables = g_list_length (list);
@ -2190,10 +2188,10 @@ image_get_selected_drawables_invoker (GimpProcedure *procedure,
{
gint i;
drawables = g_new (GimpItem *, num_drawables);
drawables = g_new0 (GimpDrawable *, num_drawables + 1);
for (i = 0; i < num_drawables; i++, list = g_list_next (list))
drawables[i] = g_object_ref (list->data);
drawables[i] = list->data;
}
}
@ -2201,10 +2199,7 @@ image_get_selected_drawables_invoker (GimpProcedure *procedure,
error ? *error : NULL);
if (success)
{
g_value_set_int (gimp_value_array_index (return_vals, 1), num_drawables);
gimp_value_take_object_array (gimp_value_array_index (return_vals, 2), GIMP_TYPE_ITEM, (GObject **) drawables, num_drawables);
}
g_value_take_boxed (gimp_value_array_index (return_vals, 1), drawables);
return return_vals;
}
@ -3674,17 +3669,11 @@ register_image_procs (GimpPDB *pdb)
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("num-drawables",
"num drawables",
"The number of drawables",
1, G_MAXINT32, 1,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_object_array ("drawables",
gimp_param_spec_core_object_array ("drawables",
"drawables",
"The drawables to pick from",
GIMP_TYPE_ITEM,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_double ("x",
"x",
@ -5087,16 +5076,10 @@ register_image_procs (GimpPDB *pdb)
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_int ("num-drawables",
"num drawables",
"The number of selected drawables in the image",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_object_array ("drawables",
gimp_param_spec_core_object_array ("drawables",
"drawables",
"The list of selected drawables in the image.",
GIMP_TYPE_ITEM,
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);

View file

@ -197,29 +197,27 @@ selection_float_invoker (GimpProcedure *procedure,
{
gboolean success = TRUE;
GimpValueArray *return_vals;
gint num_drawables;
const GimpItem **drawables;
const GimpDrawable **drawables;
gint offx;
gint offy;
GimpLayer *layer = NULL;
num_drawables = g_value_get_int (gimp_value_array_index (args, 0));
drawables = (const GimpItem **) gimp_value_get_object_array (gimp_value_array_index (args, 1));
offx = g_value_get_int (gimp_value_array_index (args, 2));
offy = g_value_get_int (gimp_value_array_index (args, 3));
drawables = g_value_get_boxed (gimp_value_array_index (args, 0));
offx = g_value_get_int (gimp_value_array_index (args, 1));
offy = g_value_get_int (gimp_value_array_index (args, 2));
if (success)
{
GimpImage *image = NULL;
gint i;
if (num_drawables < 1)
if (drawables == NULL || drawables[0] == NULL)
{
success = FALSE;
}
else
{
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
GIMP_PDB_ITEM_CONTENT, error) ||
@ -240,7 +238,7 @@ selection_float_invoker (GimpProcedure *procedure,
{
GList *drawable_list = NULL;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
drawable_list = g_list_prepend (drawable_list, (gpointer) drawables[i]);
layer = gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
@ -694,17 +692,11 @@ register_selection_procs (GimpPDB *pdb)
"Spencer Kimball & Peter Mattis",
"1995-1996");
gimp_procedure_add_argument (procedure,
g_param_spec_int ("num-drawables",
"num drawables",
"The number of drawables",
1, G_MAXINT32, 1,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_object_array ("drawables",
gimp_param_spec_core_object_array ("drawables",
"drawables",
"The drawables from which to float selection",
GIMP_TYPE_ITEM,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("offx",
"offx",

View file

@ -433,6 +433,7 @@ gimp_main (GType plug_in_type,
GIMP_TYPE_INT32_ARRAY, GIMP_TYPE_PARAM_INT32_ARRAY,
GIMP_TYPE_FLOAT_ARRAY, GIMP_TYPE_PARAM_FLOAT_ARRAY,
GIMP_TYPE_OBJECT_ARRAY, GIMP_TYPE_PARAM_OBJECT_ARRAY,
GIMP_TYPE_CORE_OBJECT_ARRAY, GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY,
GIMP_TYPE_DISPLAY, GIMP_TYPE_PARAM_DISPLAY,
GIMP_TYPE_IMAGE, GIMP_TYPE_PARAM_IMAGE,
@ -452,7 +453,7 @@ gimp_main (GType plug_in_type,
GIMP_TYPE_PALETTE, GIMP_TYPE_PARAM_PALETTE,
GIMP_TYPE_PATTERN, GIMP_TYPE_PARAM_PATTERN,
GIMP_TYPE_UNIT, GIMP_TYPE_PARAM_UNIT
GIMP_TYPE_UNIT, GIMP_TYPE_PARAM_UNIT,
};
gint i;

View file

@ -38,8 +38,7 @@
/**
* gimp_edit_cut:
* @num_drawables: The number of drawables.
* @drawables: (array length=num_drawables) (element-type GimpItem): The drawables to cut from.
* @drawables: (element-type GimpDrawable) (array zero-terminated=1): The drawables to cut from.
*
* Cut from the specified drawables.
*
@ -56,18 +55,15 @@
* Returns: TRUE if the cut was successful, FALSE if there was nothing to copy from.
**/
gboolean
gimp_edit_cut (gint num_drawables,
const GimpItem **drawables)
gimp_edit_cut (const GimpDrawable **drawables)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean non_empty = FALSE;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_INT, num_drawables,
GIMP_TYPE_OBJECT_ARRAY, NULL,
GIMP_TYPE_CORE_OBJECT_ARRAY, drawables,
G_TYPE_NONE);
gimp_value_set_object_array (gimp_value_array_index (args, 1), GIMP_TYPE_ITEM, (GObject **) drawables, num_drawables);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-edit-cut",
@ -84,8 +80,7 @@ gimp_edit_cut (gint num_drawables,
/**
* gimp_edit_copy:
* @num_drawables: The number of drawables to save.
* @drawables: (array length=num_drawables) (element-type GimpItem): Drawables to copy from.
* @drawables: (element-type GimpDrawable) (array zero-terminated=1): Drawables to copy from.
*
* Copy from the specified drawables.
*
@ -103,18 +98,15 @@ gimp_edit_cut (gint num_drawables,
* Returns: TRUE if the cut was successful, FALSE if there was nothing to copy from.
**/
gboolean
gimp_edit_copy (gint num_drawables,
const GimpItem **drawables)
gimp_edit_copy (const GimpDrawable **drawables)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean non_empty = FALSE;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_INT, num_drawables,
GIMP_TYPE_OBJECT_ARRAY, NULL,
GIMP_TYPE_CORE_OBJECT_ARRAY, drawables,
G_TYPE_NONE);
gimp_value_set_object_array (gimp_value_array_index (args, 1), GIMP_TYPE_ITEM, (GObject **) drawables, num_drawables);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-edit-copy",
@ -174,38 +166,36 @@ gimp_edit_copy_visible (GimpImage *image)
* gimp_edit_paste:
* @drawable: The drawable to paste to.
* @paste_into: Clear selection, or paste behind it?
* @num_layers: (out): The newly pasted layers.
*
* Paste buffer to the specified drawable.
*
* This procedure pastes a copy of the internal GIMP edit buffer to the
* specified drawable. The GIMP edit buffer will be empty unless a call
* was previously made to either gimp_edit_cut() or gimp_edit_copy().
* The \"paste_into\" option specifies whether to clear the current
* image selection, or to paste the buffer \"behind\" the selection.
* This allows the selection to act as a mask for the pasted buffer.
* Anywhere that the selection mask is non-zero, the pasted buffer will
* show through. The pasted data may be a floating selection when
* relevant, layers otherwise. If the image has a floating selection at
* the time of pasting, the old floating selection will be anchored to
* its drawable before the new floating selection is added.
* This procedure returns the new layers (floating or not). If the
* was previously made to either [func@Gimp.edit_cut] or
* [func@Gimp.edit_copy]. The \"paste_into\" option specifies whether
* to clear the current image selection, or to paste the buffer
* \"behind\" the selection. This allows the selection to act as a mask
* for the pasted buffer. Anywhere that the selection mask is non-zero,
* the pasted buffer will show through. The pasted data may be a
* floating selection when relevant, layers otherwise. If the image has
* a floating selection at the time of pasting, the old floating
* selection will be anchored to its drawable before the new floating
* selection is added.
* This procedure returns the new drawables (floating or not). If the
* result is a floating selection, it will already be attached to the
* specified drawable, and a subsequent call to floating_sel_attach is
* not needed.
* specified drawable, and a subsequent call to
* [func@Gimp.floating_sel_attach] is not needed.
*
* Returns: (array length=num_layers) (element-type GimpLayer) (transfer container):
* Returns: (element-type GimpDrawable) (array zero-terminated=1) (transfer container):
* The list of pasted layers.
* The returned value must be freed with g_free().
**/
GimpLayer **
GimpDrawable **
gimp_edit_paste (GimpDrawable *drawable,
gboolean paste_into,
gint *num_layers)
gboolean paste_into)
{
GimpValueArray *args;
GimpValueArray *return_vals;
GimpLayer **layers = NULL;
GimpDrawable **new_drawables = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_DRAWABLE, drawable,
@ -217,17 +207,12 @@ gimp_edit_paste (GimpDrawable *drawable,
args);
gimp_value_array_unref (args);
*num_layers = 0;
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
{
*num_layers = GIMP_VALUES_GET_INT (return_vals, 1);
{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index (return_vals, 2)); if (a) layers = g_memdup2 (a->data, a->length * sizeof (gpointer)); };
}
new_drawables = g_value_dup_boxed (gimp_value_array_index (return_vals, 1));
gimp_value_array_unref (return_vals);
return layers;
return new_drawables;
}
/**
@ -269,8 +254,7 @@ gimp_edit_paste_as_new_image (void)
/**
* gimp_edit_named_cut:
* @num_drawables: The number of drawables.
* @drawables: (array length=num_drawables) (element-type GimpItem): The drawables to cut from.
* @drawables: (element-type GimpDrawable) (array zero-terminated=1): The drawables to cut from.
* @buffer_name: The name of the buffer to create.
*
* Cut into a named buffer.
@ -287,8 +271,7 @@ gimp_edit_paste_as_new_image (void)
* Since: 2.4
**/
gchar *
gimp_edit_named_cut (gint num_drawables,
const GimpItem **drawables,
gimp_edit_named_cut (const GimpDrawable **drawables,
const gchar *buffer_name)
{
GimpValueArray *args;
@ -296,11 +279,9 @@ gimp_edit_named_cut (gint num_drawables,
gchar *real_name = NULL;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_INT, num_drawables,
GIMP_TYPE_OBJECT_ARRAY, NULL,
GIMP_TYPE_CORE_OBJECT_ARRAY, drawables,
G_TYPE_STRING, buffer_name,
G_TYPE_NONE);
gimp_value_set_object_array (gimp_value_array_index (args, 1), GIMP_TYPE_ITEM, (GObject **) drawables, num_drawables);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-edit-named-cut",
@ -317,8 +298,7 @@ gimp_edit_named_cut (gint num_drawables,
/**
* gimp_edit_named_copy:
* @num_drawables: The number of drawables.
* @drawables: (array length=num_drawables) (element-type GimpItem): The drawables to copy from.
* @drawables: (element-type GimpDrawable) (array zero-terminated=1): The drawables to copy from.
* @buffer_name: The name of the buffer to create.
*
* Copy into a named buffer.
@ -335,8 +315,7 @@ gimp_edit_named_cut (gint num_drawables,
* Since: 2.4
**/
gchar *
gimp_edit_named_copy (gint num_drawables,
const GimpItem **drawables,
gimp_edit_named_copy (const GimpDrawable **drawables,
const gchar *buffer_name)
{
GimpValueArray *args;
@ -344,11 +323,9 @@ gimp_edit_named_copy (gint num_drawables,
gchar *real_name = NULL;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_INT, num_drawables,
GIMP_TYPE_OBJECT_ARRAY, NULL,
GIMP_TYPE_CORE_OBJECT_ARRAY, drawables,
G_TYPE_STRING, buffer_name,
G_TYPE_NONE);
gimp_value_set_object_array (gimp_value_array_index (args, 1), GIMP_TYPE_ITEM, (GObject **) drawables, num_drawables);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-edit-named-copy",

View file

@ -32,20 +32,15 @@ G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
gboolean gimp_edit_cut (gint num_drawables,
const GimpItem **drawables);
gboolean gimp_edit_copy (gint num_drawables,
const GimpItem **drawables);
gboolean gimp_edit_cut (const GimpDrawable **drawables);
gboolean gimp_edit_copy (const GimpDrawable **drawables);
gboolean gimp_edit_copy_visible (GimpImage *image);
GimpLayer** gimp_edit_paste (GimpDrawable *drawable,
gboolean paste_into,
gint *num_layers);
GimpDrawable** gimp_edit_paste (GimpDrawable *drawable,
gboolean paste_into);
GimpImage* gimp_edit_paste_as_new_image (void);
gchar* gimp_edit_named_cut (gint num_drawables,
const GimpItem **drawables,
gchar* gimp_edit_named_cut (const GimpDrawable **drawables,
const gchar *buffer_name);
gchar* gimp_edit_named_copy (gint num_drawables,
const GimpItem **drawables,
gchar* gimp_edit_named_copy (const GimpDrawable **drawables,
const gchar *buffer_name);
gchar* gimp_edit_named_copy_visible (GimpImage *image,
const gchar *buffer_name);

View file

@ -513,6 +513,13 @@ _gimp_param_spec_to_gp_param_def (GParamSpec *pspec,
else
param_def->meta.m_resource.default_resource_id = 0;
}
else if (GIMP_IS_PARAM_SPEC_CORE_OBJECT_ARRAY (pspec))
{
param_def->param_def_type = GP_PARAM_DEF_TYPE_ID_ARRAY;
param_def->meta.m_id_array.type_name =
(gchar *) g_type_name (GIMP_PARAM_SPEC_CORE_OBJECT_ARRAY (pspec)->object_type);
}
else if (GIMP_IS_PARAM_SPEC_OBJECT_ARRAY (pspec))
{
param_def->param_def_type = GP_PARAM_DEF_TYPE_ID_ARRAY;
@ -903,6 +910,59 @@ gimp_gp_param_to_value (gpointer gimp,
g_value_take_boxed (value, colors);
}
else if (GIMP_VALUE_HOLDS_CORE_OBJECT_ARRAY (value))
{
GType object_type = G_TYPE_INVALID;
GObject **objects;
gint i;
if (param->data.d_id_array.type_name != NULL)
{
/* An empty array from a NULL has an arbitrary type_name set earlier. */
object_type = g_type_from_name (param->data.d_id_array.type_name);
}
else if (pspec != NULL)
{
object_type = GIMP_PARAM_SPEC_CORE_OBJECT_ARRAY (pspec)->object_type;
}
if (param->data.d_id_array.size > 1 && ! g_type_is_a (object_type, G_TYPE_OBJECT))
{
g_warning ("%s: GimpCoreObjectArray of unknown type.", G_STRFUNC);
return;
}
/* size might be zero. */
objects = g_new0 (GObject *, param->data.d_id_array.size + 1);
for (i = 0; i < param->data.d_id_array.size; i++)
{
gint id = param->data.d_id_array.data[i];
if (object_type == GIMP_TYPE_IMAGE)
{
objects[i] = (GObject *) get_image_by_id (gimp, id);
}
else if (g_type_is_a (object_type, GIMP_TYPE_ITEM))
{
objects[i] = (GObject *) get_item_by_id (gimp, id);
}
else if (g_type_is_a (object_type, GIMP_TYPE_DISPLAY))
{
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);
}
}
/* Even when size is zero, set gvalue to an empty GimpObjectArray object,
* having a valid but possibly arbitrary type of its elements.
*/
g_value_set_boxed (value, objects);
}
else if (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value))
{
GType object_type = G_TYPE_INVALID;
@ -1369,6 +1429,105 @@ gimp_value_to_gp_param (const GValue *value,
else
param->data.d_strv = array;
}
else if (GIMP_VALUE_HOLDS_CORE_OBJECT_ARRAY (value))
{
GObject **array = g_value_get_boxed (value);
param->param_type = GP_PARAM_TYPE_ID_ARRAY;
param->data.d_id_array.type_name = NULL;
if (array && array[0])
{
GType element_type = G_TYPE_NONE;
gsize array_length;
gint i;
for (i = 0; array[i] != NULL; i++)
{
if (element_type != G_TYPE_NONE)
{
if (! g_type_is_a (G_TYPE_FROM_INSTANCE (array[i]), element_type))
{
g_warning ("%s: GimpCoreObjectArray with element type %s holds unsupported element of type '%s'", G_STRFUNC,
g_type_name (element_type), g_type_name (G_TYPE_FROM_INSTANCE (array[i])));
break;
}
continue;
}
if (GIMP_IS_IMAGE (array[i]))
{
element_type = GIMP_TYPE_IMAGE;
}
else if (GIMP_IS_ITEM (array[i]))
{
element_type = GIMP_TYPE_ITEM;
}
else if (GIMP_IS_DISPLAY (array[i]))
{
element_type = GIMP_TYPE_DISPLAY;
}
else if (GIMP_IS_RESOURCE (array[i]))
{
element_type = GIMP_TYPE_RESOURCE;
}
else
{
g_warning ("%s: GimpCoreObjectArray holds unsupported type '%s'", G_STRFUNC,
g_type_name (G_TYPE_FROM_INSTANCE (array[i])));
break;
}
}
array_length = i;
param->data.d_id_array.size = array_length;
if (array_length > 0)
{
if (full_copy)
param->data.d_id_array.type_name = g_strdup (g_type_name (element_type));
else
param->data.d_id_array.type_name = (gchar *) g_type_name (element_type);
/* must be free'd also for full_copy == FALSE */
param->data.d_id_array.data = g_new (gint32, array_length);
}
for (i = 0; i < array_length; i++)
{
if (GIMP_IS_IMAGE (array[i]))
{
param->data.d_id_array.data[i] =
gimp_image_get_id (GIMP_IMAGE (array[i]));
}
else if (GIMP_IS_ITEM (array[i]))
{
param->data.d_id_array.data[i] =
gimp_item_get_id (GIMP_ITEM (array[i]));
}
else if (GIMP_IS_DISPLAY (array[i]))
{
param->data.d_id_array.data[i] =
gimp_display_get_id (GIMP_DISPLAY (array[i]));
}
else if (GIMP_IS_RESOURCE (array[i]))
{
param->data.d_id_array.data[i] = get_resource_id (array[i]);
}
else
{
param->data.d_id_array.data[i] = -1;
}
}
}
else
{
/* GValue intended to hold an array of objects is NULL.
* For convenience, we allow this, meaning empty.
*/
param->data.d_id_array.size = 0;
param->data.d_id_array.data = NULL;
}
}
else if (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value))
{
GimpObjectArray *array = g_value_get_boxed (value);

View file

@ -546,14 +546,13 @@ gimp_image_list_paths (GimpImage *image)
GList *
gimp_image_list_selected_drawables (GimpImage *image)
{
GimpItem **drawables;
gint num_drawables;
GimpDrawable **drawables;
GList *list = NULL;
gint i;
drawables = gimp_image_get_selected_drawables (image, &num_drawables);
drawables = gimp_image_get_selected_drawables (image);
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
list = g_list_prepend (list, drawables[i]);
g_free (drawables);

View file

@ -716,8 +716,7 @@ gimp_image_floating_sel_attached_to (GimpImage *image)
/**
* gimp_image_pick_color:
* @image: The image.
* @num_drawables: The number of drawables.
* @drawables: (array length=num_drawables) (element-type GimpItem): The drawables to pick from.
* @drawables: (element-type GimpDrawable) (array zero-terminated=1): The drawables to pick from.
* @x: x coordinate of upper-left corner of rectangle.
* @y: y coordinate of upper-left corner of rectangle.
* @sample_merged: Use the composite image, not the drawables.
@ -747,8 +746,7 @@ gimp_image_floating_sel_attached_to (GimpImage *image)
**/
gboolean
gimp_image_pick_color (GimpImage *image,
gint num_drawables,
const GimpItem **drawables,
const GimpDrawable **drawables,
gdouble x,
gdouble y,
gboolean sample_merged,
@ -762,15 +760,13 @@ gimp_image_pick_color (GimpImage *image,
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_IMAGE, image,
G_TYPE_INT, num_drawables,
GIMP_TYPE_OBJECT_ARRAY, NULL,
GIMP_TYPE_CORE_OBJECT_ARRAY, drawables,
G_TYPE_DOUBLE, x,
G_TYPE_DOUBLE, y,
G_TYPE_BOOLEAN, sample_merged,
G_TYPE_BOOLEAN, sample_average,
G_TYPE_DOUBLE, average_radius,
G_TYPE_NONE);
gimp_value_set_object_array (gimp_value_array_index (args, 2), GIMP_TYPE_ITEM, (GObject **) drawables, num_drawables);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-image-pick-color",
@ -2473,7 +2469,6 @@ gimp_image_set_selected_paths (GimpImage *image,
/**
* gimp_image_get_selected_drawables:
* @image: The image.
* @num_drawables: (out): The number of selected drawables in the image.
*
* Get the image's selected drawables
*
@ -2485,19 +2480,17 @@ gimp_image_set_selected_paths (GimpImage *image,
* has a layer mask and the layer mask is in edit mode, then the layer
* mask is the active drawable.
*
* Returns: (array length=num_drawables) (element-type GimpItem) (transfer container):
* Returns: (element-type GimpDrawable) (array zero-terminated=1) (transfer container):
* The list of selected drawables in the image.
* The returned value must be freed with g_free().
*
* Since: 3.0.0
**/
GimpItem **
gimp_image_get_selected_drawables (GimpImage *image,
gint *num_drawables)
GimpDrawable **
gimp_image_get_selected_drawables (GimpImage *image)
{
GimpValueArray *args;
GimpValueArray *return_vals;
GimpItem **drawables = NULL;
GimpDrawable **drawables = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_IMAGE, image,
@ -2508,13 +2501,8 @@ gimp_image_get_selected_drawables (GimpImage *image,
args);
gimp_value_array_unref (args);
*num_drawables = 0;
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
{
*num_drawables = GIMP_VALUES_GET_INT (return_vals, 1);
{ GimpObjectArray *a = g_value_get_boxed (gimp_value_array_index (return_vals, 2)); if (a) drawables = g_memdup2 (a->data, a->length * sizeof (gpointer)); };
}
drawables = g_value_dup_boxed (gimp_value_array_index (return_vals, 1));
gimp_value_array_unref (return_vals);

View file

@ -58,8 +58,7 @@ gboolean gimp_image_unset_active_channel (GimpImage
GimpLayer* gimp_image_get_floating_sel (GimpImage *image);
GimpDrawable* gimp_image_floating_sel_attached_to (GimpImage *image);
gboolean gimp_image_pick_color (GimpImage *image,
gint num_drawables,
const GimpItem **drawables,
const GimpDrawable **drawables,
gdouble x,
gdouble y,
gboolean sample_merged,
@ -161,8 +160,7 @@ GimpPath** gimp_image_get_selected_paths (GimpImage
gboolean gimp_image_set_selected_paths (GimpImage *image,
gint num_paths,
const GimpPath **paths);
GimpItem** gimp_image_get_selected_drawables (GimpImage *image,
gint *num_drawables);
GimpDrawable** gimp_image_get_selected_drawables (GimpImage *image);
GimpSelection* gimp_image_get_selection (GimpImage *image);
gboolean gimp_image_get_component_active (GimpImage *image,
GimpChannelType component);

View file

@ -73,8 +73,7 @@ gimp_selection_get_by_id (gint32 selection_id)
/**
* gimp_selection_float:
* @image: ignored
* @n_drawables: Size of @drawables.
* @drawables: (array length=n_drawables): The drawables from which to
* @drawables: (array zero-terminated=1): The drawables from which to
* float selection.
* @offx: x offset for translation.
* @offy: y offset for translation.
@ -92,13 +91,9 @@ gimp_selection_get_by_id (gint32 selection_id)
*/
GimpLayer *
gimp_selection_float (GimpImage *image,
gint n_drawables,
GimpDrawable **drawables,
gint offx,
gint offy)
{
return _gimp_selection_float (n_drawables,
(const GimpItem **) drawables,
offx,
offy);
return _gimp_selection_float ((const GimpDrawable **) drawables, offx, offy);
}

View file

@ -40,7 +40,6 @@ G_DECLARE_FINAL_TYPE (GimpSelection, gimp_selection, GIMP, SELECTION, GimpChanne
GimpSelection * gimp_selection_get_by_id (gint32 selection_id);
GimpLayer * gimp_selection_float (GimpImage *image,
gint n_drawables,
GimpDrawable **drawables,
gint offx,
gint offy);

View file

@ -222,8 +222,7 @@ gimp_selection_translate (GimpImage *image,
/**
* _gimp_selection_float:
* @num_drawables: The number of drawables.
* @drawables: (array length=num_drawables) (element-type GimpItem): The drawables from which to float selection.
* @drawables: (element-type GimpDrawable) (array zero-terminated=1): The drawables from which to float selection.
* @offx: x offset for translation.
* @offy: y offset for translation.
*
@ -239,8 +238,7 @@ gimp_selection_translate (GimpImage *image,
* Returns: (transfer none): The floated layer.
**/
GimpLayer *
_gimp_selection_float (gint num_drawables,
const GimpItem **drawables,
_gimp_selection_float (const GimpDrawable **drawables,
gint offx,
gint offy)
{
@ -249,12 +247,10 @@ _gimp_selection_float (gint num_drawables,
GimpLayer *layer = NULL;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_INT, num_drawables,
GIMP_TYPE_OBJECT_ARRAY, NULL,
GIMP_TYPE_CORE_OBJECT_ARRAY, drawables,
G_TYPE_INT, offx,
G_TYPE_INT, offy,
G_TYPE_NONE);
gimp_value_set_object_array (gimp_value_array_index (args, 1), GIMP_TYPE_ITEM, (GObject **) drawables, num_drawables);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-selection-float",

View file

@ -45,8 +45,7 @@ gboolean gimp_selection_is_empty (GimpImage *image);
gboolean gimp_selection_translate (GimpImage *image,
gint offx,
gint offy);
G_GNUC_INTERNAL GimpLayer* _gimp_selection_float (gint num_drawables,
const GimpItem **drawables,
G_GNUC_INTERNAL GimpLayer* _gimp_selection_float (const GimpDrawable **drawables,
gint offx,
gint offy);
gboolean gimp_selection_invert (GimpImage *image);

View file

@ -41,17 +41,17 @@ gimp_c_test_run (GimpProcedure *procedure,
/* 1. Fail with no selection */
GIMP_TEST_START("Gimp.Selection.float - no selection")
GIMP_TEST_END(gimp_selection_float (img, 1, &layer1, 10, 10) == NULL)
GIMP_TEST_END(gimp_selection_float (img, (GimpDrawable *[2]) { layer1, NULL }, 10, 10) == NULL)
/* 2. Fail on a group layer */
GIMP_TEST_START("Gimp.Selection.float - group layer")
GIMP_TEST_END(gimp_selection_float (img, 1, &group1, 10, 10) == NULL)
GIMP_TEST_END(gimp_selection_float (img, (GimpDrawable *[2]) { group1, NULL }, 10, 10) == NULL)
/* 3. Succeed on a normal layer */
gimp_image_select_rectangle (img, GIMP_CHANNEL_OP_REPLACE, 5, 5, 20, 20);
GIMP_TEST_START("gimp_selection_float - normal layer")
float_layer = gimp_selection_float (img, 1, &layer1, 10, 10);
float_layer = gimp_selection_float (img, (GimpDrawable *[2]) { layer1, NULL }, 10, 10);
GIMP_TEST_END(GIMP_IS_LAYER (float_layer))
GIMP_TEST_START("gimp_floating_sel_remove")
@ -61,7 +61,7 @@ gimp_c_test_run (GimpProcedure *procedure,
gimp_image_select_rectangle (img, GIMP_CHANNEL_OP_REPLACE, 5, 5, 20, 20);
GIMP_TEST_START("gimp_selection_float - layer inside group")
float_layer = gimp_selection_float (img, 1, &layer2, 10, 10);
float_layer = gimp_selection_float (img, (GimpDrawable *[2]) { layer2, NULL }, 10, 10);
GIMP_TEST_END(GIMP_IS_LAYER (float_layer))
GIMP_TEST_START("gimp_floating_sel_remove")

View file

@ -38,6 +38,7 @@ EXPORTS
gimp_component_type_get_type
gimp_convert_palette_type_get_type
gimp_convolve_type_get_type
gimp_core_object_array_get_type
gimp_cpu_accel_get_support
gimp_cpu_accel_set_use
gimp_data_directory
@ -125,6 +126,7 @@ EXPORTS
gimp_paint_application_mode_get_type
gimp_param_array_get_type
gimp_param_choice_get_type
gimp_param_core_object_array_get_type
gimp_param_export_options_get_type
gimp_param_float_array_get_type
gimp_param_int32_array_get_type
@ -134,6 +136,7 @@ EXPORTS
gimp_param_parasite_get_type
gimp_param_spec_array
gimp_param_spec_choice
gimp_param_spec_core_object_array
gimp_param_spec_export_options
gimp_param_spec_float_array
gimp_param_spec_int32_array

View file

@ -865,6 +865,223 @@ gimp_color_array_get_length (GimpColorArray array)
}
/*
* GIMP_TYPE_CORE_OBJECT_ARRAY
*/
static GimpCoreObjectArray gimp_core_object_array_copy (GimpCoreObjectArray array);
static gsize gimp_core_object_array_get_length (GimpCoreObjectArray array);
GType
gimp_core_object_array_get_type (void)
{
static gsize static_g_define_type_id = 0;
if (g_once_init_enter (&static_g_define_type_id))
{
GType g_define_type_id =
g_boxed_type_register_static (g_intern_static_string ("GimpCoreObjectArray"),
(GBoxedCopyFunc) gimp_core_object_array_copy,
(GBoxedFreeFunc) g_free);
g_once_init_leave (&static_g_define_type_id, g_define_type_id);
}
return static_g_define_type_id;
}
/**
* gimp_core_object_array_copy:
* @array: an array of core_objects.
*
* Duplicate a new #GimpCoreObjectArray, which is basically simply a
* %NULL-terminated array of [class@GObject.Object]. Note that you
* should only use this alias type for arrays of core type objects
* internally hold by `libgimp`, such as layers, channels, paths, images
* and so on, because no reference is hold to the element objects.
*
* As a consequence, the copy also makes a shallow copy of the elements.
*
* Returns: (transfer container) (array zero-terminated=1): a new #GimpCoreObjectArray.
**/
static GimpCoreObjectArray
gimp_core_object_array_copy (GimpCoreObjectArray array)
{
GObject **copy;
gsize length = gimp_core_object_array_get_length (array);
copy = g_malloc0 (sizeof (GObject *) * (length + 1));
for (gint i = 0; i < length; i++)
copy[i] = array[i];
return copy;
}
/**
* gimp_core_object_array_get_length:
* @array: an array of core_objects.
*
* Returns: the number of [class@GObject.Object] in @array.
**/
static gsize
gimp_core_object_array_get_length (GimpCoreObjectArray array)
{
gsize length = 0;
while (array && array[length] != NULL)
length++;
return length;
}
/*
* GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY
*/
static void gimp_param_core_object_array_class_init (GParamSpecClass *klass);
static void gimp_param_core_object_array_init (GParamSpec *pspec);
static gboolean gimp_param_core_object_array_validate (GParamSpec *pspec,
GValue *value);
static gint gimp_param_core_object_array_values_cmp (GParamSpec *pspec,
const GValue *value1,
const GValue *value2);
GType
gimp_param_core_object_array_get_type (void)
{
static GType type = 0;
if (! type)
{
const GTypeInfo info =
{
sizeof (GParamSpecClass),
NULL, NULL,
(GClassInitFunc) gimp_param_core_object_array_class_init,
NULL, NULL,
sizeof (GimpParamSpecCoreObjectArray),
0,
(GInstanceInitFunc) gimp_param_core_object_array_init
};
type = g_type_register_static (G_TYPE_PARAM_BOXED,
"GimpParamCoreObjectArray", &info, 0);
}
return type;
}
static void
gimp_param_core_object_array_class_init (GParamSpecClass *klass)
{
klass->value_type = GIMP_TYPE_CORE_OBJECT_ARRAY;
klass->value_validate = gimp_param_core_object_array_validate;
klass->values_cmp = gimp_param_core_object_array_values_cmp;
}
static void
gimp_param_core_object_array_init (GParamSpec *pspec)
{
}
static gboolean
gimp_param_core_object_array_validate (GParamSpec *pspec,
GValue *value)
{
GimpParamSpecCoreObjectArray *array_spec = GIMP_PARAM_SPEC_CORE_OBJECT_ARRAY (pspec);
GObject **array = value->data[0].v_pointer;
if (array)
{
gsize length = gimp_core_object_array_get_length (array);
gsize i;
if (length == 0)
{
g_value_set_boxed (value, NULL);
return FALSE;
}
for (i = 0; i < length; i++)
{
if (array[i] && ! g_type_is_a (G_OBJECT_TYPE (array[i]), array_spec->object_type))
{
g_value_set_boxed (value, NULL);
return TRUE;
}
}
}
return FALSE;
}
static gint
gimp_param_core_object_array_values_cmp (GParamSpec *pspec,
const GValue *value1,
const GValue *value2)
{
GObject **array1 = value1->data[0].v_pointer;
GObject **array2 = value2->data[0].v_pointer;
/* try to return at least *something*, it's useless anyway... */
if (! array1)
return array2 != NULL ? -1 : 0;
else if (! array2)
return array1 != NULL ? 1 : 0;
else if (gimp_core_object_array_get_length (array1) < gimp_core_object_array_get_length (array2))
return -1;
else if (gimp_core_object_array_get_length (array1) > gimp_core_object_array_get_length (array2))
return 1;
for (gsize i = 0; i < gimp_core_object_array_get_length (array1); i++)
if (array1[0] != array2[0])
return 1;
return 0;
}
/**
* gimp_param_spec_core_object_array:
* @name: Canonical name of the property specified.
* @nick: Nick name of the property specified.
* @blurb: Description of the property specified.
* @object_type: GType of the array's elements.
* @flags: Flags for the property specified.
*
* Creates a new #GimpParamSpecCoreObjectArray specifying a
* [type@CoreObjectArray] property.
*
* See g_param_spec_internal() for details on property names.
*
* Returns: (transfer floating): The newly created #GimpParamSpecCoreObjectArray.
*
* Since: 3.0
**/
GParamSpec *
gimp_param_spec_core_object_array (const gchar *name,
const gchar *nick,
const gchar *blurb,
GType object_type,
GParamFlags flags)
{
GimpParamSpecCoreObjectArray *array_spec;
g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
array_spec = g_param_spec_internal (GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY,
name, nick, blurb, flags);
g_return_val_if_fail (array_spec, NULL);
array_spec->object_type = object_type;
return G_PARAM_SPEC (array_spec);
}
/*
* GIMP_TYPE_OBJECT_ARRAY
*/

View file

@ -345,6 +345,58 @@ void gimp_color_array_free (GimpColorArray array);
gint gimp_color_array_get_length (GimpColorArray array);
/*
* GIMP_TYPE_CORE_OBJECT_ARRAY
*/
/**
* GimpCoreObjectArray:
*
* A boxed type which is nothing more than an alias to a %NULL-terminated array
* of [class@GObject.Object]. No reference is being hold on contents
* because core objects are owned by `libgimp`.
*
* The reason of existence for this alias is to have common arrays of
* objects as a boxed type easy to use as plug-in's procedure argument.
*
* You should never have to interact with this type directly.
*
* Since: 3.0
*/
typedef GObject** GimpCoreObjectArray;
#define GIMP_TYPE_CORE_OBJECT_ARRAY (gimp_core_object_array_get_type ())
#define GIMP_VALUE_HOLDS_CORE_OBJECT_ARRAY(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_CORE_OBJECT_ARRAY))
GType gimp_core_object_array_get_type (void) G_GNUC_CONST;
/*
* GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY
*/
#define GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY (gimp_param_core_object_array_get_type ())
#define GIMP_PARAM_SPEC_CORE_OBJECT_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY, GimpParamSpecCoreObjectArray))
#define GIMP_IS_PARAM_SPEC_CORE_OBJECT_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY))
typedef struct _GimpParamSpecCoreObjectArray GimpParamSpecCoreObjectArray;
struct _GimpParamSpecCoreObjectArray
{
GParamSpecBoxed parent_instance;
GType object_type;
};
GType gimp_param_core_object_array_get_type (void) G_GNUC_CONST;
GParamSpec * gimp_param_spec_core_object_array (const gchar *name,
const gchar *nick,
const gchar *blurb,
GType object_type,
GParamFlags flags);
/*
* GIMP_TYPE_OBJECT_ARRAY
*/

View file

@ -696,6 +696,15 @@ gimp_param_spec_object_array ("$name",
"$blurb",
GIMP_TYPE_ITEM,
$flags)
CODE
}
elsif ($pdbtype eq 'drawablearray') {
$pspec = <<CODE;
gimp_param_spec_core_object_array ("$name",
"$nick",
"$blurb",
GIMP_TYPE_DRAWABLE,
$flags)
CODE
}
elsif ($pdbtype eq 'layerarray') {

View file

@ -35,12 +35,8 @@ HELP
&std_pdb_misc;
@inargs = (
{ name => 'drawables', type => 'itemarray',
desc => 'The drawables to cut from',
no_validate => 1,
array => { name => 'num_drawables',
type => '1 <= int32',
desc => "The number of drawables" } }
{ name => 'drawables', type => 'drawablearray',
desc => 'The drawables to cut from' }
);
@outargs = (
@ -56,7 +52,7 @@ HELP
GList *drawable_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
GIMP_PDB_ITEM_CONTENT, error) ||
@ -127,12 +123,8 @@ HELP
&std_pdb_misc;
@inargs = (
{ name => 'drawables', type => 'itemarray',
desc => 'Drawables to copy from',
no_validate => 1,
array => { name => 'num_drawables',
type => '1 <= int32',
desc => "The number of drawables to save" } },
{ name => 'drawables', type => 'drawablearray',
desc => 'Drawables to copy from' }
);
@outargs = (
@ -148,7 +140,7 @@ HELP
GList *drawables_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL, 0, error))
{
@ -167,7 +159,7 @@ HELP
drawables_list = g_list_prepend (drawables_list, (gpointer) drawables[i]);
}
if (success && num_drawables > 0)
if (success && g_list_length (drawables_list) > 0)
{
GError *my_error = NULL;
@ -238,8 +230,8 @@ sub edit_paste {
$help = <<'HELP';
This procedure pastes a copy of the internal GIMP edit buffer to the
specified drawable. The GIMP edit buffer will be empty unless a call
was previously made to either gimp_edit_cut() or gimp_edit_copy(). The
"paste_into" option specifies whether to clear the current image
was previously made to either [func@Gimp.edit_cut] or [func@Gimp.edit_copy].
The "paste_into" option specifies whether to clear the current image
selection, or to paste the buffer "behind" the selection. This allows
the selection to act as a mask for the pasted buffer. Anywhere that
the selection mask is non-zero, the pasted buffer will show
@ -249,9 +241,9 @@ If the image has a floating selection at the time of pasting, the old
floating selection will be anchored to its drawable before the new
floating selection is added.
This procedure returns the new layers (floating or not). If the result
This procedure returns the new drawables (floating or not). If the result
is a floating selection, it will already be attached to the specified
drawable, and a subsequent call to floating_sel_attach is not needed.
drawable, and a subsequent call to [func@Gimp.floating_sel_attach] is not needed.
HELP
&std_pdb_misc;
@ -264,10 +256,8 @@ HELP
);
@outargs = (
{ name => 'layers', type => 'layerarray',
desc => 'The list of pasted layers.',
array => { name => 'num_layers',
desc => 'The newly pasted layers' } }
{ name => 'new_drawables', type => 'drawablearray',
desc => 'The list of pasted layers.' }
);
%invoke = (
@ -282,6 +272,7 @@ HELP
{
GList *drawables = NULL;
GList *list;
gint num_drawables;
gint i;
if (drawable != NULL)
@ -299,11 +290,11 @@ HELP
if (! list)
success = FALSE;
num_layers = g_list_length (list);
layers = g_new (GimpLayer *, num_layers);
num_drawables = g_list_length (list);
new_drawables = g_new0 (GimpDrawable *, num_drawables + 1);
for (i = 0; i < num_layers; i++, list = g_list_next (list))
layers[i] = g_object_ref (list->data);
for (i = 0; i < num_drawables; i++, list = g_list_next (list))
new_drawables[i] = g_object_ref (list->data);
g_list_free (list);
}
@ -359,12 +350,8 @@ HELP
&mitch_pdb_misc('2005', '2.4');
@inargs = (
{ name => 'drawables', type => 'itemarray',
desc => 'The drawables to cut from',
no_validate => 1,
array => { name => 'num_drawables',
type => '1 <= int32',
desc => "The number of drawables" } },
{ name => 'drawables', type => 'drawablearray',
desc => 'The drawables to cut from' },
{ name => 'buffer_name', type => 'string', non_empty => 1,
desc => 'The name of the buffer to create' }
);
@ -382,7 +369,7 @@ HELP
GList *drawable_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
GIMP_PDB_ITEM_CONTENT, error) ||
@ -449,12 +436,8 @@ HELP
&mitch_pdb_misc('2005', '2.4');
@inargs = (
{ name => 'drawables', type => 'itemarray',
desc => 'The drawables to copy from',
no_validate => 1,
array => { name => 'num_drawables',
type => '1 <= int32',
desc => "The number of drawables" } },
{ name => 'drawables', type => 'drawablearray',
desc => 'The drawables to copy from' },
{ name => 'buffer_name', type => 'string', non_empty => 1,
desc => 'The name of the buffer to create' }
);
@ -472,7 +455,7 @@ HELP
GList *drawable_list = NULL;
gint i;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
0, error))

View file

@ -429,12 +429,8 @@ HELP
@inargs = (
{ name => 'image', type => 'image',
desc => 'The image' },
{ name => 'drawables', type => 'itemarray',
desc => 'The drawables to pick from',
no_validate => 1,
array => { name => 'num_drawables',
type => '1 <= int32',
desc => "The number of drawables" } },
{ name => 'drawables', type => 'drawablearray',
desc => 'The drawables to pick from' },
{ name => 'x', type => 'float',
desc => 'x coordinate of upper-left corner of rectangle' },
{ name => 'y', type => 'float',
@ -461,13 +457,13 @@ HELP
if (! sample_merged)
{
if (num_drawables == 0)
if (drawables == NULL || drawables[0] == NULL)
{
success = FALSE;
}
else
{
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
if (gimp_item_get_image (GIMP_ITEM (drawables[i])) != image)
{
success = FALSE;
@ -486,7 +482,7 @@ HELP
{
GList *drawable_list = NULL;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
GimpPickable *pickable = (GimpPickable *) drawables[i];
@ -2231,16 +2227,15 @@ HELP
);
@outargs = (
{ name => 'drawables', type => 'itemarray',
desc => 'The list of selected drawables in the image.',
array => { name => 'num_drawables',
desc => 'The number of selected drawables in the image' } }
{ name => 'drawables', type => 'drawablearray',
desc => 'The list of selected drawables in the image.' }
);
%invoke = (
code => <<'CODE'
{
GList *list = gimp_image_get_selected_drawables (image);
gsize num_drawables;
num_drawables = g_list_length (list);
@ -2248,10 +2243,10 @@ HELP
{
gint i;
drawables = g_new (GimpItem *, num_drawables);
drawables = g_new0 (GimpDrawable *, num_drawables + 1);
for (i = 0; i < num_drawables; i++, list = g_list_next (list))
drawables[i] = g_object_ref (list->data);
drawables[i] = list->data;
}
}
CODE

View file

@ -181,12 +181,8 @@ HELP
$lib_private = 1;
@inargs = (
{ name => 'drawables', type => 'itemarray',
desc => 'The drawables from which to float selection',
no_validate => 1,
array => { name => 'num_drawables',
type => '1 <= int32',
desc => "The number of drawables" } },
{ name => 'drawables', type => 'drawablearray',
desc => 'The drawables from which to float selection' },
{ name => 'offx', type => 'int32',
desc => 'x offset for translation' },
{ name => 'offy', type => 'int32',
@ -204,13 +200,13 @@ HELP
GimpImage *image = NULL;
gint i;
if (num_drawables < 1)
if (drawables == NULL || drawables[0] == NULL)
{
success = FALSE;
}
else
{
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
{
if (! gimp_pdb_item_is_attached (GIMP_ITEM (drawables[i]), NULL,
GIMP_PDB_ITEM_CONTENT, error) ||
@ -231,7 +227,7 @@ HELP
{
GList *drawable_list = NULL;
for (i = 0; i < num_drawables; i++)
for (i = 0; drawables[i] != NULL; i++)
drawable_list = g_list_prepend (drawable_list, (gpointer) drawables[i]);
layer = gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),

View file

@ -135,6 +135,18 @@ package Gimp::CodeGen::pdb;
set_value_func => 'gimp_value_set_object_array ($value, GIMP_TYPE_ITEM, (GObject **) $var, $var_len)',
take_value_func => 'gimp_value_take_object_array ($value, GIMP_TYPE_ITEM, (GObject **) $var, $var_len)' },
drawablearray => { name => 'DRAWABLEARRAY',
gtype => 'GIMP_TYPE_CORE_OBJECT_ARRAY',
type => 'GimpDrawable **',
const_type => 'const GimpDrawable **',
init_value => 'NULL',
in_annotate => '(element-type GimpDrawable) (array zero-terminated=1)',
out_annotate => '(element-type GimpDrawable) (array zero-terminated=1) (transfer container)',
get_value_func => '$var = g_value_get_boxed ($value)',
dup_value_func => '$var = g_value_dup_boxed (gimp_value_array_index ($value))',
set_value_func => 'g_value_set_boxed ($value, $var)',
take_value_func => 'g_value_take_boxed ($value, $var)' },
layerarray => { name => 'LAYERARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',
type => 'GimpLayer **',

View file

@ -593,18 +593,19 @@ p_if_selection_float_it (GimpImage *image,
if (non_empty && sel_channel)
{
const GimpDrawable *drawables[2] = { (GimpDrawable *) layer, NULL };
/* selection is TRUE, make a layer (floating selection) from
the selection */
if (gimp_edit_copy (1, (const GimpItem **) &layer))
if (gimp_edit_copy (drawables))
{
GimpLayer **layers;
gint num_layers;
GimpDrawable **layers;
layers = gimp_edit_paste (GIMP_DRAWABLE (layer), FALSE, &num_layers);
layers = gimp_edit_paste (GIMP_DRAWABLE (layer), FALSE);
/* Since we explicitly copied a single layer, there should
* be no more than a single layer in the paste as well.
*/
layer = num_layers ? layers[0] : NULL;
layer = (GimpLayer *) (layers && layers[0] ? layers[0] : NULL);
g_free (layers);
}

View file

@ -713,16 +713,16 @@ pdf_export_image (GimpProcedure *procedure,
gint32 n_layers;
gdouble x_res, y_res;
gdouble x_scale, y_scale;
GimpItem **drawables;
gint n_drawables;
GimpDrawable **drawables;
gint j;
drawables = gimp_image_get_selected_drawables (image, &n_drawables);
if (n_drawables == 0)
drawables = gimp_image_get_selected_drawables (image);
if (drawables[0] == NULL)
{
g_free (drawables);
continue;
}
g_free (drawables);
/* Save the state of the surface before any changes, so that
* settings from one page won't affect all the others
@ -1597,9 +1597,9 @@ drawText (GimpLayer *layer,
if (type == GIMP_RGBA_IMAGE)
color = gimp_text_layer_get_color (GIMP_TEXT_LAYER (layer));
else
gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)), 1,
(const GimpItem**) &layer, x, y, FALSE, FALSE, 0,
&color);
gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)),
(const GimpDrawable*[2]) { GIMP_DRAWABLE (layer), NULL },
x, y, FALSE, FALSE, 0, &color);
/* TODO: this export plug-in is not space-aware yet, so we draw everything as
* sRGB for the time being.

View file

@ -1289,10 +1289,9 @@ load_image (GFile *file,
{
GimpLayer *current_layer;
gchar *name;
GimpItem **tmp_drawables;
gint n_drawables;
GimpDrawable **tmp_drawables;
tmp_drawables = gimp_image_get_selected_drawables (image_list[k], &n_drawables);
tmp_drawables = gimp_image_get_selected_drawables (image_list[k]);
name = gimp_item_get_name (GIMP_ITEM (tmp_drawables[0]));

View file

@ -571,11 +571,10 @@ write_dds (GFile *file,
if (! is_duplicate_image)
{
GimpImage *duplicate_image = gimp_image_duplicate (image);
GimpItem **drawables;
gint n_drawables;
GimpDrawable **drawables;
drawables = gimp_image_get_selected_drawables (duplicate_image, &n_drawables);
rc = write_image (fp, duplicate_image, GIMP_DRAWABLE (drawables[0]), config);
drawables = gimp_image_get_selected_drawables (duplicate_image);
rc = write_image (fp, duplicate_image, drawables[0], config);
gimp_image_delete (duplicate_image);
g_free (drawables);
}

View file

@ -292,11 +292,10 @@ fits_export (GimpProcedure *procedure,
gpointer run_data)
{
GimpImage *duplicate_image;
GimpItem **flipped_drawables;
GimpDrawable **flipped_drawables;
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpExportReturn export = GIMP_EXPORT_IGNORE;
GList *drawables;
gint n_drawables;
GError *error = NULL;
gegl_init (NULL, NULL);
@ -307,16 +306,13 @@ fits_export (GimpProcedure *procedure,
export = gimp_export_options_get_image (options, &image);
drawables = gimp_image_list_layers (image);
n_drawables = g_list_length (drawables);
/* Flip image vertical since FITS writes from bottom to top */
duplicate_image = gimp_image_duplicate (image);
gimp_image_flip (duplicate_image, GIMP_ORIENTATION_VERTICAL);
flipped_drawables =
gimp_image_get_selected_drawables (duplicate_image, &n_drawables);
flipped_drawables = gimp_image_get_selected_drawables (duplicate_image);
if (! export_image (file, image, GIMP_DRAWABLE (flipped_drawables[0]),
&error))
if (! export_image (file, image, flipped_drawables[0], &error))
status = GIMP_PDB_EXECUTION_ERROR;
gimp_image_delete (duplicate_image);