because they are deprecated.
Change GIMP_ICON_TYPE_INLINE_PIXBUF to GIMP_ICON_TYPE_PIXBUF and the
libgimp API to (icon-name, GdkPixbuf, GFile). Use the file's uri and a
PNG blob of the pixbuf to pass around on the wire and for storage in
pluginrc.
Pass the help-id specified by the procedure to the core, and use it in
the core if set instead of always using the procedure's name (which
was probably good enough for all eternity, but it's still more
consistent this way).
Apart from being less code, this actually gives us a nice performance
improvement. Up until a few years ago, if you pass `NULL` as the
marshaller for a signal, GLib would fall back to
`g_cclosure_marshal_generic` which uses libffi to pack/unpack its
arguments. One could avoid this by specifying a more specific
marshaller which would then be used to immediately pack and unpack into
GValues with the correct type.
Lately however, as a way of optimizing signal emission (which can be
quite expensive), GLib added a possibility to set a va_marshaller, which
skips the unnecessary GValue packing and unpacking and just uses a
valist variant.
Since the performance difference is big enough, if the marshaller
argument is NULL, `g_signal_new()` will now check for the simple
marshallers (return type NONE and a single argument) and set both the
generic and the valist marshaller. In other words, less code for us with
bigger optimizations.
In case you also want va_marshallers for more complex signals, you can
use `g_signal_set_va_marshaller()`.
In gimp_palette_mru_add(), if the added color doesn't match an
existing color, don't look for two duplicate existing colors (which
has quadratic complexity), since there shouldn't be any under
normal circumstances (as we're not adding duplicates to begin
with).
for procedure arguments. This implies creating a new value array in
gimp_procedure_run() if the passed array is too short, instead of
just appending to the passed array, which was ugly anyway.
Which return proper GParamSpecs. Incuding some useless testing code in
gimp_procedural_db_proc_info(), to make sure things work, will go away
again soon.
Also generate comments like "Must be freed with g_free()" for all
return values instead of manually and inconsistently having them on
some return values only.
allow to pass booleans and enums to GIMP_TYPE_INT32 arguments. We
didn't have them in the old plug-in API, and being less strict allows
for booleans and enums being passed to old procedures transparently.
`g_object_notify()` actually takes a global lock to look up the property
by its name, which means there is a performance hit (albeit tiny) every
time this function is called. For this reason, always try to use
`g_object_notify_by_pspec()` instead.
Basically this commit makes sure that all return values that are marked
as "Returns:" also have a `(nullable)` annotation if it is mentioned on
the same line that NULL can also be returned.
This will prevent a few problems in GObject-introspection.
Documentation-wise in C, this doesn't matter a lot, but it allows
GObject-Introspection based bindings to use their built-in versions when
they want to render any kind of documentation (for example, docs for
Python plugins can render `%NULL` as `None`).
In GimpPaintbrush, calculate grad_point in
_gimp_paintbrush_motion() independently of any stroke, and pass
its value down to GimpPaintbrush::get_paint_params() at each
stroke, so that the color is the same for all strokes, even when
using a color/random dynamics.
In GimpFilterTool, add a new "clipping" option, which can be either
Adjust or Clip. This option is controllable for layers, when
there's no selection mask.
When set to Adjust, which is used by default, the filter's output
may extent past the drawable's boundary, and the drawable will be
resized to match the output when committed.
In GimpDrawableFilter, add a new gimp_drawable_filter_set_clip()
function, which controls whether the filter clips the result to the
drawable's boundary, or extends it past it. The latter is only
possible for layers, when the selection mask is empty.
Add a new "clip" parameter to gimp_drawable_merge_filter(). When
set to FALSE, the function resizes the drawable to the bounding box
of the filter's output, instead of clipping the output to the
drawable's boundary.
In gimp_gegl_apply_cached_operation(), copy the cached results to
the destination buffer *before* reconnecting the operation node, as
this may cause the cache to be cleared (see commit
gegl@4347255cd9d5031e6757c70fdde5c63539d5f508).
In GimpGroupLayer, when recalculating the group's size as a result
of a change to one of the child layers (now including in response
to a child layer's GimpDrawable::bounding-box-changed signal),
calculate the group's bounding box (the bounding box of all its
child layers' bounding boxes) alongside its logical bounds. Like
in GimpLayer, use the logical bounds as the bounding box if the
group has a mask.
This bounding box is passed to the group's projection, via
GimpGroupLayer's GimpProjectable::get_bounding_box()
implementation, resulting in a buffer whose extent is the same as
the bounding box.
In GimpProjectable, replace gimp_projectable_get_size(), which only
returned a width and a height, with
gimp_projectable_get_bounding_box(), which returns a full
rectangle. This allows projectables to have an arbitrary bounding
box, not limited to a (0, 0) top-left corner.
Adapt GimpProjection, creating a buffer with corresponding extent
to the projectable's bounding box.
Adapt GimpImage and GimpGroupLayer.
Implement GimpDrawable::get_bounding_box() for GimpLayer, by
returning the bounding box of its source node. If the layer has a
mask, we simply return its logical boundary, since the layer can't
extend past the mask.
Maintain the bounding box of drawables (i.e., the bounds of their
actual rendered content) separately from their logical boundary (as
shown in the UI).
The bounding box is calculated through the new
GimpDrawable::get_bounding_box() virtual function, which has a
corresponding gimp_drawable_get_bounding_box() function; the
default implementation simply returns the drawable's logical
boundary. The bounding box is specified in drawable coordinates,
i.e., it's not affected by the drawable's offset.
The bounding box is recalculated through
gimp_drawable_update_bounding_box(), which should be called
whenever a change may affect the bounding box (for example, when
setting a new buffer, as done implicitly by GimpDrawable's
::set_buffer() implementation, or when a drawable filter's
properties change, as will be done by GimpDrawableFilter in a
following commit). When the bounding box changes, the affected
regions of the drawable are updated, and the
GimpDrawable::bounding-box-changed signal is emitted.
When gimp_drawable_update() is called with negative width/height
values, the entire drawable's bounding box is updated, rather than
only its logical boundary.
Likewise, GimpDrawableStack and GimpLayerStack are adapted to use
the bounding box, instead of the logical bounds, when updating the
drawable's area.
In GimpDrawable::set_buffer(), and the corresponding
gimp_drawable_set_buffer_full() function, take a bounds rectangle,
which specifies both the drawable's new offset and its new size,
instead of only taking the new offset. In
gimp_drawable_real_set_buffer(), set the item size according to the
rect dimensions, instead of the buffer dimensions. The rect's
width/height may be 0, in which case the buffer's dimensions are
used.
Adapt the rest of the code.
We do this in preparation for maintaining the drawable's bounding
box separately from its logical bounds, allowing the drawable
content to extend beyond its bounds.
This is especially true since procedures are defined by plug-ins,
possibly third-party. So they may not have a first run mode parameter.
Also we don't want plug-ins to generate CRITICALs in the core
application.
Therefore before trying to get and/or set the run mode parameter, always
check that this first parameter exists, and if so, is it a GimpRunMode
enum?
Fixes similar errors:
> GIMP-CRITICAL: gimp_value_array_index: assertion 'index < value_array->n_values' failed
Moreover it also makes sense to allow plug-ins to not have such
parameter. What if you make a plug-in which always work in a single mode
and don't ever plan/want to make it work interactively for instance?
Lastly old Python 2 plug-ins didn't even have a run mode parameter (I
guess our old Python 2 wrapper was getting rid of it?).