Commit graph

5987 commits

Author SHA1 Message Date
Ell
184762cd81 app: fix empty mask when duplicating a group layer
In gimp_group_layer_mask_changed(), avoid recalculating the group's
bounding box if it hasn't been calculated yet, since, not only is
this unnecessary in this case, but it causes the group's mask to
be erroneously clipped upon duplication, when set by
gimp_layer_duplicate() while the group is still empty.
2019-09-07 10:27:16 +03:00
Michael Natterer
b6b8e2c28d Revert the *enums.c part of the last commit
- it was changing generated files
- no dialog-specific mnemonics on generic enum labels
2019-09-06 01:39:36 +02:00
Sabri Ünal
2e766f67d4 Missing mnemonics on several dialogs
paste as brush, paste as pattern, select to new brush, select to new pattern
fill selection outline, fill path, stroke selection, distort, rounded rectangle
indexed color conversion, merge visible layers, new guide, new guide (by percent)
image properties, newsprint, fractal explorer, sample colorize, new layer

metadata editor (just a button), spyroplus (only common buttons)
2019-09-05 22:41:19 +03:00
Ell
17f8cff6f6 app: add "show all" support to the bucket-fill tool in "fill similar colors" mode
In the bucket-fill tool, allow using the tool outside the canvas
bounds with "sample merged" active in "fill similar colors" mode,
when the current display is in "show all" mode.  Additionally,
ignore "sample merged" in "fill whole selection" mode, on which it
has no effect.
2019-09-05 18:04:12 +03:00
Ell
99759a57e8 app: in gimp_pickable_contiguous_region_by_seed(), add support for arbitrary buffer extents 2019-09-05 18:04:11 +03:00
Ell
cf3638391d app: add support for color picking in "show all" mode
Add a show_all parameter to gimp_image_pick_color(), which, when
TRUE, allows picking colors outside the canvas bounds in sample-
merged mode.  Forward the display's "show all" mode through this
parameter where applicable (in particular, in the color-picker tool
and the pointer dockable).
2019-09-04 20:51:43 +03:00
Ell
02943e22f6 app: fix gimp_projection_get_pixel_at() for general bounding boxes 2019-09-04 20:51:43 +03:00
Ell
bce4d32d75 app: add GimpImageViewable class
Add a new GimpImageViewable class, which acts as a proxy viewable
for an image.  Unlike the image itself, whose preview is always
restricted to the size of the canvas, a GimpImageViewable provides
a show-all property, which controls whether the preview includes
the full image contents.  We're going to use GimpImageViewable as
the source viewable for GimpNavigationView.
2019-09-04 20:51:41 +03:00
Ell
a64dc8d618 app: defer GimpViewable::size-changed signal emission while frozen
In GimpViewable, defer emission of the size-changed signal while
the viewable's preview is frozen, and only emit the signal once
thawed.
2019-09-04 20:47:25 +03:00
Ell
697ab6a91a app: in GimpImage, ignore "show all" when image used as pickable
In GimpImage, make sure the image's pickable interface keeps
behaving as before (i.e., restricted to the canvas size), even when
the image is in "show all" mode.  In contrast, the image's
projection, when used as a pickable, *is* affected by "show all".
2019-09-04 19:16:42 +03:00
Ell
1f9d0d275c app: add gimp_image_invalidate_all()
... which invalidates the entire image.  This replaces all calls to
gimp_image_invalidate() with the full canvas size, since the image
content can now be larger than the canvas.
2019-09-04 19:16:42 +03:00
Ell
7f629a630c app: add "show all" mode to GimpImage
Add a "show all" mode to GimpImage, which, when active, causes the
image projection's bounding box to be adjusted dynamically to the
combined bounding box of all layers and the canvas.  This mode is
controlled through the new gimp_image_{inc,dec}_show_all()
functions, which should be called by the display; a corresponding
display toggle will be added in the following commits.

Note that from the user's perspective, "show all" is a display
mode, rather than an image mode.  The GimpImage "show all" mode is
therefore merely an implementation detail, and shouldn't have any
effect on displays that don't use "show all" mode, or the PDB.
The ability to use the image with or without taking its "show all"
mode into account will be facilitated by the next commits.
2019-09-04 19:16:41 +03:00
Ell
bcf2b937d9 app: notify GimpProjection::buffer when freeing the projection's buffer
... instead of only when subsequently reallocating it, so that
listeners can respond to the buffer being freed.
2019-09-04 19:16:41 +03:00
Ell
49bbf13911 app: in GimpProjection, avoid invalidating preview on flush while rendering
In GimpProjection, avoid erroneously invalidating the projectable's
preview when flushing the projection and there's nothing to be
flushed, if the chunk renderer is still running, and hence the
projection is not fully rendered yet.
2019-09-04 19:16:40 +03:00
Michael Natterer
7019eaa56b app, libgimp: share the code of libgimp/gimpparamspecs.c with app/
move the code to gimpparamspecs-body.c and include it from both app/
and libgimp/. They are the same apart from a minor difference which we

Also share the entire libgimp/gimpparamspecs.h header with the core.
2019-09-04 16:48:26 +02:00
Michael Natterer
b92dd2c8e3 app: split GimpDisplay in two classes: GimpDisplay and GimpDisplayImpl
GimpDisplay contains only the ID logic and the "gimp" and "config"
pointers, and lives in the core.

GimpDisplayImpl is a subclass and contains all the actual display
stuff. The subclass is only an implementation detail and doesn't
appear in any API.

Remove all hacks which pass displays as gpointer, GObject or
GimpObject through the core, or even lookup its type by name,
just use GimpDisplay.
2019-09-04 14:30:43 +02:00
Michael Natterer
392f00baf5 app, libgimp: get rid of all ID GTypes and ID param specs
Turn all ID param specs into object param specs (e.g. GimpParamImageID
becomes GimpParamImage) and convert between IDs and objects in
gimpgpparams.c directly above the the wire protocol, so all of app/,
libgimp/ and plug-ins/ can deal directly with objects down to the
lowest level and not care about IDs.

Use the actual object param specs for procedure arguments and return
values again instead of a plain g_param_spec_object() and bring back
the none_ok parameter.

This implies changing the PDB type checking functions to work on pure
integers instead of IDs (one can't check whether object creation is
possible if performing that check requires the object to already
exist).

For example gimp_foo_is_valid() becomes gimp_foo_id_is_valid() and is
not involved in automatic object creation magic at the protocol
level. Added wrappers which still say gimp_foo_is_valid() and take the
respective objects.

Adapted all code, and it all becomes nicer and less convoluted, even
the generated PDB wrappers in app/ and libgimp/.
2019-08-29 11:39:34 +02:00
Jehan
6391b2bcff Issue #3263: fix critical error on bucket fill tool.
Fixes the error:
> Critical error: gimp_line_art_thaw: assertion 'line_art->priv->frozen'

This may happen in cases when we didn't actually freeze the line art at
pointer click, because we were in an invalid case (for instance,
clicking out of selection), hence we must not thaw the line art either
at button release.
2019-08-27 12:41:49 +02:00
Michael Natterer
7201d48231 Get rid of capitalized "ID" in function and variable names
and use "id" instead.
2019-08-23 22:23:23 +02:00
Michael Natterer
d62e75a41f Move GimpParamSpecString from libgimp back to app
It's just too weird to be public. Remove its properties from the wire
protocol and from pluginrc. Instead, have all GParamSpecs' flags on
the wire and in pluginrc, so we can use stuff like
GIMP_PARAM_NO_VALIDATE.

Port the remaining few places to GIMP_PROC_ARG_STRING().

I'm sure something is broken now wrt UTF-8 validation,
will add tighter checks in the next commit.
2019-08-19 12:54:52 +02:00
Niels De Graef
284ba5c870 libgimpconfig: Prevent GIR conflicts in GimpConfigWriter
GimpConfigWriter contains several constructors with the convention
`gimp_config_writer_new_* ()`. This will lead to problems however with
languages like Vala, where it cannot disambiguate the following:

```
// calls config_writer_new_string()
Gimp.ConfigWriter w = new ConfigWriter.string("xxx");
// calls config_writer_string()
w.string("xxx")
```

Using `from_` in constructors is general practice in GObject-bsed
libraries because of this.

This also fixes an error when trying to use vapigen on the GIMP .GIR
file.
2019-08-16 10:04:39 +00:00
Michael Natterer
652fd75891 Rename GIMP_TYPE_INT8_ARRAY to GIMP_TYPE_UINT8_ARRAY
and GimpParamSpecInt8Array to GimpParamSpecUInt8Array
2019-08-15 15:04:34 +02:00
Michael Natterer
5a09523214 Remove GIMP_TYPE_INT32 and GimpParamSpecInt32
Use gint and GParamSpecInt instead.
2019-08-15 14:04:56 +02:00
luz.paz
7e99aa59f5 Add other misc. typo fixes 2019-08-13 11:50:51 -04:00
Ell
1577174739 app: update projection-buffer extent when projectable size changes
In GimpProjection, when the projectable's size changes, while its
offset remains the same, simply update the projection buffer's
extent, instead of allocating a new buffer and copying the contents
over.
2019-08-13 17:44:11 +03:00
Michael Natterer
dcb6a2c064 app: re-use the generated gimp_enums_init() code from libgimp
In gimp_init(), call gimp_enums_init(). We need to make all enum types
known to the type system by name because the PDB is now based on enum
type names.
2019-08-12 19:26:08 +02:00
Ell
c45f1b4148 app: add gimp_image_transform()
Add a new gimp_image_transform() function, which transforms the
entire image, including all layers, channels (including selection
mask), vectors, guides, and sample points, according to a
transformation matrix.  The canvas is resized according to the
clip_result parameter, the same way drawables are resized during
transformation; the layers are resized using ADJUST mode
regardless.
2019-08-11 00:28:09 +03:00
Ell
ae080f06f9 app: add gimp_image_flip_full()
... which takes the symmetry axis as a parameter, instead of hard-
coding the axis to the middle of the image, and which additionally
takes the clipping mode as a parameter, controlling whether to clip
or resize the canvas.  Note that the actual canvas size never
changes, but it may be offset when flipped around an off-center
axis, without clipping.

Implement gimp_image_flip() in terms of gimp_image_flip_full().
2019-08-11 00:28:08 +03:00
Ell
d13c6ce3e0 app: fix sample-point OOB check in gimp_image_resize[_with_layers]() 2019-08-11 00:28:08 +03:00
Niels De Graef
d3e9e5617d app/core: Use G_DECLARE_INTERFACE()
This cuts aways a little of the GObject boilerplate.
2019-08-09 19:48:21 +00:00
Ell
33a389cd0c app, pdb: use gimp_item_get_clip() everywhere
Remove the special clipping-mode handling for channels throughout
the transform (and drawable-filter) code, and rather use
gimp_item_get_clip(), added in the previous commit, instead.  As
mentioned in the previous commit, we only modify the clipping mode
in top-level code, while having lower-level code use the clipping
mode as-is.  This not only hides the actual clipping-mode logic
from the transform code, but, in particular, allows code performing
transformation internally to use arbitrary clipping modes.

Also, this commit fixes a bunch of PDB bugs all over the place :)
2019-08-09 22:23:17 +03:00
Ell
d5cdcc6c02 app: add gimp_item_get_clip()
Add a new GimpItem::get_clip() virtual function, and a
corresponding gimp_item_get_clip() function, which return the
actual clipping mode to be used when transforming (or applying a
filter to) a given item, given the original clipping mode.  This
applies only to whole-item transformations (i.e., when not creating
a floating selection), and should be used by the top-level code
applying the transformation, rather than by the actual
transformation code, so that the item can be transformed using a
different clipping mode internally.

Provide a default implementation that simply returns the input
clipping mode, and override for GimpChannel (to always return CLIP)
and for GimpVecotrs (to always return ADJUST).
2019-08-09 22:22:50 +03:00
Ell
f9fb3e6fad app: fix layer-mask offset when applying filter to layer without clipping 2019-08-09 22:22:50 +03:00
Michael Natterer
d3d621b502 libgimpconfig: add a GimpScanner typedef and make it a boxed type
Replace _destroy() by _ref() and _unref().
2019-08-09 12:42:52 +02:00
Niels De Graef
39e4aa3c57 app/core: Use NULL for "simple" signals
Apart from being less code, this actually gives us a nice performance
improvement. Up until a few years ago, if you pass `NULL` as the
marshaller for a signal, GLib would fall back to
`g_cclosure_marshal_generic` which uses libffi to pack/unpack its
arguments. One could avoid this by specifying a more specific
marshaller which would then be used to immediately pack and unpack into
GValues with the correct type.

Lately however, as a way of optimizing signal emission (which can be
quite expensive), GLib added a possibility to set a va_marshaller, which
skips the unnecessary GValue packing and unpacking and just uses a
valist variant.

Since the performance difference is big enough, if the marshaller
argument is NULL, `g_signal_new()` will now check for the simple
marshallers (return type NONE and a single argument) and set both the
generic and the valist marshaller. In other words, less code for us with
bigger optimizations.

In case you also want va_marshallers for more complex signals, you can
use `g_signal_set_va_marshaller()`.
2019-08-07 16:33:10 +00:00
Ell
07b7d63a7d app: limit color-history palette size
Limit the color-history palette size (currently, to 256 colors), to
avoid slowdowns, especially during loading.
2019-08-07 19:20:52 +03:00
Ell
e60829767e Issue #3718 - Large colorrc file causes lag when painting with a new color
In gimp_palette_mru_add(), if the added color doesn't match an
existing color, don't look for two duplicate existing colors (which
has quadratic complexity), since there shouldn't be any under
normal circumstances (as we're not adding duplicates to begin
with).
2019-08-07 19:20:52 +03:00
Michael Natterer
0f8747f10a app: avoid GIMP_TYPE_INT32 with gimp_pdb_execute_procedure_by_name()
Instead, use the actual enum type, G_TYPE_BOOLEAN, and G_TYPE_INT for
plain integers.
2019-08-04 14:10:42 +02:00
Niels De Graef
529aa743dd Start using g_object_notify_by_pspec()
`g_object_notify()` actually takes a global lock to look up the property
by its name, which means there is a performance hit (albeit tiny) every
time this function is called. For this reason, always try to use
`g_object_notify_by_pspec()` instead.
2019-08-03 15:57:10 +00:00
Niels De Graef
5f92ced1f3 Add (nullable) if applicable
Basically this commit makes sure that all return values that are marked
as "Returns:" also have a `(nullable)` annotation if it is mentioned on
the same line that NULL can also be returned.

This will prevent a few problems in GObject-introspection.
2019-08-03 07:53:47 +00:00
Niels De Graef
1dda60154c Use "Returns:" to annotate return values
To be able to annotate return values through GObject-introspection, you
need to make sure it is tagged with `Returns:` and not something else.
2019-08-03 07:53:47 +00:00
Niels De Graef
746a72b956 Make sure to use % for constants
Documentation-wise in C, this doesn't matter a lot, but it allows
GObject-Introspection based bindings to use their built-in versions when
they want to render any kind of documentation (for example, docs for
Python plugins can render `%NULL` as `None`).
2019-08-03 07:53:47 +00:00
Ell
b7f53262fc app: add gimp_drawable_filter_set_clip()
In GimpDrawableFilter, add a new gimp_drawable_filter_set_clip()
function, which controls whether the filter clips the result to the
drawable's boundary, or extends it past it.  The latter is only
possible for layers, when the selection mask is empty.
2019-08-02 00:40:01 +03:00
Ell
89a9cf7e49 app: add "clip" parameter to gimp_drawable_merge_filter()
Add a new "clip" parameter to gimp_drawable_merge_filter().  When
set to FALSE, the function resizes the drawable to the bounding box
of the filter's output, instead of clipping the output to the
drawable's boundary.
2019-08-02 00:40:01 +03:00
Ell
ad1f3d20fb app: calculate bounding box of group layers
In GimpGroupLayer, when recalculating the group's size as a result
of a change to one of the child layers (now including in response
to a child layer's GimpDrawable::bounding-box-changed signal),
calculate the group's bounding box (the bounding box of all its
child layers' bounding boxes) alongside its logical bounds.  Like
in GimpLayer, use the logical bounds as the bounding box if the
group has a mask.

This bounding box is passed to the group's projection, via
GimpGroupLayer's GimpProjectable::get_bounding_box()
implementation, resulting in a buffer whose extent is the same as
the bounding box.
2019-08-02 00:40:01 +03:00
Ell
8ff43942d6 app: add support for projectables with an arbitrary bounding box
In GimpProjectable, replace gimp_projectable_get_size(), which only
returned a width and a height, with
gimp_projectable_get_bounding_box(), which returns a full
rectangle.  This allows projectables to have an arbitrary bounding
box, not limited to a (0, 0) top-left corner.

Adapt GimpProjection, creating a buffer with corresponding extent
to the projectable's bounding box.

Adapt GimpImage and GimpGroupLayer.
2019-08-02 00:40:01 +03:00
Ell
7a05d15f7e app: implement GimpDrawable::get_bounding_box() for GimpLayer
Implement GimpDrawable::get_bounding_box() for GimpLayer, by
returning the bounding box of its source node.  If the layer has a
mask, we simply return its logical boundary, since the layer can't
extend past the mask.
2019-08-02 00:40:01 +03:00
Ell
153cb33eec app: maintain drawable bounding box separately from its logical boundary
Maintain the bounding box of drawables (i.e., the bounds of their
actual rendered content) separately from their logical boundary (as
shown in the UI).

The bounding box is calculated through the new
GimpDrawable::get_bounding_box() virtual function, which has a
corresponding gimp_drawable_get_bounding_box() function; the
default implementation simply returns the drawable's logical
boundary.  The bounding box is specified in drawable coordinates,
i.e., it's not affected by the drawable's offset.

The bounding box is recalculated through
gimp_drawable_update_bounding_box(), which should be called
whenever a change may affect the bounding box (for example, when
setting a new buffer, as done implicitly by GimpDrawable's
::set_buffer() implementation, or when a drawable filter's
properties change, as will be done by GimpDrawableFilter in a
following commit).  When the bounding box changes, the affected
regions of the drawable are updated, and the
GimpDrawable::bounding-box-changed signal is emitted.

When gimp_drawable_update() is called with negative width/height
values, the entire drawable's bounding box is updated, rather than
only its logical boundary.

Likewise, GimpDrawableStack and GimpLayerStack are adapted to use
the bounding box, instead of the logical bounds, when updating the
drawable's area.
2019-08-02 00:40:01 +03:00
Ell
3afdd7c5c2 app: in GimpDrawable::set_buffer(), take bounds rect instead of offset only
In GimpDrawable::set_buffer(), and the corresponding
gimp_drawable_set_buffer_full() function, take a bounds rectangle,
which specifies both the drawable's new offset and its new size,
instead of only taking the new offset.  In
gimp_drawable_real_set_buffer(), set the item size according to the
rect dimensions, instead of the buffer dimensions.  The rect's
width/height may be 0, in which case the buffer's dimensions are
used.

Adapt the rest of the code.

We do this in preparation for maintaining the drawable's bounding
box separately from its logical bounds, allowing the drawable
content to extend beyond its bounds.
2019-08-02 00:40:01 +03:00
Michael Natterer
63695b4b21 libgimbase: merge gimpparam.h into gimpparamspecs.h
which means that it's now included normally via gimpbase.h
and not any longer via gimpbasetypes.h which we only did out
of lazyness. A *lot* of files in libgimp* and app/ now need to
2019-07-31 10:16:21 +02:00
Ell
2331b88d7d app: fix #include in gimpdrawable.c
Local foo leak.
2019-07-30 21:36:38 +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
Michael Natterer
c0fb66254e Use g_ascii_dtostr() instead of g_ascii_formatd()
The latter is broken and doesn't guarantee a decimal point with the
current bug. Also, g_ascii_dtostr() doesn't need the format parameter
and produces nicer output.
2019-07-30 15:57:36 +02:00
Michael Natterer
32ea28b6b1 app, libgimp, libgimpbase: plug-in and PDB protocol refactoring part two
- Change the wire protocol's GPProcInstall to transmit the entire
  information needed for constructing all GParamSpecs we use, don't
  use GimpPDBArgType in GPProcInstall but an enum private to the wire
  protocol plus the GParamSpec's GType name. Bump the wire protocol
  version.

- Add gimpgpparamspecs.[ch] in both app/plug-in/ and libgimp/ which
  take care of converting between GPParamDef and GParamSpec. They
  share code as far as possible.

- Change pluginrc writing and parsing to re-use GPParamDef and the
  utility functions from gimpgpparamspecs.

- Remove gimp_pdb_compat_param_spec() from app/pdb/gimp-pdb-compat.[ch],
  the entire core uses proper GParamSpecs from the wire protocol now,
  the whole file will follow down the drain once we use a GValue
  representation on the wire too.

- In gimp_plug_in_handle_proc_install(), change the "run-mode"
  parameter to a GParamSpecEnum(GIMP_TYPE_RUN_MODE) (if it is not
  already an enum). and change all places in app/ to treat it as an
  enum value.

- plug-ins: fix cml-explorer to register correctly, a typo in
  "run-mode" was never noticed until now.

- Add gimpgpcompat.[ch] in libgimp to deal with all the transforms
  between old-style wire communication and using GParamSpec and
  GValue, it contains some functions that are subject to change or
  even removal in the next steps.

- Change the libgimp GimpProcedure and GimpPlugIn in many ways to be
  able to actually install procedures the new way.

- plug-ins: change goat-exercise to completely use the new GimpPlugIn
  and GimpProcedure API, look here to see how plug-ins will look in
  the future, of course subject to change until this is finished.

- Next: changing GPParam to transmit all information about a GValue.
2019-07-28 17:34:40 +02:00
Michael Natterer
76ee0f6559 app, libgimpbase: move lots of GValue and GParamSpec types to libgimpbase
all the stuff from app/core/gimpparamspecs.[ch] that is not about
image, drawable etc IDs, these will have to go to libgimp with
different implementations than in app/.
2019-07-26 15:54:33 +02:00
Michael Natterer
5c7134f3a5 app, pdb: rename GIMP_TYPE_COLOR_ARRAY to GIMP_TYPE_RGB_ARRAY
and rename its GParamSpec too. Also, always say "foo_array" not
"fooarray".
2019-07-26 12:58:19 +02:00
Michael Natterer
6cb8a59501 app: fix gimp_value_set_drawable(), set_channel()
to work like gimp_value_set_item() and properly deal with all sorts of
drawables and channels.
2019-07-26 12:14:25 +02:00
Ell
ebb3ec4925 app: reduce time complexity of layer-group translation
When translating a layer group, avoid separately updating the
original area of the child layers before translating them (as per
the fix to issue #3484), as this results in quadratic time
complexity w.r.t. to the maximal subgroup nesting level.  Instead,
simply defer the updating of the group's offset until *after*
translating the child layers, so that their original area isn't
clipped by the parent, while their new area is still properly
updated even if the parent's size changes (see comment in code).
2019-07-23 10:55:54 +03:00
Jehan
5d2dbfe2e8 app: gdk_threads_(enter|leave)() deprecated since GDK 3.6.
There are no replacements. Just we must make sure that all GTK+/GDK
calls are run from the main thread, which is already what we were doing.

Actually I don't even think these were doing anything as we were not
calling gdk_threads_init() so the default lock functions were not set
anyway. These were just bogus calls.
2019-07-22 11:25:24 +02:00
Jehan
03f645cd2d Issue #3070: CRITICAL when converting to Indexed image.
Revert the previous commit 786686a541 and comes up with a better fix.

Let's actually change the image base type and add its colormap as close
as possible without any GUI calls in-between. I also add an explicative
comment so that people are aware of this call proximity requirement to
avoid future problems when the code gets remixed.

It should be better than hacking around with exception in GUI code, and
should (hopefully) avoid other similar bugs.
2019-07-17 13:11:57 +02:00
Jehan
a49a79e244 Issue #3641: gimp-drawable-offset does no longer work in script-fu...
... when one of the offsets is zero.

Found by Ell.
2019-07-11 11:59:02 +02:00
Jehan
a6ad02a60a Issue #2685: Crash when distributing layers horizontally.
Make the returned values of g_list_length() a gint to avoid implicit
type conversion converting a possibly negative integer numberator into
unsigned int (which ends as a huge unsigned int instead of being
negative).

Found by Massimo!
2019-07-10 17:15:12 +02:00
Michael Natterer
3b6b3fc189 app: GtkAction -> GAction madness part two
Change all action callbacks so they can be invoked by a GAction:

- add GimpActionCallback typedef:
  void (* cb) (GimpAction*, GVariant*, gpointer)
- change all action callbacks to the GimpActionCallback signature
- add "gimp-activate" and "gimp-change-state" signals to GimpAction,
  with the same signature as the resp. GAction signals
- remove all other custom action signals and only use the new
  GimpAction signals
- pass around appropriate GVariants containing booleans, int32,
  strings
- badly hack around to force a GimpProcedure pointer into a
  uint64 variant
- remove all G_CALLBACK() casts from all action callbacks,
  they all have the same signature now
2019-07-04 01:11:48 +02:00
Michael Natterer
e72a9d88a5 app: get rid of manual object type registration
and all deprecated use of private instance registration.
2019-06-29 16:41:41 +02:00
Michael Natterer
4c58386ead app: allocate GimpCurve's points with g_new0() and not just g_new()
so gimp_curve_equal() doesn't fail on random uninitialized padding
bits. Fixes finding previously used settings in the curves tool (they
were piling up just by re-applying a previously used setting).
2019-06-26 16:24:29 +02:00
Michael Natterer
d67f4604aa Issue #3500 - Preferences option to convert to Preferred RGB profile...
...doesn't work

Rename the labels to "built-in sRGB color profile" and "built-in
grayscale color profile" because that's what the option does, it never
converted to the preferred profiles from preferences.
2019-06-21 12:49:42 +02:00
Michael Natterer
c4ee350f02 Issue #3532 - Wrong color profile on nikon taken photos, it's...
...always AdobeRGB!

Enable the code in gimp_image_metadata_update_colorspace() which syncs
the DCF information to the image's actual color profile, at least as
good as it can, and otherwise sets it to "unspecified".

Also fixes issue #301.
2019-06-21 10:02:58 +02:00
Michael Natterer
b9829eddfe app: consolidate all metadata syncing code into gimpimage-metadata.c
Add gimp_image_metadata_update_pixel_size(), _bits_per_sample(),
_resolution() and use them from gimp_image_set_metadata() and from
various places in gimpimage.c which had identical copies of the same
code.

Also add gimp_image_metadata_update_colorspace() which syncs the color
space stored in the image's metadata with the color space of the
image's actual color profile. Call the function from the right places.

The body of gimp_image_metadata_update_colorspace() is currently
disabled because the syncing of color space information is
controversial, see issue ##3532 and issue #301.
2019-06-20 16:13:19 +02:00
Michael Natterer
5160f51676 app: some files were missing from the previous commit 2019-06-16 17:06:08 +02:00
Michael Natterer
aace6b179b Issue #3512 - feather selection doesn't work at edges of images
Add a "gboolean edge_lock" parameter to GimpChannel::feather() and a
"Selected areas continue outside the image" toggle to the "Feather
Selection" dialog, just like they exist for shrink selection and
border selection. At the end, convert the boolean to the right abyss
policy for gegl:gaussian-blur.
2019-06-16 16:51:30 +02:00
Ell
4a20a75dc3 Issue #3484 - While moving a nested layer group, some area isn't updated
In gimp_group_layer_translate(), when translating a nested group
layer, call gimp_drawable_update_all() to update the child-layers'
original area *before* updating the group's offset, at which point
the group parent's size is updated, causing subsequent area-updates
during translation to be clipped to the parent's new bounds,
preventing the original areas from being properly cleared.
2019-06-10 03:55:38 -04:00
Ell
3e5cbb03d9 app: add gimp_drawable_update_all()
Add a new GimpDrawable::update_all() virtual function, and a
corresponding gimp_drawable_update_all() function, which updates
the full contents of the drawable.  Unlike calling
`gimp_drawable_update (drawable, 0, 0, -1, -1)`, which updates the
entire drawable area, gimp_drawable_update_all() only updates the
area that has actual content.  While the default implentation does
simply update the entire drawable area, GimpGroupLayer overrides
this function to recursively update its child layers, rather than
the its entire area.
2019-06-10 03:55:37 -04:00
Ell
30429e30e2 app: various fixes/cleanups to last commits 2019-06-06 03:08:38 -04:00
Ell
5b2f3980bd app: implement gimp_drawable_offset() in terms of gimp:offset
Implement gimp_drawable_offset() in terms of gimp:offset, added in
the previous commit.  Other than avoiding duplication, this also
allows gimp_drawable_offset() to respect the current selection and
component mask (see issue #39.)
2019-06-05 19:06:55 -04:00
Michael Natterer
8d1c36d9ce app: remove redundant assignment in gimptoolpreset.c 2019-06-02 15:04:38 +02:00
Ell
d928a80b7f app: avoid unnecessarily updating drawable after merging filter
In gimp_drawable_merge_filter(), add an "update" parameter, which
specifies whether to update the affected region of the drawable
after applying the filter.  Avoid updating the drawable when
commiting a GimpDrawableFilter (and manually update the drawable if
filter application was cancelled), and when anchoring a floating
selection, since in both cases the relevant region of the drawable
has already been updated.
2019-06-01 13:29:00 -04:00
Ell
6425bf820a app: add "alpha" propertry to gimp:mask-components
In gimp:mask-components, add an "alpha" property, which controls
the masked-in alpha value in case there's no aux buffer.  Set it to
0 by default, so that gimp:mask-components behaves normally in the
absence of an aux buffer (as if the aux buffer was empty).  Set it
to 1 in the image's visible-mask node, to maintain the current
alpha-component visibility behavior.

This fixes incorrect results when the output bounding box of a
drawable filter is smaller than the drawable, which can lead to a
NULL aux buffer being fed to the filter's gimp:mask-components
node.
2019-05-31 13:11:14 -04:00
Michael Natterer
792264ba6a app: add gimp_suggest_trc_for_component_type()
and use it in GimpTemplateEditor and convert-precision-dialog, instead
of duplicating the logic.
2019-05-31 17:28:20 +02:00
Michael Natterer
317b09c90f app: rename gimp_rec_rm() to gimp_file_delete_recursive()
and move it to the right place in gimp-utils.[ch].
2019-05-31 17:11:50 +02:00
Michael Natterer
add4500a16 app: don't generate profiles from built-in profiles
gimp_image_convert_precision(): if the conversion changes the TRC and
the image's profile is a built-in profile, don't create a profile from
it but instead simply use the new TRC's built-in profile.
2019-05-30 18:42:56 +02:00
Michael Natterer
710cfc1f47 app: fix undoing image parasite attach/detach to emit the right signals
Add "gboolean push_undo" parameters to gimp_image_parasite_attach()
and _detach() and use the API also from undo, instead of implementing
attaching/removing manually and forgetting about the signals.

Fixes updating of the image properties color profile page.
2019-05-30 16:51:29 +02:00
Michael Natterer
07ffef38c3 app: make sure builtin profiles *really* don't get attached to images
gimp_image_parasite_attach(): when we detected that a builtin profile
is about to be attached, actually bail out after removing the old
profile, instead of continuing to attaching the builtin profile
anyway. Gah...
2019-05-30 16:07:57 +02:00
Michael Natterer
e7307194cf app: use the DEFAULT_USE_PATTERN define instead of TRUE in GimpPreset 2019-05-30 11:47:16 +02:00
Ell
8ef461bb70 app: s/gimp_list_compare()/gimp_g_list_compare()/
... so we don't clash with the GimpList namespace.
2019-05-30 03:31:46 -04:00
Ell
1e95481feb app: allow moving an intersecting pair of guides with the Move tool
This commit adds support for moving together an intersecting pair
of guides using the Move tool, by dragging the guides at their
point of intersection.  This is useful when the guides are used to
mark a point, rather than a pair of lines (e.g., as is the case for
the mandala symmetry guides, which mark the symmetry's point of
origin).

Add gimp_image_pick_guides(), which can return a set of guides,
rather than a single guide.  The API allows an arbitrary set of
guides to be returned, but, in practice, at most two intersecting
guides are returned, as per the above.

In GimpMoveTool and GimpGuideTool, add support for moving multiple
guides together, and, in GimpMoveTool, use gimp_image_pick_guides()
to potentially pick multiple guides.
2019-05-30 01:51:06 -04:00
Ell
c4ce70a2d3 app: add gimp_list_compare()
... which lexicographically (shallowly) compares a pair of GLists.
2019-05-30 01:51:06 -04:00
Ell
60a3965020 app: implement gimp_symmetry_get_operation() in terms of gimp_symmetry_get_matrix()
Remove the GimpSymmetry::get_operation() virtual function, and
instead implement gimp_symmetry_get_operation() by returning an
appropriate gegl:transform node based on the matrix returned by
gimp_symmetry_get_matrix().  The returned node is owned by the
caller; since we no longer use the node's identity for caching
trnasformed brushes, we no longer cache the transformation nodes.

Remove the function's paint_width and paint_height parameters, and
instead return a transformation that should be applied at the
center of the brush.  This simplifies the application of the
transformation in the Clone and Heal tools, as per the next commit.

Remove the implementation of GimpSymmetry::get_operation() from all
its subclasses, which should now only implement
GimpSymmetry::get_transform().
2019-05-29 05:26:42 -04:00
Ell
cd7bcd081b app: add gimp_symmetry_get_matrix()
... which returns the brush transform corresponding to a given
GimpSymmetry stroke as a GimpMatrix3, as per
gimp_symmetry_get_transform().
2019-05-29 05:26:40 -04:00
Michael Natterer
901350ba20 app: use g_clear_pointer() in more places 2019-05-27 17:47:55 +02:00
Jehan
cc7af306b6 app: new gimp_extension_get_screenshot() screenshot.
This first version of this API only returns the default screenshot.
Further improvements should allow to return all the available extension
screenshots.
2019-05-27 17:31:18 +02:00
Jehan
400b564648 app: do not crash when an extension has no description tag. 2019-05-27 17:31:18 +02:00
Michael Natterer
1e07f00a95 Issue #3067 - "Make New from Visible" produces wrong results
Call gimp_projectable_structure_changed() when the image's profile
changes so the projection buffer gets reallocated.
2019-05-27 15:20:15 +02:00
Michael Natterer
c1cba759f8 app: minor formatting fixes in gimpdrawable-bucket-fill.c 2019-05-27 00:29:41 +02:00
Ell
b63af476bd app: use gimp_symmetry_get_transform() in paint code
Use gimp_symmetry_get_transform() instead of
gimp_symmetry_get_operation() throughout the paint code, where
possible.  This allows us to combine the symmetry transform with
the ordinary brush transform, simplifying the code, improving
performance, and avoiding multiple resamplings.  This also fixes
the paint-buffer size when using mandala symmetry with non-round
brushes, avoiding artifacts.
2019-05-26 14:45:39 -04:00
Ell
e0f2a6f1be app: add gimp_symmetry_get_transform()
Add a GimpSymmetry::get_transform() virtual function, and a
corresponding gimp_symmetry_get_transform() function, which return
the brush transform corresponding to a given symmetry stroke in
terms of the rotation angle and reflection flag (in contrast to
gimp_symmetry_get_operation() which returns the same transforation
in terms of a GeglNode).  This would allow us to simplify, fix, and
improve the painting-code perofmrnace in the next commits.

Implement GimpSymmetry::get_transform() in its various subclasses.
2019-05-26 14:45:38 -04:00
Michael Natterer
1f57675a46 Issue #3124 - layer mask pastes as a greyscale layer/grayscale layer...
...in a color image/colour image

gimp_edit_paste_get_layer(): only use the pasted-to drawable's format
with alpha if this is really a floating paste, use the image's layer
format with alpha for "as new layer" cases.
2019-05-25 17:05:49 +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
1c91578bb2 app: don't show result-size warning when transforming a selection
In gimp_drawable_transform_get_effective_clip(), always return
RESIZE_CLIP when the input drawable is the image mask, since the
presence of a selection doesn't matter in this case.  This avoids
erroneously displaying a result-size warning when transforming the
selection using any of the selection tools.
2019-05-21 08:19:21 -04:00
luz.paz
86edc31b11 Misc. typos
Found via `codespell`
2019-05-09 09:13:37 -04:00
Jehan
09ca1e8962 app: add undo_remove ability to the extension manager.
This allows an extension removal to be cancelable for a given session
(at end of session, the extension removal is definitive and you have to
reinstall it if you want it back).
2019-05-01 23:13:06 +09:00
Jehan
50aa7233b2 app: add extension installation in GimpExtensionManager.
This completes my earlier commit 406279e4ef.
Extension installation is not about just decompressing a file in the
right folder. We must also make the extension manager and the GUI aware
of this newly available extension.
2019-04-29 20:56:28 +09:00
Jehan
f7e483dd64 app: add ability to remove an extension.
Removing an extension means just unloading it and temporarily move it to
an "uninstalled" list. The actual files will only be deleted when
cleanly exiting the program, hence finalizing the extension manager.
This will allow undoing an extension removal easily.
2019-04-29 20:56:28 +09:00
Ell
33e47c85a2 app: add smooth/corner curve-point types
Allow setting the type of GimpCurve control-points to either SMOOTH
or CORNER.  Smooth points produce a smooth curve, while corner
points produce a sharp curve (previously, all points were smooth).

In GimpCureView, display corner points using a diamond shape,
instead of a circle.

In the Curves tool, allow changing the curve's point types.
2019-04-19 10:34:32 -04:00
Ell
b6d829a1b2 app: streamline GimpCurve
In GimpCurve, replace the use of a fixed-length control-point array
with a dynamically-sized array.  Adapt GimpCurve's interface, and
the rest of the code.

In addition to simplifying the code, this fixes a bug where the
curve object could be broken by moving the mouse too fast (yep...),
and allows more accurate point placement, both in the GUI editor,
and through canvas interaction in the Curves tool (see issue #814).
2019-04-19 10:34:29 -04:00
Michael Natterer
aee6d44b61 app: remove defines GIMP_BRUSH_FILE_VERSION and GIMP_PATTERN_FILE_VERSION
they were unused and wrong. Also clean up the brush and pattern
headers a bit.
2019-04-12 16:30:29 +02:00
Jehan
5d5ced88a8 Issue #3224: Fill by Line Art Detection Bug (Fatal Error with Crash).
Typos in gimp_pickable_contiguous_region_by_line_art().
Thanks to Massimo for debugging these!
2019-04-12 14:48:15 +02:00
Michael Natterer
40863bffdd app: fix legacy .gpb parsing code in gimp_brush_load_brush()
Only seek back to after the end of the actual brush if a following
pattern was *not* found. Got this logic wrong in the original port of
the plug-in code.
2019-04-09 23:11:55 +02:00
Ell
c95502266a app: in GimpChunkIterator, avoid preparing rect before merging
In GimpChunkIterator, avoid preparing the current rect before
merging it back to the iterator's region, to save some work.

Additionally, strengthen the iterator's invariants and simplify
code.
2019-03-31 05:03:38 -04:00
Ell
d182c41f8f app: small fix to GimpChunkIterator 2019-03-30 16:36:26 -04:00
Ell
91f4c809d8 app: more responsiveness improvements to GimpChunkIterator
Improve GimpChunkIterator's responsiveness to changes in processing
speed.
2019-03-30 11:18:00 -04:00
Ell
9dabad4cb9 app: don't invalidate viewable preview when thawed unless explicitly requested
In GimpViewable, don't invalidate the preview when thawed, unless
there was an explicit call to gimp_viewable_invalidate_preview()
while it was frozen.  This avoids invalidating the previews of an
invisible drawable's ancestors when the drawable's preview is
frozen/thawed.
2019-03-29 04:54:07 -04:00
Ell
24ed9dbdf5 app: avoid risky alloca() in gimp_brush_save()
Replace an arbitrarily-sized g_alloca() with g_malloc() in
gimp_brush_save().
2019-03-28 16:55:55 -04:00
Ell
de36e33347 app: avoid freezing image preview if drawable is not attached
When freezing/thawing a top-level drawable's preview, only freeze/
thaw the image preview if the drawable is attached.
2019-03-28 12:36:44 -04:00
Ell
e2ea2e4a82 app: when freezing a drawable's preview, freeze ancestors' previews
Add GimpViewable::preview_{freeze,thaw}() virtual functions, which
get called when the viewable's preview is frozen/thawed.  Implement
the functions in GimpDrawable, recursively freezing the parent
drawable's preview (or the image's preview, for top-level
drawables) while the drawable's preview is frozen.  For layer
masks, freeze the associated layer's parent.

This avoids updating layer-group/image previews while painting on,
or applying a filter to, a descendant layer.  This both reduces
lag, and fixes a discrepancy between the layer's preview, which
isn't updated, and its parents' previews.
2019-03-28 12:26:44 -04:00
Jehan
d821b088e2 app: change antialias feature in fill by line art into Feather Edges.
This was actually more of a feathering feature I added earlier, and we
already have a function for that: gimp_gegl_apply_feather(). This is
using a gaussian blur, just as what I was doing anyway. This commit also
adds the "Feather Radius" scale, similar to other tools with the
"Feather Edges". So that makes it consistent (and more useful as you can
adapt to your needs).
2019-03-28 14:06:17 +01:00
Ell
1846764d3b app: include system gimp.css file in theme.css
Include the system-wide gimp.css file, in addition to the user-
specific gimp.css file, in the generated theme.css file, instead of
copying the former into the latter when creating the user's
gimpdir.  This allows us to modify the system-wide gimp.css file,
and having the changes take effect in existing installations.
2019-03-27 20:14:10 -04:00
Ell
234f76b6fb app: use gimp:fill-source in gimp_drawable_edit_fill()
In gimp_drawable_edit_fill(), when performing a non-direct fill,
use a GimpDrawableFilter with gimp:fill-source, added in the
previous commit, instead of using gimp_drawable_apply_buffer() with
an intermediate fill buffer.  This avoids allocating a full-size
fill buffer, which may occupy a lot of space in pattern fills.
2019-03-27 15:45:59 -04:00
Ell
3c1634ee0d app: improve gimp_drawable_fill_buffer() for patterns
In gimp_drawable_fill_buffer(), when the fill-source is a pattern,
avoid going through an intermediate buffer when there's no profile
transform, and use the destination-buffer format for the
intermediate buffer, instead of the pattern format, when there is a
profile transform.
2019-03-27 15:45:58 -04:00
Ell
245a17c79f app: use compositing format for fill buffer
Add gimp_fill_options_get_format(), which returns the format to be
used for the fill buffer; this is the same format used during
compositing.  Use this format in gimp_fill_options_create_buffer(),
instead of the drawable format.

This fixes the result of fill operations when the fill color/
pattern is not representable in the drawable format, and speeds up
color fills by avoiding color-conversion for the fill buffer during
processing.
2019-03-27 15:45:58 -04:00
Ell
b0dfc1e7c7 app: in GimpDrawableFilter, set underlying operation
In GimpDrawableFilter, use
gimp_gegl_node_set_underlying_operation() to the the input
operation node as the underlying operation of the filter node.
2019-03-27 15:45:57 -04:00
Ell
8f845d3a51 app: in gimp_drawable_apply_buffer(), work in chunks
In gimp_drawable_real_apply_buffer(), use GimpChunkIterator to blit
the applicator's output to the drawable's buffer in chunks, to
minimize the space used for intermediate results.
2019-03-27 15:45:30 -04:00
Ell
e904b71242 app: improve responsiveness of GimpChunkIterator
In GimpChunkIterator, redajust the target area at each step,
instead of at each iteration, to adapt more quickly to the current
processing speed.  To avoid creating uneven chunks as a result,
only change the chunk height at the beginning of rows, unless the
resulting area would be more than twice as big as the target area.
2019-03-27 15:45:30 -04:00
Ell
9d80ccc3e6 app: preserve projection priority rect across structure/bounds changes
In GimpProjection, store the priority rect in image coordinates,
and only convert it to projectable coordinates when initializing
the chunk-iterator's priority rect.  This allows us to preserve the
priority rect across projectable structure/bounds changes.
2019-03-26 04:58:51 -04:00
Ell
30da2f3d6f app: don't disable filter format conversion if != drawable format
In gimp_drawable_merge_filter(), don't disable the filter
applicator's output-format conversion node if the output format is
different than the drawable's format, since it may change the
result.
2019-03-25 09:16:23 -04:00
Ell
733a6ec01c app: skip cache and format conversion when merging a drawable filter
In gimp_drawable_merge_filter(), disable the filter applicator's
cache and output-format conversion nodes before processing the
uncached region of the filter, so that the result is written
directly to the drawable's buffer.
2019-03-25 09:02:27 -04:00
Ell
106df3b794 Issue #3142 - Filters on-canvas preview doesn't work ...
... immediately after an image precision change

When flushing a projection, make sure it has a buffer, instead of
bailing if it doesn't.  We rely on the image projection's "update"
signal to update the display after certain operations that free the
buffer, which would previously fail to happen, and cause subsequent
flushes to be ignored until the buffer is explicitly accessed.

This fixes commit b07f810273.
2019-03-24 03:20:39 -04:00
Ell
a712308f20 Issue #3134 - Deleting last layer of group not updating image
In gimp_group_layer_get_size(), make sure to always set *width and
*height, even when the group is empty, so that when the function is
called through gimp_projectable_get_size() by the group's
projection, the correct size is reported.  This makes sure we
update the correct area when the group becomes empty.
2019-03-20 17:48:47 -04:00
Ell
8e77347cac app: improve gimpchannel-{combine,select}
In gimpchannel-select, move some of the common functionality of the
various gimp_channel_select_foo() functions to gimpchannel-combine.
Furthermore, don't special-case CHANNEL_OP_INTERSECT, but rather
pass it over to gimpchannel-combine, which is now prepared to
handle it in all functions, as per the previous commits.

In gimpchannel-combine, factor out the common functionality of the
various gimp_channel_combine_foo() functions into a pair of
gimp_channel_combine_{start,end}() functions, which are called
before/after the actual gimp_gegl_mask_combine_foo() function,
respectively.  In particular, these functions deal with calculating
the new channel bounds.  Previously, the various
gimp_gegl_mask_combine_foo() functions would implicitly invalidate
the channel bounds (since commit
d0ae244fe8), rendering the bounds-
recalculation code ineffective.  This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 16:24:37 -04:00
Ell
1044342393 app: improve gimp_gegl_mask_combine_ellipse[_rect]()
Improve gimp_gegl_mask_combine_ellipse_rect() -- the funciton
responsible for rendering ellipse/rounded-rectangle selections.

Most notably, this commit significantly improves the function's
performance, by identifying whole tiles, whole rows, or parts of a
row, that are fully inside, or fully outside, the ellipse, and
filling them in bulk, instead of calculating the anti-aliasing
value at each pixel, which is now only done along the
circumference.

This commit also improves anti-aliasing, by more accurately
approximating the distance from a pixel to the ellipse, and by
normalizing the distance according to the pixel's cross-section
length in the direction of the said point.  In particular, we
guarantee that pixels that are fully inside/outside the ellipse
have a value of 1/0, respectively, facilitating the aforementioned
optimization.

Additionally, this commit fixes various edge cases where several
primitives coincide at a single pixel (in the rounded-rectangle
case), adds support for CHANNEL_OP_INTERSECT, and parallelizes
processing.
2019-03-20 15:58:29 -04:00
Jehan
ebc3ef3c5e Issue #3087: error compiling for Windows.
s/THREAD_MODE_ABOVE_NORMAL/THREAD_PRIORITY_ABOVE_NORMAL/
Thanks to Sylvie Alexandre for noticing and searching this.
2019-03-08 17:29:16 +01:00
Jehan
31b2b55b28 Issue #3041: Color Picker no longer selects Colormap entry.
Do not take "Sample merge" into account when picking colors in a
single-layer image. The reason is to be able to get the index
information on indexed image. This information is lost otherwise when
using the whole image as a pickable.

Of course, other exceptions are possible, when you'd pick exactly a
colormap color, but I don't think it's worth making the code
extra-complicated for these. My previous commit will anyway already
select the right color in the colormap on common cases. Though it will
still fail to select the right index when several indexes store the same
color, on a multi-layer image, if you check "Sample merged" while the
right index was not the first one amongst the duplicates.
2019-03-07 18:43:05 +01:00
Jehan
f1cca8ee2e app: save the accurate color in the colormap palette when possible.
The colormap saves colors as unsigned char, which can be very inaccurate
compared to high precision colors. When adding colors from GimpRGB into
the colormap, use the original value to fill the colormap palette
instead of making a round trip conversion from double to uchar, then
back to double.

This also fixes a direct bug I encountered when adding the current
foreground color in the image colormap. Yet the GimpFgBgEditor or the
GimpColorHistory would still show the color out-of-gamut in cases when
the returned RGB after the roundtrip was not close enough to the
original RGB (even despite using an epsilon in GimpPalette code).
2019-03-07 00:02:56 +01:00
Ell
caad9ca649 app: various fixes to last commit 2019-03-06 15:56:09 -05:00
Ell
d8e69d66bc app: allow canceling line-art computation
Line-art computation can take a long time, and it's therefore
desirable for it to be interruptable.  While we do cancel the line-
art async when its result is no longer needed, most parts of the
computation don't respond to the cancelation request, leaving the
async operation running in the background, blocking subsequent
async operations.

Implement cancelation support of line-art computation, by passing
down the async object to the various functions, and periodically
checking for its cancelation at various points.  When the async is
canceled, we quickly abort the operation.

Even though cancelation now happens relatively quickly, some parts
of the computation are still uninterruptable and may incur some
latency, so we avoid waiting for the async opration to be aborted
after cancelation, as we did before.
2019-03-06 15:24:14 -05: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
190095c97b app: fix indepndent-async thread priority on Windows
Positive and negative priorities got swapped...
2019-03-06 00:08:01 -05:00
Ell
fa2e4dcce0 app: add gimp_parallel_run_async_independent_full()
... which is equivalent to gimp_parallel_run_async_independent(),
except that it takes an additional "priority" parameter, which
specifies the task's priority, with 0 being the default priority,
and lower values indicating higher priority.  Unlike
gimp_parallel_run_async_full(), the priority parameter doesn't
directly control the task's priority in a queue, but rather, we use
it to control the priority of the task's dedicated thread, on
supported platforms (previously, all independent async tasks would
run with low priority.)

Use low priority when loading fonts, which can take a long time, to
keep the existing behavior.
2019-03-06 00:01:59 -05:00
Ell
b0de51b6bf app: clean up last commit
Remove gimp_item_tree_clear(), added in last commit, and move its
code to gimp_item_tree_dispose().  Likewise, in
gimp_image_dispose(), use g_object_run_dispose() on the image item-
trees, instead of gimp_item_tree_clear().
2019-03-05 16:42:44 -05:00
Ell
d7e3a1e226 app: fix segfault when closing an image with a floating selection
Add gimp_item_tree_clear(), which removes all the items of a
GimpItemTree, and clear the layers/channels/vectors item trees in
gimp_image_dispose(), *before* finalizing the image, so that the
corresponding items' desctructors are called while the image is
still alive.  In particular, this allows the destructors to safely
call gimp_item_is_attached(), which happens when the image has a
floating selection, since commit
8d4e5e0ff7.
2019-03-05 09:32:58 -05:00
Ell
9886b69dac Issue #3062 - Picking by hue using "Select by Color" goes awry ...
... in GIMP 2.10.9 from git

In gimppickable-contiguous-region's pixel_difference() function,
which is used, among other things, by the select-by-color and
fuzzy-select tools, when selecting by LCh/HSV hue, treat a pair of
colors as inifinitely far apart if one of them has positive chroma/
saturation, and the other has chroma/saturation that's very close
to 0; conversely, treat a pair of colors as equal if both of them
have chroma/sautation that's close to 0.

As a result, when the seed color is saturated, gray pixels are
never selected, while when the seed color is desaturated, all, and
only, gray pixels are selected.
2019-03-05 09:01:36 -05:00
Jehan
f310db6c21 app: improve line art filling when clicking on a line art closure.
When clicking on a line art pixel, only this pixel gets colored, which
is fine for actual (original) line art pixels. But on generated ones
(closure pixels, which are internal only), you end up with a single
pixel colored while the whole surrounding area is empty. This feels like
a bug (even though it was not one technically) as you have no way to
guess you are clicking on a closure pixel.
Instead, when this happens, simulate clicks on all neighbour pixels,
hence potentially coloring all surrounding regions, which is most likely
what you wanted.
2019-03-04 18:31:13 +01:00
Jehan
3a317e72aa app: fixing the line art GimpBusyBox visibility.
Commit bc187cc5cc was a bit wrong as it was possible to get some race
conditions when changing settings quickly in a short time frame.
2019-03-04 16:55:51 +01:00
Jehan
c0996241f6 app: avoid useless line art closure recomputation.
On various property changes, only recompute the line art when the
property actually changed. Also add a gimp_line_art_bind_gap_length() to
avoid computing twice the line art when changing both type of closure
(splines and segments) together, as is currently the case.
2019-03-04 16:43:19 +01:00
Jehan
bc187cc5cc app: add a GimpBusyBox near the "Line Art Detection" label in…
… Bucket Fill tool options.
This will provide feedback when the line art closure is being computed,
which may be useful on big images where it may take some time. Otherwise
painter may be left hanging without knowing what takes time.
2019-03-04 16:06:59 +01:00
Michael Natterer
8d4e5e0ff7 app: optimize gimp_layer_invalidate_boundary()
Don't mess with the image's mask if the layer is not attached or not
visible.

(cherry picked from commit 1c66573f4c)
2019-03-03 20:28:20 +01:00
Michael Natterer
e742b4a95b app: factor out gimp_brush_pipe_set_params() from gimp_brush_pipe_load() 2019-03-03 19:44:02 +01:00
Ell
a6c79770c3 Issue #1554 - Select by Color tool does not select pixel(s) or area(s) of pixel(s)
In gimp_pickable_contiguous_region_by_color(), add a small epsilon
to the threshold value, to allow for small errors due to the input
color and pickable pixel-colors being converted to the common
format through different paths.

While we *could* special-case threshold == 0 when the input color
comes from the same pickable, as is the case for the select-by-
color tool, and perform an exact comparison in the original format,
in the more general case the input color can come from an arbitrary
source, such as a plug-in.
2019-02-28 09:27:43 -05:00
Ell
e83d8ac4f2 app: merge layers in chunks, and show progress
In gimp_image_merge_layers() -- the internal function used by the
various layer-merging/flattenning functions -- process the merged-
layer graph in chunks, using gimp_gegl_apply_operation(), instead
of in one go, using gegl_node_blit_buffer().  Processing in chunks
better utilizes the cache, since it reduces the size of
intermediate buffers, reducing the chances of hitting the swap when
merging large images (see, for example, issue #3012.)

Additionally, this allows us to show progress indication.  Have the
relevant gimpimage-merge functions take a GimpProgress, and pass it
down to gimp_image_merge_layers().  Adapt all callers.
2019-02-25 05:10:50 -05:00
Ell
0a1e62768a app: accept a const GimpTempBuf in more temp-buf functions
In gimp_temp_buf_{ref,unref}(), and
gimp_temp_buf_create_{buffer,pixmap}(), accept a const GimpTempBuf
argument.
2019-02-24 13:20:31 -05:00
Michael Natterer
aee097fa97 app: implement saving of GimpBrushPipes in the core
Just the GimpData::save() and ::copy() part that is needed to
duplicate and rename them, the image-to-pipe logic from the export
plug-in remains to be ported.
2019-02-23 19:41:06 +01:00
Ell
bb645bae17 app: add temp-buf-total varaible to the dashboard
Add a temp-buf-total variable to the dashboard's misc group,
showing the total size of all GimpTempBuf objects.
2019-02-22 08:47:05 -05:00
Michael Natterer
4b456e6079 app: some changes to GimpBrushPipe in preparation for .git image loading
- don't clear the names of the individual brushes, we need them for
  a load -> save roundtrip
- for the same reason, and for convenience, store the parameter string
  in the object
- clean up gimp_brush_pipe_finalize()
2019-02-19 23:24:41 +01: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
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
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
Michael Natterer
a95c169091 app: don't unref a NULL GimpTempBuf in gimp_pattern_copy() 2019-02-12 21:15:35 +01: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
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
Jehan
c4beca8c90 app: clarify function to validate line art closure.
Add some comments and string docs as it is not that obvious to
understand the whole logics, invert the return value (returning TRUE
when the closure line is accepted, instead of the opposite) and rename
it to more appropriate gimp_line_art_allow_closure().
2019-02-11 15:16:02 +01:00
Jehan
14e7424403 app: proper signedness for return value of gimp_edgel_region_area().
It is just weird to return a negative area and multiply it by -1.
Just apply the proper signs from the start.
2019-02-11 15:16:02 +01:00
Michael Natterer
a4e77e57f6 app, plug-ins: start consolidating brush and pattern loading/saving code
We currently have brush and pattern I/O code in both the core and
plug-ins. This commit starts removing plug-in code in favor of having
one copy of the code in the core, much like XCF loading and saving is
implemented.

Add app/file-data/ module with file procedure registering code, for
now just with an implementation of file-gbr-load.

Remove the file-gbr-load code from the file-gbr plug-in.
2019-02-11 12:51:31 +01:00
Michael Natterer
619f999280 app: add all missing festures from file-gbr-load to the core brush loader
gimp_brush_load_brush(): support legacy gpb brushes, and port a check
for gsize overflow what was added to the plug-in.
2019-02-11 12:31:18 +01:00
Jehan
72092fbdbc app: improve line art bucket fill by filling unsignificant areas.
The line art imaginary segments/splines are not added when they create
too small zones, unless when these are just too small ("unsignificant").
Why the original algorithm keeps such micro-zones is because there may
be such zones created when several splines or segments are leaving from
a same key point (and we don't necessarily won't to forbid this). Also
we had cases when using very spiky brushes (for the line art) would
create many zones, and such micro-zones would appear just too often
(whereas with very smooth lines, they are much rarer, if not totally
absent most of the time).
Also it is to be noted that the original paper would call these
"unsignificant" indeed, but these are definitely significant for the
artists. Therefore having to "fix" the filling afterwards (with a brush
for instance) kind of defeat the whole purpose of this tool.

I already had code which would special-case (fill) 1-pixel zones in the
end, but bigger micro zones could appear (up to 4 pixels in the current
code, but this could change). Also I don't want to use the "Remove
Holes" (gimp:flood) operation as I want to make sure I remove only
micro-holes created by the line art closure code (not micro-holes from
original line arts in particular).

This code takes care of this issue by filling the micro-holes with
imaginary line art pixels, which may later be potentially bucket filled
when water-filling the line art.
2019-02-07 18:09:30 +01:00
Ell
9d19e804ed app: avoid unnecessary calls to gimp_temp_buf_data_clear()
Avoid unnecessary calls to gimp_temp_buf_data_clear() in various
places, where either the entire buffer is being written to, or most
of it is, only requiring clearing the edges.
2019-02-06 16:51:01 -05:00
Ell
8ef1113dee Issue #2372 - Reduced quality of the Parametric brush in 2.10
Promote the precision of generated brushes to 32-bit float, and
modify brush preview generation, and gimpbrushcore-loops, to handle
float brushes.  This avoids posterization in large brushes.

Note that non-generated brushes are still uint8.
2019-02-06 14:30:48 -05:00
Ell
12dde445c4 app: add gimp_temp_buf_{lock,unlock}()
In GimpTempBuf, add gimp_temp_buf_lock() and gimp_temp_buf_unlock()
functions, which lock/unlock the buffer for data access.  Unlike
gimp_temp_buf_get_data(), which returns a direct pointer to the
buffer's data, the new functions take a format parameter and may
return a temporary buffer, allowing the buffer to be accessed using
an arbitrary format.
2019-02-06 14:30:47 -05:00
Ell
59ef222c7f app: in gimp_transform_matrix_generic(), apply matrix even if invalid
In gimp_transform_matrix_generic(), apply the resulting matrix even
if the transformation is invalid, since GimpGenericTransformTool
relies on the matrix to properly update the transform-grid widget.
2019-02-04 15:59:52 -05:00
Michael Natterer
08b4b944dc app: remove GimpDrawableFilter's own color profile conversion hack
it's wrong and harmful after space invasion.
2019-01-28 20:13:12 +01:00
Ell
4db566f0e1 app: fix indentation in gimpmaskundo.h 2019-01-20 10:33:53 -05:00
Ell
7cd768f3d8 app: align mask-undo buffer to tile grid
In GimpMaskUndo, align the copied region to the source buffer's
tile grid, so that all copied tiles are COWed.
2019-01-20 10:06:55 -05:00
Ell
ac5e4f4c33 app: improve gimp_channel_clear()
When clearing a channel, do nothing if the channel is already
empty; otherwise, align the cleared rectangle to the channel
buffer's tile grid, so that all affected tiles are dropped, rather
than zeroed.  Furthermore, only update the affected region of the
channel.
2019-01-17 15:15:56 -05:00
Ell
de4e7b4770 app: update drawable filter upon alpha-lock change
In GimpDrawableFilter, when operating on a layer, update the filter
when the layer's lock-alpha flag changes.
2019-01-17 14:19:58 -05:00
Ell
8571d7812f app: parallelize gimp_pickable_contiguous_region_by_color()
... by distributing the processed area over multiple threads.
2019-01-17 09:30:45 -05:00
Ell
9719dff9c5 app: convert gimppickable-contiguous-region to C++ 2019-01-17 09:30:45 -05:00
Jehan
aa04258620 app: improved fix to commit 036ccc70cf.
After discussion with Sébastien Fourey and David Tschumperlé, it was
decided that a better fix for the edge case raised in #2785 was to add a
keypoint anyway, even if the point and none of its neigbours have a
positive smoothed curvature, yet they have a positive raw curvature. In
such case, we use the local maximum raw curvature instead of the local
maximum smoothed curvature.
2019-01-17 13:21:18 +01:00
Jehan
c71b4916af app: add the concept of line art source to Bucket Fill tool.
Additionally to sample merge and active layer, now we can only use the
layer above or below the active layer as line art source.

The line art fill is meant to work on drawing lines. Though sample merge
still is ok in many cases, the more you fill with colors, the more the
line art computation becomes unecessarily complex. Also when you use a
lot of layers with some of them already filled with colors, it makes it
impossible to colorize some line art zones with the tool. Moreover you
just don't want to have to hide every layers out there to colorize one
layer (especially background layers and such as you may want to see the
result with your background).
Thus we want to be able to set the source as a unique layer, while it
not being necessarily the active one (because you want lines and colors
on different layers). In this case, I am assuming that the color and the
line layers are next to each other (most common organization).
2019-01-15 16:06:50 +01:00
Jehan
036ccc70cf Issue #2785: Fill by line art detection produces Segmentation fault...
... with some images.
2019-01-13 17:40:25 +01:00
Ell
9833da3431 app: clear priority rect when finishing projection rendering
In gimp_projection_finish_draw(), clear the chunk iterator's
priority rect before finishing rendering, since it's not needed at
this point, and this is slightly more efficient.
2019-01-13 08:23:01 -05:00
Ell
42845c9462 app: in gimp_projection_chunk_render_start(), properly invalidate preview
In gimp_projection_chunk_render_start(), when the current
projection rendering is complete, but not finalized yet, and no new
rendering is started (since the current update region is empty),
make sure to invalidate the projectable's preview, since it
normally happens when rendering is finalized, which doesn't happen
in this case.
2019-01-12 08:33:16 -05:00
Ell
0e5de95760 app: in gimp_projection_chunk_render_start(), don't leak empty region
In gimp_projection_chunk_render_start(), don't leak the current
update region when it's empty, but not NULL, and properly shut down
the idle source.
2019-01-12 08:20:10 -05:00
Ell
942e1aa939 app: fix gimp_chunk_iterator_set_priority_rect() 2019-01-12 07:31:33 -05:00
Ell
a61f29e30a app: in gimpchunkiterator.c, #include <stdlib.h>
... for qsort().
2019-01-12 06:16:48 -05:00
Ell
246e782858 app: use GimpChunkIterator in GimpProjection
Replace the custom chunking logic of GimpProjection with
GimpChunkIterator, added in the previous commit.
2019-01-12 04:50:57 -05:00
Ell
ba9ce34e10 app: add GimpChunkIterator
Factor out the region-chunking logic of GimpProjection into a new
GimpChunkIterator type, providing a generic mechanism for iterating
over a cairo region in discrete chunks.  The iterator doesn't
perform any processing itself, but rather dispenses rectangular
chunks, which the user then processes.

Iteration is broken into intervals, the duration of which is
configurable.  Each iteration begins with a call to
gimp_chunk_iterator_next(), after which
gimp_chunk_iterator_get_rect() should be called in succession to
fetch a rectangle to process, until it returns FALSE, which marks
the end of the iteration.  Updates to the UI should take place in
the interval between iterations, but not during an iteration.  The
iterator dynamically adjusts the chunk size according to processing
speed, in order to match the target iteration interval.

The iterator can be given a priority rectangle, which is processed
before the rest of the region.  It can also be given a
representative tile rectangle, defining a regular tile grid;
dispensed chunks are aligned to the tile grid as much as possible.
2019-01-12 04:50:57 -05:00
Jehan
005bc1406b app: add link to Smart Colorization scientific paper.
This is sometimes asked, and myself also need to find it from time to
time. I may as well put the link inside the code comments, where it is
just easy to find!
2019-01-12 00:26:19 +01:00
Jehan
90e9eb3fca app: alt-click to pick a layer will loop through candidate layers.
If you click on a zone filled in several visible layers, you don't
necessarily want the top layer. You may want one below. With this
change, as long as you hold alt, you will loop through all candidate
layers from top to bottom (then looping back top when reaching the
bottom).
In a first alt-click, you will always end up to the top candidate.
2019-01-07 23:08:48 +01:00
Ell
823d4a0d24 app: in bucket-fill tool, avoid calculating line art when not in line-art mode
In the bucket-fill tool, don't pre-calculate the line art when not
using a line-art fill area.  Also, misc. cleanup.
2019-01-06 16:30:41 -05:00
Ell
889e2e26ee app: remove gimp-scratch; replace with gegl-scratch
The scratch allocator has been moved to GEGL (commit
gegl@b99032d799dda3436ffa8c1cc28f8b0d34fb965d).  Remove gimp-
scratch, and replace all its uses with gegl-scratch.
2019-01-06 07:37:19 -05:00
Ell
d56d663eaa app: In GimpHistogram, align copied buffer region to tile rect
In gimp_histogram_calculate_async(), align the copied region of the
drawable and mask buffers to the tile grid, so that all copied
tiles are COWed.
2019-01-04 08:16:51 -05:00
Michael Natterer
b2cb334b47 app, libgimp: forgot to add /*< pdb-skip >*/ to enum GimpBucketFillMode
so it was still exported to libgimp.
2019-01-02 16:18:28 +01:00
Michael Natterer
07e46abb72 app, libgimp*: move enum GimpBucketFillMode to the core
The libgimp API using it is gone.
2019-01-02 16:07:20 +01:00
Michael Natterer
abd7cbfc8d Issue #1788 - Inconsistency between FG color and selected color in...
...palette views despite selected color being in the currently
selected pallette

As suggested by Massimo, changing the color comparison EPSILON in
gimppalette.c from 1e-10 to 1e-6 fixes this, and is really small
enough.

Also, generally clean up color comparison epsilons:

- use a #define, not hardcoded values for all uses of
  gimp_rgb[a]_distance()
- call the #defines RGB_EPSILON and RGBA_EPSILON
- make them all 1e-6 or larger
2019-01-02 01:49:43 +01:00
Michael Natterer
8a4aacb52f Issue #2667 - When copying a text layer, paste should create a new...
...text layer, not an image of the text

In gimp_edit_paste_get_layer(), when pasting as floating selection,
collapse the pasted layer into an ordinary layer only if it's a group
layer. There is nothing that speaks against having a floating text
layer, it works just fine.
2019-01-02 00:14:35 +01:00
Michael Natterer
a338220fa6 app: fix the layer formats of indexed images to contain the space
Add gimp_image_colormap_update_formats() which does:

- always update the cached palette formats based on the current space
  of the image
- always set the palette entries on the palette formats

Make sure the function is called whenever the space or the colormap
change.

Fix gimp_image_convert_profile_colormap() to convert the colormap
entries between the right spaces.
2019-01-01 19:06:23 +01:00
Michael Natterer
78f5d39e1a app, libgimpcolor: handle palette formats across babl_format_with_space()
Don't just pass the input format's encoding because that loses the
palette. Instead, pass the input format directly so
babl_format_with_space() can do its job of preserving the palette.
2019-01-01 16:34:57 +01:00
Ell
3738ff3ffd app: small fix to gimp_drawable_edit_fill() 2018-12-31 05:33:42 -05:00
Ell
6384ff01b6 app: in gimp_drawable_edit_fill(), make trivial alpha-only fill a NOP
In gimp_drawable_edit_fill(), if the fill only affects the alpha
channel, and if the drawable has no alpha channel, or the alpha
channel is masked out, do nothing, instead of unnecessarily
performing the fill, which has no effect.
2018-12-31 04:40:09 -05:00
Ell
b846ffed19 app: in GimpDrawableFilter, only update crop/preview area when updating whole drawable
In GimpDrawableFilter, when updating the entire filter area, only
update the crop/preview area (as set by
gimp_drawable_filter_set_{crop,preview}()), instead of the entire
drawable.
2018-12-30 05:13:01 -05:00
Ell
5c27d14fdf app: add gimp_drawable_filter_set_crop()
Add gimp_drawable_filter_set_crop(), which allows setting an output
crop rectangle for the filter; anything outside the rectangle
doesn't get filtered.  The crop area is combined with the preview
area to determine the filtered area during preview, however, unlike
the preview area, the crop area remains in effect while committing
the filter.

Consequently, when merging a drawable filter, if the filter has a
crop, only process the cropped area.
2018-12-30 05:13:01 -05:00
Ell
7534ae53d6 app: rename gimp_applicator_set_preview() to _set_crop(); add _get_crop()
We're going to use GimpApplicator's output crop for more than just
split previews.  Rename gimp_applicator_set_preview() to
gimp_applicator_set_crop(), and add gimp_applicator_get_crop(),
which returns the output crop rectangle, or NULL if cropping is
disabled.
2018-12-30 05:13:00 -05:00
Ell
b201f73562 app: use GimpDrawableFilter in gimp_drawable_apply_operation()
In gimp_drawable_apply_operation(), use a temporary
GimpDrawableFilter to apply the operation, instead of using a
shadow buffer.  This renders and composits the op directly into the
drawable buffer, avoiding an intermediate buffer, requiring less
space and speeding up processing.
2018-12-29 14:28:43 -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
cba4bc4781 app: in gimp_drawable_merge_filter(), align undo rect to tile grid
In gimp_drawable_merge_filter(), align the region copied to the
undo buffer to the drawable buffer's tile grid, so that the copied
tiles are COWed.
2018-12-28 08:30:59 -05:00
Ell
95393722cc Revert "Bug 796090 - (wrong) true-color preview of GEGL filter ops, ..."
We now perform the conversion of filter output to the drawable
format as part of the individual filter nodes (see the last few
commits), so there's no need for another conversion after the
filter stack.

This reverts commit d6e0ca5054.
2018-12-28 03:56:31 -05:00
Ell
3f45e893bf app: cache result of floating selections
Use an output cache for floating-selection filters, to speed up
anchoring.
2018-12-28 03:55:35 -05:00
Ell
0560c5a6fe app: use drawable format as floating-sel applicator output format
Set the output format of floating-selection applicators to the
target drawable format.  We're going to remove the global
GipDrawable convert-format node, which we use to get correct
previews for indexed drawables, so that each filter now has to do
its own format conversion.
2018-12-28 03:55:34 -05:00
Ell
8e57ee2265 app: in GimpDrawableFilter, use the drawable format as the cache format
In GimpDrawableFilter, set the applicator's output format to the
drawable format, so that the cache uses the drawable format, and so
copying the cached result to the drawble's buffer when comitting
the filter becomes much cheaper, and, in particular, doesn't
require reading tiles out of the swap.  This notably improves
commit speed in large images, at the expense of requiring a few
extra conversions during preview.
2018-12-28 03:55:34 -05:00
Ell
85e454bae8 app: add GimpDrawable::format-changed signal
... which is emitted when the drawable's format is changed.
2018-12-28 03:55:33 -05:00
Ell
ef9b1f6694 app: in GimpLineArt, use "invalidate-preview" signal of input viewable
In GimpLineArt, use the "invalidate-preview" signal of the input
viewable, instead of its "painted" or "rendered" signals, for
asynchronously computing the line art.  Subsequently, remove the
aforementioned signals from GimpDrawable and GimpProjection,
respectively.  This simplifies the code, and reduces the number of
signals.
2018-12-27 17:14:28 -05:00
Ell
ed7ea51fb7 app: remove "Edit -> Fade..."
This commit completely removes the "Edit -> Fade..." feature,
because...

- The main reason is that "fade" requires us to keep two buffers,
  instead of one, for each fadeable undo step, doubling (or worse,
  since the extra buffer might have higher precision than the
  drawable) the space consumed by these steps.  This has notable
  impact when editing large images.  This overhead is incurred even
  when not actually using "fade", and since it seems to be very
  rarely used, this is too wasteful.

- "Fade" is broken in 2.10: when comitting a filter, we copy the
  cached parts of the result into the apply buffer.  However, the
  result cache sits after the mode node, while the apply buffer
  should contain the result of the filter *before* the mode node,
  which can lead to wrong results in the general case.

- The same behavior can be trivially achieved "manually", by
  duplicating the layer, editing the duplicate, and changing its
  opacity/mode.

- If we really want this feature, now that most filters are GEGL
  ops, it makes more sense to just add opacity/mode options to the
  filter tool, instead of having this be a separate step.
2018-12-27 11:44:25 -05:00
Jehan
503775a5a0 app: rename and merge the spline and segment length properties...
... in GimpBucketFillOptions for the line art algorithm.

Inside GimpLineArt, there are still 2 properties, but we don't show them
anymore in the Bucket Fill tool options. One of the main reason is
probably that it's hard to differentiate their usage. One is to close
with curved lines, the other with straight segments. Yet we don't
actually have any control on one or the other. All one knows is that you
can have "holes" in your drawing of a given size and you want them
close-like for filling. Only reason I can see to have 2 types of closure
is whether you'd want to totally disable one type of closure (then you
set it to 0). But this is a very limited reason for making the options
less understandable overall, IMO.
So for the time being, let's show up only a single option which sets
both properties in GimpLineArt. As patdavid says "it makes sense as a
first pass".

Also rename the option to shorter/simpler "Maximum gap length". Thanks
to patdavid and pippin for helping on figuring out this better label!

Finally I am bumping the default for the gaps to 100px. The original
values were ok for the basic small images used in demos, but not for
real life image where it was always too short (even 100px may still be
too short actually, but much better than the 20 and 60px from before!).
2018-12-24 13:33:58 +01:00
Ell
93f4b18704 app: improve gradient color-sampling speed
Improve the speed of gimp_gradient_get_color_at(), which is used by
gimp:gradient during processing when the gradient cache is too big,
by disabling type checking, and inlining and avoiding some function
calls.
2018-12-20 08:32:17 -05:00
Jehan
0a2d066168 app: allow setting line art spline and segment length to 0.
Practically it means that the algorithm won't close line art anymore
with both settings at 0. This can nevertheless still be a very useful
tool when you have a drawing style with well-closed lines. In such a
case, you will still profit from the color flooding under the line art
part of the algorithm.
Moreover with such well-closed zones from start, you don't get the
over-segmentation anymore and the threaded processing will be faster
obviously.
2018-12-17 15:46:47 +01:00
Jehan
cd924f453a app: do not make line art bucket fill a GimpSelectCriterion anymore.
This was my initial choice, but the more I think about it, the less I am
sure this was the right choice. There was some common code (as I was
making a common composite bucket fill once the line art was generated),
but there is also a lot of different code and the functions were filled
of exception when we were doing a line art fill. Also though there is a
bit of color works (the way we decide whether a pixel is part of a
stroke or not, though currently this is basic grayscale threshold), this
is really not the same as other criterions. In particular this was made
obvious on the Select by Color tool where the line art criterion was
completely meaningless and would have had to be opted-out!

This commit split a bit the code. Instead of finding the line art in the
criterion list, I add a third choice to the "Fill whole selection"/"Fill
similar colors" radio. In turn I create a new GimpBucketFillArea type
with the 3 choices, and remove line art value from GimpSelectCriterion.

I am not fully happy yet of this code, as it creates a bit of duplicate
code, and I would appreciate to move some code away from gimpdrawable-*
and gimppickable-* files. This may happen later. I break the work in
pieces to not get too messy.
Also this removes access to the smart colorization from the API, but
that's probably ok as I prefer to not freeze options too early in the
process since API needs to be stable. Probably we should get a concept
of experimental API.
2018-12-12 15:27:48 +01:00
Jehan
db18c679f3 app: reorganize the line art code inside a GimpLineArt object.
The code was too much spread out, in core and tool code, and also it was
made too specific to fill. I'll want to reuse this code at least in the
fuzzy select tool. This will avoid code duplication, and also make this
new process more self-contained and simpler to review later (the
algorithm also has a lot of settings and it is much cleaner to have them
as properties rather than passing these as parameters through many
functions).

The refactoring may not be finished; that's at least a first step.
2018-12-07 22:18:06 +01:00
Ell
c9c2397b0d app: in GimpProjection, fix reinit. of current row when chunk height changes
In GimpProjection's chunk renderer, when the chunk height changes
in the middle of a row, we need to merge the remainder of the
current render area back into the renderer's update region, and
refetch the remainder of the row as the new render area, so that we
don't miss any unrendered area, or re-render already-rendered area,
due to the change in chunk height.  However, we should previously
fail to verify that the fetched area is, in fact, the remainder of
the current row, which could cause us to render the wrong area,
missing parts of the update region.

Fix this, by breaking up some of the chunk-renderer fucntions into
smaller sub-functions, and using those in order to explicitly set
the new render area to the remainder of the current row when the
chunk height changes.  This also avoids erroneously merging the
unflushed update region of the projection into the renderer's
update region.
2018-12-06 08:50:59 -05:00
Ell
411ddb7e48 Revert "app: save images with fractional grid coordinates as version-10 XCFs"
Actually, image grids are saved as parasites, so even though older
GIMP versions round their coordinates upon loading, they maintain
the fractional coordinates when re-saving the image, hence bumping
the XCF version is not really necessary.

This reverts commit 13119efda33a7aba323dc13e6a56207a15a9f000.
2018-12-05 13:52:38 -05:00
Ell
a90322278d app: save images with fractional grid coordinates as version-10 XCFs
Fractional-coordinate support for image grids was added in commit
1572bccc9f, right before the
introduction of XCF version 10.  While images with fractional grid
coordinates can be loaded with earilier versions of GIMP, the grid
coordinates are rounded to the nearest integer.

Bump the minimal XCF version when saving images with fractional
grid coordinates to 10, which should have been the case all along.
2018-12-05 13:33:39 -05:00
Ell
83250eb57c app: don't use direct-buffer fill when some components are masked 2018-12-03 09:54:10 -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
dac9bfe334 app: add "direct" parameter to gimp_projection_flush_now()
Add a boolean "direct" parameter to gimp_projection_flush_now(),
which specifies if the projection buffer should only be invalidated
(FALSE), or rendered directly (TRUE).

Pass TRUE when flushing the projection during painting, so that the
affected regions are rendered in a single step, instead of tile-by-
tile.  We previously only invalidated the projection buffer, but
since we synchronously flush the display right after that, the
invalidated regions would still get rendered, albeit less
efficiently.

Likewise, pass TRUE when benchmarking the projection through the
debug action, and avoid flushing the display, to more accurately
measure the render time.
2018-12-02 10:14:58 -05:00
Ell
42b82419b1 app: another fix to drawable direct-fill criterion
Don't use a direct-buffer fill when filling using a pattern with
alpha, even when the mode is subtractive.
2018-12-02 03:43:25 -05:00
Ell
660f53d300 app: fix drawable direct-fill criterion
Don't use a direct-buffer fill if the mode is subtractive, and the
composite region includes the source.  Currently, this never
actually happens.
2018-12-02 03:33:56 -05:00
Ell
dd8268c0a2 app: optimize simple whole-drawable fill/clear
In gimp_drawable_edit_fill(), when filling/clearing the whole
drawable, without any special compositing (i.e., when there's no
selection, the opacity is 100%, and the layer mode is trivial),
fill/clear the drawable's buffer directly, without using an
applicator.  This makes such operations much faster, especially in
big images.
2018-12-02 03:10:31 -05:00
Ell
45fc4cb4f9 app: add gimp_fill_options_fill_buffer()
... which is similar to gimp_fill_options_create_buffer(), however,
it fills an existing buffer, instead of creating a new buffer.

Implement gimp_fill_options_create_buffer() in terms of the new
function.
2018-12-02 03:10:30 -05:00
Ell
bb9dd049fb app: align drawable undo rectangle to tile grid
When creating a drawable undo from the drawable's buffer, align the
copied rectangle to the buffer's tile grid, so that all the copied
tiles are COWed, saving memory and gaining speed.

Add applied_x and applied_y fields to GimpDrawableUndo, specifying
the position at which to apply the applied_buffer, so that we apply
it in the right place, even if the undo rect has changed due to
alignment.
2018-12-02 03:10:28 -05:00
Ell
f27b38808f app: a few improvements to gimp-scratch
Simplify code a bit, and add branch-prediction annotations.
2018-12-01 10:04:11 -05:00
Ell
8c9eb1c743 app: #include <string.h> in gimp-scratch.h
... for memset().
2018-12-01 06:06:27 -05:00
Ell
5d1a79a34f app: fix definition signature of gimp_scratch_get_total() 2018-12-01 05:58:10 -05:00
Ell
698d1af798 app: add scratch-total variable to the dashboard
Add a scratch-total variable to the dashboard's misc group, showing
the total amount of memory used by the scratch allocator.
2018-12-01 05:55:16 -05:00
Ell
a8a8655285 app: add gimp-scratch allocator
gimp-scratch is a fast memory allocator (on the order of magnitude
of alloca()), suitable for small (up to a few megabytes), short-
lived (usually, bound to the current stack-frame) allocations.
Unlike alloca(), gimp-scratch doesn't use the stack, and is
therefore safer, and will also serve bigger requests, by falling-
back to malloc().

The allocator itself is very simple:  We keep a per-thread stack of
cached memory blocks (allocated using the normal allocator).  When
serving an allocation request, we simply pop the top block off the
stack, and return it. If the block is too small, we replace it with
a big-enough block.  When the block is freed, we push it back to
the top of the stack (note that even though each thread uses a
separate stack, blocks can be migrated between threads, i.e.,
allocated on one thread, and freed on another thread, although this
is not really an intended usage pattern.)  The idea is that the
stacks will ultimately stabalize to contain blocks that can serve
all the encountered allocation patterns, without needing to reisze
any of the blocks; as a consequence, the amount of scratch memory
allocated at any given time should really be kept to a minimum.
2018-12-01 05:55:15 -05:00
Ell
01f9409902 app: in GimpBacktrace Linux backend, don't leak backtrace when dropping threads
Should have been part of commit
a29d040db5.
2018-12-01 04:33:45 -05:00
Ell
c749097dcc app: in GimpBacktrace Linux backend, make blacklisted_thread_names const 2018-12-01 03:52:31 -05:00
Ell
49fd2847ac app: add gimp_async_add_callback_for_object()
... which is similar to gimp_async_add_callback(), taking an
additional GObject argument.  The object is kept alive for the
duration of the callback, and the callback is automatically removed
when the object is destroyed (if it hasn't been already called).

This is analogous to g_signal_connect_object(), compared to
g_signal_connect().
2018-11-30 03:30:51 -05:00
Ell
a779dd3849 app: unref async when removing last callback if idle is pending
In gimp_async_remove_callback(), if removing the last callback
while the callback idle-source is already pending, cancel the idle
source and unref the async object (the async is reffed when adding
the idle source.)
2018-11-30 03:30:51 -05:00
Jehan
d71efdec20 app: add the segment and spline max length options for line art.
We can't just hardcode this. On huge images in particular, you'll want
to increase this value.
2018-11-29 17:29:42 +01:00
Jehan
f7a4ce1051 app: some code cleaning in gimplineart.
In particular, make simpler code in a few places, taking abyss value
into account (rather than checking the position).
2018-11-29 14:13:50 +01:00
Ell
d6f0ca5531 app: use gimp_tile_handler_validate_validate() in GimpProjection
Use gimp_tile_handler_validate_validate(), added in the last
commit, in GimpProjection, in order to render the projection,
instead of separately invalidating the buffer, undoing the
invalidation, and then rendering the graph.  This is more
efficient, and more idiomatic.
2018-11-28 13:26:38 -05:00
Ell
5a623fc54b app: add GimpTileHandlerValidate::{begin,end}_validate() vfuncs
Add begin_validate() and end_validate() virtual functions, and
corresponding free functions, to GimpTileHandlerValidate.  These
functions are called before/after validation happens, and should
perform any necessary steps to prepare for validation.  The default
implementation suspends validation on tile access, so that the
assigned buffer may be accessed without causing validation.

Implement the new functions in GimpTileHandlerProjectable, by
calling gimp_projectable_begin_render() and
gimp_projectable_end_render(), respectively, instead of calling
these functions in the ::validate() implementation (which, in turn,
allows us to use the default ::validate() implementation.)

In GimpProjection, use the new functions in place of
gimp_projectable_{begin,end}_render().
2018-11-28 13:25:33 -05:00
Ell
8a47b68194 app: avoid starting the chunk renderer while finishing drawing a projection
In gimp_projection_finish_draw(), make sure we don't accidentally
re-start the chunk renderer idle source while running the remaining
iterations, in case the chunk height changes, and we need to reinit
the renderer state.
2018-11-28 13:25:32 -05:00
Ell
b07f810273 app: avoid flushing bufferless projections
Don't needlessly flush projections whose buffer hasn't been
allocated yet.  This can happen when opening an image, in which
case the image is flushed before its projection has a buffer.
2018-11-28 13:25:32 -05:00
Jehan
744d67939d app: flood isolated pixels in smart colorization fill.
The smart colorization was leaving irritating single pixels in between
colorized regions, after growing and combining. So let's just flood
these. We don't flood bigger regions (and in particular don't use
gimp_gegl_apply_flood()) on purpose, because there may be small yet
actual regions inside regions which we'd want in other colors. 1-pixel
regions is the extreme case where chances that one wanted it filled are
just higher.
2018-11-27 15:12:18 +01:00
Jehan
6bec0bc82d app: radius map actually not useful during smart colorization grow step.
The distance map has all the information we need already. Also we will
actually grow up to the max radius pixel (middle pixel of a stroke).
After discussing with Aryeom, we realized it was better to fill a stroke
fully (for cases of overflowing, I already added the "Maximum growing
size" property anyway).
2018-11-27 14:59:35 +01:00
Jehan
613bf7c5ab app, libgimpconfig: make various usage of g_file_replace() safer.
When an error occurs, we want to prevent overwriting any previous
version of the file by incomplete contents. So run
g_output_stream_close() with a cancelled GCancellable to do so.
See also discussion in #2565.
2018-11-26 15:50:38 +01:00
Jehan
d2f9549c9f app: add possibility to antialias line art colorization. 2018-11-26 12:33:45 +01:00