... which is similar to the TRANSFORM_GRID controller, supporting
multiple transformation matrices.
Implement the TRANSFORM_GRIDS controller in GimpFilterTool, using
the new GimpToolWidgetGroup to display multiple transform grids.
(cherry picked from commit 5e953ece85)
This is mostly core code which we want to keep in sync with master as
long as possible, so I picked this one even though not strictly
neccessary.
(cherry picked from commit 1b7d63cce9)
In the threshold and levels tools, use gimp_wait() to wait for
histogram calculation to complete before applying auto-adjustment,
so that a message is displayed in the meantime. Allow the
operation to be canceled, in which case we simply abort the auto-
adjustment, but let the histogram calculation continue.
While fonts are loading, show a GimpBusyBox with an appropriate
message above the text tool options, and make the options
themselves insensitive, and in font views, such as in the fonts
dialog (through gimp_container_editor_bind_to_async_set(), added in
the previous commit).
We already avoid rendering text layers while fonts are loading,
showing an appropriate message, but this will soon be replaced with
waiting for the fonts to finish loading.
Instead, don't allow the text tool to start at all while the fonts
are loading (showing an appropriate tool message, and a BAD cursor
modifier), and halt the tool when reloading fonts if it's already
started.
Have GimpAsync implement the GimpWaitable and GimpCancelable
interfaces, added in the previous two commits, instead of providing
its own public version of the corresponding functions.
Add gimp_async_cancel_and_wait() as a convenience function for both
canceling an async operation, and waiting for it to complete.
Adapt the rest of the code to the change.
(cherry picked from commit e2c56ef407)
...in weird ways
In gimp_rectangle_tool_button_press(), when the press triggers a
GimpEditSelectionTool operation (like moving a floating selection),
make sure we don't call COMMIT on a zero-size rectangle, because that
would get special treatment by commit(). Instead, CANCEL a zero-size
rectangle so stuff behaves as if it has never been there.
That was an obvious faux ami with French.
Status changed to "press Enter to refine", with the requirement of
staying not too long (this is a status message, not documentation), and
that also announces what will be the next step.
It is not obvious that you have to hit Enter to validate the first step
of Foreground Selection tool, i.e. the rough free selection. Adding this
information in status message.
Since Enter would only work once the free selection is closed or that
you have at least 3 points (then Enter closes the selection for you), I
also add gimp_free_select_tool_get_n_points() so that we can know how
many points were created from the Foreground Select tool, and only
update the status message when relevant.
In GimpCurvesTool, calculate the histogram of the target drawable
asynchronously, rather than synchronously, to avoid blocking the UI
while the histogram is calculated.
In GimpLevelsTool, calculate the histogram of the target drawable
asynchronously, rather than synchronously, to avoid blocking the UI
while the histogram is calculated.
In GimpThresholdTool, calculate the histogram of the target
drawable asynchronously, rather than synchronously, to avoid
blocking the UI while the histogram is calculated.
Additionally, fix the initial "low" threshold value for > 8bpc
images (127/255 => 0.5).
In the gradient-tool editor, when responding to an endpoint size-
entry "changed" signal, make sure there is a selected handle, and
bail otherwise. We can receive a "changed" signal without a
selected handle, if the endpoint is deselected while a change to
the size-entry's value is in progress, causing the the tool GUI to
be unmapped, and the changed value to be committed.
When in anti-erase mode, always return TRUE, since it's only
effective when the drawable has an alpha channel.
Also, remove an unnecessary #include in gimp_ink_tool.c.
Add a GimpPaintTool::is_alpha_only() virtual function, which
subclasses can override to indicate whether painting only affects
the alpha channel (assuming FALSE by default). Override the
function in Gimp{PaintBrush,Ink,Clone}Tool, returning TRUE when the
current paint mode only affects the alpha (as per
gimp_layer_mode_is_alpha_only(); see the previous commit,) and in
GimpEraserTool, returning TRUE when the target drawable has an
alpha channel.
When the function returns TRUE, and the target drawable doesn't
have an alpha channel, or the alpha channel is locked, show a BAD
cursor modifier, and raise an appropriate warning when attempting
to paint.
In GimpTextTool, when starting the editor in response to a button
press, always set the text tool's image first, so that the style
editor picks the correct resolution for the text-size entry.
Currently the image is only set when clicking inside the active
drawable's bounds.
gimp_rectangle_select_tool_cursor_update(): always set a cursor and
cursor modifier even if no GimpToolRectangle widget exists, so we are
not stuck with the last set cursor after committing or halting the
tool.
Add gimp_drawable_gradient_adjust_coords(), which adjusts the
gradient segment coords according to the gradient type, so that, in
cases where the gradient span is unrelated to the segment length,
the gradient cache (in GimpOperationGradient) is big enough not to
produce banding. Use the new function in gimp_drawable_gradient()
and in the gradient tool, instead of duplicating the logic.
Move the shapreburst coordinate-adjustment logic to the new
function, and add appropriate logic for conical gradients.
Remove the code that avoids using the gradient cache for conical
gradients from GimpOperationGradient.
In the various types of fill operations, and in fade operations,
use the paint composite-mode of the current paint mode, which is
the composite mode we use during painting, instead of AUTO, which
results in the default mode we use for layer compositing. This
effectively means that filling using any non-legacy, non-
subtractive mode can paint over transparent areas, rather than
being limited to nontransparent areas.
In gimp_text_tool_connect(), when auto-removing empty text layers upon
text layer or tool change, make sure we don't try to remove a layer
that has already been removed, which can happen if this function is
reached *because* somehow the layer was removed externally (e.g. by
the user in the layers dialog).
... when using default aspect ratio
The call to
gimp_{crop,rectangle_select}_tool_update_option_defaults() when
starting the crop/rectangle-select tools seems to no longer be
necessary, while it overrides user modification to the default
ratio's landscape/portrait orinetation (which only really matters
for the crop tool, since the rectangle-select tools' default ratio
is 1:1). Fix this by simply removing the call.
Commit ddfc7715cb changed the
airbrush periodic stamp behavior, so that instead of using the main
brush, it issued a full MOTION event, potentially using a different
brush when using a GIH brush.
Fix this, by renaming the "timeout" signal of GimpAirbrush to
"stamp", and by adding a new gimp_airbrush_stamp() function, which
should be used for painting the periodic airbrush dab in response,
instead of calling gimp_paint_core_paint() directly, and which
calls gimp_airbrush_paint() instead, as the old code did.
In order to call this function from the paint thread, we replace
the various gimp_paint_tool_paint_core_foo() functions, introduced
in the above commit, with a generic gimp_paint_tool_paint_push()
function, which takes a callback (and a data pointer) to run on the
paint thread, and queues it for execution (when not using the paint
thread, the function is called directly from the calling thread.)
...(Pixel, Position and Size, Alpha Channel) are enabled.
gimp_edit_selection_tool_translate(): add checks for locks and bail
out with a message if the item is NULL or locked.
gimp_move_tool_button_press(): refactor NULL and lock checks to look
more like the new code added above, and also check "lock-content" of
channels and masks: moving them changes their pixels.
GimpAirbrush currently performs painting and flushes the image on
its own during the airbrush timeout. This is unsafe w.r.t. the
paint thread, since the timeout is run on the main thread, while
paint commands should run on the paint thread.
Add a "timeout" signal to GimpAirbrush, and simply emit this signal
during the airbrush timeout, rather than actually painting.
Connect to this signal in GimpAirbrushTool, and use
gimppaintool-paint to perform the actual painting, in a thread-safe
manner (see the previous commit.)
We'd like subclasses of GimpPaintTool to be able to issue paint
commands to the tool's paint-core (in particular, see the next
commit.) Since paint commands should be executed on the paint
thread, the subclasses must not call the paint-core functions
directly, but should rather let gimppainttool-paint issue the
commands on their behalf.
Reorgainze gimppainttool-paint to make it usable for this purpose
by subclasses. In particular, add
gimp_paint_tool_paint_core_paint() and
gimp_paint_tool_paint_core_interpolate(), which call the
corresponding paint-core functions on the paint thread.
Additionally, rename the {start,end,flush}_paint() virtual
functions of GimpPaintTool to paint_{start,end,flush}(), and rename
gimp_paint_tool_is_painting() to gimp_paint_tool_paint_is_active(),
so that all the gimppainttool-paint-related stuff are grouped under
the same namespace.
Rename gimpblendtool{.c,-editor.{c,h}} to
gimpgradientool{.c,-editor.{c,h}}. Note that this commit only
renames the files; the actual changes are done in the next commit,
so that git doesn't consider them new files.
Partially revert commits 4f2e078ccb
and b0beb0197a, since the changes
they introduced to some of the renamed files were big enough for
git to consider them entirely new files, hence we lost their
history. The next few commits fix this.
This commit also partially or entirely undoes followup commits
5f6dfc7617,
c3f98cccbd,
6b0f5136e0,
and 3736bfd189, which will be
restored by the next few commits as well.
In GimpBrushTool, remember the settings used for the last cached
brush boundary, and avoid creating a new copy if the settings
didn't change. This should lower the overhead of
gimp_brush_tool_flush_paint() when not using dynamics.
Commit f5cb1fed85, which performed
brush outline generation in GimpPaintTool in synchrony with the
paint thread, wasn't enough, since GimpSourceTool could still call
gimp_brush_tool_create_outline() directly during its
GimpDrawTool::draw() method, leading to the same race condition
when executed concurrently with the paint thread.
Partially revert the above commit, so that outline generation is
handled as before, as far as GimpPaintTool is concenered. Instead,
add GimpPaintTool::{start,end,flush}_paint() virtual functions; the
first two are called when starting/ending painting using the paint
thread, while the third is called during the display-update
timeout, while the main thread and the paint thread are
synchronized. This allows subclasses to perform non-thread-safe
actions while the threads are synchronized.
Override these functions in GimpBrushTool, and cache the brush
boundary in the flush() function. Use the cached boundary in
gimp_brush_tool_create_outline() while painting, to avoid the above
race condition, both when this function is called through
GimpPaintTool, and through GimpSourceTool.
First WIP commit, adds:
- enum GimpGradientBlendColorSpace { RGB_PERCEPTUAL, RGB_LINEAR }
- linear blending mode for gradient segments
- tool options GUI for the blend and paint tools which use gradients
Most expected behavior in normal transform is to see the preview,
whereas you usually don't want to see it in corrective mode. In 2.8
actually, it seems like it was not even possible to see the image
preview in corrective mode.
So let's set "show-preview" to these defaults when "direction" property
is updated. It is still possible to change it manually for any specific
use cases (i.e. you can hide the preview in normal transform, and
oppositely you can show it in corrective transform), but at least now
defaults are sane.
... or during rotation.
If checked before rotation, it works as expected, i.e. one sees only the
original or the rotated image.
While rotation is in progress: if unchecked, one sees neither the
original nor the image preview; if checked, one sees both original and
rotated preview.
Let's make the behavior consistent and only show exactly one version at
all time.
In GimpPaintTool, brush outline generation took place during
gimp_paint_tool_draw() even while painting. This function is run
concurrently with the paint thread. When using dynamics, this
introduced a race conidition between updating the brush mask in the
paint thread, and updating the brush boundary in the main thread.
Move brush outline generation during painting to
gimppainttool-paint.c, and perform it in the display-update
timeout, while the main thread and the paint thread are
synchronized.
After last commit, all paint tools work correctly with a separate
paint thread, so we can remove the option for specific paint tools
to opt out. Particularly, GimpMybrushTool now uses a separate
paint thread too.
Note that the separate paint thread can still be disabled through
the GIMP_NO_PAINT_THREAD environment variable.
Reorganize/clean up gimppainttool-paint. In particular, move all
paint-core interaction during painting to gimppainttool-paint.c, so
that we can have more control over what's going on; specifically,
enter the drawable into paint mode *before* starting the paint
core, so that it picks up the correct buffer. This fixes painting
with the paint thread using GimpApplicator, and enables us to use
the paint thread with GimpMybrushTool.
Add gimppainttool-paint.[ch], which takes care of painting during
motion events in GimpPaintTool. Perform the actual painting in a
separate thread, so that display updates, which can have a
significant synchronization overhead, don't stall painting.
Allow specific paint tools to opt-out of a separate paint thread,
and avoid it in GimpMybrushTool, since it doesn't seem to work.
The separate paint thread can be explicitly disabled by setting the
GIMP_NO_PAINT_THREAD environment variable.
Similar to commit 845eb522b6, I had a CRITICAL which happened on a
device_changed, triggering gimp_display_shell_update_focus(), this time
in focus in.
Commit fd6d4931c8 accidentally
introduced a bug that caused Wilber's eyes to misbehave. This
commit is an attempt to fix this issue. Unfortunately, it seems
like the bug can still be triggered through a certain sequence of
actions...
Add signal GimpTextBuffer::color-applied which is emitted when text is
inserted or when color is applied to a span of text.
In GimpTextTool, connect to the signal and update the global color
history.
Unrelated: rename gimp_text_tag_get_color() to get_fg_color() and add
boolean return values to get_fg_color() and get_fg_color() which
indicates if a color is set on the tag at all. This ended up unneeded
in the fix but is an improvement regardless.
Add a crop_input parameter to gimp_gegl_apply_[cached_]operation().
When TRUE, the functions crop the op's input to the destination
rect. This is particularly useful for functions that process the
entire input in one go (by means of get_cached_region()). See the
next commit.
Pass crop_input = FALSE at all call sites for now, to keep the
current behavior.
Focus change events were expecting the current tool control to be
inactive, which was the case most of the time. Yet with stylus, the
canvas was sometimes receiving GDK_BUTTON_PRESS events before
GDK_FOCUS_CHANGE. In particular the canvas was receiving a button press
before the focus out, then button release and focus in. Therefore by the
time the focus out event happens, the tool control is active, which
broke a few calls.
Therefore I add a few checks and returns immediately when
gimp_tool_control_is_active() return TRUE, especially since we also run
gimp_display_shell_update_focus() calls after a button press anyway so
the state should already be consistent.
Add a gimp_filter_tool_reset_widget() function, which resets the
tool widget associated with the filter's controller -- i.e., it
resets those properties of the widget that aren't controlled by the
op's properties to some "default" state. For most controller types
this is a NOP; for transform-grid controllers, we move the pivot
back to the center of the drawable, w.r.t. the current transform.
Call gimp_filter_tool_reset_widget() after resetting or reloading
the tool's config.
...only remembers horizontal radius, duplicates it for vertical
Keep a list of the GUI's chain buttons around. When changing the
entire config object like on reset or selecting saved settings, unlik
them all after remembering their "active" state, and after changing
the settings activate the ones that were active before, but only if
the values they link are still the same.
... when gradient_type >= GIMP_GRADIENT_SHAPEBURST_ANGULAR.
Our current GUI code for the Blend tool options disables the "Repeat"
widget with any of the shaped and spiral gradient types, which means (I
assume) no repeat mode is allowed on these gradients. Nevertheless it
was possible to change the repeat mode in another gradient type, then
switch to one of these and get the repeat processed even though the GUI
shows insensitive.
I could simply reset the repeat mode to GIMP_REPEAT_NONE when setting
one of these gradient types, but I think you'd want the repeat to stay
at its value (being insensitive is enough to mean whatever value is set
is not taken into account). So instead, I just unsync this specific
property when appropriate.
Note also I don't do this in the gimp:blend operation code because I am
not sure this specific behavior is meant to be a generic blend behavior
or just relative to the tool (render of the shaped gradients is barely
different with a repeat, but there is still a difference).
It seems old blend tool (from GIMP 2.8) was using manhattan distance,
whereas the new one uses euclidean. I guess there must be use cases for
both. In any case, it is a good idea to simply propose the option since
the property exists in the "gegl:distance-transform" operation.
See also bug 781621.
When starting the tool with one of the gradient types for which the
repeat option should be deactivated, it is not. Run the handler function
once at GUI creation.
Also compare the gradient type with an enum value, which makes the test
clearer than using an int.
... which allows ops to create a transform-grid widget, similar to
the unified-transform tool, which can be used to control a
transformation matrix.
Implement the transform-grid controller in GimpFilterTool.
... current aspect ratio
In gimp_{rectangle_select,crop}_tool_start(), move
GimpToolRectangle signal connection to the end of the function. In
particular, connect the signals *after* the call to
gimp_{rectangle_select,crop}_tool_update_option_defaults(), since
it may result in an emission of a "change-complete" signal, whose
handler calls the function again with ignore_pending == FALSE, which
would override the ratio set with ignore_pending == TRUE.
Don't choke when calling gimp_tool_rectangle_set_constraint() while
there's no active image, or while the active image has no active
layer, which can happen when updating the default aspect ratio of
the crop tool. This would previously result in CRITICALs.
Additionally, use weak pointers for the crop tool's current_image
and current_layer members, to avoid potential dangling pointers.
While not currently necessary, this makes the code less dependent
on the exact order of events.
... current aspect ratio
When updating the default aspect ratio of a widget-less crop tool,
construct a temporary GimpToolRectangle widget, so that we can use
it to call gimp_tool_rectangle_constraint_size_set() and pick the
correct ratio, instead of just bailing.
When halting the crop tool, update the default aspect ratio, which
now does the right thing, as per the above.
Update the default aspect ratio upon changes to the active layer of
the current image, and to the size of the active layer, which
affect the default aspect ratio when "current layer only" is
toggled.
... current aspect ratio
When starting the rectangle-select (and ellipse-select) tools,
properly reset their default aspect ratio to 1:1. This fixes an
issue where the tool would use the aspect ratio of the last
rectangle when there's no user-overriden aspect ratio specified.
This restores the 2.8 behavior, except for the fact that the aspect
ratio resets to 1:1 when the tool is commited (if there's no user-
overriden ratio), rather than keeping the aspect ratio of the last
rectangle (i.e. "Current"); in 2.8 this only happend when halting.
The current behavior seems more consistent anyway.
Set the scale of the GimpRectangleOptions highlight-opacity
spinscale to 100, so that the spinscale's range is 0-100, instead
of 0-1, like the rest of our opacity spinscales.
... a selection.
The crash was the result of an unmatched gimp_item_end_move() call,
which is an error. Add the matching gimp_item_start_move() call
when starting to drag a selection in GimpEditSelectionTool. Revert
last commit, so that unmatched gimp_layer_end_move() calls are not
silently ignored, and add a check instead.
which is just a #define to g_assert for now, but can now easily be
turned into something that does some nicer debugging using our new
stack trace infrastructure. This commit also reverts all constructed()
functions to use assert again.
A tool commit can be triggered in various cases, and the tool manager
relies on gimp_tool_has_display() to decide whether to run a tool
action. This function does much more than just checking GimpTool's
display. It also checks status_displays, and for a transform tool in
particular, it checks GimpDrawTool's display. This may be right for
other tools (I have no idea), so I can't just change this function.
Anyway we have to assume it is not a programming error if a transform
tool gets a COMMIT action while display is NULL (i.e. tool is halted).
When this happens, let's simply ignore.
This fixes the edge case raised by Ell, in comment 2 of bug 793150: when
an image has no layer, transform tools can't work and display is NULL.
But it still outputs status messages and therefore status_displays is
not empty. So the tool manager will still run a COMMIT action, which is
not an error. We only have to discard such COMMIT silently.
Improving previous commit. Rather than calling:
> GIMP_TOOL_GET_CLASS (tool)->control (tool,
GIMP_TOOL_ACTION_HALT,
display)
> gimp_tool_clear_status()
... in the COMMIT action, which is basically what the HALT action does,
simply pass through from one case to the other. It also adds the call to
gimp_tool_control_halt() which is most likely right anyway since we are
halting the tool. This also makes the code consistent and any future
changes to HALT case will be directly enabled after COMMIT.
... 'GIMP_IS_DISPLAY (display)' failed.
This may happen when committing first a transform tool, then switching
to another tool. In this case, the tool manager will attempt to commit
again because gimp_tool_has_display() returns TRUE since status displays
were not cleared. Unfortunately transform tools don't handle very well
trying to commit when it was already done (hence both GimpTool and
GimpDrawTool displays are NULL).
The proposed solution is to clear the statuses after committing.
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
This reverts 2069496af3 for
gimpmeasuretool.c, we can't use gimp_display_shell_get_line_status()
here because the angle to show is *not* the angle as shown in the
paint tools (between x1,y1 and x2,y2), it is determined by a possible
third point.
Also, the info window and the statusbar were using different
coordintates to detemine the line length. This would have been easily
fixable, but the wrong angle wasn't.
Derive GimpUnifiedTransformTool, GimpPerspectiveTool, and
GimpHandleTransformTool from GimpGenericTransformTool, eliminating
their common logic.
Remove gimp_transform_matrix_handles(), which is no longer used.
A subclass of GimpTransformTool, to be used as a base class for
transform tools that calculate their matrix based on 4 pairs of
input/output points, and that display the transform matrix as their
GUI (this includes the unified, perspective, and handle transform
tools; the next commit ports them over to
GimpGenericTransformTool).
When the resulting matrix of the input/output mapping sends any of
the output points to, or past, infinity, GimpGenericTransformTool
sets GimpTransformTool::transform_valid to FALSE, and displays an
appropriate message in the tool GUI, instead of showing the matrix.
... which specifies whether the transform matrix is valid.
Subclasses can then set this member to indicate that the current
transformation is invalid (which can happen in the unified,
perspective, and handle transform tools). When the transform is
invalid, GimpTransformTool doesn't apply it upon committing, and
returns an error instead.
This commit doesn't set the transform_valid member in any of the
subclasses, so there's no effective change. The next commit adds a
GimpGenericTransformTool subclass, that will use the new member.
The four remaining "classic" color tools (Brightness-Contrast, Curves,
Levels and Threshold) are in fact just special UIs for otherwise
completely normal filter ops.
Add normal filter actions for them and invoke them like all
other filters, which makes them show up in the filter history
automatically.
The only small hack needed is to special case them in
gimp_gegl_procedure_execute_async() so the right tools are created
instead of the default GimpOperationTool. Also, blacklist the
automatically generated tools actions from action search and the
shortcut editor.
...instead of center
The scale tool implicitly uses GimpToolTransformGrid's "pivot-x" and
"pivot-y" properties, so they need to be properly initialized and
updated to be at the grid's center.
Also add a tool options toggle "Around center".
When the active modifier mode is GIMP_TOOL_ACTIVE_MODIFIERS_SAME (the
tool does not want to distinguish between modifier states depending
on whether or not the first mouse button down), we need to make sure
these states are in sync in GimpTool's bookkeeping, and we must not
generate synthetic modifier releases when the mouse button is
released.
...and present linear RGB Histograms
This is step one: implement the feature at all (without new defaults
or proper GUI, cough).
Add boolean "linear" properties to GimpOperationPointFilter,
GimpCurvesConfig and GimpLevelsConfig.
In the filter, simply set the input/output formats to linear in
prepare().
In the curves and levels tools, add "Linear" toggles from hell,
like in the histogram dockable, and make sure things work right
wrt changing and resetting the property, switching from levels
to curves, and picking colors.
The result currently changes when switching a non-nop curves/levels
between perceptual and linear, because adjusting the parameters
between the spaces is not implemented yet.
Add "clamp-input" (which clamps the input values to [0..1])
and "clamp-output" (which clips the final result to [0..1]),
properties, parameters and GUI to:
- GimpLevelsConfig
- GimpOperationLevels
- The levels tool dialog
- The gimp_drawable_levels() PDB API
The old deprecated gimp_levels() PDB API now sets both clamping
options to TRUE which restores the 2.8 behavior.
Also reorder some stuff in GimpLevelsConfig and elsewhere so the
levels parameters are always in the same order.
...outside area of Crop Tool -> Highlight option
Add "highlight-opacity" property and turn the controlling GUI into an
expanding toggle that reveals an opacity slider.
If the user enters a value in the shear tool dialog, that value must
be honored. Always set the shear direction to the edited axis and
reset the other axis to 0.
Replace the "lock brush size to zoom" paint option with a "lock
brush to view" option, which links the entire brush transform to
the view transform, so that the brush remains invariant in display
space under scaling, rotation, and reflection.
Add support for reflecting brushes as part of their transformation.
The reflection is performed as the last step of the transformation,
across the vertical axis.
The option to reflect the brush is not exposed in the UI, or
through the PDB, but is intended to be used for linking the brush
transformation to the view transformation, in the next commit.
Add an offset_angle parameter to gimp_constrain_line(), which
offsets the radial lines by a given angle.
Add gimpdisplayshell-utils.[ch], with two new functions:
- gimp_display_shell_get_constrained_line_offset_angle():
Returns the offset angle to be passed to
gimp_constrain_line(), in order to constrain line angles in
display space, according to the shell's rotation angle and
flip mode.
- gimp_display_shell_constrain_line(): A convenience function
which calls gimp_constrain_line() with the said offset angle.
Use the new functions in all instances where we constrain line
angles, so that angles are constrained in display space, rather
than image space.
The only exception is GimpEditSelectionTool, which keeps
constraining angles in image space, since it's not entirely obvious
that we want to constrain angles of dragged layers/selections in
display space.
Replace the GIMP_BOUNDARY_HALF_WAY macro by two others : one for perceptual and
one for linear gamma.
Use the GIMP_BOUNDARY_HALF_WAY_LINEAR to compute channels and floating selection
boundaries.
The free select tool now commits on double click inside a closed
polygon, which caused the foreground select tool to switch modes in
the middle of a click, breaking both its own and its parent class'
state.
Fixed by detecting whether the commit was done by double click and
delaying the mode switch until after the parent class button release
code is done.
Unrelated: Don't call both COMMIT and HALT, the generic tool mechanism
does that automatically now, forgot to port this file.
...is a regression in common cases
Commit the free select tool on double click inside the polygon.
Done by implementing GimpCanvasItem::hit() in GimpCanvasPolygon, using
ugly code.
Update the dprod production of generated enum files to include
abbreviated value descriptions, as per the previous commits.
Add a comment for translators above the abbreviated descriptions,
specifying the full description they abbreviate.
When a single blend-tool action adds and removes the same gradient
stop, restore the original gradient, rather than actually adding
and removing the stop, so that the affected midpoint returns to its
original state at the beginning of the action, rather than being
reset (and, consequently, so that the redo stack isn't lost.)
... from the undo stack
When a blend-tool edit action modifies the gradient, do a deep
comparison of the original gradient against the current gradient,
to test if anything changed, instead of just assuming that
something did change.
In GimpCanvasTransformPreview, use the transform matrix to
determine if we're doing a perspective transform, rather than
relying on a separate property, so that we don't use the slow
perspective path unnecessarily.
Consequently, remove the does_perspective member of
GimpTransformTool, since it's no longer used.
Change gimp_tool_set_active_modifier_state() to honor the new
GimpToolControlSetting. Explicitly set the mode to SEPARATE in
all tools that require modifier keys during a stroke.
And here comes the actual fix: change GimpTransformTool and
GimpToolTransformGrid to use SAME mode, and remove their
active_modifer_key() and hover_modifier() impls, so it makes no
difference whether a modifier is pressed before of after mouse button
press/release.
Add new enum GimpToolActiveModifiers { OFF, SAME, SEPARATE } and
new API gimp_tool_control_set,get_active_modifiers(), the default
value is OFF.
OFF: the tool gets no modifier keys at all during a stroke
SAME: all modifiers are always delivered via GimpTool::modifier_key(),
and no magic is applied whatsoever when a mouse button is pressed or
released.
SEPARATE: this is the "classic" way: modifiers while hovering and
while stroking are delivered separately, and hover modifiers don't
affect stroke modifiers.
Add a framework for saving and restoring internal data objects, in
gimp-internal-data.c. Internal data objects are saved in separate
files under a new "internal-data" subdirectory of the user's gimp
directory. The internal data is saved, restored, and cleared
together with the tool options.
Use this to save and restore the custom gradient. In the future,
we might add similar writable internal data objects that we'd want
to save.
gimp_dockable_blink() is used to attract the user's attention to a
specific dockable. Generalize this to arbitrary widgets, by
replacing gimp_dockable_blink[_cancel]() with
gimp_widget_blink[_cancel](), in gimpwidgets-utils.c.
Allow propgui constructors to specify an (optional) callback function
when creating pickers, to be called when a color/coordinate is picked,
similarly to controller callbacks.
Implement picker callback support in GimpFilterTool. When the active
picker has an associated callback function, call it instead of the
class's color_picked() function.
Add lots of "#include <gegl.h>" to .c files that miss it, which is
now necessary, since this commit adds a Babl* parameter in
propgui-types.h.
When one of the line widget's properties changes, only update the
blend tool filter if the property has an effect on the result. In
particular, don't update the filter when only the selection
changes.
Separate the handling of changes to the FG/BG color from the gradient
dirty signal handling, so that the gradient editor doesn't purge the
history in response. Additionally, correctly respond to such changes
whenever the gradient has segments that depend on the FG/BG colors,
even if the dependency is introduced after the gradient is selected.
Move the tool undo functionality of the blend tool to the editor,
and add support for undoing gradient edit operations. Each undo
step that affects the gradient holds, in addition to the line
endpoint poisitions, a copy of the gradient at the beginning of the
operation, as well as necessary information to allow the selection
to "follow" undo. When undoing the operation, the saved gradient
is copied back to the active gradient.
To avoid all kinds of complex scenarios, when the active gradient
changes, or when the gradient is modified externally (e.g., by the
(old) gradient editor), all undo steps that affect the gradient are
deleted from the history, while those that affect only the endpoint
positions are kept.
Allows setting the midpoint's position, blending function, and
coloring type.
The midpoint can be converted to a stop, and centered, through
editor buttons.
Allows setting the stop's position, and its left and right colors
and color types. A chain button can be used to modify the two
colors (and color types) together.
The stop can be deleted through an editor button.
To be used by the blend tool gradient editor to edit the gradient
endpoint/stop/midpoint properties corresponding to the selected
handle.
The GUI is currently empty; the following commits add its contents.
When a midpoint is double-clicked, convert it into a gradient stop
(i.e., split the corresponding segment at the midpoint,) by
responding to the line's handle-clicked signal.
Add a tentative_gradient member to GimpBlendTool, which, when set,
is displayed instead of the current gradient.
Use this to show a version of the gradient with the currently
selected stop deleted, upon receiving a prepare-to-remove-slider
signal, i.e., when the slider is about to be removed.
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.
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.
Repalce the two separate size entries, used for the position and
size properties of GimpRectangleOptions, with a single size entry
with two fields, so that they accept ratio expressions. Note that
this doesn't change the UI.
... the matrix is not actually used
Don't abort transform-tool commits when the transformation matrix
is the identity, for transform tools that don't calculate a
transformation matrix to begin with (i.e., the flip tool),
otherwise they do nothing.
...in both the core and libgimp.
Images now know what the default mode for new layers is:
- NORMAL for empty images
- NORMAL for images with any non-legacy layer
- NORMAL_LEGAVY for images with only legacy layers
This changes behavior when layers are created from the UI, but *also*
when created by plug-ins (yes there is a compat issue here):
- Most (all?) single-layer file importers now create NORMAL layers
- Screenshot, Webpage etc also create NORMAL layers
Scripts that create images from scratch (logos etc) should not be
affected because they usually have NORMAL_LEGACY hardcoded.
3rd party plug-ins and scripts will also behave old-style unless they
get ported to gimp_image_get_default_new_layer_mode().
Paint tools in straight line mode (shift click) will now display the
angle in status bar. Angle 0 is considered as the horizontal line from
left to right, and angle is measured counterclockwise from there, which
is the most common convention.
Add "gboolean with_filters" to gimp_drawable_calculate_histogram(),
which is passed as FALSE in almost all places, except the histogram
dockable where we want to see both the drawable's unmodified histogram
*and* the histogram after filters are applied.
and update the grid as soon as a constraint is changed, not only on
the next motion. Change GimpTransformTool to forward the events to the
widget if it exists, but still handle them if it doesn't (yes this
code duplication is ugly, but the widget can hardly handle events if
it doesn't exist...).
More than 2000 lines of code less in app/, instead of
if (instance->member)
{
g_object_unref/g_free/g_whatever (instance->member);
instance->member = NULL;
}
we now simply use
g_clear_object/pointer (&instance->member);
Change the text selection to draw an outline around each selected
glyph. It looks just as ugly as before but at least keeps the text
readable regardless of its color.
if did revert to the previous selection and thus break stuff like
enbaling quick mask or inverting the selection, because I merged the
undo magic it does into gimp_rectangle_select_tool_halt(), whereas
before it was done by the former gimp_rectangle_tool_cancel(), so only
on explicit cancel not HALT from whatever source.
Do the same in the new code and move the undo magic from halt() to
rectangle_response(CANCEL), which is exactly the same distinction as
with the old GimpRectangleTool code.
Don't unconditionally call COMMIT in rectangle_response(), because
that now implicitly HALTs the tool. Instead, check if we got here
because of a click, and call our commit() directly.
GimpOperationTool's aux inputs were not properly ported to the new way
filter tools work (complete destruction and re-creation of the tool
dialog).
Split creating the operation GUI and adding it to the dialog into
separate functions, and call them at the right places.
Call HALT generically in gimp_tool_control() after calling COMMIT, and
remove all hacks in tools that call both COMMIT and HALT or call
halt() from commit().
Some tools interact with their subclasses (e.g. filter tool and
operation tool), and it's essential that COMMIT runs through the
entire class hierarchy before HALT.
Probably breaks something, please test.
Need to keep around the operation's name and its description, so
everything can be re-created when an image is clicked.
Instead, completely shut down GimpOperationTool when GimpGeglTool is
halted, so the next click will bring up a dialog with only the
operation selection combo.