Previously, when using shortcuts to increase or decrease the font size of
the selected text, the size would jump to 0. This behavior occurred because,
if the text did not yet have a font tag, the initial font size was evaluated as 0.
This commit ensures that the text tool's default font size is used when
no font tag is present. This prevents the font size from jumping to 0 the
first time the shortcuts are used.
When moving a floating layer or selection, we draw a solid
border around the object. However, we also let the "marching
ants" selection continue (if the user has it enabled). This slows
down performance when moving, especially on large selections.
This patch incorporates logic from the Selection tools into the
Edit Selection tool (which the Move Tool uses for translation).
It stores the user's "Show Selection" setting, sets it to FALSE
while moving the layer or selection, then restores it to its
prior value when the cursor is released.
This logic also extends to using Ctrl + Alt to drag a floating
selection out of a layer that already has a selection.
Try proxy bindings before the IM context. On macOS and Windows,
the IM context consumes Alt+key events (Option produces special
characters on macOS; Alt triggers alt-codes on Windows), so
bindings such as Alt+Plus/Minus (size) and Alt+arrows
(baseline/kerning) would never be reached otherwise.
Unlike for Curves (commit 7b4f0993e8), we cannot just change the "trc"
default of "gimp:levels", because then it could break any existing
script, made during the 3.0 series, which was applying this filter on
layers.
Instead, the "trc" stays linear by default for the op, but the tool's
dialog will override it to perceptual.
When we'll have implemented proper op versioning, we will be able to
change the default.
In 046c8f27, we added a new function
gimp_selection_options_get_mode_box () so that the
Paint Select tool would use the same enum as other
selection tools. Code was added to move the
GIMP_CHANNEL_OP_REPLACE enum to the front only if
it was greater than the min value and less than the max value
that was passed in. This was to allow the Paint Select tool to
keep GIMP_CHANNEL_OP_ADD at the front while leaving the
other selection tools as they are.
However, the original call used 0, 0 for those values, so the
rearrangement code never ran at all. This patch changes the
parameter max value to GIMP_CHANNEL_OP_INTERSECT so
that Replace is moved for non-Paint Select tools.
In the path tool, when setting a new vector layer as
the editable path, we try to disconnect the old signal for
gimp_path_tool_vector_layer_path_changed () from the
vector layer options. However, if this code is triggered
because we rasterized the vector layer while the path
tool was active, it will throw a warning because the
layer options are NULL. This patch adds a check to make
sure the options exist before trying to disconnect their
"notify::path" signal.
When copying and pasting a vector layer into
another image, the display would jump back to
the original image. This also happened if you
re-selected the pasted vector layer in the new
image after choosing another layer.
This patch makes sure that when updating the
selected path in the Path tool, it grabs the display
from the pasted vector layer rather than the old
image's path.
Note that this may be a "symptom" rather than a
root cause, due to a number of remaining issues
with copying and pasting vector layers.
Per user request, this allows you to use
arrow keys to adjust the shear tool.
Left/right move the shear on the X axis,
up/down move the shear on the Y axis.
By default, it moves one pixel at a time.
If you hold shift (similar to the move
tool), it moves based on the slider's
page increment setting (factoring in the
current zoom).
This patch conditionally adds an alpha
channel to a layer when using the Crop
Tool, under the following conditions:
1) "Selected layers only" is checked
2) "Allow growing" is checked
3) "Fill with" is set to transparency
4) The crop rectangle is larger than the
width or height of the layer
5) The layer does not already have an
alpha channel.
Per user request, this allows you to flip
on-canvas items with the arrow keys when
the Flip tool is active. Left/right arrow keys flip
horizontally, up/down arrow keys flip vertically.
Note that having an active guide highlighted overrides
this distinction - pressing any arrow key will always flip
over the guide, same as with the mouse.
In particular, for indexed images, color choice will happen within the
colormap.
The following uses are made context-aware:
* Test tool options color;
* Fill colors.
These other uses will not be context-aware:
* Padding, quick-mask and padding colors;
* Out-of-gamut colors;
* Generically generated color buttons (e.g. in filter dialogs);
* Foreground selection's mask color;
* Grid colors.
... to get limits in image coordinates instead of gimp_ruler_get_range.
Rulers return values in the active unit (e.g. mm, inches), while the
overlay logic works in pixels. This unit mismatch caused incorrect
clamping of the text overlay position, making it jump
when dragging if the unit wasn't set to pixels.
Resolves#15418
Destructive tools can not be used on non-raster layers
(vector, text, link). However, the Crop Tool is only destructive
when "Delete Pixels" option is enabled - otherwise it just crops
the canvas size. This patch toggles the GimpTool classes'
"is_destructive" setting based on the value of "Delete Pixels".
To avoid duplicating code, I make a friend function to be reusable in
Paint Select options code: gimp_selection_options_get_mode_box().
I also get rid of GimpPaintSelectMode enum, which was clearly a
duplicate type to GimpChannelOps. Right now only ADD and SUBTRACT are
supported in Paint Select tool, yet we are perfectly able to generate
widgets showing only partial data. Which is what I do here by adding
appropriate min/max value args to the new function.
Note though that I don't see why we should not be able to replace or
intersect using Paint Select. But since these 2 modes are not
implemented right now, I haven't tried to add support in this commit.
For now, only making our GUI consistent so that Paint Select looks like
any other selection tools (simply only with 2 modes).
Every time we press for a selection update, we will start with a blank
tri-map, instead of reusing previous "scribbles". In my various tests,
it felt like I would get better results this way. Also if you do some
mistakes (maybe getting off-border of your object in a previous stroke),
it would be much harder to fix, unless you are alway showing the
scribbles.
One can consider that once you edited the image selection, what is done
is done. You don't constantly edit the past, and your resulting
selection could have been done with any other selection tool (how it was
done doesn't matter anymore). This makes the tool actually stateless
in-between strokes.
Note that I reset the tri-map at the start of a stroke, rather than at
the end. This way, it still allows one to see the previous stroke (it
can be useful for verifying how it was done before undoing and
retrying).
This change won't do much right now, using upstream libmaxflow (though
it won't hurt either). It will really show its usefulness together once
this patch will have been merged in libmaxflow:
https://github.com/gerddie/maxflow/pull/8
… then once done, I will push also a small update in "gegl:paint-select"
code on GEGL repo, which will in turn report the progression as reported
by libmaxflow.
This is particularly needed for big images on limited hardware, which is
when the current algorithm or its implementation will start showing some
weakness. I had cases (on 4000×3000 images in Balanced power mode) where
the processing inside graph->maxflow() could take more than 10 seconds,
the GUI would look frozen and the desktop would warn you through a popup
that the software "is not responding" (with the option to kill the
process). Furthermore without any kind of feedback, you have no idea if
processing will be soon finished or if it will take 10 minutes, or 1
hour, or even if you may be stuck in some infinite loop. In such
conditions, even 10 seconds actually feel long and the software appear
broken.
But when you have the progression feedback, you see that processing is
soon finished, and when working on huge images, you may expect that some
things may take longer than others. In such a case, even longer time may
actually feel very acceptable.
Note: an alternative to show progression would have been to use a
GeglProcessor, but apparently it gets its progression status a different
way, by cutting the image into smaller pieces. This doesn't work with
"gegl:paint-select", or at least its current implementation. Using the
"progress" signal works fine though.
Increasing the viewport region with the region of same size, yet
centered around the cursor position (whether the button_release() one or
even any motion() position) doesn't make much sense.
If the idea is to limit the work on the viewport, which is indeed quite
interesting performance-wise, but also worflow-wise to allow targetting
parts of an image while ignoring the rest, then let's stick to the
actual viewport indeed!
I am only adding half the "brush size" to every edge of the viewport,
because technically we can move the cursor so that half of the brush
preview is off-view. Though even this, I am hesitating. Indeed
workflow-wise, it may be much more interesting to be able to really
limit where want the selection to stop. Selecting a bit further than
"what you see" may be unwanted, even if the brush itself could
technically go further.
… respectively Add or Subtract modes.
When all the "scribbles" are already inside the fully selected area, it
is likely unneeded to recompute the paint selection (it's not entirely
true, algorithmically-wise, but workflow-wise, it makes sense: if you
are not happy with your selection and want to add some parts of the
image, you would obviously "paint" in the area which you want to add in.
And reciprocally for removing some of the selection, you'd paint within
the existing selection.
This also cleans out some of the logic in the button_press() code, where
we were adding the initial "scribble" to the mask. In original code,
when clicking without any motion, what was happening was that you were
only adding this one round selection and nothing else was happening,
which I always found weird (when you want to add some tiny piece of the
image into the selection, you may not have a lot of space to move and
would still want to do a quick click while hoping it will compute a bit
more into the selection). Now the new code anyway computes during
button_release() so adding this initial small-round mask is even more
unneeded.
Last, I am moving more of the motion() code into button_release().
I can see why this was added when we used to re-process the graph during
motion (it was already slow and would have just been so much slower),
but if we only process at the end, it is simply counter-productive not
to store all motion events. It doesn't actually make the finale
processing (on release) slower, at least not obviously, and we get more
data for more accurate (hopefully) selection.
I can read in the source paper that the original goal was to have
instant feedback "as they drag the mouse", but truth is that right now,
this doesn't work out. On bigger images (yet reasonably sized, like
3000×4000, which is even smaller than what the paper claims should be
instant), we end up reprocessing for 10 seconds (on my laptop, in
"Balanced" power mode) multiple times in a single stroke!
Only processing on releasing the stroke (and only storing the
"scribbles" into the trimap during the stroke), we get back to a more
reasonable wait time, such as **once** 10 seconds on my test image and
laptop. And for smaller test images, like near-FullHD, we get very quick
processing on releasing the pointer click.
This may not be ideal, and the problem may be that our implementation is
not ideal and could be improved (I think it should be multi-threadable,
at least that's what it looks like when I read libmaxflow code — this is
where most of the processing time is actually spent! —, and also the
source paper mentions "multi-core graph-cut as an optimization). But
then we can revert to during-motion processing later. For now, all it
does is make this tool unusable.
Resolves#12755
gimp_edit_selection_tool_active_modifier_key () assumed
that if you press a modifier key while a selection/move tool
is active, we should move the selected item to the last place
recorded. However, it's possible to run this function before
we've moved anything, thus defaulting the "original position"
to 0, 0.
This is most noticeable in the Move Tool, where pressing Ctrl
or Shift after clicking a layer but before moving it will cause
the layer to "jump" based on where the cursor is placed on the
item.
This patch adds an additional condition to the motion function
in gimp_edit_selection_tool_active_modifier_key (), so that
we only do it if we've already moved the cursor at least once.
This patch swaps out the GtkBox in
gimp_enum_icon_box_new_with_toggle ()
with a GtkButtonBox and sets it to EXPAND
so that the buttons are pressed together.
It also adds some CSS style to complete
the effect.
This patch ensures that the text style editor is destroyed whenever a text layer
is selected, even switching between them clicking on different textboxes.
This is necessary to ensure that the on-canvas editor is positioned
correctly according to the coordinates of the selected text layer.
This commit prevents the on-canvas text editor from being dragged outside
the image bounds by checking the overlay's position and adjusting the
coordinates to keep it within the canvas. Additionally, it checks whether
the overlay is entirely outside the canvas and, if so, pushes it back inside.
This commit adds a button inside the on-canvas text editor
that restores the editor to its original position after it has
been moved. The button is only visible when the editor has been
moved, and disappears when it returns to its default position.
... to reset its position via right-click menu
This commit adds the ability to restore the original position of the
on-canvas text editor after it has been moved, by accessing the option
from the context menu opened with a right-click on the text box.
Once the on-canvas text editor has been moved, its position should be
preserved across editing sessions. This commit stores the editor's
position per text layer and restores it when the layer is activated again.
After the on-canvas text editor has been moved, it should remain fixed
on the screen when zooming or panning the canvas. This commit preserves
the current behavior when the editor is in its original position, and
fixes its position on-screen after it has been moved.
This implies both when canceling or committing a filter.
Part of the fix is that we don't store filter tools as part of the tool
history, which means that when we swap back to the previous tool, the
filter tool info is dropped as though we never went through it. This
way, filter tools don't actually look as other tools (even though they
technically still are, since this is how we can implement canvas
interaction for some of the filters).
Per review, let's avoid having all the tools history in every
GimpContext.
Also a further commit will work on special-casing filter tools, which is
why we are storing up to 3 tool infos, instead of only 2.
Rasterizable objects are all created from some side data and can be
renamed automatically based on this data (from the link file for link
layers; from the path for vector layers; from the text for text layers).
So let's share code.
- Getting rid of the dedicated vector layer options dialog (with fill
and stroke settings) which appeared when double-clicking on a vector
layer. This is a duplicated with the Path tool options.
- Double-clicking a vector layer instead will simply start the Path tool
(same as double-clicking a text layer starts the Text tool).
- The path choice settings only is missing from the Path tool options.
Instead of moving it there, I move it to the generic layer options
dialog. I don't think it's the kind of setting you really change often
(most of the time, you likely just make a new vector layer).
- Offsets are ignored too and hidden for vector layers.
- Also making sure that the path changes shows live when editing the
setting in dialog, but it is properly reverted if canceling the
attributes edition.
- Also make sure the undo step changes the path back.
The analogue of Control key on macOS is the Command key, this means that
`GDK_CONTROL_MASK` has not the expected behavior on macOS. This commit
changes the modifier for unformatted paste in text tool from Control to
Primary, which maps to Command on macOS and Control on other platforms.
This patch adds a Paste Unformatted Text item inside the
right-click menu of Text Tool, which allows user to paste
previously copied, possibly formatted (marked) text as plain
text with no markup.
- The "Create New Vector Layer" button is now always active, as long as
there is an image.
- When a path is selected with no matching vector layer, the button's
label will be "Create Vector Layer from Path", indicating that it will
create a new vector layer from the current path.
- When selecting a path while the Path tool is active, let's update the
selected layers to all the layers (it may be several layers!) tied to
this path. Otherwise, this can be quite confusing, showing a path
while another layer is selected, or worse, showing a path while the
selected layer is a vector layer (but not tied to this path).
This is the result of a UX session with Aryeom. Just showing a message
forbidding editing of non-rasterized text/link/vector layers is
problematic, because it doesn't help people understand how to unblock
their situation (if they really want to just edit directly the layer).
Additionally we are now blinking the layer.
A possible alternative could have been to pop a dialog up, with the
same message but also with a quick-action button to allow rasterize in a
click (similar to how we are popping a dialog up to revert the
rasterization when clicking on a text layer with the text tool or a
vector layer with the path tool). The problem is that even though the
need to edit directly a non-raster layer arises from time to time, most
of the time, when you use such layers, you don't intend to edit these
(unlike editing text/path with matching tools, you more often wanted to
edit the relevant data).
Therefore it is more often than not just a mistake when you try to paint
directly on such a layer. I.e. that very often, you were intending to
paint on another layer, or add a new layer above your non-raster layer.
Therefore a dialog popping up every time you made such a mistake would
be annoying and workflow-breaking. A simple error message and some
blinking leave for a fluid process.
The previous code was preventing initializing, but some succession of
actions could go round this check: Rasterize then Revert Rasterize. In
this state, the next click would not try to initialize again, which
first is not very good if the initialization was necessary, and second
would allow drawing on a non-rasterized text/link/vector layer.
So let's just have all the code blocking drawing on rasterizable
drawables in the generic gimp_tool_button_press() code only.
Share the whole rasterize logic of the text, link and vector layer into
an interface. I didn't write it as an abstract parent class, because we
might have more rasterizable items in the future, which may not be
layers (e.g. there were discussions of vector masks).
… "Confirm Text Editing" one on Text tool.
When selecting a rasterized vector layer, this will suggest to edit it
anyway (hence losing any modification since rasterization), create a new
layer based off the same path, or cancel.