Commit Graph

38 Commits

Author SHA1 Message Date
Jehan 75e6f1062e app: fix "Luma Lighten/Darken only" layer modes.
This is a continuation of #5888 as I realized that most layer modes were
fixed with my commit b3fc24268a (and follow-up f40dc40cbc) but at least
2 were still crashing GIMP: "Luma Lighten/Darken only" modes.

There were 2 bugs here:

* The first bug was that when gimp_operation_layer_mode_real_process()
  ran, gimp_operation_layer_mode_prepare() had not been run yet.
  prepare() is called before the process() of GeglOperation, but it
  would seem the process() of GimpOperationLayerMode on the other end
  happens before GeglOperation's prepare() is run. I am absolutely
  unsure if this is expected or not and have a hard time figuring out
  all the details of the C/C++ cohabitation.
  As a solution, I am moving out the fish caching (the needed part
  inside gimp_operation_layer_mode_real_process()) in its own function
  so that I can easily call it separately before inspecting the fishes.

* The second issue was that some blend functions needed more than a
  GeglOperation alone. E.g. blend_function() for luma lighten
  gimp_operation_layer_mode_blend_luma_lighten_only() would call
  gegl_operation_get_source_space() which requires the node to exist.
  Similarly for the Luma darken only mode. So I keep both the node and
  operation around, and when finalizing, I free the node (which in turn
  frees the operation).

Ell > if you are reading our commits, I would really appreciate your
review (or fixes) of my code here! :)
2020-11-10 17:25:34 +01:00
Jehan f40dc40cbc app: fix autotools build.
My previous commit broke the autotools build. Apparently when using
g_object_unref(), some C++ symbol leaked into libapppaint.a archive
library, hence the main binaries (e.g. gimp-2.99) could not be linked
without adding -lstdc++ flag:

> /usr/bin/ld: paint/libapppaint.a(gimppaintcore-loops.o): undefined reference to symbol '__gxx_personality_v0@@CXXABI_1.3'
> /usr/bin/ld: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line

Not exactly sure why using this GLib function in particular caused this,
but let's just try another approach in order not to link the main binary
with C++ standard lib.
Instead let's manage all GeglOperation allocation in gimp-layer-modes.c
by adding a gimp_layer_modes_exit() function and some static array for
storing operation object of each layer mode.
2020-11-10 12:52:01 +01:00
Jehan b3fc24268a Issue #5888: GIMP 2.99.2 crash when using brush in multiply mode.
The GimpOperationLayerMode variable member in DoLayerBlend was not
properly constructed. C++ class constructor can be called by creating
object variables, but with GObject, we have to do it with pointers.
Otherwise here we were only allocating the memory for the struct, but
not actually calling any initialization functions.

Also it would seem that the struct was not initialized at zero, as the
space_fish variable was not NULL when it should (i.e. even with same
composite and blend space), hence composite_to_blend_fish was not NULL
and since the operation was not a valid GeglOperation when entering
gimp_operation_layer_mode_real_process(), we crashed.
Not sure how it went unseen for so long!

So instead let's make the layer_mode class member into a pointer. As
such, I have to properly allocate and free it. This is also why I am
adding a copy constructor which will ref the pointer (otherwise we unref
more than we ref as the default copy constructor would just copy the
pointer).
2020-11-10 01:11:01 +01:00
Ell 646c804c04 app: fix compositing of layers with masks, outside the mask bounds
In GimpOperationLayerMode, when the op has a mask connected, and
we're processing an area outside the mask bounds, set the op's
opacity to 0, so that the backdrop shows through.  The actual
process() function gets a NULL mask pointer in this case, and so
would composite the layer as if it had no mask, exposing areas that
should be masked out.

Add a GimpOperationLayerMode::parent_process() function, which
subclasses can override instead of GeglOperation::process(), and
make sure to update the GimpOperationLayerMode::opacity field
before calling this function (and, subsequently, before calling
GimpOperationLayerMode::process()).

Clean up the rest of the fields, and adjust the rest of the code.
2020-02-21 22:54:16 +02:00
Ell 9fe33702fb Issue #4354 - When using color to fade dynamics and gradient with transparency ...
... brush does not have transparency

In the PAINT_MASK_TO_COMP_MASK paintcore-loops algorithm, used when
painting incrementally, multiply the paint mask values by the paint
opacity.  Previously, the paint opacity was ignored, breaking
various dynamics affecting the opacity.
2020-01-09 22:36:41 +02:00
Ell a5962e4049 app: disregard composite space in non-union alpha-only layer modes
In gimp_layer_mode_get_format(), disregard the requested composite
space when selecting the format, if the input layer mode is alpha-
only, and the requested composite mode is not UNION, since, in this
case, the layer mode doesn't combine the layer/backdrop colors, and
rather only modifies the alpha of one of them.  This allows us to
use the preferred format, avoiding gamma conversion.

This particularly improves the performance of the Eraser tool in
perceptual images.
2019-05-24 01:43:20 -04:00
Ell f24bca5156 app: don't modify paint buffer when pasting to canvas
We now have enough machinery in gimppaintcore-loops to avoid
modifying the paint buffer in gimp_paint_core_paste() in the no-
applicator case, by using the same set of algorithms as
gimp_paint_core_replace().  Other than reducing the number of
different code paths we have, this is both more efficient, and
allows us to reuse the paint buffer across dabs, as done in the
following commits.

Implement gimp_paint_core_replace() in terms of
gimp_paint_core_paste().  We keep the two functions separate, since
their implementation is still differnet when using an applicator.

Suppress the paint-buffer-modifying algorithms in
gimppaintcore-loops, but keep them around; using the same logic for
normal painting as we use for REPLACE painting is possible due to
the fact that all our current non-REPLACE modes treat alpha values
and mask values interchangeably.  In the future we might have modes
that distinguish between alpha and mask values, requiring the old
algorithms.
2019-05-15 10:53:12 -04:00
Ell 03810861d2 app: in gimppaintcore-loops, improve CanvasBufferIterator algorithm helper-class
In gimppaintcore-loops, fix the CanvasBufferIterator algorithm
helper-class so that it may appear more than twice in the
hierarchy, and integrate it into the normal dispatch-dependency
system, instead of having dependent algorithms inherit it directly.
2019-03-02 16:24:48 -05:00
Ell 6fe57a946b app: in gimppaintcore-loops, unsuppress COMBINE_PAINT_MASK_TO_CANVAS_BUFFER algorithm
In gimppaintcore-loops, unsuppress the
COMBINE_PAINT_MASK_TO_CANVAS_BUFFER algorithm (partially
reverts commit b717ead1abd487f663668ac131883dff0ffe4557.)

In gimp_paint_core_paste() it's always used together with
CANVAS_BUFFER_TO_PAINT_BUF_ALPHA, which matches a combined
algorithm, preventing it from being called, however, it can still
be called through gimp_paint_core_replace(), which uses it
together with CANVAS_BUFFER_TO_COMP_MASK, which doesn't have a
combined algorithm.  We can, however, filter out
CANVAS_BUFFER_TO_PAINT_BUF_ALPHA whenver
COMBINE_PAINT_MASK_TO_CANVAS_BUFFER is matched (since the combined
algorithm will be matched beforehand when both algorithms are
included).
2019-02-16 14:19:09 -05:00
Ell e513e9e054 app: in gimppaintcore-loops, in MaskComponents::finalize_step(), chain up 2019-02-16 10:11:00 -05:00
Ell c7d8d9ba2e app: use MASK_COMPONENTS algorithm in gimp_paint_core_{paste,replace}()
Remove the mask_components_onto() gimppaintcore-loops function, and
the GimpPaintCore::comp_buffer member.  Instead, in
gimp_paint_core_paste() and gimp_paint_core_replace(), use the
MASK_COMPONENTS algorithm, added in the previous commit.
2019-02-16 09:56:30 -05:00
Ell 08fa46ea41 app: in gimppaintcore-loops, add MASK_COMPONENTS algorithm
In gimppaintcore-loops, add a new MASK_COMPONENTS algorithm, which
masks the output of compositing into the destination buffer,
according to a component mask.  The algorithm uses the same code as
gimp:mask-comopnents, and can be used as part of a
gimp_paint_core_loops_process() pipeline, instead of using a
separate function.
2019-02-16 09:56:30 -05:00
Ell 858f30a609 app: in gimppaintcore-loops, add [Temp]CompBuffer algorithm helper-classes
In gimppaintcore-loops, add a CompBuffer algorithm helper-class,
which provides access to the output buffer used for compositing,
to be used by the DO_LAYER_BLEND algorithm instead of the
destination buffer.

CompVuffer itself doesn't provide the storage for the buffer; this
is rather the responsibility of the algorithms that use it.  The
TempCompBuffer algorithm helper-class provides temporary storage
for the compositing buffer, and can be used by algorithms that need
a temporary buffer.
2019-02-16 09:56:30 -05:00
Ell b717ead1ab app: in gimppaintcore-loops, mark algorithms as mandatory/suppressed
In gimppaintcore-loops, use {Mandatory,Supressed}AlgorithmDispatch,
added in the previous commit, to mark certain algorithms as always
occuring, or never occuring, in all hierarchies.
2019-02-16 09:56:30 -05:00
Ell fc7ffc71a3 app: in gimppaintcore-loops, add {Mandatory,Suppressed}AlgorithmDispatch
In gimppaintcore-loops, add MandatoryAlgorithmDispatch and
SuppressedAlgorithmDispatch class templates, which implement
dispatch functions suitable for algorithms which are always part of
the hierarchy, or never part of the hierarchy, respectively.  Using
one of these classes as the dispatch function for a given algorithm
verifies that the algorithm is/isn't included in the requested-
algorithm set, but doesn't otherwise increase the number of
instanciated hierarchies, since only one of these cases has to be
handled.
2019-02-16 09:56:30 -05:00
Ell 95761db557 app: in gimppaintcore-loops, remove individual-algorithm functions
In gimppaintcore-loops, remove the individual-algorithm convenience
functions, which are merely wrappers around
gimp_paint_core_loops_process(), and aren't used anywhere anymore.
This allows us to avoid instanciating certain algorithm-hierarchies
which aren't used in practice, as will be done by the following
commits.
2019-02-16 09:56:30 -05:00
Ell 4ecbf33e18 app: in gimppaintcore-loops, fix indentation in DispatchPaintMaskToCompMask 2019-02-12 09:36:50 -05:00
Ell 183a55613e app: in gimppaintcore-loops, add {CANVAS_BUFFER,PAINT_MASK}_TO_COMP_MASK algorithms
In gimppaintcore-loops, add CANVAS_BUFFER_TO_COMP_MASK and
PAINT_MASK_TO_COMP_MASK paint algorithms, which copy the canvas
buffer and the paint mask, respectively, to the compositing mask.
When there is an image mask buffer, the algorithms additionally
combine the copied mask with the mask buffer.  When possible, the
algorithms use the canvas buffer/paint mask data directly as the
compositing mask data, instead of copying.

These algorithms are necessary in order to implement
gimp_paint_core_replace() in terms of
gimp_paint_core_loops_process(), which is done by the next commit.
2019-02-12 09:22:19 -05:00
Ell f9c072c328 app: in gimppaintcore-loops, make sure dest_buffer is the primary iterator buffer
In gimppaintcore-loops, in the DO_LAYER_BLEND paint algorithm, and
in the CanvasBufferIterator algorithm helper-class, initialize the
iterator *before* initializing the base class, to make sure that
dest_buffer, or canvas_buffer, respectively and in that order, is
the primary buffer of the iterator.  In particular, this avoids the
mask buffer being the primary buffer.  This is desirable, since
most of the buffers we iterate over are tile-aligned to the dest/
canvas buffers.
2019-02-12 08:25:39 -05:00
Ell 44281ce2c4 app: in gimppaintcore-loops, add MaskBufferIterator algorithm helper-class
In gimppaintcore-loops, add a MaskBufferIterator algorithm helper-
class, which provides read-only iterator access to the mask buffer,
if one is used.

Use the new class in DoLayerBlend, instead of manually managing the
mask-buffer iterator.
2019-02-12 08:25:39 -05:00
Ell e36847febb app: in gimppaintcore-loops, add [Temp]CompMask algorithm helper-classes
In gimppaintcore-loops, add a CompMask algorithm helper-class,
which provides access to the mask buffer used for compositing, to
be used by the DO_LAYER_BLEND algorithm instead of the image mask
buffer.

CompMask itself doesn't provide the storage for the mask; this is
rather the responsibility of the algorithms that use it.  The
TempCompMask algorithm helper-class provides temporary storage for
the compositing mask, and can be used by algorithms that need a
temporary mask.
2019-02-12 08:25:38 -05:00
Ell d23e239fed app: in gimppaintcore-loops, name algorithms more consistently
In gimppaintcore-loops, make the algorithm names, and the names of
the corresponding functions, more consistent.
2019-02-12 08:25:36 -05:00
Ell 2788444df4 app: in gimppaintcore-loops, allow specifying dependencies to BasicDispatch
... which are dispatched before the algorithm, as in
AlgorithmDispatch.
2019-02-12 08:17:51 -05:00
Ell 4d2ce15400 app: in gimppaintcore-loops, add finalize[_step]() algorithm functions
In gimppaintcore-loops, add finalize() and finalize_step()
algorithm functions, which get called at the end of processing the
entire area, and at the end of processing each chunk, respectively.
Algorithms can use these functions to clean up allocated resources.
2019-02-12 08:17:50 -05:00
Ell 0d1f724112 app: in gimppaintcore-loops, make CanvasBufferIterator self-contained
In gimppaintcore-loops, make the CanvasBufferIterator algorithm
helper-class self-contained, not having to rely on AlgorithmBase.
2019-02-12 08:17:50 -05:00
Ell 9d1d21e716 app: in gimppaintcore-loops, use dynamic iterator indices
In the various gimppaintcore-loops algorithms, assign each
algorithm's iterator indices dynamically, rather than statically,
so that algorithms have more freedom in the way they initialize the
iterator.
2019-02-12 08:17:49 -05:00
Ell 053e5edc93 libgimpcolor, app, modules, plug-ins: remove GEGL_ITERATOR2 define
... it's no longer needed, since GEGL commit
gegl@9dcd2cde63f95a080bf16a58c10e9ffbdd99aace.

Partially reverts commits:

6fca9959c7
cc10af72cc
49c53568d7
8edbc0d491
29f63616d2
3a2014984d
ee48ec6877
4165a315d5
764085278f
b7633c722e
6ab12061b7
754a3c5b18
22b4b647bd
55b3438328
c6d23add65
f03a84d607
822f9f0d2b
95358ca1fa
cdda37f4ee
41e8035635
6761da42b2
fb5d7832a8
97ed7817d8
46e9036578
ea9c5e6a49
24fbdfb591
beb4ecb238
4b77831e03
fcf113a39c
567ffe94ff
2018-12-02 11:15:37 -05:00
Ell 2736cee577 app: remove gimp_parallel_distribute(); use gegl_parallel_distribute()
The parallel_distribute() family of functions has been migrated to
GEGL.  Remove the gimp_parallel_distribute() functions from
gimp-parallel, and replace all uses of these functions with the
corresponding gegl_parallel_distrubte() functions.
2018-11-14 10:52:06 -05:00
Ell 6c6a7514a4 app: some cleanup in gimppaintcore-loops
In gimp_paint_core_loops_process(), initialize the iterator with
sufficient room for the number of iterators used by the algorithm
hierarchy, instead of a fixed number.

Add an additional 'rect' parameter to the init_step() and
process_rows() algorithm member functions, which receives the area
of the currently-processed chunk, to be used instead of the
iterator's ROI member.  This allows us to pass a NULL iterator to
hierarchies that don't use an iterator, and avoid the stack-
allocated iterator hack we used in this case (and which became even
more problematic with the new iterator API).
2018-09-11 04:05:00 -04:00
Øyvind Kolås fb5d7832a8 app: migrate paintcore loops to new iterator api 2018-09-11 01:35:22 +02:00
Michael Natterer e09e563a70 Initial space invasion commit in GIMP
All babl formats now have a space equivalent to a color profile,
determining the format's primaries and TRCs. This commit makes GIMP
aware of this.

libgimp:

- enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA
  as deprecated aliases, add PERCEPTUAL values so we now have LINEAR,
  NON_LINEAR and PERCPTUAL for each encoding, matching the babl
  encoding variants RGB, R'G'B' and R~G~B~.

- gimp_color_transform_can_gegl_copy() now returns TRUE if both
  profiles can return a babl space, increasing the amount of fast babl
  color conversions significantly.

- TODO: no solution yet for getting libgimp drawable proxy buffers in
  the right format with space.

plug-ins:

- follow the GimpPrecision change.

- TODO: everything else unchanged and partly broken or sub-optimal,
  like setting a new image's color profile too late.

app:

- add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as
  replacement for all "linear" booleans.

- change gimp-babl functions to take babl spaces and GimpTRCType
  parameters and support all sorts of new perceptual ~ formats.

- a lot of places changed in the early days of goat invasion didn't
  take advantage of gimp-babl utility functions and constructed
  formats manually. They all needed revisiting and many now use much
  simpler code calling gimp-babl API.

- change gimp_babl_format_get_color_profile() to really extract a
  newly allocated color profile from the format, and add
  gimp_babl_get_builtin_color_profile() which does the same as
  gimp_babl_format_get_color_profile() did before. Visited all callers
  to decide whether they are looking for the format's actual profile,
  or for one of the builtin profiles, simplifying code that only needs
  builtin profiles.

- drawables have a new get_space_api(), get_linear() is now get_trc().

- images now have a "layer space" and an API to get it,
  gimp_image_get_layer_format() returns formats in that space.

- an image's layer space is created from the image's color profile,
  change gimpimage-color-profile to deal with that correctly

- change many babl_format() calls to babl_format_with_space() and take
  the space from passed formats or drawables

- add function gimp_layer_fix_format_space() which replaces the
  layer's buffer with one that has the image's layer format, but
  doesn't change pixel values

- use gimp_layer_fix_format_space() to make sure layers loaded from
  XCF and created by plug-ins have the right space when added to the
  image, because it's impossible to always assign the right space upon
  layer creation

- "assign color profile" and "discard color profile" now require use
  of gimp_layer_fix_format_space() too because the profile is now
  embedded in all formats via the space.  Add
  gimp_image_assign_color_profile() which does all that and call it
  instead of a simple gimp_image_set_color_profile(), also from the
  PDB set-color-profile functions, which are essentially "assign" and
  "discard" calls.

- generally, make sure a new image's color profile is set before
  adding layers to it, gimp_image_set_color_profile() is more than
  before considered know-what-you-are-doing API.

- take special precaution in all places that call
  gimp_drawable_convert_type(), we now must pass a new_profile from
  all callers that convert layers within the same image (such as
  image_convert_type, image_convert_precision), because the layer's
  new space can't be determined from the image's layer format during
  the call.

- change all "linear" properties to "trc", in all config objects like
  for levels and curves, in the histogram, in the widgets. This results
  in some GUI that now has three choices instead of two.
  TODO: we might want to reduce that back to two later.

- keep "linear" boolean properties around as compat if needed for file
  pasring, but always convert the parsed parsed boolean to
  GimpTRCType.

- TODO: the image's "enable color management" switch is currently
  broken, will fix that in another commit.
2018-07-21 16:42:57 +02:00
Michael Natterer 5f700549e7 Change the license URL from http://www.gnu.org/licenses/ to https:// 2018-07-11 23:29:46 +02:00
Ell 8a881ca61a app: properly handle NULL rectangle arguments in gimp-gegl-loops
... and gimppaintcore-loops

When a rectangle argument is NULL, use the extents of the
corresponding buffer, instead of raising a CRITICAL, to match the
old behavior.
2018-06-21 08:11:16 -04:00
luz.paz 4a77ff2d3d Bug 795557 - Misc. typo fixes in source, comments and doxygen (pt3)
Found via `codespell` and grep.
2018-04-25 23:49:06 +02:00
Ell f2a1fd5bf0 app: refactor gimppaintcore-loops to coalesce iteration
The gimppaintcore-loops functions perform very little actual
computational work (in case of do_layer_blend(), at least for
simple blend modes), which makes the cost of buffer iteration, and
memory bandwidth, nonnegligible factors.  Since these functions are
usually called in succession, acessing the same region of the same
buffers, using the same foramts, coalescing them into a single
function, which performs all the necessary processing in a single
step, can improve performance when these functions are the
bottleneck.

Add a gimp_paint_core_loops_process() function, which does just
that: it takes a set of algorithms to run, and a set of parameters,
and performs all of them in one go.  The individual functions are
kept for convenience, but are merely wrappers around
gimp_paint_core_loops_process().

Be warned: the implementation uses unholy C++ from outer space, in
order to make this (sort of) managable.  See the comments for more
details.
2018-04-19 05:36:31 -04:00
Ell 082a6404c9 app: fix iterator area in canvas_buffer_to_paint_buf_alpha()
The entire ROI was processed in all threads, instead of only the
thread-specific area, causing artifacts.
2018-04-05 02:19:52 -04:00
Ell 3df757ffd7 app: parallelize gimppaintcore-loops.cc
Ditto.
2018-04-04 17:49:47 -04:00
Ell e8a14deecf app: switch gimppaintcore-loops.c to C++
Ditto.
2018-04-04 17:49:46 -04:00