Don't destroy the color frames when the number of points changes.
Instead, simply hide them so they keep their color model, but add an
upper limit of an arbitrary number of 16 frames to keep around.
The extension dialog will show details about an extension (long
description, screenshot, upstream URLs, etc.) with this widget.
Update the GimpExtensionList to send a "extension-activated" signal on
double click, and make the extensions dialog react on it to display the
extension details for the activated extension.
This is all still mostly a skeleton GUI, but it is starting to get into
shape.
This is using GTK+3 widgets, so I make sure to keep it well separated
from core code. The gimp-2-10 version will have to rework the GUI, but
the GtkListBox and GtkSwitch are nice and make things easier, so it is
worth using them here).
To be used in the next commit.
I keep the GUI and core changes well separated in different commits so
that the core is easy to cherry-pick even though I will have to have
different GUI code.
GIMP_APP_VERSION does not include the micro version.
Also make version comparison with org.gimp.GIMP mandatory to force good
practice. This way, extension makers will have to advertize the version
of GIMP it works for, which will make a sane ecosystem of working
extensions only (hopefully!).
... (valgrind reports Invalid read)
Add gimp_babl_is_valid(), which takes a GimpImageBaseType and a
GimpPrecision, and determines whether the image-type/precision
combination is valid. Use this function to validate that loaded
XCFs use a valid type/precision combination, before trying to
create the image. Otherwise, we get a CRITICAL, and eventually a
segfault, when the combination is invalid.
Use the same function to validate the arguments of
gimp_image_new().
Introduce GIMP_PATTERN_MAX_SIZE (10000) and GIMP_PATTERN_MAX_NAME (256)
and validate pattern dimensions and pattern name length against them.
Add GIMP_BRUSH_MAX_NAME and validate that too.
Also make sure that the names are properly terminated, and some
cleanup.
In app_exit_after_callback(), call gimp_gegl_exit() before
gegl_exit() when performing a quick shut-down in stable versions,
so that gimp-parallel, and, in particular, the async thread pool,
is properly shut down. Code running in the async thread pool may
use GEGL (in particular, now the drawable previews are rendered
asynchronously), and calling gegl_exit() while it's still running
is unsafe.
In GimpAction, instead of connecting the action-history log
function to the action's "activate" signal as a user-provided
handler, call it directly from the default handler.
In subclasses of GimpAction, chain to the parent's activate()
function before emitting the "selected" signal, so that we always
log the action in the history before responding to it.
This allows us to avoid the hack in commit
6544ce4301.
In xcf_write_int8(), avoid calling g_output_stream_write_all() with
data == NULL and count == 0, in which case it raises a CRITICAL and
doesn't set bytes_written, which we proceed to use uninitialized.
This can happen, e.g., when writing an empty parasite.
In gimp_color_profile_new_from_icc_profile() and
gimp_image_validate_icc_profile(), don't raise a critical when
encountering an empty profile, but rather reject it gracefully with
an error.
... (Invalid read reported by valgrind)
In gimp_image_parasite_validate(), don't segfault when validating
a "gimp-comment" parasite of size 0 (i.e., whose data is a 0-byte
array, not an empty string), and just consider it invalid.
... (Invalid read reported by valgrind)
In xcf_read_int8(), avoid calling g_input_stream_read_all() with
data == NULL and count == 0, in which case it raises a CRITICAL and
doesn't set bytes_read, which we proceed to use uninitialized.
This can happen, e.g., when reading an empty parasite.
In gimp_action_history_activate_callback(), bail if history.gimp is
NULL, instead of dereferencing it. This can happen if GIMP is shut
down during the execution of a temporary procedure, such as a
script-fu script. See the code comment for details.
In GimpMeter, use cairo_path_extents() for getting the history
graph's extents, rather than cairo_clip_extents(), since the latter
may also include clipping applied by GTK.