Add a boolean "modify active gradient" option to the blend tool.
when checked, the active gradient is modified in-place while edited.
When unchecked, the active gradient is copied to the internal
"custom" gradient upon editing, and the custom gradient becomes
subsequently active.
Show a hint when the option is checked, but the active gradient is
non-writable, and can't be edited directly.
This commit adds the new gimpblendtool-editor.[hc] files, which are
where the gradient-editing related functionality of the blend tool
is going to go.
Add a boolean "instant mode" option to the blend tool, togglable
using shift. When checked, commit the gradient immediately when
the mouse is released.
When not in instant mode, don't commit the gradient when clicking
outside the line, since this will become easy to do accidentally
once we add on-canvas gradient editing.
Add gimp_color_panel_dialong_response() to GimpColorPanel, which
emits a response for the color panel's color dialog, if shown.
Add a "response" signal to GimpColorPanel, which is emitted upon
color dialog response.
In both cases, the response is a GimpColorDialogState, which should
be either GIMP_COLOR_DIALOG_OK or GIMP_COLOR_DIALOG_CANCEL, and not
an actual dialog response id.
Use gimp_gradient_get_{left,right}_flat_color(), instead of
gimp_gradient_get_color_at(), to get the selection endpoints'
colors in the gradient editor, so that the correct colors are used
under any condition (in particular, if there are 0-length
segments.)
When using gimp_gradient_segment_range_compress() to expand a 0-
length segment, redistribute the range's endpoints and midpoints
uniformly, rather than using the regular code path, which would
result in NaN values.
Make sure that the left and right endpoints of the range are
*exactly* equal to the new left and right values. Previously,
they could be slightly off due to numerical errors.
Treat gradient segment exents as [left, right) ranges, instead of
[left, right], so that they don't overlap, and each point
corresponds to a unique color.
Perform less comparisons in gimp_gradient_get_segment_at_internal().
... which merges a segment range into a single segment, that spans
the entire range, and has the same endpoint colors. The merged
segment's midpoint is at its center, and its blend function and
coloring type are those of the range's segments if they're uniform,
or the default ones otherwise.
... which returns the flat (context-independent) left and right
colors of a egment. Replace code that calculates the flat color
explicitly with calls to these functions.
An internal gradient object, that will be used by the blend tool
when editing a gradient. By default, the active gradient will not
be edited directly, but rather, upon editing, the active gradient's
contents will be copied to the custom gradient, which will then
become the active gradient and be edited. This allows editing both
writable and nonwritable gradients without modifying them, and
without having to duplicate them.
... which copies the contents of a GimpData into an existing GimpData,
without creating a new instance.
Add a copy() virtual function to GimpData, which subclasses can
override to implement copying; gimp_data_copy() may only be called
for types that implement copy(). Keep the duplicate() virtual
function around, but provide a default implementation that creates
a new object of the source type, and uses copy() to copy the source
object into it.
Add parameters, controlling the behavior and appearance of sliders,
to GimpControllerSlider. The macro GIMP_CONTROLLER_SLIDER_DEFAULT
expands to a nonmodifiable lvalue of type GimpControllerSlider,
whose members are initialized with the most common default values.
Handle the new parameters in GimpToolLine. A slider using the new
"autohide" mode is only visible when selected, or when the cursor
is close enough to the line, between the slider's min and max
values, and no other handle is grabbed or hovered-over.
... which is emitted when a handle is single/double/tripple clicked.
The signal handler returns a boolean value. A return value of TRUE
stops further event processing, while a return value of FALSE allows
it.
The signal is emitted when a slider is dragged away from the line,
and will be removed when the button is released, and when the
slider is dragged back to the vicinity of the line, and won't be
removed. The last parameter of the signal is a boolean flag
differentiating between the two cases.
Note that a remove-slider signal may be emitted without a preceeding
prepare-to-remove-slider signal, however, is a prepare-to-remove-
slider signal is emitted with a TRUE last parameter, it must be
eventually followed by a remove-slider signal, or by another
prepare-to-remove-slider signal with a FALSE last parameter.
Add support for adding and removing sliders to/from a GimpToolLine,
using three new signals:
- can-add-slider: Takes a double argument in the range [0,1],
indicating a location along the line, and returns a boolean
value, indicating whether a slider can be added at that
location.
- add-slider: Takes a double argument in the range [0,1],
indicating a location along the line, for which can-add-slider
returned TRUE. In response, should add a new slider at that
location, and return its index, or a negative value if no
slider was added.
- remove-slider: Takes a slider index. In response, may remove
the slider.
On the UI side, when the cursor is close enough to the line, but
not within the hit area of an existing handle, GimpToolLine checks
if a slider can be added at the cursor position, using can-add-
slider. If a slider can be added, a dashed circle appears at the
cursor position along the line, indicating where a slider will be
added. The cursor is added by clicking, which emits an add-slider
signal; if the signal returns a slider index, the new slider is
selected, and can be subsequently dragged.
Removing a slider is done by either selecting the slider and
pressing backspace (or delete, although we don't actually forward
it to the tool atm,) or by "tearing" the slider: when dragging
the slider, if the cursor is far enough from the liner, a dashed
circle appears around the slider, and releasing the mouse removes
the slider.
En route to on-canvas gradient editing, add support for persistent
handle selection to GimpToolLine (a handle being either an endpoint
or a slider). Handles are selected through clicking, however,
unlike before, the selection persists after the mouse is released.
A new "selection" property specifies the currently-selected handle
(who knows, maybe in the future we'll add multi-selection), and a
new "selection-changed" signal is emitted when the selection changes.
The visual feedback has been changed to better suit the new behavior,
and the behaviors yet to be added: The selected handle is marked
using highlighting; the highlighting doesn't change while hovering
over other handles. Only the hit-test circle is used as hover
indication, however, we use a fixed-size circle, and only show the
circle for the currently hovered-over handle -- no more trippy
expanding circles :)
A few minor changes along the way:
- The selected handle is now the (first) one that's closest to the
cursor, instead of the first one to pass hit-testing.
- We don't move the selectd handle upon button-press, only upon
motion, so that handles can be selected without moving them.
- Show a MOVE cursor modifier when hovering over a handle.
otherwise, implicit transitive linking will pull in the installed
libs, not the ones from the source tree, and the build can fail when
any of the libs' APIs changes.
Also remove some useless #includes.
Tweak the layer group saving code so that the saved PSDs match
Photoshop-produced PSDs a bit more closely. For the most part, it
doesn't seem to matter much, but it does somewhat improve
compatibility with other programs that read PSDs.
... and ignore language setting (e.g. en_US).
The problem came from the fact that these settings names are class
properties of GimpPaintOptions/GimpContext which is first instanciated
when the Gimp object is created. This unfortunately happened before
language_init() since we needed these objects when loading gimprc
(making inversion of calls rather complicated).
Therefore they were localized with the system language, not the
configured language.
The solution was to create a very simple object GimpLangRC which
implements the GimpConfig interface, for sole purpose to read the
language from `gimprc` in a first pass. gimp_load_config() will still
happen later as a second pass to properly load the rest of the
configuration.
I had an error in the previous commit (2 args in 1). Also adding access
so that the file `bookmarks` is visible from the contained GIMP
(otherwise bookmarked folders are lost in flatpak and that's bad
experience).
For some reason, the "cleanup" tag won't delete the files produced by
the BaseApp inside the main GIMP manifest (I still need them for build,
but want to delete them for runtime).
This is a workaround to delete them with a few command lines for now.
See: https://github.com/flatpak/flatpak/issues/1082
... off-by one size in special cases
The last commit wasn't drastic enough. We changed SIGNED_ROUND()
to use RINT(), which, in turn, may use rint(). However, rint()
effectively breaks ties to even, so that we get stuff like
'rint (1.5) - rint (0.5) == 2.0 - 0.0 == 2.0'. This can't be
good--it's entirely possible that we're bitten by this in other
cases without noticing.
Avoid rint() entirely in RINT(), and always use 'floor (x) + 0.5'
instead, which always breaks ties up. Hopefully, this doesn't
break anything else...
... off-by one size in special cases
SIGNED_ROUND(), which is used by GimpToolRectangle, among other
things, used to round negative values which lie exactly between
two integers, i.e., -foo.5, down. This could lead to the rectangle
being one pixel bigger than expected, in either dimension, when one
of its edges had a negative coordinate, and the opposite edge had a
positive coordinate.
Fix SIGNED_ROUND() to always round such values up, regardless of
sign.
Keeping all dependencies inside the main manifest is very annoying
because flatpak-builder will check them every time the package is
rebuilt. Worse, sometimes the cache won't be hit (even though it should
have), resulting into a rebuild of many dependencies. I create a BaseApp
build which is the recommended process (and not creating our own runtime
based on GNOME one's, as I first thought) which won't need to be built
as often as the main manifests. The other advantage is obviously that
this BaseApp can be shared between the dev and nightly (and likely even
the stable later) builds. I will only keep differences inside the main
manifests (for instance lcms2 which requires a higher version on master
than on the GNOME runtime and the last dev release).
I also move webkitgtk as the first dependencies since it takes too long
and flatpak uses a sequential dependency graph (so any change to a
previously listed dependency, even when actually unrelated, was
triggering a rebuild of webkitgtk!).
Only remaining issue is that I don't manage yet to run the cleanup of
the BaseApp at the end of the main manifests (for files needed for
building, but not at runtime).
So I discover today that there is an option --ccache to request
flatpak-builder to compile using ccache, which is obviously a great idea
when rebuilding the same deps too often. Update the howto with the info.
While I am at it, let's spread the improvement to options_box which was
also a weak pointer with g_object_add_weak_pointer(). Let's make it
rather a GWeakRef for the same reason as I did options_gui.
Other than multi-threading (which here is not the problem), using
GWeakRef has the other advantage that it makes the type of pointer
obvious, hence avoiding the kind of errors as fixed in commit 12df796.
One can't just change the pointer value directly, and has to use
g_weak_ref_set(), so such problem won't happen again.