Commit graph

436 commits

Author SHA1 Message Date
Ondřej Míchal
ce5efe29d6 pdb: Encode param info with unsupported type in a placeholder spec
To prevent losing all information about a type (and also reporting a
different API by dropping a parameter when retrieving an operation's
pspecs, create a placeholder type with a known name and type and put the
rest of the information into its blurb. A little hack-y but filter
browser can now show information of parameters with unsupported types.
2025-08-03 21:38:28 +00:00
Jehan
74d79ba0c6 app, pdb, libimp: prevent core process from raising WARNING on libgimp call.
Whatever a plug-in does, it should not be able to trigger WARNINGs or
CRITICALs on the core process. Here this was possible when requesting an
array of param specs with gimp_drawable_filter_operation_get_pspecs() on
a GEGL operation, while GIMP doesn't support all types for this filter's
arguments. Trying to send unsupported type specs through the wire would
fail.

Unfortunately just saying that we must add support for these types is
not enough because we simply cannot support every possible types. First
because even in current GEGL core filters, there are types we might
never support (e.g. audio fragments?). But even more because third-party
filters could have custom types too (just like our own filters have
custom GIMP types).

So instead, acknowledge that some types cannot be sent through the wire,
verify when it's one such argument and simply output an informational
message on stderr (because the info of a non-supported type is still
interesting in case this is something we should in fact add support for;
it's much better than silently ignoring the argument).
2025-08-03 21:38:28 +00:00
Ondřej Míchal
4694c9178a pdb: Add procedures to inspect filter operations
The primary consumer of these procedures is an upcoming browser for
available GEGL operations introduced in a follow-up commit.
2025-08-03 21:38:28 +00:00
Ondřej Míchal
faca688dba pdb: Extract GEGL operation validation into its own function
A follow-up commit will make use of it in multiple places.
2025-08-03 21:38:28 +00:00
Michael Natterer
6eae69d2a4 app, pdb: rename gimp_container_get_children_type() to get_child_type() 2025-07-18 08:19:13 +02:00
Alx Sa
5f65133e20 pdb: Set image file when using gimp-file-save
gimp_file_save () lets you save an image to
any supported file format, but it did not
update the GimpImage's file or exported
file accordingly. This patch adds code to
do just that, patterned after /app/file/file-save.c's
file_save ().
2025-07-08 14:06:00 +00:00
Michael Natterer
69f84942fa app: rename app/vectors/ to app/path/ 2025-07-07 15:44:15 +02:00
Michael Natterer
bee7b8713b app, pdb: a lot of vectors -> path renaming 2025-07-07 13:18:02 +02:00
Michael Natterer
fd3852af31 pdb: remove -private suffixes
from gimp-drawable-append-filter and -merge-filters. They are not
needed any longer, and it's not an API change because they are
private.
2025-07-05 14:15:17 +02:00
Jehan
7262faed16 app, pdb: allow rendering font previews with theme colors.
This also depends on the same settings to render brushes with theme
colors, because this is data, not user interface. Therefore following
theme colors is not necessarily what creators would expect.
2025-06-20 00:11:08 +02:00
Jehan
80fe32dfc6 pdb: also allow none_ok on PDB type 'guide'.
This would be theoretically useful for gimp-image-find-next-guide except
that this function was already using the int type, and allowing 0. I'm
not changing to 'guide' type with none_ok because it would break the
libgimp API (the signature would change, with the type changing from
gint to guint).

Since it already works like this, I just leave a TODO for further
update.

With this and previous commit, we now fully replaced commit 69894d8bbf
attempts for allowing 0 to some types. There was in fact also some
change on 'tattoo' type, but I went through all the PDB functions we
had, one by one, and I don't think we currently have a single case where
we need to allow 0 as a tattoo value. If this need ever arises then we
can always add none_ok support easily in the future.
2025-06-12 13:21:52 +02:00
Jehan
bf14d3db20 Issue #14205: gimp-image-find-next-sample-point returns error when…
… passed "0" as argument.

Adding support of none_ok for arguments of type sample_point, allowing
to pass 0 as a special value and use it on this function.
2025-06-12 12:59:10 +02:00
Michael Natterer
bf877a8aa3 app, pdb: move filter duplication to one place in
GimpItem::duplicate().
2025-05-28 17:28:01 +02:00
Jehan
3038c751bc app, pdb: use the real theme background color for brushes with GIMP_VIEW_BG_USE_STYLE.
Previous code was using the correct background color from the theme, but
the foreground color was always either white or black (depending on GUI
config color scheme). Instead, just use the foreground color from theme.

Since core/ doesn't have access to GTK, hence the theme, we had to
update GimpViewable's get_preview() and get_pixbuf() abstract methods to
have a color argument for recoloring previews (when relevant, which for
most types of viewables is not).
2025-05-22 21:14:20 +00:00
Idriss Fekir
8328dfb25b GimpFontFactory: Move font loading to another thread
This is to make sure than regardless of how many fonts there are, font loading
won't delay startup.

FontConfig if compiled against libxml2 might fail to parse huge xml configs.
So instead of passing it a huge xml, pass the xml every MAX_NUM_FONTS_PER_CONFIG (currently 1000) fonts.

Also made GimpFontFactory custom config strings private because there is no reason for them to be public.
2025-05-14 22:42:22 +00:00
Alx Sa
2c31c0e34d libgimp, plug-ins: Prevent GFig crash with NULL brush
The GFig plug-in assumes that there is always
a valid brush selected when creating its
dialogue. However, a NULL brush is possible,
and GFig's assumption can cause a crash
in GIMP by attempting to get a buffer from
a NULL brush.
This patch adds conditional checks for the
brush to not be NULL before using it.
2025-05-05 09:36:04 +00:00
Alx Sa
aa94975003 pdb: Make gimp-plug-ins-query public
The Plug-in Browser plug-in makes a call
to gimp-plug-ins-query to get plug-in
information. Since this PDB was made
private, the browser could no longer load
plug-in information.
This patch makes gimp-plug-ins-query
public again so it can be used.
2025-04-23 14:05:16 +00:00
Jacob Boerema
5273f26ef0 app, pdb: fix #13480 inconsistent use of maximum radius...
for generated brushes.
The maximum radius we allowed for generated brushes was not used
consistently everywhere.
In the API call we clamped it to 0.0-32767.0, while the param_spec
set min and max to 0.1 and 4000.0, and the brush editor used a
maximum of 1000.0.
Using a large value (probably anything larger than 4000) would
sooner or later lead to a crash.

Instead of manual changes everywhere, let's define a maximum and
minimum in one place and use that wherever we need the min/max values.
Use the values as set in the param_spec for the defines.
The only place we can't easily do that is in brush.pdb, so we add
a comment above our defines that the values need updating there too.

Actually we should probably use more defines for other values too,
that way there is less chance of min/max values getting out of synch
throughout our code.
2025-04-11 02:02:40 +00:00
Alx Sa
e494538393 pdb: Pass GIMP object when creating text layer via API
After discussing with Idriss, we found that if you create
a GimpTextLayer via the public API, the GIMP object
was not being stored in the GimpText object.
If markup like bold/italics was then applied, GIMP
would crash on saving as XCF because the serialization
code tried to access text->gimp_font_factory.
This patch resolves the issue by passing the GIMP
object into GimpText when we create it via the
API.
2025-03-31 11:07:14 +00:00
Jehan
61c1014ba6 app, pdb: (gimp-pdb-proc-exists) should only return TRUE for public procedures. 2025-02-26 14:12:25 +01:00
Jehan
711be6db8c app, libgimp, pdb: clean up some more code redundancy. 2025-02-25 20:17:05 +01:00
Jehan
269463389e app, pdb: internal procedures are simply ones with type GIMP_PDB_PROC_TYPE_INTERNAL.
Adding an is_internal value was a mistake, or rather it was redundant.
We already had a procedure type and all internal procedure are set as
GIMP_PDB_PROC_TYPE_INTERNAL.

I also double-checked that it is not possible for a plug-in to create a
procedure with this type (it is rejected), so it's very fine.
2025-02-25 20:01:29 +01:00
Jehan
ad0b02d2b7 app, libgimp, pdb, plug-ins: rename gimp_procedure_is_core() to…
… gimp_procedure_is_internal().

I realized we were already naming these "internal procedures" in the
Procedure Browser and this is in fact a better naming than "core
procedure".
2025-02-25 20:01:29 +01:00
Jehan
4f44ef6ed1 app, pdb: add parameter validation for (gimp-text-layer-new).
Even though the libgimp wrapper has annotations, it is still possible to
pass a NULL font through, in Script-Fu for instance by not passing all
arguments (and very likely in a plug-in by calling the PDB procedure
directly rather). And unfortunately this would crash GIMP when it tries
to work on the NULL font.

Let's do some sanity check!
2025-02-17 22:21:24 +01:00
Jehan
1a794ad77c app, pdb: gimp_text_layer_set_font_size() allows the pixel unit. 2025-02-15 17:42:52 +01:00
Jehan
b01ecf80e6 app, libgimp, pdb: allow NULL input drawable to the new crop procedures.
Cropping relatively to the full image contents is a common usage (it is
in fact the "Crop to Content" feature we have in the Image menu) so I
found it a bit frustrating that these 2 functions only allow to crop
relatively to a single drawable.

Therefore, I make NULL an acceptable input which will default to
cropping to the full image content instead.
2025-02-09 19:24:41 +01:00
Jehan
d7b6647647 app, pdb: fix implementation of gimp_image_autocrop_selected_layers()…
… taking into account drawable's offsets.
2025-02-09 18:50:19 +01:00
Jehan
3c21b768c5 app, libgimp, pdb: improve docs and names of autocrop functions.
- Clean up a bit the 2 procedures' descriptions and add more info in
  gimp_image_autocrop() description to explain how the input drawable is
  used.
- Rename gimp_image_autocrop_layer() to gimp_image_autocrop_selected_layers(),
  which makes it clearer.
2025-02-09 18:23:42 +01:00
lloyd konneker
9e2d8e4e16 API: fix #12860 autocrop is internal, not a compatibility plugin
Rename plug_in_compat.pdb to image_autocrop.pdb so we retain commit history.

All procedures defined there are related to autocrop.
   - made internal, not plugins
   - renamed from plug-in- to gimp-image-
   - exposed in libgimp

If we need plugin compatibility PDB group in the future,
a starting template can be recovered from plug_in_compat.pdb 2.10 or late 2.99.

Fixed plugins that call.  The C plugin now calls libgimp instead of a PDB procedure.
2025-02-09 16:51:13 +00:00
Jehan
ac0a722bf6 Issue #12569: clip issue with new filter API.
It was not a bug per-say. Simply the filters were set as having "clip"
set by default. We should add a libgimp function to let people choose
instead, but I want to think a bit better how we handle clip and masks
in filters before creating more API. Cf. #12874.

So for now, let's just set clip to FALSE. If we have to choose a single
possible clip value for filters made by the libgimp API, I believe this
is the nicer value.
2025-02-09 02:07:08 +01:00
Jehan
679220d8f5 Issue #12568: support GIMP's GEGL operations with a custom config argument…
… in new filter API.
2025-01-27 16:34:11 +01:00
Jehan
6dfc9f96c5 app, libgimp, pdb, plug-ins: improve and rename gimp_file_save_thumbnail() to…
… gimp_file_create_thumbnail().

One more case where "save" is misleading, and even more as it's not a
procedure where we control where an image is stored. We only say
basically "make a thumbnail which maps to this file according to my
platform's rules".

As a side fix, I also improved a bit the logic so that it allows @file
to be the exported or — as last fallback — the imported file.

And finally improve the function's docs.
2025-01-21 20:31:27 +01:00
Jehan
602e8f71c7 app, libgimp, pdb: reword some save/export API documentation.
Followup of the save/export difference, plug-ins can only register
"export" handler procedure (save handlers are registered by core). Also
rename _gimp_pdb_set_file_proc_save_handler() though it's private so it
doesn't matter much.

Now gimp_file_save() is a special case, because it can indeed "save" to
XCF or "export" to any other format. So I just leave it named this way,
but I make the function's documentation more exhaustive.
2025-01-21 17:40:11 +01:00
Jehan
9f204e7441 Issue #12772: fix annotations. 2025-01-21 15:04:34 +01:00
Jehan
18d88c207c app, libgimp, pdb, plug-ins: PDB (gimp-group-layer-new) made public. 2025-01-20 22:38:01 +01:00
Jehan
957d76fd14 app, libgimp, pdb, plug-ins: PDB (gimp-layer-copy) made public.
Not sure what I had in mind with the class method copy() in libgimp
GimpLayer. The core duplicate code already takes care of returning an
object of the right type. Also the GimpTextLayer implementation was not
a perfect copy (only text, font and font size were copied). Now it is
because, again, core has all the duplication code necessary.

Finally this makes this function visible to PDB, hence Script-Fu, again.
2025-01-20 22:38:01 +01:00
Jehan
65635e8a0c app, libgimp, pdb: also get rid of gimp_text_layer_new() wrapper.
See previous commit.
2025-01-20 20:55:48 +01:00
Jehan
e125c30cfd Issue #12771: (gimp-layer-new) is missing.
The libgimp wrapper was just calling the PDB procedure. Get rid of the
wrapper and make the PDB proc public. Also reorder the name argument to
be in the second place, just like it was for the wrapper.
2025-01-20 20:55:48 +01:00
Jehan
305303330c app, libgimp, pdb: fix a null_ok/none_ok mixup.
We had 2 flags to indicate that a PDB argument could be nullable:
null_ok and none_ok. That was a huge mixup and the PDB generation code
was using sometimes one, sometimes the other. Let's settle for only
none_ok.

This fixes a bunch of annotations.
2025-01-20 20:55:48 +01:00
Jehan
45af19e917 app, libgimp, pdb: adding concept of core and private PDB procedures.
Core procedures are all the procedures created for libgimp basically. In
opposition, procedures created by plug-ins are not core procedures.

GimpProcedure class in libgimp now has a gimp_procedure_is_core() which
will tell you if a procedure is core or not.

Private procedures already existed, except that they were only marked as
"private" in libgimp (e.g. _gimp_font_get_lookup_name()) starting with
an underscore and marked as G_GNUC_INTERNAL. Now we also store this
information in the procedure object itself for reuse.
2025-01-20 00:01:23 +01:00
Jehan
aa2d35c5fc app, pdb, plug-ins: replace (plug-in-bump-map).
For plug-in writers reference, these are equivalent:

- (plug-in-bump-map RUN-NONINTERACTIVE img drawable bump-layer azimuth elevation depth 0 0 0 0 FALSE FALSE 0)
+ (let* ((filter (car (gimp-drawable-filter-new drawable "gegl:bump-map" ""))))
+   (gimp-drawable-filter-configure filter LAYER-MODE-REPLACE 1.0
+                                   "azimuth" azimuth "elevation" elevation "depth" depth
+                                   "offset-x" 0 "offset-y" 0 "waterlevel" 0.0 "ambient" 0.0
+                                   "compensate" FALSE "invert" FALSE "type" "linear"
+                                   "tiled" FALSE)
+   (gimp-drawable-filter-set-aux-input filter "aux" bump-layer)
+   (gimp-drawable-merge-filter drawable filter)
+ )

The "type" argument now uses strings.

This commit also do a big cleanup of remaining now-unused helper
functions in the compat PDB code.
2024-12-17 16:24:54 +00:00
Jehan
e2d7cc163e app, pdb, plug-ins: replace (plug-in-displace).
For plug-in writers reference, these are equivalent:

- (plug-in-displace RUN-NONINTERACTIVE work-image frame-layer
-                   x-displacement y-displacement
-                   TRUE TRUE aux1 aux2 abyss))
+ (let* ((abyss "black")
+        (filter (car (gimp-drawable-filter-new frame-layer "gegl:displace" ""))))
+
+   (if (= edge-type 1) (set! abyss "loop"))
+   (if (= edge-type 2) (set! abyss "clamp"))
+
+   (gimp-drawable-filter-configure filter LAYER-MODE-REPLACE 1.0
+                                   "amount-x" x-displacement "amount-x" y-displacement "abyss-policy" abyss
+                                   "sampler-type" "cubic" "displace-mode" "cartesian")
+   (gimp-drawable-filter-set-aux-input filter "aux" aux1)
+   (gimp-drawable-filter-set-aux-input filter "aux2" aux2)
+   (gimp-drawable-merge-filter frame-layer filter)
+ )

I also changed a test which (I think) was just a no-op since do-x and
do-y were 0 0 (hence FALSE). Therefore the whole filter processing was
ignored. Note though that unlike the rippling animation filter, I
haven't tested the test script.
2024-12-17 16:24:54 +00:00
Jehan
a6392ed84a app, libgimp, pdb, plug-ins: add a few Script-fu wrapper of libgimp filter API.
In particular (gimp-drawable-filter-configure),
(gimp-drawable-merge-filter) and (gimp-drawable-append-filter) are
proper Script-fu methods.

I had to rename the PDB procedures for the 2 latter because they were
clashing with these wrapper. I had not realized that private PDB
procedures are still visible by Script-fu. This is not so glop. :-/

Right now, it doesn't look so useful compared to the -new- one-liner
variant procedures. But it will make sense when I will add aux input C
procedure wrappers.
2024-12-17 16:24:54 +00:00
Jehan
6480ba2ad6 app, libgimp, pdb: new gimp_drawable_filter_set_aux_input() public API.
It is this way possible to set a drawable as auxiliary input to a filter
in C and GObject-Introspected bindings.

Note that such filters can only be merged, not appended
non-destructively for the time being.
2024-12-17 16:24:54 +00:00
Jehan
1fbd2acc84 app, pdb, plug-ins: get rid of (plug-in-rotate).
It can be reimplemented with (gimp-image-rotate) and
(gimp-item-transform-rotate-simple), with even more capabilities for the
latter.

The item rotate procedure is a bit more tricky though, since it takes
into account the selection. It means that either you want to just remove
the selection before (that's what I did here, because this script was
already losing the selection anyway), or you want to store the selection
(with (gimp-channel-copy)), then reapply it (very likely with
(gimp-channel-combine-masks)) at the end, after also rotating it
appropriately the same way as the image if needed.
2024-12-17 16:24:54 +00:00
Jehan
c26b2cd08f app, pdb, plug-ins: replace (plug-in-noisify).
For plug-in writers reference, these are equivalent:

- (plug-in-noisify RUN-NONINTERACTIVE theImage mLayer TRUE r g b a)
+ (gimp-drawable-merge-new-filter mLayer "gegl:noise-rgb" 0 LAYER-MODE-REPLACE 1.0
+                                 "independent" TRUE "red" r "green" g "blue" b "alpha" a
+                                 "correlated" FALSE "seed" (msrg-rand) "linear" TRUE)

Notes:

* When "independent" is FALSE, then you only need to set "red" (which is
  equivalent to a "value" field) and "alpha".
* Original plug-in was using the second value ('g', a.k.a. noise_2 in
  the PDB args) as alpha when the source drawable was grayscale. This
  logic is meaningless now. Just set "alpha".
* The PDB procedure was wrapping the operation between
  "gegl:cast-format" nodes to cast the input buffer to linear. This is
  useless as the "gegl:noise-rgb" has already a "linear" argument
  (defaulting to TRUE, but I specify it explicitly in this commit, for
  clarity) which requests linear input when set.
2024-12-17 16:24:54 +00:00
Jehan
dc4daa8396 app, pdb, plug-ins: replace (plug-in-emboss).
For plug-in writers reference, these are equivalent:

- (plug-in-emboss RUN-NONINTERACTIVE img mask-emboss 315.0 45.0 7 TRUE)
+ (gimp-drawable-merge-new-filter mask-emboss "gegl:emboss" 0 LAYER-MODE-REPLACE 1.0 "azimuth" 315.0 "elevation" 45.0 "depth" 7 "type" "emboss")

Note: the last arg, emboss, must be replaced by a string, "emboss" when
it was TRUE, "bumpmap" when FALSE.

Similarly to "gegl:gaussian-blur", the call to wrap_in_gamma_cast() was
useless because "gegl:emboss" already sets its output format to linear,
as well as its input format (through GeglOperationAreaFilter parent
class).
2024-12-17 16:24:54 +00:00
Jehan
1c4a00de78 app, pdb, plug-ins: replace (plug-in-gauss).
For plug-in writers reference, these are equivalent:

- (plug-in-gauss RUN-NONINTERACTIVE image layer hblur vblur 0)
+ (gimp-drawable-merge-new-filter layer "gegl:gaussian-blur" 0 LAYER-MODE-REPLACE 1.0 "std-dev-x" hblur "std-dev-y" vblur "filter" "auto")

Note: the method arg { AUTO (0), FIR (1), IIR (2) } is transformed into
a string in lowercase. E.g. 1 becomes "fir".

At first, I was a bit annoyed by the wrap_in_gamma_cast() call which
converts the buffer to linear first, but looking at "gegl:gaussian-blur"
implementation, it is just a meta op to 2 "gegl:gblur-1d" which anyway
sets input format (to various formats, but always linear).

This legacy cast code must be a remnant from older times where it might
have been needed. Clearly it's not anymore.
2024-12-17 16:24:54 +00:00
Jehan
b0ac59b421 app, pdb, plug-ins: replace (plug-in-plasma).
This time, it's a Python plug-in, which is a bit more involved than C or
Script-fu usage (where we have variable args one-liner function) though
it's not too bad either. It's actually very similar (on purpose) to how
PDB procedures are run.
2024-12-17 16:24:54 +00:00
Jehan
082ba3bb1f app, pdb, plug-ins: replace (plug-in-waves).
For plug-in writers reference, these are equivalent:

- (plug-in-waves RUN-NONINTERACTIVE
-                image
-                source-layer
-                amplitude
-                phase
-                wavelength
-                0
-                FALSE)
+
+ (let* (
+       (phi phase)
+       (width (car (gimp-drawable-get-width source-layer)))
+       (height (car (gimp-drawable-get-height source-layer)))
+       (aspect (/ width height))
+       )
+
+   (while (< phi 0)
+     (set! phi (+ phi 360.0))
+   )
+   (set! phi (/ (- (modulo phase 360.0) 180.0) 180.0))
+
+   (if (< aspect 0.1)
+     (set! aspect 0.1))
+   (if (> aspect 10.0)
+     (set! aspect 10.0))
+   (gimp-drawable-merge-new-filter source-layer "gegl:waves" 0 LAYER-MODE-REPLACE 1.0 "amplitude" amplitude "phi" phi
+                                                                                      "period" (* wavelength 2.0)
+                                                                                      "clamp" TRUE "aspect" aspect)
+ )

Notes:

* The old type argument is the negated value of "clamp".
* The last argument (reflective) was unused.
2024-12-17 16:24:54 +00:00