Commit graph

21879 commits

Author SHA1 Message Date
Jehan
7f05ec00cd app: reimplement gimp_widget_flush_expose().
gimp_widget_flush_expose() has been removed since commit 3089a20167.
I now reimplemented it by simply checking if event sources are waiting
to be processed.
This was heavily needed as the statusbar was not showing any progress
(at least on highly demanding process, such as saving or loading files),
and therefore we were stuck with a seamingly frozen GUI.

Despite the name, this does not apply to a widget in particular anymore,
but to the whole program events.
2019-02-19 15:31:50 +01: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
7c1429d1ff app: in gimp:mask-components, handle half-precision float formats 2019-02-16 13:09:41 -05:00
Ell
af2c7d1b33 app: in GimpDrawableFilter, don't mask-out alpha comonent for alpha-less drawables
In gimp_drawable_filter_sync_affect(), don't mask-out the filter's
alpha component when the drawable doesn't have an alpha channel,
since this is no longer necessary -- we now explicitly convert the
output to the drawable format as part of the graph -- and it
prevents the gimp:mask-components node from becoming a NOP.
2019-02-16 13:09:40 -05:00
Ell
1b900bfa16 app: set/clear component-mask alpha-bit of alpha-less drawables, to make mask uniform
In gimp_drawable_get_active_mask(), when the drawable doesn't have
an alpha channel, set or clear the mask's alpha bit, according to
the state of the other bits, so that it never gets in the way of a
fully set/clear mask.  The value of the alpha bit doesn't matter
when there's no alpha channel, however, having a uniform mask
allows us to skip component masking altogether.

Additionally, provide a default implementation for
GimpDrawable::get_active_mask() which returns a full mask, and
remove the equivalent implementation for GimpChannel.
2019-02-16 13:09:39 -05:00
Michael Natterer
90164c4951 app, plug-ins: move brush (gbr) saving to the core
just the export logic remains in the plug-in, just as for patterns.
2019-02-16 19:01:33 +01: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
ee156b8fd6 app: improve gimp:mask-components
Add specialized versions of gimp:mask-components for 8-, 16-, and
32-bpc formats, to improve efficiency, and to preserve the contents
of masked-out components exactly.

Provide public functions for format-selection and processing, which
we'll use in the painting code, instead of reimplementing component
masking.
2019-02-16 09:56:27 -05:00
Ell
a7f7a485bd app: convert gimp:mask-components to C++
... in preperation for next commit.
2019-02-16 09:47:29 -05:00
Jehan
248477a125 app: some small improvements in line art code.
Mostly I am adding a counter to the insignifiant zone fill, to be double
sure we are not going to fill huge areas (this should not happen already
anyway) and also it is no use to sample the line art buffer in such
case.
2019-02-16 12:35:10 +01:00
Ell
0d21f2469b app: in gimp_gegl_apply_cached_operation(), don't dup src buffer for point ops
In gimp_gegl_apply_cached_operation(), when the source and
destination buffers are the same, avoid duplicating the source
buffer when the applied operation is a point operation, since
applying it in chunks from/to the same buffer is not a problem in
this case.
2019-02-15 12:38:54 -05:00
Ell
918f2e75bd app: add gimp_gegl_node_is_point_operation()
... which takes a GeglNode, and determines if the associated
operation is a point operation.

Use in GimpFilterTool, instead of performing the same check
manually.
2019-02-15 12:38:53 -05:00
Ell
0cf77b0a3b app: #include <string.h> in gimpoperationreplace.c
... for memset().
2019-02-14 11:09:17 -05:00
Ell
27e8f452b3 app: change behavior of REPLACE mode for fully-transparent pixels
When the result of compositing has an alpha value of 0, the
corresponding color value is not mathematically defined.
Currently, all out layer modes opt to preserve the destination's
color value in this case.  However, REPLACE mode is different
enough to warrant a different behavior:

Unlike the other layer modes, when the compositing opacity
approaches 0 or 1, the output color value approaches the
destination or source color values, respectively, regardless of the
output alpha value.  When the opacity doesn't approach 0 or 1, the
output color value generally doesn't approach a limit as the output
alpha value approaches 0, however, when both the destination and
source alpha values are equal, the output color value is always a
simple linear interpolation between the destination and source
color values, according to the opacity.  In other words, this means
that it's reasonable to simply use the above linear interpolation
for the output color value, whenever the output alpha value is 0.

Since filters are commonly combined with the input using REPALCE
mode with full opacity, this has the effect that filters may now
modify the color values of fully-transparent pixels.  This is
generally desirable, IMO, especially for point filters.  Indeed,
painting with REPLACE mode (i.e., with tools that use
gimp_paint_core_replace()) behaved excatly as described above, and
had this property, before we switched gimp_paint_core_replace() to
use the common compositing code; this created a discrepancy between
painting and applying filters, which is now gone.

A side effect of this change is that we can now turn gimp:replace
into a NOP when the opacity is 100% and there's no mask, which
avoids the compositing step when applying filters.  We could
previously only apply this optimization to PASS_THROUGH mode, which
is a subclass of REPLACE mode.

Note that the discussion above concerns the UNION composite mode,
which is the only mode we currently use REPLACE in.  We modify the
rest of the composite modes to match the new behavior:
CLIP_TO_BACKDROP always preserves the color values of the
destionation, CLIP_TO_LAYER always preserves the color values of
the source, and INTERSECTION always produces fully-zeroed pixels.
2019-02-14 11:04:53 -05:00
Ell
d2f8413173 app: remove gimp_gegl_replace()
Remove gimp_gegl_replace(), which is not used anywhere since the
last commit.  It's redundant with the rest of our compositing code,
in particular, gimp:replace and gimp:mask-components.
2019-02-14 11:04:52 -05:00
Ell
2074accb60 app: remove gimp_drawable_replace_buffer()
Remove gimp_drawable_replace_buffer(), which is no longer used
anywhere since commits ddb69b77a7 and
3451ffb62c.  This eliminates
redundancy, since all compositing is now done through the layer-
mode code.

Furthermore, gimp_drawable_replace_buffer() used the drawable's
active-component array, whose layout depends on the image mode, as
an argument to gimp_gegl_replace(), which always expects an RGBA
component array, resulting in broken component masking in non-RGB
images.
2019-02-14 11:04:52 -05:00
Jehan
0636c302a3 app: gimp_edgel_region_area() may return < 0 for non-closed zones.
The algorithm to compute a zone area by following its border only works
well for fully closed zones. It may return negative values otherwise.
Let's just assume the created zone is big in this case (which may or may
not be the case, but this is the safe case as it does not prevent
closure creation).
2019-02-14 13:53:33 +01:00
Alexandre Prokoudine
616efae3b0 Remap Linear Invert's mnemonic to I to remove a duplicate with Levels 2019-02-14 01:18:09 +03:00
Jehan
636b77f7d3 app: fix a "Floating point exception" crash.
`icon_space_width` is set when GtkWidget::style-updated signal is
emitted. In some cases, it was possible that gimp_statusbar_set_text()
is run before this happens, in which case, a division by zero would
crash the software.

I encountered this case in some rare occasions when duplicating an image
with ctrl-d, then as Ctrl was hold, the message "Click in any image to
pick the foreground color" was pushed on the brand new statusbar as it
is created (hence a race condition occurs with the signal handler and
this message). This was therefore not reproducible every time, but easy
enough to reproduce with multiple tests.
2019-02-13 21:06:08 +01:00
Ell
72d4977574 app: in gimpbrushcore-loops, fix memory corruption in clear_edges()
s/width/height/

Fixes commit 9d19e804ed.
2019-02-13 12:33:31 -05:00
Jehan
9090de96f2 app: out-of-gamut for grayscale images too in GimpFgBgEditor.
I realized that the same issue as for indexed images could also apply to
grayscale. If your fg/bg colors are not gray, it should not be expected
for them to be paintable. So let's give the out-of-gamut hint.
2019-02-13 15:48:27 +01:00
Jehan
7b4c96d03d app: GimpFgBgEditor displays the out-of-gamut color for indexed images.
If a color is not within the indexed image's palette, we can consider it
to be out-of-gamut too (the gamut of such image being its palette).

This is a first step towards fixing #2938. Basically currently opening
indexed images is not made obvious and you can end up thinking GIMP is
broken as when you try to paint with a given FG or BG color, you may get
a completely different color on the canvas. And it is not obvious to
realize why. Now at least, the FG/BG color will tell you when the color
you are trying to paint with is not within the accepted palette.
2019-02-13 15:30:50 +01:00
Jehan
1cda00d426 app: allow GimpColorHistory widgets to be on 1 or 2 rows.
Current implementation was always making 2 rows. Yet sometimes the dock
can be made wide enough to accomodate all the color icons on 1 row,
hence saving vertical space, as well as not leaving this ugly space on
the side of the widget.
Now the widget will be able to compute an optimal size. Therefore if
there is enough space to align all color icons on a single row, this
will be organized this way. Otherwise, the widget will request more
vertical space to use 2 rows, hence allow a narrower dock as well.
Basically this will adapt to how you organize your docks, depending on
whatever screen size, pixel density, etc.
2019-02-13 14:44:14 +01:00
Jehan
41e27a8428 app: make GimpFgBgEditor a width-for-height widget.
This widget was not working well without setting a size request. In
particular, in the color editor, if we were not packing with expand and
fill to TRUE, then it ended up as an invisible widget (too small to be
seen). On the other hand, with expand/fill, it ended up taking as much
place as possible, and in particular expanding horizontally in an ugly
way.

First of all, I make it a width-for-height widget, so that it keeps by
default a pretty ratio (the width must be a bit bigger than the height).
Then I give it a default size request because this widget makes no sense
if it is too small (it packs quite a lot of elements with fg and bg
colors, swap and default colors icons).
Finally I can remove the expand/fill request in the GimpColorEditor. And
now the fg/bg widget appears with a nice ratio.

Note: this is GTK+3 only commit as the size request mode didn't exist
back in GTK+2.
2019-02-13 14:44:14 +01:00
Jehan
45adf9d0d7 app: pack color picker and hexadecimal entry on same line in Color dock.
There was no use to pack them on 2 lines. It was just making the FG/BG
widget overly huge, and the color picker button and hex entry very long.
This was just ugly. Also this dock is tall enough, so packing things
horizontally when it makes sense is better.
2019-02-13 14:44:14 +01:00
Michael Natterer
b29ecfb5da app, plug-ins: move pattern saving to the core
but only the actual saving code, not the export magic and dialog.

Add new internal procedure file-pat-save-internal which is not
registered as a file procedure and always works non-interactively on
the passed arguments and only saves the passed drawable. Use the new
internal procedure from the file-pat-save code and remove all file
writing code from the plug-in.

This way all pattern file writing code duplication is killed, while
the whole export mechanism is completely unchanged.
2019-02-12 21:27:13 +01:00
Michael Natterer
a95c169091 app: don't unref a NULL GimpTempBuf in gimp_pattern_copy() 2019-02-12 21:15:35 +01:00
Ell
68b22d45ed app: link tests against libappfile-data 2019-02-12 13:54:24 -05:00
Michael Natterer
1e6b26e83a app: implement brush saving in the core
and enable duplicating the clipboard brush, like for patterns.
2019-02-12 18:51:47 +01:00
Michael Natterer
831d04ec7e app: remove useless includes from gimppattern-save.c 2019-02-12 18:45:49 +01:00
Ell
4ecbf33e18 app: in gimppaintcore-loops, fix indentation in DispatchPaintMaskToCompMask 2019-02-12 09:36:50 -05:00
Ell
3451ffb62c app: in gimp_paint_core_replace(), improve applicator path
In the applicator path of gimp_paint_core_replace(), actually use
the paint-core's applicator, instead of using
gimp_drawable_replace_buffer().  This improves speed, consolidates
code, and fixes some cases in which the latter is broken.

Furthermore, when using CONSTANT paint application-mode, use the
paint-core's undo_buffer as the compositing source, rather than the
drawable buffer, which is the correct behavior.
2019-02-12 09:22:23 -05:00
Ell
ba6713bbe1 app: in gimp_paint_core_paste(), don't copy paint mask when combining to canvas buffer
In the applicator path of gimp_paint_core_paste(), use the paint
mask directly when combining it to the canvas buffer, rather than
using a copy of it, since it's not being modified.

Fix some comments.
2019-02-12 09:22:23 -05:00
Ell
ddb69b77a7 app: implement gimp_paint_core_replace() using gimp_paint_core_loops_process()
Implement the no-applicator path of gimp_paint_core_replace() in
terms of gimp_paint_core_loops_process(), using the algorithms
added in the previous commit, instead of using
gimp_drawable_replace_buffer().  This improves speed, consolidates
code, and fixes some cases in which the latter is broken.

Furthermore, when using CONSTANT paint application-mode, use the
paint-core's undo_buffer as the compositing source, rather than the
drawable buffer, which is the correct behavior.
2019-02-12 09:22:23 -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
Michael Natterer
e93fd73fac app: implement pattern saving in the core
Add GimpData::save() implementation to GimpPattern, and change some
glue code to make patterns editable.

Also implement GimpData::duplicate() in GimpPatternClipboard, which
makes it possible to simply copy an area and duplicate the clipboard
pattern to create a new persistent pattern.
2019-02-11 20:56:07 +01:00