As a follow up to the previous commit, I noticed that the pdb functions
gimp-edit-cut and gimp-edit-named-cut also incorrectly used
gimp_pdb_item_is_group.
This can be seen by calling Filters/Blur/Tileable blur when a group
layer is selected. The error message was incorrect.
We replace the call here also to `! gimp_pdb_item_is_not_group`.
Calling gimp_selection_float from a Python plug-in could make it crash
with an error like Calling error for procedure 'gimp-selection-float':
Item x cannot be used because it is not a group item.
This is caused by an incorrect check for group layers.
gimp_pdb_item_is_group returns an error when the condition is False,
while we only want an error when a group layer is selected (True).
Thus we need to use gimp_pdb_item_is_not_group, which returns an error
when the item is a group, which is what we want.
These function names are a little confusing, we might need to think
about better naming sometime.
I added C/Python tests for this function, so that we can test whether
this works correctly.
Resolves#11250
In 2.10, we explicitly hid "dockable-preview-size-menu", the submenu
for Preview Size, if there were no previews to set sizes for in the
dockable dialogue. In 2.99, this code was removed as part of the
GAction port and code clean-up.
As a result, the Preview Size submenu is always visible even if the
options have no effect on the display. To restore the 2.10 behavior,
we set each Preview Size option's visibility. If all options are hidden,
the submenu does not appear.
In case there are no fonts loaded (which may happen in particular when starting
with --no-fonts), we need to make sure that font is initialized to NULL so that
we can return the standard GimpFont object and not a broken pointer.
Thanks to Idriss for the additional diagnosis, which would hopefully complete
commit 5dc86277e6 and take care of #11219.
Previous code would only set the class member when we were actually
loading fonts, so we ended with code paths where the member was NULL.
Fixes:
> GIMP-CRITICAL: gimp_container_get_n_children: assertion 'GIMP_IS_CONTAINER (container)' failed
It should hopefully also fix#11219 (though I couldn't reproduce this
failure).
Resolves#11256
A GError variable was created but not passed to
file_open_with_display () when opening recent files.
As a result, if an error did occur the variable would be
used while it was still NULL. This patch fixes this
by passing a reference to error as the last parameter
of file_open_with_display ().
Resolves#11075
In the DrawableChooser pop-up, choosing an image without
also picking a layer or channel causes the pop-up not to
reappear on subsequent attempts to click it. This is because
the callback is only recreated when the drawable is updated,
and choosing just an image does not update the drawable.
For 3.0, we'll set the Okay button to insensitive unless a layer
or channel is picked.
Resolves#11054
NDE Filters clip to the size of the layer when
applied. Group layers get their dimensions from
the largest layers under them, so an empty
layer has dimensions of 0 by 0. This means a
filter applied when the layer group is empty will
be clipped to 0 by 0 as well.
This patch adds code to refresh the filter's crop
whenever the group layer is resized by a
layer being added or removed.
...to accept GeglColor paramaters instead
of GimpRGB. This function is used to draw
the layer/channel color tags.
Note that a temporary GimpRGB was left
to use with gimp_rgb_composite ().
It will be replaced once that function is
also converted to use GeglColor.
752f0fb4 did not fix saving/loading filters
in .xcf files. To do this, a new function to
retrieve the clip setting was added to
gimpdrawablefilters.c, and then used to
save the value in xcf-save.c. The existing
set_clip function was used in xcf-load.c,
just like in 752f0fb4.
Resolves#10997
When filters are duplicated for export, the clip property was
not being copied over. This caused filters that go outside the
layer boundaries (like Drop Shadow and Long Shadow) to be
clipped incorrectly.
The simple fix was to copy over the clip value when the new
filter was duplicated.
Resolves#11147
Applying the same reordering code
in cbb1e816 to adding a floating selection.
When anchored, floating selections were also
merging down all layer effects onto the original
image. This patch places the float selection
under the layer effect when added, both to prevent
this and because it seems to be the expected
behavior based on user feedback.
The border-drawing code for Layer icons
has been ported to GeglColor. Note that
GimpViewRenderer still uses GimpRGB for
gimp_cairo_checkerboard_create (), which
will be fixed in a larger commit.
In 9bee3bed, Border Average's return
value was set to NULL rather than a valid
GeglColor when the procedure was
created, which caused a warning on
launch. This has been fixed.
Perspective shadow could call plug-in-gauss-rle with higher blur
radius than allowed in the wrapper. Raise the max value to
allow for this.
Fixes#11140
When the config directory is set by an environment variable, the version is
likely not part of the directory path, and therefore strstr() would return NULL.
Fixes:
> (gimp-console-2.99:41446): GLib-CRITICAL **: 13:19:34.933: g_vsnprintf: assertion 'n == 0 || string != NULL' failed
This commit is in conjunction of gimp-data@d273a18 and finally makes Windows
build able to run GIMP main binary itself (or gimp-console) in order to create
various images, before the installation step.
- Use the new GIMP_TESTING_INTERPRETER_DIRS environment variable for uninstalled
binary to find the .interp files (in particular because our build scripts are
usually Python scripts these days).
- Use the new GIMP_TESTING_ENVIRON_DIRS environment variable to find .env files
(actually running uninstalled GIMP binaries did run without this one, but it's
not a bad idea to add support anyway.
The python.env file sets a ':' separator for GI_TYPELIB_PATH environment
variable, which breaks finding the correct typelib files in the CI, when also
manually setting a previous value for this environment variable.
I'm not entirely sure the rule of swapping ':' for ';' is universally true on
Windows, whichever the variable. Let's hope that it is.
Meson subprojects just have too many problems and limitations and I can foresee
the maintenance headache and the future incoming false-positive bug reports if
we start using meson subprojects.
Comparing to the simplicity of git submodule which also has much better
notifications to help people understand when the submodule is not in sync and
how to remedy to it.
See commit gimp-data@c364adb explaining the main reasons in detail.
Note that the executables are not built yet at this point, but we just need to
pass the name for configuration. The gimp.ico generation step is run manually
anyway and requires a fully functional and installed GIMP.
See commit gimp-data@40d4822.
This commit is separate from the previous to make it immediately clear (by
comparing files) that the previous commit is a simple move with no modification
whatsoever of the icons/ directory, i.e. the symmetrical removal of add commit
gimp-data@8b54490.
We now clone gimp-data as a meson subproject. I am currently testing the
subproject feature though I am doubting a bit because of its limitations: the
git clone is not updated automatically, nor are errors clear. Therefore it would
be easy to end up with outdated data for developers not manually and regularly
running:
> meson subprojects update
Worse, it looks like even when updating the suproject, it fails to be properly
reconfigured. See: https://github.com/mesonbuild/meson/issues/12898
Resolves#7672
The Plasma wrapper gets the boundaries
of its filter area using gimp_item_mask_intersect().
If used on a selection, this gives the x and y
coordinates relative to the total canvas.
However, the GEGL operation will be drawn
relative to the selection - so this offsets
the effect within the selection rather than
filling the full space.
This patch fixes the problem by setting
the x and y position to 0 when there is an
active selection.
Layer effects that have not yet been committed are not
attached to the drawable. Trying to reorder them causes a
crash since they're required to be attached for undo/redo
purposes. This patch checks if they're committed beforehand,
and informs the user with a warning if it's not possible.
...to fully use and return GeglColor.
Also, fix gimptext-parasite sending a
GimpRGB to create a GimpText instead of
the now required GeglColor, and update
documentation in gimp_checks_get_colors
to reference GeglColor instead of GimpRGB.
Resolves#11057
Per Idriss Fekir's research, data from GBytes
should be written before the GByte is freed.
Perhaps due to luck, the data persisted on
Windows but was freed too early on Linux.
This patch should resolve the issue.
After the color space invasion, the
Clip Warning filter no longer had color
areas for its shadow, highlights, and
bogus color properties. This patch ports
them to GeglColor so the widget can be
created correctly.
GimpRGB structs are also converted to
GeglColor in GimpPanedBox and two
plug-ins.
Otherwise we are not in a valid position anymore and further loading the XCF
fails. This may happen when updating a GEGL operation (in particular removing
effect properties, or renaming them).
The two threshold color pick buttons needed to have
a GeglColor parameter for their GimpPickerCallback
rather than a const GimpRGB.
This also fixes a crash caused by trying to free the GeglColor
rather than unreferencing it.
Without this, there is no easy way to quietly check for existence of a resource by name.
Needed when plugin authors can name defaults for resource args by name.
Add tests to script-fu/test/tests
Mainly fixing GimpRGB comments and
parameters that are unused (or in unused
functions).
GimpCircle and GimpGradientChooser
have color conversions ported to use
GeglColor exclusively.
Since commit 10b96b1025, we had buffer leaks as soon as we ran filters.
gimp_drawable_get_buffer_with_effects() was either creating a new buffer (when a
drawable had filters) or not. And calling code couldn't know which is which.
Code needs to be consistent. Either we return a new reference to take ownership
to, or not. So let's change to add a new reference to the drawable' buffers so
that it always returns a new reference to free.
Though commit a14caafa8c was not wrong per-se, it's a bit too much. ;-)
Functions like g_ascii_dtostr() already exists for this very purpose of
converting a double/float to string in a locale-independent format.
CSS breaks when given a number with a comma as the radix
instead of a decimal. Depending on the system localization,
printf () may return numbers in this format when resizing
the font. This causes the theme to break unless font size is
set to 100.
To prevent this issue, we create the font size string manually
using integer division and mod operations.
- Replaces GimpRGB in Channel Dialog
with gdouble array, as was done in
channel_options_color_changed ()
- Replace %ld with G_GSIZE_FORMAT
in libgimp checkboard color message to
fix warning in Windows build
- Set file-gih documentation text as
translatable.
I think I may even have been the one who suggested to make this checkbox always
visible, but after more thought and usage, I just realize that this option is
not about showing the Welcome dialog, but about showing the Create tab of the
Welcome dialog. So I move it to the Create tab.
A very obvious case where the previous option location could have been
considered wrong is that we will always show the dialog (on the "Welcome" tab)
for updates, even if this checkbox had been unchecked. So if we left it as a
global option of the dialog, this could be considered a bug (the option is
disabled, but the dialog still opens on updates), whereas the new position and
shortened label make it clearer that this settings only apply to whether or not
we show specifically the Create dialog on start.
The splash image had a lot of empty space around it. From what I understood,
this is because we want to avoid it to be too big because it makes the dialog
overgrow the display size on small screens. But I don't think that was a very
good idea. We should find better ways to save space.
In d055564d, a pointer to the color profile
for NDE filter color properties was being
saved rather than the actual ICC profile.
This patch fixes the issue.
It also allows colors to load even if the
color profile is corrupted, with a warning.
For improved readability, int or boolean types are used in place of
guchar for PDB parameters where the parameter description better fits
one or the other type.
This change affects `plug-in-alienmap2` and `plug-in-maze`.
Also, the problem with `guchar` parameters is that they currently cannot
be modified via `GimpProcedureConfig` due to the type not being
supported.
Resolves#11003
GeglColor defaults to NULL rather than black like
GimpRGB. When selecting text with two or more colors
in the total selection, this causes NULL to be passed
to gimp_color_button_set_color () which throws an error.
This patch resolves the issue by setting GeglColor to
black if it's NULL before the call.
After the color space invasion, the
Semi-Flatten GUI was broken since it still
used GimpRGB as its color property.
This patch fixes this by porting to
GeglColor. The GimpRGB conversion was
also removed from the PDB interface
since the GeglColor comes directly from
GimpContext.
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.
Resolves#10990.
Since the "mask-color" property is now a GeglColor,
we need to use gimp_prop_gegl_color_button_new ()
rather than gimp_prop_color_button_new () to
display it in the options panel.
Per @brunolopesdsilv, the About and Quit
dialogues had custom buttons which did
not receive the text-button CSS style.
This patch adds those back so the buttons
match the styling of the others in the
dialogue.
Resolves#10762.
Updates gimpdrawable-preview.c to use
gimp_drawable_get_buffer_with_effects (),
which includes any NDE Filters applied to
the layer in the preview.
The preview is also set to update when a
filter is applied non-destructively.
Since the Image Recovery dialog is blocking the main process (and requires an
answer to be done first), let's simply move down the Welcome dialog to after
this answer was given. This way, we simply won't have both dialogs in the same
time.
...with the Enter key. Combines the single image
and multi-image opening methods so that no matter
how you open recent images (single click, button, or
multi-select and pressing Enter), it opens all selected
images in the Welcome Dialog.
The indexed conversion code was originally written for very low-memory systems,
this makes the mapping it does quantized and noisy, for examples see issue
#5159 this commit removes quality/memory use trade-offs, modern machines can
take a 2-300mb temporary table allocation.
Resolves#10882.
Before the color space invasion, INPUT_COLOR () returned
either a GimpRGB or NULL (if alpha == 0) that was used
directly in functions.
Now it's used to set a GeglColor in gegl_color_set_pixel (),
and calling that with a NULL color resulted in a Gegl-Critical.
This patch checks if INPUT_COLOR () returned NULL before
trying gegl_color_set_pixel () to prevent the issue.
The alternative solution would be to call:
> image_new_dialog_set (dialog, NULL, NULL);
This would have reset to default template. But it's still not exactly like the
"new image" action which defaults to the active image's size if there is an
opened image.
In order to avoid complicating the code further, as well as code duplication,
hence code divergence, let's call the "image-new" action, making sure that this
button will always behave exactly like the "File > New" menu item.
Then since we need to process the return value of this dialog (either re-showing
the welcome dialog in case of new image creation cancelation, or destroying the
hidden welcome dialog otherwise), I check for the singleton pointer and connect
the handlers to it.
Moreover I made the "response" signal of ImageNewDialog be handled as
G_CONNECT_AFTER otherwise we nearly never had the possibility to handle its
responses properly (because the base handler was doing it first, then often
destroying the dialog).
Use the same amount of dithering on R,G and B if they initially were all equal.
This allows us to keep achromatic gradients achromatic, while providing the
same amount of dither as before for colored gradients. Discrepancy uncovered in
issue #10756.
We were not properly duplicating the left and right colors when duplicating the
existing segments in gradient_editor_save_selection(). Therefore we ended up
freeing original GeglColor on exiting the GimpColorDialog.
Additionally to the reported crash, I add a few GeglColor freeing which were
leaked and some safeguard in gimp_gradient_get_flat_color() to ensure it always
returns a color (or raise a CRITICAL to be investigated easily).
Finally a few signals in GimpColorDialog had to be ensured disconnected when the
dialog is destroyed.
Our code expects that these GeglColor properties are always non-NULL in various
places, which may lead to crashes.
The property defaults should take care of this, and I am actually unsure why we
need to set it in the init(). Maybe the set_default() method for the GParamSpec
kicks in a bit late, while we have code syncing objects already running. I'm not
sure. It might need to be investigated later. But for now, let's simply make
sure we initialize the objects manually so that it's never NULL.
Issue #10756, without this grayscale pixels are affected by
the red part of the manipulation configuration, after this
change pixels with original saturation == 0.0 are only
changed by the master adjustment.
While doing this, I could find a lot of problems in the algorithm:
1. It looks like the original intent (from GUI and code) is that you set hue and
saturation but not really the intended lightness, rather its increase or
decrease, relatively to every pixel current lightness. I.e. that every pixel
will be set to the selected hue and saturation, and only the lightness will
change. The "lightness" field is therefore a relative value (pixel per
pixel). The first problem is that instead of lightness, we compute the
luminance, which is related but different and set this in the lightness
field.
2. The second issue is that we were using gimp_hsl_to_rgb() which after testing
(because its documentation doesn't give any TRC/space info at all) looks like
it computes a color from HSL to non-linear RGB of the same space. Yet we were
outputting to a linear RGB space. So we compute the wrong values. On the
other hand, because of the first problem, I realize (after testing) that it
makes our render closer to the intended render by chance (at least when the
TRC is sRGB's). It's still wrong, but if we were to change the output to
"R'G'B'A float" instead, the render would be much darker. In both cases, it's
wrong anyway.
I would not say that the 2 problems are canceling each others, but they are
making the final result somewhat OK.
3. Ideally we should be using babl to convert colors, and this is the best way
to actually implement the original filter intent. Unfortunately so far, doing
this is much slower (though I save a lot of time by moving out of the samples
loop and processing data in chunks, it's still slower than the current,
nearly instant, implementation).
4. Because of all previous implementation irregularities, the render is
different depending on the actual image space. I.e. that the exact same image
filtered through Colorize with the exact same operation parameters will
render differently. I would need to test further, and maybe it's normal since
HSL is also space-dependant (and that's where we work on in this operation),
but I'm wondering if the result should not be independant of the working
space.
5. I implemented our own prepare() method because the one in
GimpOperationPointFilter parent seems to allow other input or output models.
Even though in all my tests, it was always linear RGB (which is what we want
here), let's make sure by having a custom prepare() method explicitly setting
these. It's also the opportunity to create some babl fishes.
In any case, I'm leaving the code as-is for now, because it's how this operation
has been since forever (at least for as long as I was around) and I don't think
it's the right idea to change it on a whim.
This raises even more the concern of versionning GEGL operation, which we have
been discussing with pippin on IRC lately, because if ever we want to change
this one, now that operations are not just applied, but possibly
non-destructively recreated at load, we need to make sure that we recreate the
render expected at the time of creation of a XCF while allowing us to have the
filters improving when needed.
Resolves the main part of 10835. As nothing else can
be done in the GUI once all the filters are merged down
(and the GUI itself will be unavailable once closed until
a new filter is added), it makes sense to auto-close it.
gtk_widget_set_visible () was used rather than
gtk_popover_popdown () due to notes in the code about
buggy animations.
There is the possibility that users may want the GUI left
open to quickly undo the merge, so this should be
re-examined after feedback from the 2.99.18 release.
Resolves#10848.
In cc62f2b0, we moved the filter property loading code
earlier in the process. However, the opacity, mode, and
region options for GimpFilterTool were not included in
this move, so they reset back to defaults each time.
This fixes that problem so settings are retained when
editing.
- Make sure the led color is set at init().
- Unlike old GimpRGB code, values' colors must be set explicitly first.
- Make the Gimp object into a property (this one is not a problem right now, but
it's better this way).
- Don't assume the Gimp object is non-NULL. In current code, it is set to NULL.
The only consequence is that we don't use color management settings to draw
with Cairo. For this widget anyway, it feels unnecessary.
Altering the Warp tool's GEGL filter while it's being actively edited
causing a crash. More work will be needed to make these effects
work non-destructively - for now, we'll prevent users from raising or
lowering them from the NDE UI.
To simplify the logic, I created an `is_update` variable. This makes the code
much more understandable (and also simplify the redundant or over-complicated
imbricated `if` blocks).
The fix part is that the update check would have never happened for anyone
leaving the "Show Welcome Dialog" option checked, whereas we only want to bypass
the update check for new installations or updates.
Allows users to quickly configure themes and other
"controversial" options when first installed.
Also allows the welcome dialogue to appear on start,
depending on user preference.
… (u8), or CMYK is selected.
We always need a final NUL indicator in a GStrv. In these 2 cases, we might fill
all 6 first indexes, so we must have an array of size 7.
Since resources must now either belong to an image, or be tied to a file, or be
marked as internal, we must immediately save imported palettes, so that they are
tied to their file.
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.
It's actually not enough to get proper colors for inner text tags. The
main color is correct, but color for subtext is currently not managed.
This must be fixed.
In particular, the Curves, Levels and Operation tools method implemented
are updated. Also GeglColor arguments in GEGL operations are not
transformed into GimpRGB arguments anymore in GIMP. GeglColor GParamSpec
stay GeglColor now.
We don't try anymore to convert early from a pickable color to another
format/space. Now we are able to get a GeglColor and move it around,
doing only last-second (when needed) conversions.
I'm a bit unsure about the GimpMyBrushCore which doesn't have much
indication on which color space we are working in, but the new code
should not be worse than the old one (if wrong, color-wise, it should be
the same wrong as before).
Until now we only had the case of the CMYK color selector using the
soft-proofing profile. Yet this is also interesting for other color
selectors, in particular to show out-of-gamut colors. Indeed if we
enable soft-proofing on the active image, it is interesting to show the
intersection of the current RGB/Grayscale space gamut with the
soft-proofing gamut.
Right now, this is only used in GimpColorSelect when showing colors in
LCh color space.
This commit adds gimp_color_selector_set_format() which is meant to give
awareness of the target color format for which we are selecting colors.
Right now, I am only using this information on the Scales selection
method, which means that now colors you read and select are in the
target space. Even better, the out-of-gamut shown happens in the with
LCH scales is for the target space too. As tested, it already makes
quite a difference for an image in sRGB vs. say adobeRGB.
Note that right now, I only use the format information as a space, but
in fact, I made the API to be about a format because the actual format
can be used wisely too. First we may want to do different thing
depending on the color model itself (which the space may give away or
not, especially when using default spaces or when we'll have images
using models with no space in the future, such as CIE Lab). But also
whether the image is following the space TRC or is linear (or
perceptual) would change how we represent the data. If we were to show
non-linear values in the Colors dockable but when painting, the color
picker shows linear values for instance, it might be puzzling to people.
Only the color dialog was getting simulation updates when the active
image changed, or when the simulation profile changed (while the active
image stayed the same). Now the Colors dockable also get updates.
Somehow, in some cases, the event box is not getting button events. I
had the case when creating new images (though it was working fine when
loading images!). I could not yet understand the issue looking at both
GIMP and GTK code and could not even reproduce by creating simple code
sample reproducing a similar pattern (an inactive button inside an event
box placed above the button and meant to catch click events).
This works as a workaround for the time being.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
I also changed a bit the new color serialization by adding a (color …)
symbol framing the contents, for cases where we don't have a specific
property name, e.g. for the color history list stored in colorrc, unlike
for GimpConfig GeglColor properties.
While doing this, I moved GeglColor property deserialization code into
gimp_scanner_parse_color() which is now able to recognize both older
(color-rgb|rgba|hsv|hsva with no color space) and newer serialization
formats ("color", color model agnostic and space aware).
- New libgimpcolor functions: gimp_color_parse_hex() and gimp_color_parse_name().
- GimpColorHexEntry is now space-invaded. Though recognized color names
and hexadecimal syntax are sRGB only (because CSS and SVG
specifications explicitly say that this syntax is for sRGB values), it
is possible to enter non-sRGB values with
gimp_color_hex_entry_set_color().
- GimpColorSelection is now space-invaded.
We historically have both the colormap and palette concept in core GIMP,
though they are actually kinda the same concept, except that with
"colormap" we work with an array of raw data and it's a lot less
color-aware. It is still much more efficient in some specific cases,
such as when converting the image (we can then convert the whole palette
as a single buffer, because the image palette is space-restricted
anyway), when storing undo data or when storing/loading in XCF.
But for all the rest, let's use gimp_image_get_colormap_palette() and
work with the GimpPalette API.
By default a palette can contain any mix of color models and space. These new
internal API add a concept of format/space restriction. For now this will only
be used for indexed images whose palette should only contain colors for the
specific palette format and space (at least as currently implemented in GIMP).
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.
This includes improvements on the out-of-gamut colored corner being shown for
unbounded component types out of the [0; 1] range (with some small margin of
error to avoid e.g. a -0.0000001 value to show as out-of-gamut).
There are still improvements to be made on the color rendering. In particular,
it still draws as CAIRO_FORMAT_RGB24 cairo surface. We should probably move to
draw as CAIRO_FORMAT_RGBA128F eventually (more precision and even allowing to
draw unbounded colors with a possible option, instead of always clipping).
Also adding the libgimpwidgets API gimp_widget_get_render_space().
This one is kind of a huge deal, because the info returned by the color frame
was kind of messy (even though it improved lately, but space associated to color
data had to be kept in-sync by hand, which was bug-prone).
Now the color frame stores the data as a GeglColor, always aware of its space
and therefore able to do much nicer conversion. Also RGB and Grayscale options
now display the profile name of the color space (until now, we had only this for
the CMYK option using the proofing profile).
I still wish to get more options. Typically some people may want to get
RGB/Grayscale/CMYK values to other spaces (maybe sRGB, one of their favorite
profile as set in Preferences or just any random profile which they could load
from disk). Giving such ability to basically live-convert their pixel data to
various other color space would be very nice. We'll see if this will be
implemented for GIMP 3 or for after.
- New function gimp_cairo_set_source_color() which is meant to replace
gimp_cairo_set_source_rgb(a?)() eventually. This new function sets the Cairo
source color, using the target monitor's profile of the widget where the Cairo
surface is meant to be drawn on. It also uses the color management settings
(such as whether a custom profile was set, instead of using system profile, or
also simply whether color management was disabled at all). It doesn't
soft-proof the color yet.
- Padding and out-of-gamut colors drawing now use the new
gimp_cairo_set_source_color(). These don't need any soft-proofing anyway.
- Out-of-gamut color property in GimpColorConfig is now a GeglColor property.
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().
In particular, let's accept small margin of errors to determine that a value is
out of the [0; 1] range of its color space.
The specific use case is about a component at -0.000001 (or at 1.000001) which
will even just show as 0 (respectively 1) in the GUI and will be marked as
out-of-gamut. We want to avoid such thing to happen.
I also took the opportunity to get rid of a bit more GimpRGB code.
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.
I moved the function to select a valid contextual RGBA format as a core API
gimp_context_get_rgba_format(). This same API is now used in context actions, as
well as in the GimpDeviceStatus widget.
The latter now shows per-device fg/bg colors relatively to the active image's
format. The tooltip will also display contextual information (i.e. either the
image's name whose space is used, or sRGB).
Of course, this all updates when switching images by connecting to the
image-changed signal.
In space invasion world, we want color-related code to be contextual. When we
say "Increase/Decrease the red/green/blue channel by X%", it would actually mean
something different if you are working on a sRGB space or a wider gamut space.
Furthermore, it means also something different if you work on linear/perceptual,
overriding the space's actual TRC.
This is why this new code takes the active image into account and uses this as a
base for the space and TRC you are working on. In case you have no active image,
it defaults to the current GeglColor space (though really this case should not
matter too much). In case your image is not RGB to begin with, it uses sRGB
space.
- 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.
gimp_drawable_filter_apply () is affected
by the active selection. This causes display
glitches when merging all filters or
undoing a merge while an active selection
is on the image.
This patch saves the current selection,
clears it, merges/unmerges the filters,
then reapplies the selection to avoid the
problem. In the future, this should be
re-examined (when filter masks can be
edited).
Resolves#10736.
By default, any filter added with a drawable with
gimp_drawable_filter_new () will be added on top
of the filter stack. Now that we have NDE effects,
there can be multiple live filters when drawing.
The Warp tool applies a GEGL operation as well,
and now it draws on top of any existing effect.
This patch adds code to move the Warp's filter
below any other NDE effects so it operates on
the raw pixels only.
Note that a longer term solution might be to have
a separate stack for tool-based GEGL operations,
but that would be a post 3.0 discussion.
- The icon itself was changed to a "search" icon. Though it kinda made sense to
keep the "link" reference when I first implemented this, as a reference to how
we used to link items (whereas now we select them together), in the grand
scheme of things, it's not such a good idea and many won't likely understand.
But everyone will understand a "search" button. :-)
- It's now next to the label displaying the number of selected items, in the
item tree view header. This makes much more sense there. Also it makes the
long list of bottom buttons slighly shorter.
- Finally I make this feature accessible to the channels and paths, by actually
moving it out of GimpLayerTreeView and into GimpItemTreeView.
Certain filters like Supernova have a
random seed property. According to the
specifications it's an unsigned int, so we
can save and load it with existing
functions.
Resolves#10769.
Flattening an image or merging down layers caused
us to lose NDE filters on undo, as we flattened with
gimp_gegl_create_flatten_node () which didn't create
an Undo/Redo object.
To fix this, we merge the filters down beforehand with
our API so that they will be restored when undoing.
Resolves#10768.
During NDE development, the Show/Hide All
function name was changed. This was not fixed
in one location where we blocked it during popup
creation, so the signal was running on dead objects.
This patch fixes this. It also fixes a few formatting
errors made during NDE development.
Resolves#10766.
Currently, GIMP does not support applying or editing
filters when the layer is pixel locked. This patch
prevents users from attempting to edit filters via the
NDE popover UI, and notifies them of why.
If any NDE filter is hidden when merged, the entire layer
is hidden. This patch changes the behavior so that the
invisible filter is removed instead of committed when
merged down.
Some GIMP-custom GEGL operations do not use GimpConfig to
store their properties (for instance, Threshold).
Previously, we weren't copying over their values when editing an
NDE filter.
This patch adds code to copy over the Gegl properties if there is
not a GimpConfig object attached to the filter.
The Compact theme code is nearly the same as the Default one, apart from setting
palette icon size to small (which is already something done by the "Override
icon sizes" setting in Preferences), setting font-size to small (which can be
independently set by our "Font Scaling" setting) and setting 3 paddings.
Rather than having this separate theme, it feels like just moving the padding
changes as part of the icon size makes sense. In particular since, when setting
icons to "Small" right now, the default padding really feels a bit huge and out
of place. So all-in-one seems a better choice.
At first, I wanted to set a padding proportional to the icon size, but it didn't
work well. For now, I'll just choose padding sizes manually.
If you run the GEGL Operation tool without choosing
a filter, it leaves a "gegl:nop" layer effect behind.
This is not useful, so we check and set such filters as
destructive to get rid of when applying an effect.
This was provoking a CRITICAL in #9712, in the GimpFgBgEditor which was tracking
the active image, but even before this, I experienced a crash in
GimpLayerTreeView code with the same steps.
The problem is that in some cases, the image switch happens once the currently
active image is already disposed. In particular we had the case in multi-window
mode where closing a window would free a GimpImage yet without necessarily
setting another image as active, since it depends on window focus in MWM (and
the other image windows may not gain focus immediately; this depends on the
window management logic).
Therefore we had various handlers in Gimp*TreeView (or GimpFgBgEditor and
possibly other places) code which tried to disconnect or work on now freed
pointers. To handle such case, let's connect to image finalization and set the
context to NULL image.
When working on #9712, I encountered this crash first before the main issue
(with the same reproduction steps as listed by Wormnest): reason may not be set
by the method. It's better to always explicitly set this variable to NULL first.
The current GTK algorithm for finding an icon seems to be:
main icon theme in choosen style > fallback icon theme in choosen style >
main icon theme in another style > fallback icon theme in another style
Where "style" is either color or symbolic variant of a given icon. The problem
is therefore if say your prefered style is "Symbolic" and you choose a
Color-only icon theme. In such a configuration, all icons which are also
available in the system theme with a symbolic variant will be used from the
system theme (even when they are actually available in the chosen icon theme
too, yet in a color variant) and you get a weird mix of part of the icons as
symbolic from system theme and another part as color from the chosen theme.
In order to avoid this weird situation, we only set -gtk-icon-style CSS value to
the prefer-symbolic-icons property if the chosen icon theme has both style
variants. Otherwise we force the only variant of the chosen icon theme.
The icon "gimp-wilber" is used to determine whether an icon theme has both
variants, which should be documented in the developer website for icon theme
makers.
The merged icon theme is simply named "Default" and contains a color and
symbolic variant for all icons. While in 2.10, it made sense to have both icon
themes because a theme had no concept of a "symbolic" variant back then, icon
themes in 3.0 have this concept and we support this in GIMP through the "Use
symbolic icons if available" option in Preferences.
Until now, it was confusing to have both themes + this option, even more as you
could use the Color icons with the "Use symbolic icons" option, which meant that
if some icons were missing, you could end up with a mix of color and symbolic
icons (and oppositely using the Symbolic theme with the option unchecked).
The new state is much simpler and less confusing. Just 1 icon theme with both
color and symbolic variants (the latter being used by default).
Note that the identical meson.build in each size subfolder is still mandatory
because of the inability of meson (still!) to generate files with
custom_target() in a subfolder as output.
We were skipping tests when there is no display, which is always the
case on Windows. However, these tests always showed as succeeded.
Unless you looked at the test log, you wouldn't noticed that most of
the tests weren't actually performed.
Exit these tests with the value GIMP_EXIT_TEST_SKIPPED instead of
EXIT_SUCCESS.
You are not supposed to use g_assert in tests because g_assert can be
disabled using -DG_DISABLE_ASSERT, which makes tests fail.
Instead let's use the recommended replacement g_assert_true. At this
time we are not bothering using more specific g_assert_* functions,
since there are plans to change our test suite.
Until now, we were following a similar concept of color schemes as what most OS
are doing. For instance, Freedesktop recently introduced a tri-state color
scheme of "Prefer Light", "Prefer Dark" and "Default", the latter being either
whatever the software prefers (e.g. we prefer either Dark or Gray for graphics
software usually) or what the system prefers. See #8675.
Until now, with GTK, we only had a boolean "prefer dark" setting through the
"gtk-application-prefer-dark-theme" settings. There is not even a "prefer
light".
Nevertheless for graphics application, there is clearly a third case (fourth if
we added a "follow system color preferences" which we don't implement for now):
gray mode and in particular middle gray. Having a middle gray UI is often
considered a necessity when working on colors in order to protect our perception
of color from being influenced by surrounding UI.
To fill this need, we were proposing a Default vs. a Gray theme in GIMP, but
this was a bit confusing and felt illogical, as discussed on IRC some time ago.
Also depending on whether you chose "prefer dark" or not for the gray theme,
this one was itself 2 themes, which made things odd and harder to work on.
Instead this commit:
- adds a color scheme concept in GIMP with 3 variants so far: light, gray and
dark. A possible fourth (future) variant might be to follow the system
preference (do all OS provide such a queriable option?).
- Our Gray theme is merged into Default (as the gray color scheme variant).
- Custom themes can add the following CSS files: gimp-light.css, gimp-gray.css,
gimp-dark.css which are the base file for their respective scheme. gimp.css is
still used as a fallback though it is not necessary (our own Default theme
does not provide a gimp.css anymore). Custom themes don't have to provide all
3 variants. A theme can just provide one or 2 variants if it only wants to
support 1 or 2 use cases.
Chooser return GDK_EVENT_STOP so parent manager does not also popup second menu.
Specifically, return the result of the call to gimp_editor_popup_menu_at_pointer.
When a menu does pop up (for a dockable), that result is GDK_EVENT_STOP
and the event does not propagate to the parent widget.
Added a comment about why we ignore the result of a call
to gimp_editor_popup_menu_at_pointer in another place,
since it is not obvious why that call is different.
All other current behavior retained.
Other current behavior might be separate issue:
LMB or RMB outside any item, or in the current selected item,
in the chooser that popups from the toolbox,
should probably close the popup chooser, or give an audible alert,
because it does nothing.
Note that a chooser is also used in a remote dialog for a plugin,
and it closes a different way, choosing an OK button.
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.
The list of objects where the config object is a dedicated custom class (instead
of a runtime-registered class) is well known. These are the operations
registered inside gimp_operations_init().
The list inside gimp_gegl_procedure_execute_async() which the previous commit
was updating was not right: it was still missing "gimp:hue-saturation" and
"gimp:threshold" should not have been on the list (this was generating a
CRITICAL when trying to get the "config" property on this object).
Instead let's add some init/exit() functions in gimp-operation-config API to
distinguish the operations with custom config (registered during init) with all
the others. Then we add gimp_operation_config_is_custom() which can be used
everywhere where we want to verify if an operation is using a custom-made config
object or a generated class just mirroring the operation properties.
This way, we should not get out-of-sync anymore.
Adds gimp:color-balance to the list of
GIMP-specific GEGL operations we
retrieve the GimpConfig settings from.
Also prevents trying to set a GEGL
property when editing if it couldn't be
converted properly (e.g. GimpConfig)
Now that we save GEGL operation arguments ourselves (instead of relying on
GEGL-generated XML), we can serialize and deserialize GimpConfig arguments which
are used in various operations implemented within GIMP core code.
Additionally:
- Also support saving and loading all enum types.
- PROP_EFFECT_ARGUMENT renamed to PROP_FILTER_ARGUMENT for consistent naming.
- A bit more accurate handling on save and load errors with dedicated messages
to various issues.
- Use PROP_FLOAT_OPACITY instead of the obsolete 8-bit PROP_OPACITY (actually
32-bit but stored as 0-255 int).
- Fix a leaking string.
*It's possible to have one layer selected but edit the filter of another layer.
The FilterTool code was updated to use the filter's drawable if editing.
*Prevents editing if multiple layers are selected.
This is a current limitation of the filter tool itself, but it was causing issues with NDE.
*If an XCF with a filter from a third-party plug-in is loaded, the filter won't be
created if the user doesn't have it installed.
Note that GEGL still throws a lot of warnings about missing properties - not sure how to resolve that.
*Refresh drawable when finished editing a filter to fix issue with lingering preview splits
*Fix issue with loading more than one filter after XCF format changes
- 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!
Use g_signal_connect_object to ensure object passed to handler
is not destroyed in the middle of the handler by knock-on signal handling.
Note there are comments about this in gimpcontainertreeview.c line 1592.
And similar code i.e. calls to gimp_container_view_get_container
that seem to be intended to solve but might actually also be susceptible.
Those calls in icon view throw CRITICALs during this issue.
But testing of the tree view (a list instead of a grid)
doesn't seem to crash, so leave well enough alone.
Per @lukaso, the "rightwards triangle arrowhead" character
doesn't render on MacOS. This patch uses a different character
for MacOS only until a standard character can be decided on.
Resolves#10657.
d120e592 fixed a crash when pasting into an empty image.
However, it created a new issue when pasting into a layer mask.
It caused a later call to gimp_drawable_convert_type () to fail, as
the pasted image would not need to be converted if the image's
settings were used rather than the drawable.
This patch fixes both issues by checking if the selection/image is empty,
and assigned the base type and precision values from either the selection
or the image accordingly.
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.
It was not possible anymore for a plug-in to add a menu item to the
local Layers, Classes and Paths dialogs using <Layers>, <Classes> and
<Vectors> at the start of the menu path.
For the first two this was due to an extra length parameter and the
drawables now being inside a GimpObjectArray. To fix that we check
inside the object array for the correct type names.
I'm not sure if Vectors ever worked, but testing shows it only adds
runmode and image parameters. To fix that we do the same as for
ColorMap.
Resolves#10643.
Prevent gimp_modifiers_editor_show_settings () from being called
when the user clicks the Modifier Reset button in Preferences if
there is no device connected to GIMP.
For certain small selections, the pattern preview can't be loaded.
Since e1e30c6f assumes the pattern loads, this could cause a
crash if a dialogue with the preview is visible.
This patch checks if the scaled pattern was loaded before using
it, and otherwise uses the default pattern.
If a system theme sets the background-image property for stacks,
it recolors the main canvas when empty. It also adds a border to
the toolbox Wilber area.
Additionally, the Credits page of the GtkAboutDialog has odd colors
due to general viewport grid styles overriding the GTK default.
This patch fixes these problems, and adds a custom CSS class to
the GimpAboutDialog for current and future work.
The previous commit did not fully convert the title/status bar
format string to be UTF8-clean, due to a misunderstanding
of the logic behind the symbol used to indicate an image
was dirty.
Rather than always grabbing the 2nd character in the format
string, this patch now grabs the next character in the format
string after the %D, %N, %C, and %E commands.
The current code assumes that one letter is one byte long.
This caused issues when using non-ASCII UTF8 characters in
the title and statusbar format strings.
This patch replaces the loop logic with g_utf8_next_char () and g_utf8_get_char ()
to get the next letter no matter how many bytes it takes up.
As reported in issue 10604, if the Align Tool is set to align relative
to a reference object and 'use extents of layer contents' is enabled,
clicking on a path causes a CRITICAL.
This is due to gimp_pickable_auto_shrink () being called, when GimpVectors
are not GimpPickables. A datatype check is added before calling the function
to prevent the issue.
When opening images like DDS or EPS that have an options dialog,
we either get a crash, or criticals.
The critical made clear that there is a problem dereferencing:
(gimp-2.99.exe:9900): GLib-CRITICAL **: 14:52:58.831:
g_atomic_ref_count_dec: assertion 'old_value > 0' failed
Looking at gimp_file_dialog_progress_get_window_id we see that the
handle doesn't get an extra reference, while in other similar places
the handle is duplicated.
Using g_bytes_ref on the handle fixes the criticals for me.
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.
When cutting and pasting a single layer,
drawables->data might be empty. This results in a
crash on Windows and a failure to paste on Linux.
Since this function is inside an IF statement that already
confirms it has a valid image, the base type and
precision are retrieved from there instead.
There was the question on whether it needed an hyphen or not. The hyphen
naming was often used to describe the "Hard-edge painting" style, though
even for this, it was not an absolute case. Depending on English writing
style, we could also find "hard edge painting". Also Liam was noting
that when the term appears by itself, as a noun (rather than a
qualificative), it was likely best without hyphen. So we went for the
no-hyphen wording.
Then there was the capitalization question: should capitalization rules
of data labels apply to parts between parentheses? I went with the
answer that *yes*, since it's part of the title anyway. And without the
part between parentheses, we'd have several data named the same. So it's
just as important.
As a consequence, I also re-capitalized "FG to BG (HSV
Counter-Clockwise)" and "FG to BG (HSV Clockwise Hue)" gradients,
following this updated rule.
Due to a bug in commit de5c805cbb, which
changed the choice widget between line and paint tool to a
GtkStackSwitcher, changing that choice did not work anymore.
The reason being that the stroke method wasn't being updated on clicking
stroke. We fix this by setting the stroke method when OK is clicked.
When creating the dialog we also set the stroke method, to reflect the
last used choice, since that was also missing.
See discussion in !946: https://gitlab.gnome.org/GNOME/gimp/-/merge_requests/946#note_1768869
On Windows/macOS, the pad device is probably not even showing at all
right now, though I can't test. Also it could be eventually implemented
with pad actions support (see Luca Bacci comment in the same MR) using
WM_POINTER API on Windows.
On X11 though, the pad device is shown, except it is kind of pointless.
So I am disabling the frame (making it insensitive) and add a tooltip.
Handle some statefulness in actions taking a double parameter, in order
to make them friendly to GtkPadController and its pad ring/strip
integration.
The GtkPadController emits those actions with a double parameter
expressing the absolute value (e.g. 0-360 for rings, 0-1 for strips),
take care of converting these absolute values to relative changes
that increase/decrease the current GimpDoubleAction value.
Going for relative increments/decrements increases the genericity
of rings when mapped to actions, as going with the given absolute
values would mean means rings could be mainly mapped to angle-like
actions, reducing its usefulness.
We have everything in place to create GtkPadControllers converting
events into actions as configured in settings, and the signaling
to trigger the (re)generation of those as device, window or configuration
changes appear.
Only the last bit attaching those controllers to actually handle
input was missing, now done in this commit.
Since there may be multiple configured tablets and pads, we need to
keep track of per-device controllers to handle the configuration for
those. This mapping is kept in GimpImageWindow as the "main" toplevel
(i.e. the one(s) typically considered "keyboard focus" and receiving pad
events) and ensured to be kept up-to-date through the ::configure-pad
signal.
This API call will snapshot the current configuration of a device
into a GtkPadController, that is created and attached to a toplevel
(this event controller only acts on toplevels).
This controller will handle pad events, trigger actions, and update
compositor feedback (e.g. GNOME Shell pad OSD) as per the actions
mapped in the configuration dialog.
If a pad device configuration gets changed, or reset, we should trigger
the creation of new pad controllers for the existing toplevels.
Add the plumbing so that saving/resetting a device configuration will
result in the same ::configure-pad signal, and trigger it from the
relevant places.
In order to apply the pad configuration so it does something, we
need to create GtkPadController objects on each toplevel for each
configured pad device.
This signal will work as a hint that a new GtkPadController should
be generated for the given device and current configuration. At
the moment, emit it when pad devices are added or removed.
The UI is heavily inspired in the existing one for midi devices
and the such, as the restrictions are somewhat similar. Since there
is not enough information to introspect the device without the help
of libwacom (and the UI should work with tablets unsupported by
it, regardless) the list starts empty, and there exists a "grab
event" button to press pad buttons (or use rings/strips) and
create/focus a list item for the button/mode.
Double clicking on an action (or pressing the "edit" button) spawns
a different dialog with a GimpActionEditor to select an action.
And lastly, actions can be deleted with the "delete" button.
Pads may have different modes (e.g. leds in the tablet) that apply
to all pad features, the list will allow different actions to be
set on the same button in different modes. This basically multiplies
the amount of mappable actions by the number of available modes.
This object holds the mapping of pad device features (buttons/rings/strips)
to actions, given the current mode (e.g. leds in the device), and can be
serialized/deserialized from configuration files.
These are not generic undo function, but specific to the resize case (and even
more particularly when calling the GimpItem's resize() class method).
Also the variable was wrongly named no_undo when it actually was meant for the
opposite meaning, i.e. when we want to push an undo for a resize() call. This
made the call harder to understand. Furthermore the usage of double negation did
not help with understanding the code.
This is a fixup commit to MR !961, fixing a particular commit 5c2373a125 saying
that when canceling painting with layer expansion, strokes outside of the layer
remain visible.
When auto expanding layers, there is an option that allows user to fill
the newly expanded part with the pattern. But without this change, it
was not possible to change the active pattern without switching to some
other tool like bucket fill tool. This commit allows that.
Also added option in Edit->Preferences->"Tool Options"->"Paint Options
Shared Between Tools" that decides weather the options should be shared
between different tools.
Canceling a paint stroke restores the layer and mask (if present) to the
original size if they were expanded during the stroke. The part of
stroke that is outside the layer remains visible though.
In ink tool, if last_blobs is empty, the copy of blobs present in
last_blobs and blobs_to_render was same. Due to this, when layer
boundary is expanded, we move same blobs twice. Due to this a straight
line was drawn when starting painting from outside layer boundary. Fixed
the issue by storing a duplicate version in blobs_to_render. Updated
free part accordingly.
In layer expansion if user is trying to draw outside the layer boundary
with expand option turned on but the "Lock position and size" enabled,
the lock square will be blinked. If user is painting on layer mask, the
corresponding layer's lock will be blinked. It will be blinked only
once per stroke.