Commit Graph

261 Commits

Author SHA1 Message Date
Jehan b86c927210 app: fixing painting with a selection. 2021-09-14 17:59:47 +02:00
Jehan d5670644b4 app: make painting with applicator working in multi-drawable mode. 2021-09-14 17:59:47 +02:00
Jehan 8934d43975 app: make painting possibly multi-drawable aware.
- Make the various virtual methods of GimpPaintCore use a list of
  drawables as argument instead of a single drawable.
- gimp_brush_core_eval_transform_dynamics() can work with an image as
  argument rather than a drawable as it doesn't actually depends on
  specific drawable data.
- New function gimp_paint_tool_enable_multi_paint() to be used in init()
  method of paint tools to announce that this tool can work with
  multiple layers selected.
- Use gimp_paint_tool_enable_multi_paint() in the GimpSourceTool base
  class only for now.

This is a first step for multi-layer drawing, but we don't want it to be
possible in just any random cases, which is why I add a special function
to advertize this capability. We will use it for special-casing the
clone (as well as heal and perspective tools most likely) tool to work
on several layers at once. At this step, it is still very bugged and not
really working properly. In particular, since we don't process the
drawable offset early anymore (because it makes no sense when we pass a
list of drawables with different offsets), I suspect that all the
offset-related code will be very broken.
2021-09-14 17:59:47 +02:00
Ell 2523808e4a app: add gimp_paint_core_{set_show_all,get_image_pickable}()
GimpPaintCore operates indipendently of a display, and hence needs
to be explictly told when operating in "show all" mode, affecting
the result of paint tools operating in "sample merged" mode.  Add
gimp_paint_core_set_show_all() for that purpose, and call it,
passing the current display's "show all" mode, in GimpPaintTool.
This controls which pickable (the image itself, or its projection)
is used as the sampling source, as per
GimpPaintCore::saved_proj_buffer, and as returned by the new
gimp_paint_core_get_image_pickable() function.
2019-09-06 20:10:30 +03:00
Ell fb679f9efa app: guarantee fully-COWed copies in more cases in paint code 2019-07-30 20:32:43 +03:00
Ell 2d80d4d138 app: use gimp_gegl_buffer_dup() everywhere
... instead of gegl_buffer_dup().
2019-07-30 20:32:41 +03:00
Ell ab94251ae9 app: remove gimp_gegl_rectangle_align_to_tile_grid()
... and replace it with gegl_rectangle_align_to_buffer().
2019-07-30 20:32:08 +03: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 bb7f61c919 app: use gimp_gegl_buffer_copy() in various places
... instead of gegl_buffer_copy().  The former parallelizes the
format conversion.
2019-03-06 05:59:57 -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 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 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 ab52dc6bca app: in GimpApplicator, allow enabling cache/preview after construction; remove preview cache
Remove the use_split_preview and use_result_cache parameters of
gimp_applicator_new(), and allow enabling/disabling the cache
(through gimp_applicator_set_cache()) and the preview crop (through
gimp_applicator_set_preview()) after construction.

Move the preview crop node after the result cache, and remove the
separate preview cache node.  This eliminates an extra cache
buffer, reducing the space consumed by filters, and speeds up split
preview, since the cached result now includes the output
compositing.
2018-12-29 14:28:42 -05:00
Ell 861f356b63 app: in GimpPaintCore, align copied undo rect to tile grid
In gimp_paint_core_finish(), when copying the relevant region of
the cached undo buffer into a new buffer, align the region to the
buffer's tile grid, so that all copied tiles are COWed.  This
avoids lag when finishing a stroke.
2018-12-02 03:10:29 -05: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
Ell 4fefab1798 app: fix line-angle constraint when xres != yres
Fix gimp_constrain_line() and friends to properly constrain line
angles when the image's horizontal and vertical resolutions are
different, and dot-for-dot is disabled.
2018-07-15 19:09:06 -04: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 08ff2ac8c8 app: use gimp_gegl_buffer_copy() all over the place
Replace all uses of gegl_buffer_copy() in app/ with
gimp_gegl_buffer_copy(), added in the previous commit.
2018-05-25 08:12:27 -04:00
Ell bc09c71818 Bug 795909 - Multiple images opened with floating selection ...
... closing one of them crashes GIMP

GimpSymmetry keeps a strong reference to the drawable passed to
gimp_symmetry_set_origin() until the next call to set_origin(), or
until it's destroyed.  This can unnecessarily extend the lifetime
of the drawable.  In particular, it can extend the lifetime of a
floating selection past the destruction of the image mask, during
image destruction, which results in a NULL mask pointer in
gimp_layer_invalidate_boundary(), called when detaching the
floating selection as part of its destructor.

Add gimp_symmetry_clear_origin(), which clears the origin set using
gimp_symmetry_set_origin(), dropping the reference to the drawable,
and call it in gimp_paint_core_paint() after painting.  This avoids
extending the lifetime of the drawable, and fixes the bug.
2018-05-08 10:22:46 -04: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
luz.paz 7fdb963e01 Bug 794996 - Misc. typo fixes in comments in app/
Found via `codespell -q 3 --skip="./po*"`
2018-04-08 21:25:56 +02:00
Ell 984ed6cefd app: constrain line angles in display space, not image space
Add an offset_angle parameter to gimp_constrain_line(), which
offsets the radial lines by a given angle.

Add gimpdisplayshell-utils.[ch], with two new functions:

  - gimp_display_shell_get_constrained_line_offset_angle():
    Returns the offset angle to be passed to
    gimp_constrain_line(), in order to constrain line angles in
    display space, according to the shell's rotation angle and
    flip mode.

  - gimp_display_shell_constrain_line():  A convenience function
    which calls gimp_constrain_line() with the said offset angle.

Use the new functions in all instances where we constrain line
angles, so that angles are constrained in display space, rather
than image space.

The only exception is GimpEditSelectionTool, which keeps
constraining angles in image space, since it's not entirely obvious
that we want to constrain angles of dragged layers/selections in
display space.
2017-12-22 06:32:24 -05:00
Michael Natterer b926de5ada Bug 783755 - Smudge should blend the smudged colors using linear RGB
Use GIMP_LAYER_MODE_NORMAL (not NORMAL_LEGACY) when falling back from
gimp_paint_core_replace() to gimp_paint_core_paste() for layers
without alpha. Adapt the format of the used paint buffers accordingly.
2017-08-12 21:35:47 +02:00
Michael Natterer 0cb3e75f79 app: use a lot of g_clear_object() and g_clear_pointer()
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);
2017-07-15 18:42:44 +02:00
Michael Natterer 3cf423f0cd *: rename NORMAL to NORMAL_LEGACY and NORMAL_LINEAR to NORMAL
and make NORMAL_LEGACY immutable.
2017-02-26 16:26:34 +01:00
Massimo Valentini 3d58a23342 Bug 764619: Color paint dynamic parameter and square artifacts when one or two channel are disabled 2017-02-21 23:47:01 +01:00
Michael Natterer 57360a0ddc Bug 778597 - Eraser paints transparent areas with BG color
Add a "paint_composite_mode" field to GimpLayerModeInfo and set the
mode of the eraser to SRC_ATOP. Defaulting to SRC_OVER for all
painting didn't quite do it for all modes.
2017-02-14 23:04:28 +01:00
Michael Natterer 8634b5cbc3 app: make layer blend color space and compositing color space configurable
...they say it's going to get worse before it gets better...
2017-02-12 23:49:26 +01:00
Michael Natterer e1e41b86d0 app: allow painting on transparent layers with modes != normal
by using GIMP_LAYER_COMPOSITE_SRC_OVER. Please test.
2017-02-05 23:08:16 +01:00
Michael Natterer 2950fecf07 app: move layer mode enums and gimp-layer-modes.[ch] to operations/
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().
2017-02-05 15:59:29 +01:00
Michael Natterer 2a96d598c3 app: add internal and PDB API and UI to control a layer's composite mode
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.
2017-02-02 00:38:25 +01:00
Michael Natterer 485094b9da app: fix painting with the new layer mode code
by creating temp buffers matching the format needed by the
GimpLayerMode's process_pixels() function.
2017-01-21 00:27:48 +01:00
Michael Natterer 1262370544 app: remove "gboolean linear" parameters
from gimp_applicator_new() and gimp_gegl_mode_node_set_mode().
Compositing doesn't depend on the layer format any longer, only on the
layer mode. Painting with "use applicator" unchecked is still broken
in some cases and needs more fixing.
2017-01-18 00:15:55 +01:00
Michael Natterer 66060e3307 app, libgimp*, plug-ins: replace enum GimpLayerModeEffects by GimpLayerMode
with proper value names. Mark most values as _BROKEN because they use
weird alpha compositing that has to die. Move GimpLayerModeEffects to
libgimpbase, deprecate it, and set it as compat enum for GimpLayerMode.
Add the GimpLayerModeEffects values as compat constants to script-fu
and pygimp.
2017-01-08 23:00:19 +01:00
Michael Natterer 265dfec525 app: split GimpApplicator's opacity and mode API into two functions
Added gimp_applicator_set_opacity() and remove the opacity argument
from set_mode().
2016-05-18 01:51:09 +02:00
Michael Natterer a0b18c7929 app: make GimpApplicator's preview feature optional
Don't add the preview nodes if use_preview_cache is FALSE in
gimp_applicator_new().
2016-02-16 21:36:35 +01:00
Michael Natterer 02f76b4c7b app: rename GimpImage.selected_symmetry to .active_symmetry
because that's the usual naming. Also change the set/get API accordingly.
2016-02-03 21:25:17 +01:00
Jehan 76f573c981 Bug 648776 - mirror symmetries.
You can now set any paint tool to mirror painting relatively
horizontal/vertical axis or a central point (any combination of these 3
symmetries).
This has been implemented as a new multi-stroke core, where every stroke
is actually handled as a multi-stroke (default of size 1).
This is also the first usage of custom guides for symmetry guiding.
Current version has to be activated in the playground.
2016-02-02 21:15:13 +01:00
Michael Natterer 4479cedf13 app: rename mask enum values GIMP_COMPONENT_RED,GREEN,BLUE etc.
to GIMP_COMPONENT_MASK_RED,GREEN,BLUE etc.
2015-09-07 00:35:02 +02:00
Øyvind Kolås 7e6320497e follow gegl api changes from commit af5361ca8d, with an abyss policy argument
to gegl_buffer_copy.
2015-05-25 01:27:31 +02:00
Michael Natterer db2ea536da app: add an optional gegl:cache at the output of GimpApplicator
Add "gboolean use_cache" to gimp_applicator_new(). Don't use a cache
anywhere but in GimpImageMap because it incrementally fills that cache
via the projection update. In gimp_drawable_merge_filter(), get that
cache and pass it to gimp_gegl_apply_cached_operation() which then
avoids doing the work twice for the already cached results. Win!
2014-06-18 18:50:53 +02:00
Michael Natterer 697572ccc0 app,libgimp*: fix includes to follow our include policy
- don't include <gdk-pixbuf/gdk-pixbuf.h> in headers in app/
- instead, include it in many .c files instead of <glib-object.h>,
  finally acknowledging the fact that app/ depends on gdk-pixbuf almost
  globally
- fix up includes as if libgimpbase depended in GIO, which it soon will
2013-10-15 01:58:39 +02:00
Michael Natterer 125cf2a2a3 app: use the image instead of the projection for accessing a pickable 2013-09-13 23:29:06 +02:00
Michael Natterer d1795ac204 Bug 700193 - undoing paint tools doesn't update last_coords properly
paint_core->start_coords is in fact the last stroke's endpoint and
only used for storing it in GimpPaintCoreUndo, so the last endpoint
can be resotred for straight-line painting after an undo. Make the
code actually doing that.
2013-07-15 00:41:43 +02:00
Michael Natterer 741792875e app: add the GimpApplicator back for painting, but make its use optional
Default to using the new code. This is out of pure curiosity how
GEGL changes affect painting with a purely graph-based method.
2013-05-21 18:55:03 +02:00
Daniel Sabo cd91144f9e Faster paintcore
Directly access the brush and paint buffers rather than using
GEGL iterators.

Replicate the relevant parts of GimpApplicator using direct
access.
2013-05-21 04:03:28 -07:00
Michael Natterer 9c93df2d4b app: add gimp_drawable_get_linear() which currently always returns FALSE
Add "linear" parameter to GimpApplicator. Pass the drawable's "linear"
to the applicator, and to all calls to gimp_gegl_mode_node_set_mode(),
instead of hardcoding FALSE everywhere.
2013-04-27 08:41:06 +02:00
Michael Natterer 69a321ac29 app: turn GimpApplicator into a general-purpose "input + aux -> output" thing
which means adding a lot of proper API. Input, output and aux can be
pads or buffers. Make sure it uses the minimum possible graph in all
cases and doesn't reconfigure nodes unless needed. Port GimpPaintCore
to the new API.
2013-04-14 22:44:21 +02:00