It was accidentally made applicable to layers by commit
7d345071c7. Only the non-legacy
color-erase mode shoule be applicable to layers (since 2.8 didn't
allow it as a layer mode), while the legacy mode is only available
for painting, and in the fade dialog.
Pass through mode uses the same compositing logic as REPLACE mode,
however, it's a special case of REPLACE, where the layer is already
composited against the backdrop. This allows us to take a few
shortcuts that aren't generally applicable to REPLACE mode.
Add a dedicated op class for pass through mode, derived from the
REPLACE mode op, implementing these shortcuts.
this commit changes just those which make no difference to
functionality: property and object member defaults that get overridden
anyway, return values of g_return_val_if_fail(), some other stuff.
Commit 3635cf04ab moved the special
handling of bottom-layer compositing to GimpOperationLayerMode.
This required giving the op more control over the process()
function of its subclasses. As a temporary workaround, the commit
bypassed the subclasses entirely, using "gimp:layer-mode" for all
modes. This is the reckoning :)
Add a process() virtual function to GimpOperationLayerMode, which
its subclasses should override instead of
GeglOperationPointComposer3's process() functions. Reinstate the
subclasses (by returning the correct op in
gimp_layer_mode_get_oepration()), and have them override this
function.
Improve the way gimp_operation_layer_mode_process() dispatches to
the actual process function, to slightly lower its overhead and
fix some thread-safety issues.
Remove the "function" field of the layer-mode info array, and have
gimp_layer_mode_get_function() return the
GimpOperationLayerMode::process() function of the corresponding
op's class (caching the result, to keep it cheap.) This reduces
redundancy, allows us to make the ops' process() functions private,
and simplifies SSE dispatching (only used by NORMAL mode,
currently.)
Move the blend and composite functions of the non-specialized
layer modes to gimpoperationlayermode-{blend,composite}.[hc],
respectively, to improve code organization.
Move the SSE2 composite functions to a separate file, so that they
can be built as part of libapplayermodes_sse2, allowing
libapplayermodes to be built without SSE2 compiler flags. This
allows building GIMP with SSE acceleration enabled, while running
the resulting binary on a target with no SSE accelration.
Add a "blend_function" field to the layer-mode info array, and use
it to specify the blend function for the non-specialized modes.
This replaces the separate switch() statement that we used
previously.
Remove the "affected_region" field of the layer-mode info array.
We don't need it anymore, since we can go back to using
GimpOperationLayerMode's virtual get_affected_region() function.
Last but not least, a bunch of code cleanups and consistency
adjustments.
GimpFilter's is_last_node field only reflects the item's position
within the parent stack. When a layer is contained in a pass-
through group, it can be the last layer of the group, while not
being the last layer in the graph as a whole (paticularly, if
there are visible layers below the group). In fact, when we have
nested pass-through groups, whether or not a layer is the last
node depends on which group we're considering as the root (since
we exclude the backdrop from the group's projection, resulting in
different graphs for different groups).
Instead of rolling our own graph traversal, just move the relevant
logic to GimpOperationLayerMode, and let GEGL do the work for us.
At processing time, we can tell if we're the last node by checking
if we have any input.
For this to work, GimpOperationLayerMode's process() function needs
to have control over what's going on. Replace the derived op
classes, which override process(), with a call to the layer mode's
function (as per gimp_layer_mode_get_function()) in
GimpOperationLayerMode's process() function. (Well, actually, this
commit keeps the ops around, and just hacks around them in
gimp_layer_mode_get_operation(), because laziness :P)
Keep using the layer's is_last_node property to do the invalidation.
Takes a layer mode and a composite mode, and returns the region
included in the composition.
Use this function in GimpOperationLayerMode, instead of testing
for specific composite modes directly. Will also be used by
the next commit.
Indentation cleanup in gimp_layer_modes.h
... so that we can use it for other functions that involve
compositing regions (which we do in the next commit).
Rename gimp_operation_layer_mode_get_affect_mask() and
friends to _get_affected_region().
Commit 9d4084c82f skips conversion and
blending of (some) transparent source and destination pixels. When
`blend_out == blend_layer`, it banks on the fact that the alpha values
of `blend_out` would be the same as those of `blend_layer`, and hence
the same as those of `layer`; thing is, we only copy those values from
`layer` to `blend_layer` for the pixels that we *don't* skip, so this
assumption is just wrong :P This leaves us with bogus alpha values in
`blend_out` for the skipped pixels, when the above equality holds.
For composite modes that use the alpha values of `blend_op` (aka `comp`)
even for transparent input pixels (i.e., src-atop and src-in), this may
result in artifacts.
Fix this by simply initializing the alpha values of `blend_out` for
skipped pixels unconditionally.
... 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...
No need to do full back and forth RGB/HSV conversions.
Change the behavior such that fully desaturated values remain
desaturated, instead of saturating towards red.
Pixels whose source or destination alpha is zero are not blended, and
therefore do not need to be converted between the composite and blend
spaces (assuming a conversion is necessary to begin with.) When there
is a large enough segment of consecutive pixels that don't need
blending, split the conversion/blending process around it, so that
we don't convert too many unblended pixels unnecessarily.
For layers with lots of transparency, this can dramatically reduce
compositing time; for layers with no transparency, the added
overhead is rather negligible.
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.)
... possibly due to small win32 stack
Limit the number of samples processed in one go by gimp_composite_blend()
so that we don't overflow the stack when we alloca() buffers on it.
... 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.
These are more general, and more expensive, versions of the non-
subtractive compositing functions. They are used with modes that
specify the SUBTRACTIVE flag. This doesn't affect anything yet, but
the next commit ports color-erase mode to a blendfun.
Most modes only modify the *color* of overlapping dest/src regions,
however, erase and color-erase may also reduce their *alpha*, i.e.,
eliminate some of the overlapping content. Flag these modes with
the new SUBTRACTIVE flag, as they require more general compositing
code. The next commit adds the said code.
The mode group switching combo box is hard to discover, until we use the
default group instead of legacy group as default - it is better to make legacy
resemble the full old set to.
which returns an array of modes in the order they would appear in a
GimpLayerModeContext's UI (like tool options or the layers dialog),
without the separators.
Use it in context-commands.c and layers-commands.c instead of static
(and outdated) arrays for the actions that cycle through modes.