We should not have essential signal connections (such as setting tool
options from brush properties) implemented in the tool options GUI
files, because they are not active until the options GUI is created.
Also, that magic is simply too hidden in the options GUI files.
Move the signal connections and the brush property copying code to
gimppaintoptions.c where is can also be done cleaner.
However, this must only be done for the main tool options instance
that is used for the GUI. Therefore, add a "gui_mode" boolean to
GimpToolOptions and set it to TRUE for all main tool options.
(this is ugly, but much less ugly and much less hidden than all the
places where code lives (like tool_manager.c) that can now be moved
into GimpToolOptions and its subclasses, and implemented cleanly
there).
Use gimp_input_data_stream_read_line_always(), instead of
g_input_data_stream_read_line(), in a bunch of places that don't
expect EOF. If we don't do that, the code assumes the GError
parameter is set by the function and returns an error indication,
causing the caller to segfault when it tries to access
error->message. Instead, we now process an empty line when EOF is
reached, which is caught by the normal parsing logic.
Additionally:
- Use gimp_ascii_strto[id]() when loading gradients, generated
brushes, and palettes, to improve error checking for invalid
numeric input.
- Improve gradient-segment endpoint consistency check.
- Allow loading palette files with 0 colors. They can be created
during the session, so we might as well successfully load them.
... which are similar to g_ascii_strtoll() (except that
gimp_ascii_strtoi returns a gint, and not a gint64), and
g_ascii_strtod(), however, they make error checking simpler, by
returning a boolean value, indicating whether the conversion was
successful (taking both conversion and range errors into account),
and return the actual value through a pointer.
... which is a drop-in replacement for
g_data_input_stream_read_line(), however, it always returns a non-
NULL value when there's no error. If the end-of-file is reached,
an empty string is returned.
gimp_layer_create_mask(): make sure we don't do a gamma conversion
when initializing the mask from a channel. This was probably not the
last place to need this fix.
Also get rid of a second switch(add_mask_type), must be some leftover
from long gone logic.
... with a color profile other than the gimp built-in.
Remove the separate alpha-channel copy in
gimp_image_color_profile_srgb_to_pixel(). We no longer need it,
since GimpColorTransform already takes care of that itself.
We used babl_process() to copy the alpha, which would also
transform the input color from R'G'B' to the output color space.
When the same buffer was used for both input and output, this call
would overwrite the input to the subsequent
gimp_color_transform_process_pixels() call; when the output color
space was different than R'G'B', this meant we'd pass the input to
gimp_color_transform_process_pixels() in the wrong color space,
producing wrong results. This was the case when converting the
foreground color for use with the smudge tool.
...after program restart
GimpContext was always supposed to keep the names of objects (brush,
pattern, font etc.) around even if these objects don't exist, for
cases like refreshing the data in a GimpDataFactory (which worked
fine), but also for deserializing the names of objects which don't
exist *yet* (delayed loading, no-data or whatever).
This commit fixes the delayed loading case (particularly affects fonts):
gimp_context_deserialize_property(): always keep the name of the
object around when it is not found, not only in the no-data case.
gimp_context_copy_property(): always copy the object *and* its name to
the dest context.
Add GimpConfig::duplicate() and ::copy() implementations which chain
up for duplicating/copying all properties and additionally copy all
object names to the new/dest context.
It seems it was simply forgotten. PROP_MASK_ALL is used at some very
central places, so this commit might fix a few subtle bugs, or
introduce new ones, everybody look for strange tool preset behavior
please :)
Never add an alpha channel in gimp_layer_real_transform(), it was only
added because our pre-GEGL transform code was shit. This is quite the
opposite of what the bug reporter asked for, but IMO the more correct
fix.
This will NOT go to 2.10 because it changes behavior.
In gimp_image_set_colormap(), make sure the image's colormap always
has at least one color -- babl palette formats must have at least
one color.
If the function is called with 0 colors, use black. We still need
to support this case, in particular, since existing XCFs may have
an empty colormap, and since plug-ins can call
gimp-image-set-colormap with 0 colors.
Treat the gimp-core-pixbufs and gimp-icon-pixbufs resources like we
changed the cursor resources before, and clean out a lot of cruft from
icons/ (there is no need to generate stuff in all icon themes when we
include only one fallback icon from one theme).
While most of our transform tools use an interactive transform
grid, and have similar behavior, the flip tool is an odd one out.
The new "auto straighten" function of the measure tool introduces
another tool that performs transformations, while not behaving like
the rest of the transform tools.
Factor out the parts of GimpTransformTool that handle user
interaction into GimpTransformGridTool (with corresponding
GimpTransformGridOptions, and GimpTransformGridToolUndo), and only
leave the basic transform functionality and options in
GimpTransformTool (and GimpTransformOptions).
Derive all the transform tools (and transform-tool base classes)
that previously derived from GimpTransformTool, from
GimpTransformGridTool. The one exception is GimpFlipTool, which
still derives from GimpTransformTool directly. The next commit
will derive GimpMeasureTool from GimpTransformTool as well.
...won't work with older GIMP?
Make gimp_image_get_xcf_version() return a "reason" string which lists
all reasons why the image can't be saved with compatibility for older
GIMP versions. Display the reason as tooltip on the compat hint label
in the save dialog.
Instead just transform the measurement extremities appropriately to
still map to the same points.
To do so, I also added out parameters to gimp_image_resize_to_layers()
so that calling code can get offsets from old origin (as well as new
image dimensions).
specified by GimpDataLoaderEntry structs. Remove the same code from
GimpDataFactory and make it an abstract base class that only serves as
an interface for actual implementations. Also move around some stuff
in GimpDataFactory and remove virtual functions that were a bad idea
in the first place.
so pull it to the parent class. Also remove the "no_data" parameter
from the data_init() virtual function and handle it in
gimp_font_factory_data_init() itself.
Make sure gimp_async_set_wait() and gimp_async_set_cancel() work
correctly, even if the set changes in nontrivial ways as a result
of waiting-on/canceling individual operations. This is purely
theoretic right now, but why not.
Virtualize a lot of functions and move their code into the default
implementation. Also connect to changes of the "path" property and
reload data automatically when the path changes. Add "wait" method
which is by default empty but is to be implemented by fonts.
Add a GimpGui::wait() virtual function, and a corresponding
gimp_wait() function. The function takes an object implementing
the GimpWaitable interface, and a printf-style message, and waits
for the object to become ready, displaying the message as
indication in the meantime. The default implementation simply
prints the message to STDERR.
Implement the function in gui-vtable, using the busy-dialog plug-
in added in the previous commit, to display the message in a
dialog. Additionally, if the object implements the GimpCancelable
interface, provide a "cancel" button in the dialog, which, when
pressed, causes gimp_cancelable_cancel() to be called on the
object. Note that the function keeps waiting on the object even
after requesting cancelation; GimpTriviallyCancelableWaitable can
be used to stop the wait once cancelation has been requested.
Replace the boolean fonts_loading member of Gimp with
fonts_async_set, which is a GimpAsyncSet object. This allows us
to easily respond to the completion of font loading and reloading,
as will be done in the next commits.
Additionally, move the call to FcConfigSetCurrent(), used to
activate the loaded font configuration, from the async thread to
the main thread, just to be on the safe side, and avoid calling
FcInitReinitialize() in gimp_fonts_reset() if font loading is still
in progress, which is unsafe.
GimpAsyncSet represents a dynamic set of running GimpAsync objects.
The objects are automatically removed from the set once they're
synced.
GimpAsyncSet implements the GimpWaitable and GimpCancelable
interfaces, allowing the entire set to be waited-on or canceled.
Additionally, GimpAsyncSet provides an "empty" property, which
indicates whether the set is empty or not. This allows responding
to the completion of all the GimpAsync objects through the set's
"notify::empty" signal, or drive UI changes through property
bindings.
GimpTriviallyCancelableWaitable is a proxy object for another
GimpWaitable object, implementing both the GimpWaitable interface
and the GimpCancelable interface. While waiting on the proxy
simply waits on the underlying waitable, canceling the proxy
doesn't affect the underlying waitable, even if it implements
the GimpCancelable interface as well, but rather causes subsequent
wait operations on the proxy to successfully complete immediately.
This essentially causes cancelation to abort only the wait, rather
than the underlying operation.
GimpUncancelableWaitable is a simple proxy object for another
GimpWaitable object, implementing only the GimpWaitable interface.
Its main purpose is to mask away the cancelability of an object
implementing both GimpWaitable and GimpCancelable.
In gimp_parallel_run_async(), lower the priority of threads
executing independent async operations. Independent operations
are generally potentially long-standing background tasks, which we
don't want to bog down the rest of the program.
This is currently only implemented on Linux and Windows.
In gimp_parallel_run_async(), when aborting a GimpAsync operation
in reponse to its "cancel" signal, properly clean up internal data
attached to the object, to avoid use-after-free if the signal is
emitted again.