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.
In gimp_layer_new(), set opacity and mode using the setter
functions, instead of modifying the members directly, so that all
the necessary side effects take place.
Add gimp_item_get_merged_color_tag(), which returns the color tag
of the nearest ancestor (including the current item) that has a
color tag other than NONE. Use this function in GimpItemTreeView,
instead of gimp_item_get_color_tag(), to set the cell color of
items, so that item's with a NONE color tag inherit the color of
their parent. Add a boolean "inherited" parameter to
gimp_get_color_tag_color(), which indicates if the color tag is the
item's actual color tag, or an inherited color tag, and modify the
returned color accordingly, so that inherited colors are less
saturated/lighter than non-inherited ones.
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.
Keep multi-threading disable on the cage transform operation. It is now
fixed but is a lot much slower than when single-threaded, making it
painful to use on bigger images.
So let's reenable later if we can improve this. See bug 787663.
Override GimpLayer::get_effective_mode() in GimpGroupLayer, to
perform strength-reduction of pass-through groups to normal groups
under certain conditions (see gimp_group_layer_get_effective_mode()
for the logic.)
The main motivation for this is the fact that Photoshop uses pass-
through mode as the default mode for groups, resulting in many PSDs
using pass-through groups generously and unnecessarily. Since
pass-through groups are more expensive that normal groups, reducing
them to normal groups when possible can make a big difference.
Note that, while the results of the strength-reduced composition
are theoretically equivalent, there may be small differences in
practice due to numerical errors, especially when using low
precision. This is unlikely to be an issue, but, just in case,
allow disabling this optimization using the
GIMP_NO_PASS_THROUGH_STRENGTH_REDUCTION environment variable.
gimp_layer_get_effective_mode() returns the actual layer mode,
blend space, comosite space, and composite mode used for the
layer's mode node, allowing them to be different from the values of
the corresponding layer properties. The aim is to allow us to
replace expensive layer configurations with cheaper but equivalent
ones transparently. This is used in the next commit to replace
pass-through groups with normal groups under certain conditions.
The effective values are computed by the new
GimpLayer::get_effective_mode() virtual function. The default
implementation provided by GimpLayer returns the corresponding
layer properties as-is (replaceing AUTO with concrete values).
Subclasses can override this function, providing more
sophisticated logic.
When attaching a layer as a floating selection to a drawable,
unbind its visiblility from its activeness, as per the previous
commit, and use its visibility to control the activeness of the
drawable's floating selection filter.
Properly update the drawable when the floating selection's
visibility and excludes-backdrop properties change.
Add an "active" property to GimpFilter, which replaces its
"visible" property. The new property assumes the lower-level role
"visible" had -- controlling whether the filter has any effect as
part of its parent filter-stack.
Add a "visible" property to GimpItem, separate from the "active"
property, which assumes the higher-level role "visible" had --
controlling whether the item is considered "visible", as per the
GUI. By default, the item's "visible" property is bound to the
filter's "active" property, so that changes in visibility directly
affect the filter's "activeness"; this binding can be controlled
using the new gimp_item_bind_visible_to_active() function.
This distinction is currently necessary for floating selections.
Floating selection layers must not be active in their parent stack,
regardless of their visibility, in particular, so that their mode
node doesn't hide the entire backdrop when their composite mode
excludes the backdrop (i.e., when it's dst-atop or src-in).
Instead, their visibility should affect the activeness of the
floating-selection filter of the drawable they're attached to.
This is handled by the next commit.
Currently, when a GimpFilter's visibility changes, we rely on its
various visibility-changed signal handlers to rewire the filter
node's graph to reflect the change. This has two main
disadvantages:
- There's no easy, generic way to toggle a filter's effect,
especially one that is not subclassed, since GimpFilter only
takes care of the case where visibility becomes FALSE, and does
nothing by itself when it becomes TRUE again.
- While GimpDrawable does handle the visibility => TRUE case, it
doesn't disconnect the filter's input from its mode and
(potentially) source nodes when it becomes invisible. As a
result, while none of the drawable's graph is processed as part
of the composition when not visible, the mode and source nodes
do get invalidated when the filter's input is invalidated, such
as while painting on a layer below the drawable. This is
particularly bad for pass-through groups, since their source
node can be an arbitrarily complex graph, whose invlidation
incurs a nontrivial overhead.
Instead, don't touch the filter's node at all when visibility
changes, and rather have GimpFilterStack remove it from the graph
entirely when the filter becomes invisible, and re-add it once it
becomes visible again. This solves both of the above problems, as
well as simplifies the code.
When merging a drawable filter, we call
gimp_gegl_apply_cached_operation() on a node that's part of the
drawable's filter stack graph. The function rewires the node's
input, and doesn't restore its original input connection before
returning, leaving the graph in an inconsistent state. Currently,
this doesn't matter, since we remove the filter right after that,
but the next commit expects the filter stack graph to remain
consistent.
Remember the original source node of "operation" in
gimp_gegl_apply_cached_operation(), and restore it upon exit, to
fix that.
Since commit ff59aebbe8, blur-gauss plug-in and the associated
"plug-in-gauss" action don't exist anymore. Migrate any custom shortcut
to "filters-gaussian-blur", which is the expected replacement.
See also bug 775931.
Current logics of dealing with duplicate accelerators was just to delete
one randomly. This works ok in most case since we can't be in the head
of people and can't know which one they want to keep (yet we can't keep
both because that makes it very complicated to reset the shortcut
appropriately by hand/GUI, without a tedious work of researching which
other action uses the same shortcut. See commit 2a232398c4).
There is still some cases where we can be a bit more clever than random
deletion: when one of the accelerator is mapped to a non-existing
action. In this case, let's delete this accelerator in priority. Not
only the chances of this being the expected result are higher; but even
worse, there is anyway no GUI way to delete the accelerator for the
non-existing action! Thus you could try and reset your existing action's
shortcut as many times as you want in the GUI, it would always end up
deleted at next startup!
Note that if the non-existing action's shortcut has no duplicate, it
won't be deleted. This ensure that you could uninstall a plugin, then
reinstall it later and still have your custom shortcuts saved in the
meantime. A shortcut of a non-existing action will *only* be cleaned out
if it is redundant with the shortcut of an existing action.
Use gimp:buffer-source-validate, introduced in the previous commit,
for the source node of GimpDrawables. This avoids threading issues
with layer groups, or any other drawables that may use a validating
buffer, by making sure the buffer is validated before any
succeeding operations, and hence the associated graph is processed
on the same thread as the parent composition.
Restore multithreaded processing in GimpOperationLayerMode.
gimp:buffer-source-validate is a drop-in replacement for
gegl:buffer-source, however, if the attached buffer has a
validating tile-handler, it makes sure the required region is
validated during process(). This avoids a situation in which
validation happens in different worker threads at the same time
during the processing of a succeeding operation; since validation
is protected by the buffer's tile-storage mutex, this can result in
either a deadlock (currently), or an effective fallback to single-
threaded processing.
When switching a group layer from pass-through mode to a non-pass-
through mode, flush the projection synchrnously, to make sure that
the projection's buffer gets properly invalidated at that point,
and can be subsequently used as a source for the rest of the
composition.
Add a boolean 'pass_through' member to GimpGroupLayerPrivate, which
indicates if the group is a pass-through group, and use it instead
of checking the group's mode, so that we can detect that the group
used to be a pass-through group when the mode changes, and to
simplify the rest of the code.
Set the priority of group-layer projections according to the group
layer's depth, so that top-level groups have a priority of 1
(compared to a priority of 0 for the image projection), and nested
groups have a priority one greater than their parent (in other
words, shallower groups have higher priority than deeper groups,
all of which have lower priority than the image.)
This makes pass-through groups much faster, in particular.
... which control the priority of the projection's idle source.
The projection's priority is specified relatively to
GIMP_PRIORITY_PROJECTION_IDLE (i.e., a priority of 1 results in an
idle source with priority GIMP_PRIORITY_PROJECTION_IDLE + 1, etc.)
Add GimpViewable::ancestry-changed signal, which is emitted when
the viewable's ancestry changes, i.e., when its parent, or the
parent of one of its ancestors, changes.
Add gimp_viewable_get_depth() function, which returns the
viewable's depth in the hierarchy, i.e., its ancestor count.
...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.
Massimo is worried that it could unload the module (maybe in some
specific cases?), which could indeed happen when the g_type_class_ref()
just before was the first call to the class (hence it's the only ref).
So let's just unref() in the exit() function instead.
Not sure if g_type_class_ref() can actually return NULL here, but let's
add a check, just in case.
Also unref() after since we ref-ed it ourselves.
Finally reorganize a bit to keep the private functions together and
named appropriately, clean some tabs and add a comment to remind of
further check/cleanup once we port to GTK+3.
Comment by Jehan after review:
"Quick and dirty hack" but a working one. Since the bug will likely
disappear with the GTK+3 port (to be verified) which uses another theme
system, let's just do it this way.
The value descriptions of GimpGradientColor,
GimpGradientSegmentColor, and GimpGradientSegmentType enums appear
in the on-canvas gradient editor UI, as combo-box items in the tool
GUI overlay. Since we want to keep the overlay as small as
possible, we previously used abbreviations for these descriptions
(e.g., "FG (t)", instead of "Foreground (transparent)").
Replace the abbreviated descriptions with unabbreviated ones, and
move the abbreviations to the "abbrev" parameter. This way we get
the abbreviated version in the combo-box, and the full version in
the combo-box's menu.
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.
Temporarily disable multithreading for GimpOperationLayerMode, to
avoid the deadlock. The environment variable
GIMP_MULTITHREADED_COMPOSITING can be set to reenable it, for the
sake of debugging.