The next few commits are going to add support for using multiple
tool widgets simultaneously. As a first step, add a notion of a
focused tool widget, by adding gimp_tool_widget_{set,get}_focus(),
which tools/subclasses can use to control focus, and a
corresponding "focus-changed" signal, which tools/subclasses can
use to respond to focus changes.
(cherry picked from commit eeed9c413b)
When Control-Button2-Zooming, remember the start point, pass it to
gimp_display_shell_scale_drag() and force gimp_display_shell_scale()
to zoom around that point by passing GIMP_ZOOM_FOCUS_POINTER and
faking the point using gimp_display_shell_push_zoom_focus_pointer_pos().
(cherry picked from commit 792cd581a2)
and remove all clipping hacks for drawing the canvas background, turns
out they never worked and we were relying on the pattern set on the
window, gah! This optimizes away one entire step of drawing of image
size, for each expose...
... _even at low zoom levels_
Pass GIMP_ZOOM_FOCUS_POINTER to gimp_display_shell_scale() when
wheel-scrolling, and change the scaling code to really honor
GIMP_ZOOM_FOCUS_POINTER and not apply magic image centering.
This keep the same point centered under the mouse for wheel-scrolling
and the zoom tool (== when the zooming is really triggered at a
certain mouse position).
GimpDeviceInfo is the only way to store per-device settings like
color, brush etc. It used to be derived from GimpContext and therefore
limited to the context's properties, causing everything else (all
tool-individual options) to be lost on device change.
Derive it from GimpToolPreset instead, so it's capable of storing
arbitrary tool options.
Adapt things to the new class hierarchy and add a bunch of signal
handlers that make sure the active device's GimpDeviceInfo is updated
properly when the tool changes. Also change device switching
accordingly.
Change GimpDeviceStatus to only show the stuff that is relevant to
each device's tool.
And various small changes to make things work properly...
Commit b279c2d217 was breaking a specific use case, which I oversaw:
when space bar activates the move tool, you may want to release the
space bar while mouse button is pressed, and expect to still be able to
move the layer/selection/guide, but releasing space was stopping the
move immediately. The move tool must only be deactivated when both space
and button 1 are released, and the move itself must continue as long as
button 1 is pressed (when started while space was pressed).
As a nice side effect of this commit, panning and canvas rotation are
also improved since now they can be continued while releasing space
(respectively shift-space) if mouse button 1 was pressed, and up until
the mouse button is released. Pressing space again, then releasing the
mouse, back and forth, also work as expected (i.e. move tool stay
activated though the move stops; and panning or rotation continue).
Of course now we don't get anymore panning/rotation stuck while neither
space nor mouse buttons are pressed (which was the original bug). At
least one of these need to stay pressed for panning/rotation/move to
stay activated. And initial activation is obviously always through
(shift-)space only.
Invert zoom adjustment using the mouse or the keyboard when in
inverse mode. Take zoom factor into account when panning using the
keyboard. Fix motion cancelation.
GimpToolGyroscope is a tool widget providing canvas interaction for
3D rotation. The widget doesn't preset a UI, but rather
facilitates panning, rotation, and zoom, by dragging the canvas, or
using the keyboard.
Rotation is expressed using yaw/pitch/roll angles (performed in
this order). A zoom factor can be specified, which affects the
magnitude of the rotation per distance traveled. The widget can
operate in inverse mode, performing an inverse transformation.
Align rectangles added to the display paint area, in
gimp_display_paint_area(), to a coarse grid, to reduce the
complexity of ther overall area. This is similar to commit
49285463e6, however the alignment
happens in display space, instead of image space.
Last commit caused -xobjective-c to be passed during linking on
Mac, causing object files to be treated as source files. Add a
-xnone flag to AM_LDFLAGS, canceling the effect of -xobjective-c.
Additinally, add a -xobjective-c++ flag to AM_CXXFLAGS, so that we
can use Objective-C in C++ files on Mac, if we ever need to.
On Mac, pass -xobjective-c to the compiler through AM_CFLAGS, not
AM_CPPFLAGS, so that it's only used for C sources, and not C++
sources. In the latter case, it clashes with the -std=... flag,
spewing an error. Thanks, Partha :)
Statusbar progress updates that update the progress bar are
relatively expensive, slowing down operations that report progress
frequently. Only update the progress bar if a certain amount of
time has passed since the last update, to counter that.
Remove the connect_after() hack from GimpImageWindow again and instead
add gimp_display_shell_canvas_realize_after() and restore the configured
ruler visibility there. Should work for all cases now.
Add "ellipsize" property to GimpColorFrame and set it to
PANGO_ELLIPSIZE_END in the the pointer information dockable.
Better cut off long numbers than make them expand the dock.
gimp_image_window_constructed(): connect_after to the notebook's
"switch-page" signal so gimp_display_shell_appearance_update() is
called after gimp_display_shell_canvas_realize(). Just another hack
to fix the hack...
This keeps the same rectangle packing behaviour, so to behave exactly as
before for what concerns batching the updates, but should be lighter
when looping to find the first good rectangle to use.
In rtree_insert(), some conditions in the if tests are implied by
previous conditions. And therefore the 2 successive for loops are
actually identical.
In rtree_node_insert(), it is wrong/harmful to insert zero sized
rectangles in the tree because they can never be selected and just make
the list longer. So rtree_node_create() should just return NULL when w
or h are 0.
See bug 694917, comments 51 to 61.
As suggested by massimo in bug #694917, move unconditional creation/destruction
of a wrapper GeglBuffer object from top-level scope of the function to the
single conditional scope where it is used.
... scrolling in progress.
In particular, this could happen while panning with mouse middle click
and hitting space. This space should simply be ignored.
The bug was affecting actually both canvas rotation and panning when
done with space key. If the first mouse button was also clicked, then
released after the space key, we ended up in some stuck action. It could
only be unstuck by hitting/releasing space again.
I am actually unsure that this was not originally done on purpose,
especially since the code has these 2 status variables space_pressed and
space_release_pending, but really apart from looking at this code, the
behavior just looks very buggy and impracticable.
The new behavior is to just stop the canvas panning/rotation as soon as
space is released (which is also how it is documented in our manual, and
how everyone seems to use the feature). I only kept the variable
space_release_pending, which I use as was used space_pressed before.
Avoid redrawing GimpCanvasProgress items upon
GimpProgress::set_value() if a minimal amount of time hasn't passed
since the last call. This notably improves performance of
frequently-updated GimpCanvasProgress items.
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.
Since a few commits, I don't generate the traces anymore in errors.c but
delay this to gui-message.c and rely on the message severity to decide
whether or not generating traces.
Unfortunately none of the current severities are properly describing
this new type of messages. Even GIMP_MESSAGE_ERROR is used everywhere in
our code NOT for actual programming bug, but often for data errors
(which are not bugs but proper messages and should obviously not prompt
a debug trace).
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.
This avoids warnings when the handle positions the handle-transform
tool result in a matrix that transforms the TransformGrid's handles
(which are all invisible) to coordinates that are outside of the
corresponding properties' range.
Fix indentation, typos, style. Use array parameters for the
control points, instead of using individual by-value parameters.
Use GArray* for the results, instead of GArray**. Verify
arguments.
Adapt the rest of the code to the changes.
Add a "clip" property to GimpCavnasTransformGuides. When set, use
gimp_transform_polygon() for transforming the guides and the
bounding box, so that they're properly clipped.
Add a corresponding "clip-guides" property to
GimpToolTransformGrid, and set it to TRUE in GimpToolHandleGrid, so
that the handle-transform tool's guides are clipped properly.
the angle arc and the small helper line were displayed on opposite
sides of the first point. Now they are on the same side, just like for
all other angles.
... gimp_transform_matrix_generic()
Replace the separate x/y coordinate arrays of GimpHandleGrid with
GimpVector2 arrays, and use gimp_transform_matrix_generic(),
instead of gimp_transform_matrix_handles(), when calculating the
matrix. When the resulting matrix is invalid, hide the guides.
... which can be used to control the guides' visibility.
Will be used by the next commit, to hide the guides in
GimpToolHandleGrid when the tranformation is invalid.
...if "Show rulers" is disabled
Add HACK to gimp_display_shell_canvas_realize() that makes sure the
rulers are always mapped once for each new GimpDisplayShell. This
seems to magically fix all the crashes.
Before you get too exceited -- no, this commit doesn't integrate
transform previews into the image graph :) We still use a
separate canvas-item overlay, just like before, but instead of
using an impromptu implementation to render the preview, we use
gegl:transform. We properly adjust the matrix passed to the op
according to the display scale, so that we still render only as
much as needed.
This is both notably faster than the current code, and, for
perspective transforms, more accurate.
This reverts commit 36258a671a.
This commit was making the rotated canvas rendering quite horrible to
the point that I think it would make the canvas rotation feature barely
usable. See bug 759287, comments 13 to 18.
I think we will need to find other ways to accelerate rendering.
Compromise on quality is possible, but I think that in this case, this
was more than just a compromise. It was more like completely abandonning
quality. We could even see the lines "spiking" while you were rotating!
Like your drawing was alive!
Improve the disabling/enabling of extended input events for the
canvas during enter/leave-notify events, in particular, so that
enter-notify events that are a result of pointer ungrabbing don't
erroneously reeanble extended input events.
Something about the unqueueing and requeueing of the entire event
queue during motion compression fries GTK's brain w.r.t. extended
input events. Instead, have gimp_display_shell_compress_motion()
return the first non-compressed event to the caller, making it
responsible for dispatching it after handling the motion event.
...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.
After commit 8029508fbe, we always
render the image in chunks that are at most
GIMP_DISPLAY_RENDER_BUF_WIDTH x GIMP_DISPLAY_RENDER_BUF_HEIGHT,
even when the window's scale factor is > 1.
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.
When you move an endpoint in the Blend Tool, angle and distance
information are especially important, in case you want to draw a
gradient with specific values.
Currently Blend tool only shows the vector coordinates whose usefulness
is a bit of a question. Now it will also show distance (in current shell
unit) and angle!
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.
Add gimp_display_shell_[un]transform_with_scale(), which are
similar to gimp_display_shell_[un]transform(), however, they
transform the bounding box to/from uniformly-scaled image space,
given the scale factor as a parameter. These functions are more
accurate than using gimp_display_shell_[un]transform() and applying
the scaling separately, in particular, when the scale matches the
(horizontal or vertical) display scale.
Use these functions in gimp_display_shell_draw_image(), to avoid an
off-by-one error when transforming screen-space chunks to image-
space chunks, which leads to the symptoms described in the bug.
Fix another potential off-by-one error affecting non-uniformly
scaled images, and window scale factors other than 1.
Use CAIRO_FILTER_FAST when painting the xfer surface to the
screen. This notably improves performance when the canvas is
rotated, at the cost of lower filtering quality.
Based on a patch by Massimo.
Move the entire image-space/screen-space transformation logic from
gimp_display_shell_render() to gimp_display_shell_draw_image(), so
that the former works entirely in image space, and do the chunking
and clipping in screen-space, making sure that image-space chunks
are never larger than
GIMP_DISPLAY_RENDER_BUF_WIDTH x GIMP_DISPLAY_RENDER_BUF_HEIGHT,
even when the window's scale factor is greater than 1.
Add a GIMP_BRICK_WALL environment variable, which, when set, shows
the screen-space chunk bounds.
...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.
Now add also flip information in the status bar so that one knows that
the canvas is flipped horizontally and/or vertically. Especially if you
often flip and rotate the canvas (or if you did it by mistake), at some
point, it may become confusing to remember whether this is the case. Now
it will be possible to check in a single glimpse at the status bar.
Similarly to what I previously did for the rotation information, hitting
the flip icons in status will allow to unflip easily without having to
go in menus or remember all shortcuts.
These information will be visible only when the canvas is flipped or
rotated.
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.
Return FALSE from gimp_display_shell_has_filter() when there are
filters, but they're all disabled, to avoid unnecessary extra
color conversions during rendering.
When we have display filters, break the color profile transform in
two: first, convert from the image profile to sRGB, then apply the
filters, then convert from sRGB to the monitor profile.
When a display filter's configure() function returns NULL, use a
propgui for the filter, instead of not showing a widget at all, to
spare filters the need to manually construct a configuration gui.
When processing display filters, shift the filter buffer to the
top-left corner of the render area, and pass the actual render
area, instead of an area whose top-left coords are (0, 0), to the
display filter. This allows for position-dependent display
filters.
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.
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.
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.
In gimp_canvas_sample_point_get_extents(), use the drawn number's
actual size instead of some random constant that was good enough for
my own font size.