Resolves#10992.
GimpTextLayer's color attribute was
updated from GimpRGB to GeglColor,
but gimp-text-layer-set-color still passed
in GimpRGB. This patch updates the PDB
call to match the property type.
Most of the C boiler-plate code is generated so that all you have to do is
implement the run() function with test code in it.
Also adding a README to make it all very clear and easy to add new tests.
With Python binding, it gets very easy to test new functions. I've been
wondering if we need C counterparts, but really since it's a GObject
Introspection binding, if a function succeeds there, it should also succeed in C
code.
For now, I'm testing a few of GimpPalette API. Not all of it yet. Also I test
both the direct C binding and PDB procedure since in some cases, one or the
other may not properly working. See #10885.
We were missing GimpColorArray support in one function. Note that the specific
example in Python in #10885 still doesn't work, but for a second reason:
gimp_value_array_index() returns a GValue which pygobject automatically tries to
transform to the contained data. And unfortunately it doesn't know about our
GimpColorArray type so we end with unusable boxed type generic data.
Since the color space invasion, GimpRGB
properties do not create widgets anymore.
For Python plug-ins, we need to add
GeglColor properties as GObjects with
GeglColor value types as a workaround.
This patch does this and updates the
Foggify plug-in with the new datatype.
Though I had already implemented passing GeglColor through the PDB, it was not
complete. In particular, the protocol was not able to pass GeglParamColor specs.
Fixes:
> LibGimp-WARNING **: 16:06:09.451: _gimp_gp_param_def_to_param_spec: GParamSpec type unsupported 'GeglParamColor'
This is part of the fix to issue #10811, though it's not complete yet.
I still see some limitations in GimpGradient, and in particular, they are still
always stored as RGB in GGR files. It would be nice if we could store the actual
color format. This way, if someone chooses a gradient stop as Lab or CMYK color,
that's what the gradient file would keep track of. But also even storing the
space of a color (instead of storing/loading always in sRGB, even though this
may still work fine as we store unbounded double values). This might warrant for
a v2 of GGR file format.
This commit also fixes loading of SVG gradient which was apparently broken
regarding hexadecimal color parsing.
Finally I improve gegl_color_set_alpha() by adding an alpha channel when the
initial format had none.
The invasion extended to some core widgets too, in particular GimpColorPanel (a
subclass of GimpColorButton). There was quite a lot of code depending on these
widgets.
We pass 2 GeglColor through the wire now. Since it is passed very early
(when sharing the configuration), I had some issues with initialization
order of GEGL, and in particular when calling gegl_init() before
gegl_config() inside _gimp_config(), I had a bunch of such criticals:
> Plugin script-fu: GLib-GObject: CRITICAL: Two different plugins tried to register 'GeglOpPlugIn-transform-core'
Anyway in the end, I store the passed colors as raw bytes and strings in
the GPConfig object, and re-construct the GeglColor last minute in
_gimp_config().
One of the big improvement in this commit is that text layers are now much
better at space accuracy. They were already space-aware, yet rendered as sRGB u8
only before being converted to the image's space. It means that text layers had
the following limitations:
* Any color out of sRGB gamut were trimmed.
* Precision was always 8-bit (even if the image was high-bit depth).
Now GimpTextLayout keeps track of its source space (for RGB and CMYK only, this
won't be as easy when we will support more backend, since Cairo has only RGB
support for image data) and the image TRC (in case it bypasses the color space's
TRB) and it draws within this gamut and space.
It means first that we are not limited to sRGB colors; we will draw text main
color in the full image gamut, with still 2 remaining limitations:
* Unbounded colors are impossible because Pango format (to color text) uses
hexadecimal (so even with half/float images, you can't draw out-of-gamut text
unfortunately).
* Main color precision is still 8-bit, yet a tiny bit better than before as we
at least follow TRC (so we avoid some of the precision loss when converting,
even though the bit-depth is still the biggest loss).
The outline color on the other hand is drawn through Cairo API entirely, in
float. This means that the outline color will now be without any precision loss.
Note that this depends on CAIRO_FORMAT_RGBA128F which is only available since
Cairo 1.17.2 which is not in Debian bookworm (our current baseline for GIMP
3.0). It means that the old precision will still happen with older Cairo
version, as determined by #if code at compilation.
- app: gimp_context_get_(foreground|background)() are now returning a GeglColor.
- libgimp: PDB functions named similarly in libgimp are returning a newly
allocated GeglColor too.
- A few other PDB functions (the ones using these functions) were updated and
their signature changed to use GeglColor too, when relevant. Plug-ins which
use any of the changed libgimp functions were fixed.
- GimpContext: signals "(foreground|background)-changed" are now passing a
GeglColor.
- libgimpconfig: new macro GIMP_CONFIG_PROP_COLOR using gegl_param_spec_color().
- GimpContext: properties "foreground" and "background" are now GeglParamColor
properties.
- app: All code interacting with GimpContext objects were updated to receive a
GeglColor (that they may still convert, or no, to GimpRGB for now).
- app: gimp_prop_gegl_color_button_new() was added as an alternative to
gimp_prop_color_button_new() when the property is a GeglParamColor. Eventually
the former should replace completely the latter.
- libgimpwidgets: gimp_prop_color_area_new() now works on GeglParamColor
properties only.
- libgimp: gimp_procedure_dialog_get_widget() will generate a GimpColorArea for
GeglTypeParamColor arguments.
Also the color is internally stored as GeglColor, though there are still get
APIs and signals using GimpRGB.
The equivalent PDB functions are also changed to use GeglColor, same as app/
functions.
This is a first commit to really getting rid of GimpRGB within core and
PDB/plug-in code. This will make color conversion reliability a lot better as
GeglColor will handle conversions for us. The goal is that we should keep origin
color space (for instance when picking colors in a GimpPickable, or when storing
in the FG/BG colors or in paletters) until the last second and convert at use
only.
It's still very much work-in-progress.
These 2 functions were removed in commit 89c359ce. They were in fact used and
clearly this historical API seems interesting (though we can likely do the same
thing using the drawable GeglBuffer, but this way is much easier).
This is now reimplemented using GeglColor instead of raw data.
Eventually this is meant to fully replace GimpRGB (as well as GimpHSV, GimpHSL
and GimpCMYK), both in libgimp and in core code, as part of both the space
invasion and the API rework. For this first commit, I keep this new object side
by side to GimpRGB.
MINGW64
- uses 0x601 as value for _WIN32_WINNT. No need for us to define
it to that value or even lower values in some places.
This also gets rid of: warning: "_WIN32_WINNT" redefined
- has 0x0502 for WINVER, so get rid of us setting it to 0x0500 in
gimp-app-test-utils.h. It also seems that the need to use G_OS_WIN32
has disappeared here.
- DIRECTINPUT_VERSION is 0x0800, no need for us to set it to that value.
- AI_ADDRCONFIG was apparently missing from the MINGW headers in the
past, but not anymore.
- Do not leak allocated return value of gegl_node_to_xml_full().
- When merging layer effects, use gimp_drawable_filter_commit(), making
sure we use the exact same code path as when applying layer effects
destructively from the start. This also ensures that filters are
properly removed from the filter stack (unlike
gimp_drawable_merge_filter()), which was the reason why the rendering
was wrong (hence getting the buffer without effects first, then
reapplying it after was only a workaround to an actual bug).
- When removing a filter, verify the object still exists before doing
anything with it. If this was the last reference, we don't want to
call functions on this object. In gimp_drawable_filter_commit(), we
set up a weak pointer. In gimp_drawable_filter_remove_filter() itself,
we save the pointer to the filter's drawable before actual removal (as
we don't want to dereference a freed object later on).
- export_merge_layer_effects() should merge filters recursively through
layer groups.
- clean up the XCF code:
* No need to wrap the effect pointers list into 2 zero offset. Only
have one zero offset to indicate the list end.
* Add the layer effect mask in the effect structure (not in the layer
structure), similar as for layer masks.
* Effect name and icon made as main data in the structure, not as
properties.
This patch implements an initial form of
non-destructive editing. Filters now stay active
instead of being immediately merged down.
A new column is added to the layer tree view, which
can be clicked to show a pop-over menu.
Filters can currently be hidden/shown, edited, reordered,
deleted, and merged down from this pop-over menu.
Currently, this works on layers and layer selections only.
Plenty of room for improvement!
Resolves#10651
The "Remove All Guides" script calls
gimp-image-find-next-guide, which per
its description can take in 0. However,
the parameter sets 1 as the minimum
value.
This patch fixes the range so that it can
accept 0, which enables the Remove All
Guides script to work again.
It also updates the script to the new
multi-layer aware API.
Due to GObject Introspection we can't have the last part of an
identifier start with a digit, since that part will be used in Python
as the identifier, and Python doesn't allow that to start with a digit.
e.g. GIMP_ROTATE_90 would be used in Python as
image.rotate(Gimp.RotationType.90)
To fix this we add DEGREES in front of the number, without a '_',
even though that looks ugly.
These are not usable by plug-ins anymore which should store their data between
runs as arguments or aux arguments (in case of values which should be stored
from one run to another but are not really usable for non-interactive scripts).
These are per-plug-in (not polluting the whole process space with just random
strings as identifiers which could be used by other plug-ins) and even survive
restarts of GIMP.
I still keep these functions, but only internally, as they are used to store
settings of GimpAspectPreview, GimpDrawablePreview and GimpZoomPreview across
plug-in runs. Still I changed their API to set and return a GBytes directly
(mimicking the private PDB functions' API).
Also I remove gimp_pdb_get_data_size() which is useless when exchanging GBytes
directly.
Note that the 2 functions are still exported in the library, and only not
advertized through headers (so they are not really internal, just hidden), on
purpose, because we need to call them in libgimpui. So it is still relatively
easy for a plug-in to use them. Nevertheless I made clear in the function
documentation that these must not be considered public and could end up deleted
at any time. Any plug-in still trying to call these takes the risk of having
their code relying on unreliable API.
gimp_procedure_new_return_values() takes ownership of the passed GError (it
allows, among other things, to call it directly as return value). So we must not
try and free it afterwards.
The gimp_procedure_run() already existed, though it was with an ordered
GimpValueArray array of arguments. Its usage feels redundant to the series of
gimp_pdb_run_procedure*() functions (which is confusing), but
gimp_procedure_run() was actually a bit more generic, because it does not
necessarily calls GimpProcedure-s through the PDB! For instance, it can runs a
local GimpProcedure, such as the case of one procedure which would want to call
another procedure in the same plug-in, but without having to go through PDB. Of
course, for local code, you may as well run relevant functions directly, yet it
makes sense that if one of the redundant-looking function is removed, it should
be the more specific one. Also gimp_procedure_run() feels a lot simpler and
logical, API wise.
A main difference in usage is that now, plug-in developers have to first
explicitly look up the GimpPdbProcedure with gimp_pdb_lookup_procedure() when
they wish to call PDB procedures on the wire. This was done anyway in the
gimp_pdb_run_procedure*() code, now it's explicit (rather than calling by name
directly).
Concretely:
* gimp_pdb_run_procedure(), gimp_pdb_run_procedure_config() and
gimp_pdb_run_procedure_valist() are removed.
* gimp_procedure_run() API is modified to use a variable args list instead of a
GimpValueArray.
* gimp_procedure_run_config() and gimp_procedure_run_valist() are added.
* gimp_procedure_run_config() in particular will be the one used in bindings
which don't have variable args support through a (rename-to
gimp_procedure_run) annotation.
Passing (name, type, value) triplets is actually useless because we can get the
type information from the procedure/config anyway. That only adds one more
verification to do. Let's just change the function so that we pass (name, value)
couples instead, pretty much like in `g_object_set()`.
As far as plug-in API is concerned, at least the calling API, order of arguments
when calling PDB procedures doesn't matter anymore.
Order still matters for creating procedures with standard arguments (for
instance, "run-mode" is first, then image, or file, drawables or whatnot,
depending on the subtype of procedure), but not for calling with libgimp.
Concretely in this commit:
- gimp_pdb_run_procedure_argv() was removed as it's intrinsically order-based.
- gimp_pdb_run_procedure() and gimp_pdb_run_procedure_valist() stay but their
semantic changes. Instead of an ordered list of (type, value) couple, it's now
an unordered list of (name, type, value) triplets. This way, you can also
ignore as many args as you want if you intend to keep them default. For
instance, say you have a procedure with 20 args and you only want to change
the last one and keep the 19 first with default values: while you used to have
to write down all 20 args annoyingly, now you can just list the only arg you
care about.
There are 2 important consequences here:
1. Calling PDB procedures becomes much more semantic, which means scripts with
PDB calls are simpler (smaller list of arguments) and easier to read (when
you had 5 int arguments in a row, you couldn't know what they refer to,
except by always checking the PDB source; now you'll have associated names,
such as "width", "height" and so on) hence maintain.
2. We will have the ability to add arguments and even order the new arguments in
middle of existing arguments without breaking compatibility. The only thing
which will matter will be that default values of new arguments will have to
behave like when the arg didn't exist. This way, existing scripts will not be
broken. This will avoid us having to always create variants of PDB procedure
(like original "file-bla-save", then variant "file-bla-save-2" and so on)
each time we add arguments.
Note: gimp_pdb_run_procedure_array() was not removed yet because it's currently
used by the PDB. To be followed.
This partially revert some of the changes in commit 652a1b4388 because the
Windows CI suddenly failed because of this (my local build on Linux didn't have
any problem though) with:
> /usr/bin/x86_64-w64-mingw32-ld: libgimp/libgimpui-3.0-0.dll.p/gimpproceduredialog.c.obj: in function `gimp_procedure_dialog_save_defaults':
> /builds/GNOME/gimp/_build/../libgimp/gimpproceduredialog.c:2570:(.text+0x633): undefined reference to `_gimp_procedure_config_save_default'
> /usr/bin/x86_64-w64-mingw32-ld: /builds/GNOME/gimp/_build/../libgimp/gimpproceduredialog.c:2576:(.text+0x644): undefined reference to `_gimp_procedure_config_has_default'
> /usr/bin/x86_64-w64-mingw32-ld: libgimp/libgimpui-3.0-0.dll.p/gimpproceduredialog.c.obj: in function `gimp_procedure_dialog_load_defaults':
> /builds/GNOME/gimp/_build/../libgimp/gimpproceduredialog.c:2549:(.text+0xa2f): undefined reference to `_gimp_procedure_config_load_default'
> /usr/bin/x86_64-w64-mingw32-ld: libgimp/libgimpui-3.0-0.dll.p/gimpproceduredialog.c.obj: in function `gimp_procedure_dialog_constructed':
> /builds/GNOME/gimp/_build/../libgimp/gimpproceduredialog.c:368:(.text+0x11b1): undefined reference to `_gimp_procedure_config_has_default'
This is because these functions are used not only inside libgimp but also
across inside libgimpui. As a consequence, the build fails when linking
libgimpui.
This goes with our planned change of not making GimpProcedure arguments order
relevant anymore regarding the PDB API. In particular, it means we don't want to
use GimpValueArray for various procedure arguments API, but directly
GimpProcedureConfig objects.
This change will allow to add or reorder arguments in the future, so that we
won't have to create new PDB procedures when adding new arguments, while still
keeping PDB API stability.
Some of these should not even be visible by libgimp and were just fine as static
as well! For the rest, I make them really private (not only with a private
header).