GimpTileHandlerProjectable is similar to GimpTileHandlerValidate,
except that it calls {begin,end}_render() on its associated
projectable before validating.
In pass-through mode, the group layer-stack's input is connected to
the backdrop. However, when rendering the group's projection, we
want to render the stack independently of the backdrop.
Unfortunately, we can't use the stack's graph as a subgraph of two
different graphs.
To work around that, the next few commits add a mechanism for a
projectable to be notified before and after its graph is being
rendered. We use this mechanism to disconnect the stack's graph
from the backdrop before rendering the projection, and reconnect
it afterwards. Yep, it's ugly, but it's better than having to
maintain n copies of (each node of) the graph (each nesting level
requires an extra copy.)
This commit adds {begin,end}_render() functions to GimpProjectable.
These functions should be called right before/after rendering the
projectable's graph.
When any of the children of a pass-through group excludes its
backdrop, the group itself should exclude the backdrop too. Override
get_excludes_backdrop() to follow this logic, and call
update_excludes_backdrop() when this condition might change.
Note that we always composite pass-through groups using src-over mode,
so to actually hide the backdrop, we need to disconnect it from the
group's mode node's input pad (and reconnect it, when the backdrop is
no longer hidden).
Override GimpDrawable::get_source_node() for GimpGroupLayer. Use
a node that contains both the drawable's buffer-source node, and the
layer stack's graph node. Choose which one of these to connect to
the source node's output based on the group's layer mode: the stack
graph for pass-through mode, and the buffer-source node for all the
rest.
When in pass-through mode, connect the source node's input (which
receives the backdrop) to the stack graph's input. Keep maintaining
the projection in pass-through mode. ATM, the projection uses the
same graph as the source node, so it's rendered against the group's
backdrop -- we don't want that. The next few commits fix it.
Update the group's drawable directly upon filter stack update in
pass-though mode, because the group's graph doesn't go through the
projection.
TODO: if any of the group's children (or a child of a nested pass-
through group, etc.) uses dst-atop/src-in, this needs special
attention.
Make sure the input of the layer's filter node is connected to its
source node (when it has an input pad), so that, once we implement
pass-though mode, the group's source node can see the backdrop.
For pass-through groups, we want to use the group's layer-stack
graph directly in its filter node, in place of the drawable's
buffer-source node. Add a get_source_node() vfunc to GimpDrawable,
which defaults to returning the buffer-source node, and use it in
gimp_drawable_get_source_node() instead of using the buffer-source
node directly. We'll later override this function for
GimpGroupLayer.
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.
Shift-click should actually toggle only within a given group. The new
capability of toggling only a sub-item, brought by commit 970e9ac is
still feasible in 2 steps: first toggling the parent (item group), then
the desired child.
It brings now a third possibility with exclusive toggle among many
children items, without touching other groups and top-level items.
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);
Rename gimp_tool_widget_snap_offsets() to set_snap_offsets(),
and add gimp_tool_widget_get_snap_offsets().
Also rename gimp_tool_widget_status() to set_status(), and
add new function and signal set_status_coords().
When toggling visibility of a child in an item group, we should also
toggle the visibility of other items in the same group, as well as
top-level items. Otherwise toggling exclusive visibility of any item in
a group is identical to toggling the parent's exclusive visibility,
which is simply absurd.
We still don't touch visibility of items in other groups.
The GimpLayer implementation of the GimpItem transform functions,
and the GimpDrawable convert_type() function, apply their operation
to both the layer and its mask. The subclasses of GimpLayer --
GimpGroupLayer and GimpTextLayer -- override some of these
functions, providing their own logic for the layer part, and
duplicating the mask part.
Avoid this duplication by adding a set of virtual transform and
type-conversion functions to GimpLayer. Have the GimpLayer
implementaion of the corresponding GimpItem and GimpDrawable
functions use these functions to apply the operation to the layer,
while taking care of the mask themselves. Have GimpLayer's
subclasses override the new virtual functions, instead of the
GimpItem and GimpDrawable ones.
Note that the existing implementation of convert_type() in
GimpTextLayer neglected to convert the mask, hence text layer masks
retained their old format after conversion. This issue is fixed as
a side effect of this commit.
The identity parameter checks added to the raster brush
transformation functions in the previous commit are unnecessary,
since we're already testing for the identity matrix. Remove them.
Check if the brush parameters match the identity parameters, and
return the original brush mask/pixmap if they do, in the actual
mask/pixmap transformation virtual functions, instead of in their
wrappers. While the identity parameters for raster brushes are
always scale=1, aspect-ratio=0, angle=0, and hardness=1, for
generated brushes they depend on the specific brush
parameterization.
... when clipping, if they have an alpha channel
Right now, this case is only reachable through PDB, but it will become
relevant for the flip tool soon.
by encoding them directly in the string attached to all filter
actions. The code now supports both "gegl:some-operation" and
"gegl:some-operation\n<serialized config>".
Add "default_settings" to GimpGeglProcedure to store the settings of
the invoking action, much like the "default_run_mode" member.
Change filters-commands.c to parse the new operation string, create
GimpGeglProcedures with the deserialized settings, and use those
settings when the procedures are ran.
Change the filter history to be smarter about what is already in the
history, there can now be several different procedures with the same
name.
Remove the dilate and erode actions from the drawable group, and add
them to filters, they are just special cases of value-propagate with
fixed settings.
Commit 1e6acbd4e1 modified the
generated enum recipes to run gimp-mkenums from the source
directory, instead of the build directory, so that only the
basenames of the corresponding header files would appear in
the comment at the top of the generated files. This was a
mistake -- $(GIMP_MKENUMS) is expecting to be invoked from the
build directory.
Switch back to running gimp-mkenums from the build directory. To
avoid including the relative path from the build directory to the
source directory in the generated file, add a @basename@ production
variable to gimp-mkenums, which exapnds to the basename of the
input file, and use it instead of @filename@ in the recipes for the
generated enum files.
When regenerating an enum file, don't copy it back to the source
directory if it hasn't actually changed. This allows using a read-
only source directory where the enum header is newer than the
generated file, as long as they're not really out of sync.
OTOH, *do* touch the generated source-dir file even when unchanged,
in order to avoid re-running its recipe on the next build, however,
allow this to silently fail (which is harmless).
"layers-text-tool" action shows as "Text Tool" while "vectors-path-tool"
shows as "Path Tool". That's very confusing with tools-text and
tools-vectors respectively.
These actions are mostly about entering in edit mode with the active
layer or path. For text layers, it will enter text edition on canvas,
whereas just open the attributes edition dialog on other layers. For
consistency, layers-text-edit is renamed as well too layers-edit-text.
This also fix the side effect of commits 10099bd and 526918b where I
didn't realize that layers-text-tool was also working on non text layers
on purpose (being very badly named). Now there is a separate layers-edit
and layers-edit-text.
Thanks to Pat David for English corrections. :-)
When a layer is removed from a layer stack, and its backdrop needs
invalidating, emit the UPDATE signals for the backdrop only after
the layer has been removed from the container.
A subclass of GimpDrawableStack, for layer stacks. Invalidates the
layers' backdrop as/when necessary, according to the value of their
excludes_backdrop property.
Make gimp_drawable_stack_update() protected, instead of private, so
that we can use it in GimpLayerStack.
A boolean flag, specifying whether the backdrop is clipped to the
layer. That's the case when the layer's composite mode is dst-atop
or src-in.
This is a read-only property, derived from the other attributes of
the layer. We compute its value through a virtual function, so that
GimpGroupLayer will eventually be able to specialize it for pass-
through groups.
The next commit uses this property to actually do something useful.
Add the additional enum values to enum GimpSelectCriterion, and
the few needed lines to gimppickable-contiguous-region.c.
It's horribly slow, but works.
We check them into git, so this makes it easier to keep them in
sync when using a separate build directory.
Case in point -- this commit also syncs a few enum files that went
out-of-sync with their headers.
and use them for the new image in "Paste as new image". We were using
the resolution and unit of the image the paste command was invoked
from, which is entirely random and useless.
Add a "mask-only" property to GimpBrushClipboard. When TRUE, only
create a brush mask (not a pixmap brush with mask and image).
Keep two clipboard brushes around: one classic "Clipboard Image" one
to be used as "stamp", and one new "Clipboard Mask" one that turns the
clipboard into a brush mask.
Fix brush shrinking used to compensate for the blur: avoid over-
shrinking the brush and changing its aspect ratio.
Change the way hardness maps to blur radius: hardness == 0 maps to
the largest radius such that, when the kernel is applied to the
middle pixel of the brush, the kernel is completely within the brush
bounds, taking brush shrinking into account, *assuming the brush is
a circle*.
Use the dimensions of the unrotated brush when calculating the blur
radius, so that rotation doesn't affect the blur amount (the blur
itself is not isotropic, though, and is applied after rotation, so
while the blur amount remains uniform, its effect does depend on the
brush angle.)
Get rid of the blur-radius upper limit -- it's fast enough to handle
large radii now.
A few additional minor speedups.
Also, make sure we don't overflow for large blur radii. Not a
problem yet, since the blur radius is capped, but soon...
Add a specialized convolution algorithm for the hardness blur. It
uses the same kernel as before, but performs the convolution in
(amortized) O(1)-per-pixel time, instead of O(n^2), where n is the
size of the kernel (or the blur radius).
Note that the new code performs the convolution in the input color
space, instead of always using a linear space. Since our brush
pixmaps (but the not masks) are currently perceptual, the result is
a bit different.
Both in the GimpImage API and in the GUI. The toggle in the save
dialog now controls ZLIB compression directly. Changed the various
info labels accordingly. Ditch the XCF parasite that saved the XCF
compat mode.
Enable 64 bit file offsets in XCF files, starting with newly added XCF
version 11.
We use at least version 11 if:
- we would use the previous version 10 (essentially skipping 10)
- the in-memory size of the image is larger than 4 Gig
It was agreed that we should write "plug-in" consistently. Only possibly
user-visible strings were updated.
Thanks to scootergrisen for a first patch which could not make it
after changing decision on the canonical writing.
Use gimp_item_translate() instead of gimp_item_set_offset() to set
a pasted item's position, so that the offsets of pasted layer group
children are updated correctly. Otherwise, only the group itself
moves, while its children remain positioned relative to the top-left
corner of the image.
... since that's the color space it actually works in.
Keep the legacy "Color (HSV)" mode's name as is, wrong as it is,
since, well, that's what it used to be called...
When adding an item to a filter stack that doesn't have a graph yet,
calling gimp_filter_stack_update_last_node() may ultimately lead to
the invocation of gimp_filter_stack_get_graph(), which would create
a new graph, and add the item's node to it; gimp_filter_stack_add()
would then erroneously attempt to re-add the node to the graph.
Fix this by calling gimp_filter_stack_update_last_node() after
(potentially) adding the node to the graph in
gimp_filter_stack_add().
Merge mode lays the source layer on top of the destination, same as
normal mode, however, it assumes the source and destination are two
parts of an original whole, and are therefore mutually exclusive.
This is useful for blending cut & pasted content without artifacts,
or for replacing erased content in general.
Calculates the dot product of the two input colors, and uses that
as the value for all the output color's components. Basically,
a per-pixel mono mixer.
Useful for custom desaturation, component extraction, and crazier
stuff (bump mapping!)
Include erase mode in the menu for layers and general paint tools.
This makes the eraser tool somewhat unnecessary, but allows for
interesting use cases (e.g., airbrush eraser, etc.)
... and get rid of the dedicated op. This gives us support for all
the blend/composite options for this mode.
Rename COLOR_ERASE to COLOR_ERASE_LEGACY, with perceptual blending/
compositing and immutable everything, and add a new COLOR_ERASE
mode, defaulting to linear blending/compositing, with mutable
everything. Modify affected code.
being exported to libgimp, and having a non-exported value, this is a
horrible mess like with GimpLayerMode, but at least the cruft value
names are deprecated now.
Need to convert both from the drawable's profile to the filter's input
format and from the filter's output format back to the drawable's
profile. This change fixes things for the case where the filter's
input and output formats are different.
In particular, this enables grids whose points of intersection
are at the middle of the image's pixels, which is useful for
undistorted painting with odd-sized brushes using tools other than
the pencil.
This commit also changes the grid visibility behavior, so that the
the visibiltiy of horizontal and vertical grid lines (depending on
the zoom level) is independent.
A bitmask, specifying in which contexts a layer mode is applicable.
Can be a combination of:
- LAYER: usable as a layer mode for actual layers.
- GROUP: usable as a layer mode for layer groups. Currently, all
modes that specify LAYER also specify GROUP, and vice versa,
but the planned pass-through mode will be GROUP only.
- PAINT: can be used as a paint mode.
- FADE: can be used for fading.
Add a 'context' field to _GimpLayerModeInfo, and provide context
masks to all the modes.
Use the context mask for validation when setting a layer's mode.
The next commit will use the mask when populating the layer mode
menus.
set all legacy modes to completely immutable and the LAB modes'
blend mode to immutable. Change GimpLayer setters and the UI
accordingly. Remove the LAB color spaces from the GUI, they can
only be used with the LAB blend modes anyway and not changed.
and to operations/layer-modes/, respectively.
Add gimp_layer_modes_init() which asserts on the correct order of the
GimpLayerModeInfo array, and switch to accessing the array directly in
gimp_layer_mode_info().
Similar to the Photoshop mode of the same name. Assigns
either 0 or 1 to each of the channels, depending on whether the
sum of source and destination channel values is less than, or
greater than (or equals to), one, respectively.
This is equivalent to inverting the source, and using it to perform
per-pixel, per-channel threshold against the destination, which is
useful for various effects.
Largely based on a patch by Ell, with the enum type renamed and
various small changes. Adds another axis of configurability to the
existing layer mode madness, and is WIP too.
These variations on darken only and lighten only have the advantage over the
componentvise versions that they always use the full triplet of either original
or new layer - meaning no new colors/hues will be introduced. This is similar
to how these modes operated/operates in picture publisher and photo-paint.