It's still basic but will help to share code for support of various vector-able
formats, such as the logic for dimensioning them, but also the generated GUI.
Not only this, but we are paving the way for the link layers (though it'll be
after GIMP 3, we want plug-in procedures' API to stay stable) by giving a way
for a plug-in procedure to advertize a vector format support. This way, the core
will know when a source file is vector and can be directly reloaded at any
target size (right now, in my MR for link layers, the list of "vector" formats
is hardcoded, which is not reliable).
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.
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!
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.
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.
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).
This is meant to replace gimp_image_get_colormap() (see also #9477).
We likely won't need a gimp_image_set_palette() because we can simply edit the
image's colormap/palette with GimpPalette API now and it is directly updated.
For instance, the following code changes the first entry in the image palette to
red, immediately:
```python
i = Gimp.list_images()[0]
p = i.get_palette()
c = Gimp.RGB()
c.r = 1.0
p.entry_set_color(0, c)
```
For this to work fine, I added a new concept to GimpData, which is that they can
be tied to a GimpImage (instead of a GFile). Image palettes are not considered
internals, they are just tied to their image, therefore they can be edited by
scripts/plug-ins.
Additionally with this commit, editing an image's colormap from libgimp API also
generates undo steps now.
It returns all the fonts (possibly more than 1) with a given name. I left the
function gimp_font_get_by_name() as a utility when one don't want to choose (or
is not able anyway, e.g. a script with minimal information), though I wondered
if we should not simplify with a single function (the new one, which is the
correct one now that it is possible to have several fonts with a given name).
It is easy to test with fonts named the same. For instance I could find 2
different fonts, both named 'Holiday'. This call in the Python console returns
both:
> Gimp.fonts_get_by_name('Holiday')
As part of this commit, I also implemented resource arrays (or subtype arrays)
as PDB arguments and return types.
- Fonctions were renamed: s/gimp_text_fontname/gimp_text_font/ and
s/gimp_text_get_extents_fontname/gimp_text_get_extents_font/
- The size_type arguments were removed. Even in 2.10, this argument was marked
as "dead" and ignored. It was only kept for API compatibility.
- The font name (string) was replaced by a GimpFont argument.
gimp_text_font() is easily tested in the Python console with:
> Gimp.text_font(Gimp.list_images()[0], None, 10, 40, "Hello World!", 1.0, True, 100, Gimp.context_get_font())
And gimp_text_get_extents_font() with:
> Gimp.text_get_extents_font("Hello World!", 100, Gimp.context_get_font())
… function gimp_font_get_pango_font_description().
Also updating file-pdf-save which is the only plug-in using these right now.
Note that I am not fully happy with the new function
gimp_font_get_pango_font_description() because I experienced some weird behavior
in file-pdf-save which is that some fonts were wrong if this is called after
pango_cairo_font_map_set_resolution().
But let's say this is a first step looking for improvements.
Similarly to the various GimpResource select PDB calls, this allows to call a
core dialog in order to choose a drawable which will be returned back to the
calling plug-in.
This new GimpPickableSelect dialog is a subclass of GimpPdbDialog and uses the
same GimpPickableChooser widget as GimpPickablePopup, except that since it's
inter-process window management, it is harder to make a popup positioned
accurately relatively to a parent (especially on Wayland). This is why it's a
separate widget as a simpler dialog (which we will still try to make transient
as much as possible across platforms).
Similar to the latest commits for GimpBrush:
- gimp_pattern_get_buffer() returns a GeglBuffer and allow getting a scaled
version of the pattern.
- Old gimp_pattern_get_pixels() is made private.
- Moved GimpPattern into its own file and store the buffer to avoid re-querying
it through PDB continuously.
No as for the widget to select a pattern:
- Preview frame ensured to be square.
- Default size increased.
- Drawing code using the new gimp_pattern_get_buffer().
- Cleaned up code.
… and gimp_brush_get_mask().
gimp_brush_get_pixels() was a bit crappy, returning raw data with only
dimensions and bpp to go with (no color model/space, no bit depth…). So the
assumption is that we work with 8-bit per channel data, possibly with alpha
depending of number of channels as deduced from bpp, and very likely in sRGB
color space. It might be globally ok with many of the brush formats (and
historical brushes) but won't fare well as we improve brush capabilities.
- gimp_brush_get_pixels() is in fact made private.
- The 2 new functions are using this old PDB call _gimp_brush_get_pixels() to
construct buffers. This has some limitations, in particular that it returns
only 8-bit per channel sRGB data, but at least the signature won't change when
we will improve things in the future (so if some day, we pass fancy brushes in
high-bit depth, the method will stay the same).
- This new implementation also allows scaling down the brush (keeping aspect
ratio) which is useful when you need to fit a brush preview into a drawing
widget.
- Current implementation stores the buffers at native size in the libgimp's
GimpBrush object, hence save re-querying the core every time you need an
update. This can be improved as current implementation also means that you
don't get updates if the brush changed. This should handle most common use
cases for now, though.
- Also with this change, I move GimpBrush class implementation into its own
dedicated file.
- Removing useless or redundant code.
- Simplifying various logics.
- Using GimpResource directly in temporary PDB procedures, not resource names.
- Better cleanup of the core resource chooser when the plug-in dialog quits (we
need it to ask core to close also any visible resource chooser dialog).
- Replace the "Close" button by more common OK/Cancel. In particular, the
GimpPdbDialog now properly keeps track of the initial object and when hitting
"Cancel" (or Escape key), this initial object is set back.
- Clean up some of the comments, especially when the code is self explanatory.
There is still much more to clean and improve, but it's a first welcome step.
… a GimpProcedureConfig for arguments.
This also factorizes the code to load metadata. By default, a GimpLoadProcedure
will try and load metadata from a file (if Exiv2 knows the format). The run()
function will be allowed to edit the GimpMetadata object but also the load flags
before it is actually attached to the image, allowing plug-ins to have custom
metadata handling code when needed.
This is just a method to simplify transforming a GimpChoice argument into an
enum value, which is easier to deal with, in C. It also allows to benefit from
switch() warnings or the like to make sure no cases are missing.
Metadata handling is also integrated in this API:
* while giving a possibility to disable metadata saving if you want to do it
yourself (e.g. in file-heif), by setting a NULL MimeType;
* and the GimpMetadata object is added as run() argument, allowing one to edit
the metadata during the run, while still letting the infrastucture handle the
save (e.g. in file-jpeg);
* or to save intermediate metadata with gimp_procedure_config_save_metadata()
(e.g. in file-tiff).
Same as with gimp_procedure_new2(), I will end up renaming the function to
gimp_image_procedure_new() once all usage of this function will have been ported
to the new function using GimpProcedureConfig instead of GimpValueArray
arguments.
This new function is meant to replace gimp_procedure_new() when all plug-in
usage will have been switched.
This function creates the GimpProcedureConfig object on behalf of the plug-in
and calls gimp_procedure_config_begin_run() and gimp_procedure_config_end_run().
This way we ensure that all plug-in calls with successful result are properly
stored without asking the developer not to forget to call these (if a "good
practice" is in fact something we request to do every time, especially for good
user experience, we might as well make it rather a core process).
Advantages:
* Better interactive experience: using any plug-in will result in saved
previously used settings.
* for developers, working on config objects is also much more comfortable than
working on GValueArray;
* step forward for the future macro infrastructure: if we can ensure that all
plug-in calls are properly logged, then we can replay plug-in actions, in
NON_INTERACTIVE with the same settings.
Much like for images and items. Change the PDB to transmit IDs
instead of names for brush, pattern etc. and refactor a whole
lot of libgimp code to deal with it.
modified: libgimp/gimpplugin-private.h
GLib has a specific type for byte arrays: `GBytes` (and it's underlying
GType `G_TYPE_BYTES`).
By using this type, we can avoid having a `GimpUint8Array` which is a
bit cumbersome to use for both the C API, as well as bindings. By using
`GBytes`, we allow other languages to pass on byte arrays as they are
used to, while the bindings will make sure to do the right thing.
In the end, it makes the API a little bit simpler for everyone, and
reduces confusion for people who are used to working with byte arrays
in other C/GLib based code (and not having 2 different types to denote
the same thing).
Related: https://gitlab.gnome.org/GNOME/gimp/-/issues/5919
(cherry picked from commit dbf9f277a2)
Committer's (Jehan) updates:
- Component type is now int32 (int8 is not a PDB type available anymore).
- PDB files re-generated to handle changes in API and types.
Simplifies chooser widgets (e.g. GimpBrushSelect) by eliminating attributes (e.g. opacity) of chosen resource.
See #8745, but this commit fixes that by first refactoring the code.
Refactors GUI widgets (e.g. GimpBrushSelectButton and GimpBrushSelect etc.)
Refactor by "Extract class" GimpResourceSelectButton from GimpBrushSelectButton etc.
This moves common code into an inherited class (formerly called GimpSelectButton)
but the subclasses still exist.
The subclasses mainly just do drawing now.
Refactor by "Extract module" GimpResourceSelect from GimpBrushSelect etc.
Moves common code into one file, generic at runtime on type of GimpResource,
that is, the new code dispatches on type i.e. switch statements.
In the future, when core is changed some of that can be deleted.
The files gimpbrushselect.[c,h] etc. are deleted.
The module adapts the API from core to the API of callbacks to libgimp.
Note that core is running the resource chooser (select) widgets remotely.
Core is still calling back over the wire via PDB with more attributes
than necessary.
The new design gets the attributes from the resource themselves,
instead of receiving them from core callback.
The libgimp side adapts by discarding unneeded attributes.
In the future, core (running choosers for plugins) can be simplified also.
Fix gimp_prop_chooser_brush_new same as other resources.
Finish changes, and clean style.
Annotations
So procedures can declare args and GimpProcedureDialog show chooser
widgets
Fix so is no error dialog on id_is_valid for resources
Palette.pdb changes and testing
Memory mgt changes
Gradient pdb
Font and Pattern tests
Test brush, palette
Cleanup, remove generator
Rebase, edit docs, install test-dialog.py
Whitespace, and fix failed distcheck
Fix some clang-format, fix fail distcheck
Fix distcheck
Cleanup from review Jehan
Missing functions were:
* gimp_image_get_selected_channels()
* gimp_image_get_selected_vectors()
* gimp_image_list_selected_channels()
* gimp_image_list_selected_vectors()
* gimp_image_set_selected_channels()
* gimp_image_set_selected_vectors()
* gimp_image_take_selected_channels()
* gimp_image_take_selected_vectors()
There are discussions of renaming GimpVectors to GimpPath, which would
also be consistent with the GUI and make the always-plural less akward
in API. We'll see. For now keeping named like this.
Now text layers are proper types, which means that the binding API will also be
nicer (e.g. `txt_layer.set_text('hello world')` in Python).
This commit also adds the param specs allowing to create plug-in procedures with
text layer parameters.
Finally it fixes the few calls in file-pdf-save (apparently the only plug-in
using specific text layer API right now) with explicit type conversion.
This complements the existing text_layer_get_markup function and allows
scripts to create and modify complex text layers.
It adds the <markup> root tag if it was not supplied and will run the
markup through pango_parse_markup() to check for errors.
Reviewer's (Jehan) note: this is a mostly untouched patch contributed in #534,
except that code moved around. I also fixed the header set in the .pdb, a link
to pango markup docs and added the meson changes.
Adds a simulation_bpc and simulation_intent to GimpImage to allow
plug-ins to access it
for CMYK import/export.
Four pdb functions were added to enable this access:
image_get_simulation_bpc (), image_set_simulation_bpc (),
image_get_simulation_intent (), and image_set_simulation_intent ().
Next, it updates menu options and code to support GimpImage's
internal simulation intent and bpc.
New 'simulation-intent-changed' and 'simulation-bpc-changed signal
are emitted via
GimpColorManagedInterface so that relevant tools
(such as the
CYMK color picker, GimpColorFrame, and future pop-overs)
are aware of these changes.
Adds a simulation_profile to GimpImage to allow plug-ins to access it
for CMYK import/export.
Two pdb functions were added to enable this access:
image_get_simulation_profile () and image_set_simulation_profile()
Next, it updates menu options and code to support GimpImage's
internal simulation profile. Menu items are moved from View to Image's
Color Management section.
New 'simulation-profile-changed' signal is emitted via
GimpColorManagedInterface so that relevant tools (such as the
CYMK color picker, GimpColorFrame, and future dockable
dialogue) are aware of these changes.
Clearly the old logic for localizing plug-ins was "core plug-ins first":
* In particular, we were defaulting to the "gimp*-std-plugins" domain,
asking plug-ins to override it with libgimp function
gimp_plug_in_set_translation_domain(). Obviously any third-party
plug-in would have to call this function since their strings are most
likely not the same as GIMP core plug-ins.
* Moreover this was only for the localization of menu items, which means
we had to duplicate work anyway (simplified for core C plug-ins only
with the INIT_I18N macro).
* Also plug-ins had to manage the location of the Gettext catalogs,
which is simpler for core plug-ins with gimp_locale_directory(), but
more annoying for third-party plug-ins which can be installed
basically anywhere (assuming their message catalogs are in their
directory, not centrally installed on the system, especially for
non-UNIX-like packages, with relocatable GIMP, no central package
system and so on).
* Finally in this logic of centrally installed catalogs, we were
requesting that the domain name is unique, which makes sense in a
Linux world with well maintained packages to avoid name clashes, not
in a world with people making plug-ins without knowing too much what's
done by their neighbour.
So now the new logic is:
- By default, GIMP will search for a folder called locale/ on the same
level as the plug-in executable. The Gettext domain will be the name
of the executable folder (and it doesn't matter too much if it's not
unique in such configuration).
- This can be disabled by overriding set_i18n() to NULL or
reimplementing it. All our core plug-ins will do this since they will
continue to use the centrally installed "gimp*-std-plugins" domain (or
"gimp*-python" for Python plug-ins).
- When not disabled while the folder is not available, warning messages
will be outputted to stderr, so that plug-in developers can easily
detect what is missing and how to handle it (and how to easily support
internationalization of their plug-in).
- gimp_plug_in_set_translation_domain() is removed and a future commit
is going to get rid of _gimp_plug_in_domain_register() because we are
going to get rid of the core-side localization of menu items (with
logic explained in the upcoming commit).
This new function is an alternative to existing
gimp_image_metadata_save_finish, when you want to save metadata
yourself and you need only filtering processing.
It returns filtered metadata allowing the caller
to save the finalized metadata via other means
(via native format’s library for example)
This API can be used to support metadata saving of image formats
not directly supported by gexiv2/exiv2.
While we do have quite a few gimp_pdb_run_procedure*() functions now, I
always felt that one based on a config file was missing, even more as we
are getting further and further into using config objects in plug-ins.
In C, the gimp_pdb_run_procedure() function is without a doubt the
easiest one. But such variable arg functions are not available on
bindings, and having to deal with GValue and GimpValueArray is a real
pain.
Also using a config file has the very great advantage that we don't need
to care about order. For instance, if I need to set the 10th argument of
a PDB call (and leave the rest to default values), I don't have to set
all 9 previous arguments. I can set only this one if I want. This
advantage is useful also for C code by the way.
For the record, here is how you could load then export an image with the
"file-png-*" PDB procedures in Python:
> c = Gimp.get_pdb().lookup_procedure('file-png-load').create_config()
> c.set_property('file', Gio.file_new_for_path('/path/sample.png'))
> r = Gimp.get_pdb().run_procedure_config('file-png-load', c)
> d = Gimp.Display.new(r.index(1)) # Give it a display to work on it.
Now exporting:
> img = r.index(1)
> c = Gimp.get_pdb().lookup_procedure('file-png-save').create_config()
> c.set_property('image', img)
> c.set_property('file', Gio.file_new_for_path('/path/exported.png'))
> layers = img.get_layers()
> c.set_property('drawables', Gimp.ObjectArray.new(Gimp.Drawable, layers, False))
> c.set_property('num-drawables', len(layers))
> r = Gimp.get_pdb().run_procedure_config('file-png-save', c)