Commit graph

6641 commits

Author SHA1 Message Date
Bruno Lopes
811c0c8546 app: Use posix_spawn on macOS
Fixes a Apple Clang warning.
vfork is considered deprecated and unsafe on such platform
2026-03-30 16:09:13 -03:00
Bruno Lopes
af1dac3c51 app, plug-ins: Comment unused stuff on macOS
This fixes Apple Clang warnings about:

- idx
- count_large
- count_nan
- n
- iteration
- original_id
- real_pos
2026-03-29 17:19:42 -03:00
Bruno Lopes
c8c420aa18 app, plug-ins: Comment pixel, total, flags and count unused variables 2026-03-28 19:51:25 -03:00
balooii
8bdb5cbfd7 app: Fix duplicating vector layers 2026-03-26 11:52:24 -03:00
Alx Sa
d1662f8f2c core: Stop double-resizing on Fit Canvas to Layers
Resolves #16018
This patch extends a2c5d70c to also apply to the
"Fit Canvas to Layers" action. It prevents the non-rasterized
vector layer from being shifted out of place when the
canvas is resized.
2026-03-26 05:44:27 +00:00
Alx Sa
a131100075 core: Prevent double-resizing on vector image crop
Resolves #16045
This patch extends a2c5d70c to also apply to the Crop Tool.
It prevents the non-rasterized vector layer from being shifted
out of place when cropped.
2026-03-26 05:02:52 +00:00
balooii balooii
a2c5d70c92 core, path: Fix image transforms with vector layers
(Modified by CmykStudent from balooii's original merge request)
When performing image-level operations (resize, crop, scale, flip,
rotate, arbitrary transform), paths referenced by non-rasterized vector
layers were being transformed twice:

1. Via the vector layer's overrides, which explicitly transforms
   the referenced path to keep it in sync
2. Via the image-level queue that processes all paths independently

This patch adds a check for whether the layer has been rasterized.
If so, we bypass the vector layer's transform so the path is not
transformed a second time.
2026-03-25 20:29:17 -04:00
Alx Sa
c3cbd5c21f core: Use selection when counting colors...
...in Histogram Editor.
The 2.10 Colorcube Analysis plug-in took into
account the selection when displaying the colors.
The Histogram Editor itself does as well, but our
unique color count did not.
This patch adds a check in gimp_histogram_unique_colors ()
to see if there's an active selection in the image.
If so, we get its area and use that as the bounds in
gegl_buffer_iterator_new () instead of setting it to NULL.
2026-03-25 12:43:00 +00:00
Jehan
7f67536f1a Issue #16010: do not mind buffers with non-0 offsets in the case of group layers.
In fact, the previous commit was unneeded and we could have done without
reverting the old commit. On the other hand, a buffer using another
buffer as "source" may be nicer in memory.

But the previous commit alone was not right as group boundaries were
wrong. In fact, right now, we can see that group boundaries are computed
using only the children layers (except for pass-through of course), not
including any effects they might have. And the buffer passed to
gimp_drawable_set_buffer_full() was the projection's buffer itself — it
was shared, which was also why copying at setting time was wrong —, in
the case of a group layer. That means that when we translated to (0, 0)
offset, either we would have moved the render to the wrong place, or
moved the boundaries to the wrong place.
The offset needs to stay what it is, even when it's not (0, 0), for
group layers.

Another alternative fix would be instead to fix layer groups' boundaries
to encompass the full projection's render. But I just went with this
special-casing of group layers instead.
2026-03-24 20:41:53 +01:00
Jehan
af44043108 Issue #16010: adding a layer with filter to a group makes it invisible.
Part of it reverts commit 3a53e4743e.
Another part is a fix to the CRITICAL mentioned in this commit.

This being said, it's clearly not entirely right yet. The boundaries of
the layer when the filter is merged are not correct, which is especially
visible when trying to draw on this layer afterwards.
Also the layer group boundaries (when reproducing the steps in #16010)
are clearly wrong too.
2026-03-24 20:37:00 +01:00
Bruno Lopes
b697dc8a48 app: Fix critical at user_install_detect_old on distro and Flatpak packages
Closes: #16067

This fixes a regression introduced by 62467359
2026-03-22 08:17:15 -03:00
Jehan
040fac494e app: do not leak string allocated by g_ascii_strdown(). 2026-03-18 23:36:56 +01:00
Jehan
f4f83b973c app: SwatchBooker support also uses libarchive and has similar bugs! 2026-03-18 23:11:20 +01:00
Jehan
b3eaf3a577 app: better handle error cases for invalid Swatches palette.
My use case was loading a 0-bytes swatches palette. This would crash
GIMP. And so would likely a zip archive suffixed .swatches with no .json
file in it, or a corrupted archive which would return ARCHIVE_FATAL when
attempting to read entries…

This patch fixes these edge cases. It also better handle the various
return values of libarchive. E.g. we should not abandon reading when we
get ARCHIVE_RETRY; and ARCHIVE_WARN is also a success case (despite
having some warning message).

Finally I break from the archive reading loop at the first JSON file, so
that we don't leak memory if there are several JSON file. It does raise
the question if this palette format allows such use case (several
palettes in a single .swatches archive).
2026-03-18 22:41:14 +01:00
Jehan
591518fdb1 app: fix failure to read a Procreate palette with no profiles.
The sample in the description of !2613 was failing to load with a bunch
of criticals. That was because when profiles == NULL, we would call
json_reader_end_member() while we never called the associated
json_reader_read_member(). Inverting the order of tests fix this.
2026-03-18 22:32:31 +01:00
Jehan
fdda75deb8 app: localize some more strings.
Also give a bit more accurate error message when possible, e.g. when we
may have an error message from libarchive.
2026-03-18 17:57:23 +01:00
Alx Sa
ff647fccb0 path, core: Create gimp_vector_layer_set ()
Currently to change vector layer properties,
you need to grab the VectorLayerOptions
and then grab its FillOptions or the
StrokeOptions to make changes.
To make this process more self-contained,
this patch creates a gimp_vector_layer_set ()
function that operates in the same manner
as gimp_text_layer_set (). 
This patch adds properties for Fill -
Stroke properties will be added in a
follow-up commit.
This also adds
automatic tracking for Undoing/Redoing
vector property settings.
A demonstration of its use in DnD colors
and patterns onto the layer dock is
included.
2026-03-17 19:32:51 +00:00
Jehan
0074bef0ea Revert "Issue #15824: better detect the first filter."
This reverts commit 75e665f0ed.

In fact, this commit was wrong too and was creating new issues with
pass-through group layers. See #15956.
2026-03-06 21:13:52 +01:00
Bruno Lopes
6246735966 app: migrate also from ~/snap/ if the 3.0 folder is not found in XDG config home. 2026-03-03 21:33:38 -03:00
Jehan
6283ec669d app: verify all playground features to forcibly show the playground tab.
Maybe I should find a more "automatic" logic…
2026-03-02 22:25:07 +01:00
Jehan
b87bab9e8c app, libgimp*: add GimpCurve sample API in libgimp and PDB. 2026-03-01 22:33:58 +01:00
Alx Sa
804991a215 libgimp, pdb: Allow access to GimpCurve in PDB
Adds a GimpCurve object and functions in libgimp.
Rather than creating a GimpCurve object in core and
passing it back and forth, we just pass the attributes
and reconstruct it across.
In the future, we may combine this with the app/core one
and put it in libgimpbase.
2026-03-01 13:41:35 +00:00
Jehan
3a53e4743e app: copy the buffer rather than using it as source.
I think the previous code should be OK, but I had some criticals when
painting with a paint tool in the area which got extended:

> (gimp:577203): GLib-GObject-CRITICAL **: 21:37:08.402: value "-31" of type 'gint' is invalid or out of range for property 'y' of type 'gint'

It looks like there lingering pieces from the negative offset in the
buffer, which is probably a bug in GEGL?
Anyway let's go the shorter route for now, which is to copy the buffer
with a different offset. I don't think it's less efficient either
anyway.
2026-02-28 21:52:10 +01:00
Jehan
4c15be6a56 app: fix merging filters with negative top-left point.
When merging filters whose rendering was expanding in negative
ccordinates, I realized that the drawable was not properly resized (it
was resized properly when the width/height increased, but not when the x
or y points became negative, even though this "cropped" part still
showed… until you saved and reloaded your XCF!).

The problem is that drawable buffers are always stored with (0, 0)
top-left and this was just confusing our existing code. So let's check
when trying to set a buffer with a non-(0, 0) origin, and update the
offset subsequently.

I hesitated with an alternative implementation which was to edit the
buffer applied to the drawable in gimp_drawable_merge_filters(). But I
figured this would be more future-proof for other similar cases, though
I hope I did not break any use case where this was actually considered a
normal case.
2026-02-28 21:04:05 +01:00
Bruno Lopes
b7d89728c4 app, libgimpthumb, plug-ins, tools: Fix POSIX namespace warnings on MSVC 2026-02-28 10:06:46 -03:00
balooii balooii
d80ad177af Issue #13401: Fix crash opening channels after apply/undo drawable filter 2026-02-26 15:06:14 +00:00
Jehan
ad936482a2 Revert "Issue #15824: waterpixels filter on a selection appears to hang GIMP."
This reverts commit d91a8b2abe.

As reported by Liam on #15824, this commit was clearly wrong and
reintroduced the old cropping bug with multiple filters. Reverting.

The next commit was likely good, though the real hanging bug is — as far
as my test go — in the GEGL op itself. This second commit 75e665f0ed was
improving things, but obviously, as the bug is still in the op, it can
still be triggered. We'll have to fix the source bug next.
2026-02-25 23:51:56 +01:00
Jehan
75e665f0ed Issue #15824: better detect the first filter.
Ah my previous commit was working fine with a selection in the "Use the
selection as input" case, but was still hanging when "Use the entire
layer as input" was chosen.

The detection of whether we were the first filter was not working fine
when adding a new filter. Now this should work in all cases.

I don't revert the previous commit, because I think it's fine anyway.
When we have a selection, unconditionally adding a cropping-before node
on the selection boundaries seems logical to me.
Hopefully it doesn't bring back any of the cropping issues we had on
filters, but so far I could not reproduce any.
2026-02-25 15:44:29 +01:00
Jehan
d91a8b2abe Issue #15824: waterpixels filter on a selection appears to hang GIMP. 2026-02-25 15:38:23 +01:00
Alx Sa
1282384417 core: Update filter area if changed
Previously, we only updated an NDE filter's
`filter_area` if the filter itself contained a
width or height property.
However, the filter_area is also used by
GimpDrawableFilter to indicate where we
should draw the filter, and needs to be
updated if we scale/rotate/shear the layer
and change its dimensions.

This patch moves the code so that the
filter_area width and height is always
updated if we pass a GeglRectangle in to
gimp_drawable_filter_refresh_crop ().
2026-02-24 11:32:08 +00:00
Jehan
87810ae6fe app: make explicit that "White Balance" auto effect works in linear space.
This commit doesn't actually changes anything, but it fixes the
gimp_histogram_new() call, since the argument is supposed to be a
GimpTRCType, not a boolean. Yet GIMP_TRC_LINEAR is the first value in
the enum type, so it's indeed the same as FALSE.
I also set the "trc" property to "gimp:levels" config object explicitly,
to the same TRC value as the histogram, so that this doesn't depend on
the default anymore (which is linear too, right now; so this part
doesn't change a thing here again), and therefore would survive to any
possible default change in the future.

Note that it was considered to set this all to non-linear, just as it
used to be in 2.10, as requested in #15738. After discussing it with
Øyvind on IRC, we concluded that working in linear space may be a nicer
default for this feature, as we'd be doing a "meaningful rebalancing of
photon count per component". Now there may be cases where doing a
white-balancing in non-linear may yield better result, of course. For
these case, you may still go to "Levels", set to non-linear, and hit
"Auto Input Levels". This is exactly the same code runing (but in
non-linear space). The "White Balance" action still needs to be the
simple non-GUI option and keeping work in linear seems like the more
appropriate default here.
2026-02-24 01:36:32 +01:00
Alx Sa
b9d4e315e8 core: Adjust logic for gimp_drawable_filter_refresh_crop ()
In 0157a958, we prevent the NDE crop refresh
code from running unless the filter's crop
enabled is TRUE. However, this prevents
the width and height settings built into
certain filters from running, separate from
the crop nodes in GimpDrawableFilter.
This patch moves the check to only cover
the calls to gimp_drawable_filter_set_crop ().
This should fix the width/height update issue
without causing a regression to #14442.
2026-02-22 18:10:15 +00:00
Alx Sa
581afd1516 core: Fix GEGL warning after bucket fill
In 6279d7b7, I did not free the GEGL buffer created
by gimp_pickable_get_buffer_with_effects ().
This resulted in an "EEEEeEeek! 1 GeglBuffers leaked"
warning on exit, which of course could cumulate.

This patch makes to sure to clear out the src_buffer
both times it's used.
2026-02-22 00:28:16 +00:00
Alx Sa
6949400a03 core: Fix Equalize TRC compared to 2.10
In GIMP 2.10, gimp_histogram_new () takes a boolean
parameter to indicate if it should be rendered in a linear
or non-linear TRC. In GIMP 3.0, this function instead takes
a GimpTRCType where 0 is equal to the linear enum and 1
is equal to the non-linear enum.

Since gimp_drawable_equalize () still passes FALSE as it
did in 2.10, this is treated as 0 and thus setting it as a linear
operation.

This patch changes the FALSE to be GIMP_TRC_NON_LINEAR,
both for clarify and to better match the 2.10 behavior.
2026-02-20 15:00:39 +00:00
Alx Sa
4bfa65d72d core: Refresh new vector layers when pasting it
When copying and pasting vector layers, if we needed
to add a new path then the layer was not redrawn.
This would require the user to move or edit the path
to see the correct view of it.

This patch adds a call to gimp_vector_layer_refresh ()
after pasting it if it is not rasterized, in order to correct
the initial view.
2026-02-19 23:18:39 +00:00
Jehan
2b45e54b0c app: set the rasterized status properly on opening XCF files. 2026-02-14 18:30:37 +01:00
Jehan
b8e094416f Issue #15119: flipping link layers should not rasterize them. 2026-02-14 18:30:37 +01:00
Alx Sa
31eb0d86cf core: Associate color profile with SBZ palette
Color profiles were not being correctly connected to
Swatchbooker imported palettes, because the path
was included with the profile name (so a direct comparison
did not match). This patch fixes this by comparing the suffix
instead. It also fixes some minor formatting issues.
2026-02-12 02:07:49 +00:00
Alx Sa
dbc1c55de4 core, dialog: Add Procreate swatches import support
Procreate swatches are zipped JSON files.
They contain an object array of HSB
color palette values. Newer versions of the
format also support different color models,
spaces, and color profiles.

This patch adds support for importing the
palette name, colors, and associated color
profile in the original HSB format.
2026-02-12 01:49:47 +00:00
Alx Sa
f08eff5cda core: Retain SamplePoint modes when copying images
Resolves #15833
When we copied images in
gimp_image_duplicate_sample_points (), we only carried
over their X & Y position, not their pick mode.
This patch adds calls to get the original pick mode and
to set it to the new sample point created in the copied
image.
2026-02-09 12:17:11 +00:00
Jehan
d893aa373d Issue #11642: "images-delete" action not disabled when the selected…
… image's displays change in the Images dockable.
2026-02-07 00:39:12 +01:00
Alx Sa
cfba63a932 core, widgets: Don't remove inactive filters on merge
If a filter is inactive/invisible, it does not
affect the appearance of the drawable.
Therefore, when merging all active filters,
those filters should not be removed.

This patch adds conditional checks for
gimp_filter_get_active () and does not
remove filters on merge if it returns
FALSE. It also adds sensitivity checks in
the GUI so that the merge down button is
not active if there are no visible filters.
2026-02-06 21:50:13 +00:00
Jehan
955ff5b765 app: add new migration rule for property (linear) for Curves and Levels.
Property "linear" was replaced by "trc" in commit e09e563a70.
Unfortunately "linear" still stayed "as compat if needed for file
pasring" (cf. commit message) but this made a big mess, because when
setting operation properties at once, these 2 property can mess with
each other.

These migration rules are a first step in cleaning up the mess. Now we
should not have any config file with (linear) property in there,
therefore we can cleanly neutralize this property in further commits.
2026-01-30 23:38:34 +01:00
Jehan
bf6fcac0a9 Issue #14139: wait for fonts to be loaded before loading files.
This was happening when trying to load a file before fonts were fully
loaded, which may happen when loading while starting GIMP (either from
CLI, or from a file browser, etc.), or simply just after start for
people with a lot of fonts, whose font loading may take a long time as
background task.

Note that I didn't manage to reproduce properly because from reports, it
seems like the problem appears where some fonts may be only partly
loaded so gimp_font_get_hash() fails to load the font and get a hash. I
never managed to trigger such a case and no reporters answered my call
for testing of debug builds.
As a consequence, I'll just assume that simply waiting for all fonts to
be loaded before starting to load images would work out.

Note that the crash was not happening when text layers were using the
older syntax (pre-XCF 19) of text layer data, since it was not storing
any font hash, which means that we were not trying to compare hashes. It
would also not crash if fonts were not fully loaded yet, but we didn't
have any weird intermediate state where fonts appeared in the list yet
their file were not hashable (cf. what I failed to reproduce, as
explained in previous paragraph). But both these cases were not ideal
either anyway because then we could load the XCF apparently OK… except
that the correct fonts would not be associated to the related text
layers (hence as soon as you start to edit said texts, the rendering
would break). So we should wait for fonts to be loaded, and that was a
bug even when you can't reproduce the crash.

When starting GIMP without loading an image, or simply when fonts are
loaded quickly enough, it won't make any difference. So it should not
make startup any slower for most common use cases and installations.
2026-01-07 01:06:20 +01:00
Jehan
56a17c73eb app: fix gimp_get_data_factory() to support returning the tool preset…
… factory.
2026-01-07 01:06:20 +01:00
Jehan
d92c237a17 Issue #13709: wait we get our first surface focus before listing…
… input devices.

Per Carlos' advice on gtk#7534, I wait for us to get a focus, since the
pad devices are only created at that point.
Note that this is a Wayland-only issue, but since it doesn't matter too
much that input devices are not initialized before we have a focused GUI
anyway, let's make this simpler.

At the earliest, the splash focus can announce a focus, but since it is
possible to start GIMP without the splash, display shells will also
possibly announce the first focus (there will always be a display shell
focusing at some point for any GUI GIMP!).
2025-12-16 00:02:33 +01:00
Jehan
0157a9581e Issue #14442: undo crops layer rendering out of its off-border effects.
This was happening in multiple cases, such as undoing a "Rasterize
filters" action, but also with a "Layer to Image Size" being undone, and
probably any other undo cases.

In particular here the culprit was that upon undoing, we were setting
the GimpApplicator's "gimp:compose-crop" node, while it was a "gegl:nop"
before. We must be careful not to set a crop unexpectedly when the node
was not set already, explicitly.
2025-12-13 00:11:08 +01:00
Bruno Lopes
e285b70d6a
app/core: Add missing header for getpid() on Windows 2025-11-29 18:18:43 -03:00
Alx Sa
8db97f4eaf core: Create gimp_drawable_convert ()
When a drawable is converted, we check if
it has filters. If any filter has a mask, we convert it
to use the new image instead of the old one.
This prevents several crashes where the filter's mask
still pointed to the old image if it was copy/pasted
into a new one.
2025-11-27 04:56:56 +00:00
Alx Sa
7d89af790d core: Increase clipboard brush/pattern for 64 bit
Resolves #5627
The current limit for Clipboard Brush and
Pattern maximum size is set to 1024 because
that is the largest value that a 32-bit
architecture can safely handle.
64-bit architectures can support larger
dimensions, as confirmed by
Stanislav Grinkov during testing. This patch
therefore uses macros to increase the
size limit if we detect a 64-bit architecture,
and otherwise default to the 32-bit limit.
2025-11-23 05:31:57 +00:00