2006-12-09 21:33:38 +00:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-24 22:05:25 +00:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2009-01-17 22:28:01 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-24 22:05:25 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-17 22:28:01 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-24 22:05:25 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2018-07-11 23:27:07 +02:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
1997-11-24 22:05:25 +00:00
|
|
|
*/
|
2000-12-15 15:54:17 +00:00
|
|
|
|
app/appenv.h New file. Includes <math.h>. Move G_PI, RINT(), ROUND() etc
1999-09-01 Tor Lillqvist <tml@iki.fi>
* app/appenv.h
* libgimp/gimpmath.h: New file. Includes <math.h>. Move G_PI,
RINT(), ROUND() etc from app/appenv.h here, so plug-ins can
use them, too. Remove some commented-out old stuff in appenv.h.
* libgimp/gimp.h: Include gimpmath.h.
* libgimp/gimp.c (gimp_main): Win32: Don't install signal
handlers, we can't do anything useful in the handler ourselves
anyway (it would be nice to print out a backtrace, but that seems
pretty hard to do, even if not impossible). Let Windows inform the
user about the crash. If the plug-in was compiled with MSVC, and
the user also has it, she is offered a chance to start the
debugger automatically anyway.
* app/*several*.c: Include gimpmath.h for G_PI etc. Don't include
<math.h>, as gimpmath.h includes it.
* plug-ins/*/*many*.c: Include config.h. Don't include <math.h>.
Remove all the duplicated definitions of G_PI and rint(). Use
RINT() instead of rint().
* app/app_procs.[ch]: app_exit() takes a gboolean.
* app/batch.c
* app/commands.c
* app/interface.c: Call app_exit() with FALSE or TRUE.
* app/main.c (on_error): Call gimp_fatal_error. (main): Don't
install any signal handler on Win32 here, either.
* app/errors.c (gimp_fatal_error, gimp_terminate): Win32: Format
the message and call MessageBox with it. g_on_error_query doesn't
do anything useful on Win32, and printf'ing a message to stdout or
stderr doesn't do anything, either, in a windowing application.
1999-09-01 20:30:56 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2009-10-10 15:46:31 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
2013-10-15 01:58:39 +02:00
|
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
2008-10-09 20:24:04 +00:00
|
|
|
#include <gegl.h>
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2006-08-29 14:46:32 +00:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2007-03-09 13:00:01 +00:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
2006-08-29 14:46:32 +00:00
|
|
|
|
2003-09-04 12:18:40 +00:00
|
|
|
#include "core-types.h"
|
2002-08-20 10:22:23 +00:00
|
|
|
|
2013-04-08 21:54:46 +02:00
|
|
|
#include "gegl/gimp-gegl-mask-combine.h"
|
|
|
|
|
2020-05-20 18:16:30 +02:00
|
|
|
#include "gimp.h"
|
2003-09-04 12:18:40 +00:00
|
|
|
#include "gimpchannel.h"
|
|
|
|
#include "gimpchannel-combine.h"
|
2020-05-20 18:16:30 +02:00
|
|
|
#include "gimpimage.h"
|
|
|
|
#include "gimpimage-merge.h"
|
|
|
|
#include "gimpimage-new.h"
|
|
|
|
#include "gimplayer.h"
|
|
|
|
|
|
|
|
#include "vectors/gimpvectors.h"
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
typedef struct
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
GeglRectangle rect;
|
1999-08-22 11:45:31 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
gboolean bounds_known;
|
|
|
|
gboolean empty;
|
|
|
|
GeglRectangle bounds;
|
|
|
|
} GimpChannelCombineData;
|
2001-08-11 14:39:19 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
/* local function prototypes */
|
|
|
|
|
|
|
|
static void gimp_channel_combine_clear (GimpChannel *mask,
|
|
|
|
const GeglRectangle *rect);
|
|
|
|
static void gimp_channel_combine_clear_complement (GimpChannel *mask,
|
|
|
|
const GeglRectangle *rect);
|
|
|
|
|
|
|
|
static gboolean gimp_channel_combine_start (GimpChannel *mask,
|
|
|
|
GimpChannelOps op,
|
|
|
|
const GeglRectangle *rect,
|
|
|
|
gboolean full_extent,
|
|
|
|
gboolean full_value,
|
|
|
|
GimpChannelCombineData *data);
|
|
|
|
static void gimp_channel_combine_end (GimpChannel *mask,
|
|
|
|
GimpChannelCombineData *data);
|
|
|
|
|
|
|
|
|
|
|
|
/* private functions */
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_channel_combine_clear (GimpChannel *mask,
|
|
|
|
const GeglRectangle *rect)
|
|
|
|
{
|
|
|
|
GeglBuffer *buffer;
|
|
|
|
GeglRectangle area;
|
|
|
|
GeglRectangle update_area;
|
|
|
|
|
|
|
|
if (mask->bounds_known && mask->empty)
|
2013-04-08 21:54:46 +02:00
|
|
|
return;
|
2012-03-15 22:58:26 +01:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
if (rect)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
if (rect->width <= 0 || rect->height <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (mask->bounds_known)
|
|
|
|
{
|
|
|
|
if (! gegl_rectangle_intersect (&area,
|
|
|
|
GEGL_RECTANGLE (mask->x1,
|
|
|
|
mask->y1,
|
|
|
|
mask->x2 - mask->x1,
|
|
|
|
mask->y2 - mask->y1),
|
|
|
|
rect))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
area = *rect;
|
|
|
|
}
|
|
|
|
|
|
|
|
update_area = area;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
else
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
if (mask->bounds_known)
|
|
|
|
{
|
|
|
|
area.x = mask->x1;
|
|
|
|
area.y = mask->y1;
|
|
|
|
area.width = mask->x2 - mask->x1;
|
|
|
|
area.height = mask->y2 - mask->y1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
area.x = 0;
|
|
|
|
area.y = 0;
|
|
|
|
area.width = gimp_item_get_width (GIMP_ITEM (mask));
|
|
|
|
area.height = gimp_item_get_height (GIMP_ITEM (mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
update_area = area;
|
|
|
|
|
2019-07-30 16:09:36 +03:00
|
|
|
gegl_rectangle_align_to_buffer (&area, &area, buffer,
|
|
|
|
GEGL_RECTANGLE_ALIGNMENT_SUPERSET);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
|
|
|
|
gegl_buffer_clear (buffer, &area);
|
|
|
|
|
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (mask),
|
|
|
|
update_area.x, update_area.y,
|
|
|
|
update_area.width, update_area.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_channel_combine_clear_complement (GimpChannel *mask,
|
|
|
|
const GeglRectangle *rect)
|
|
|
|
{
|
|
|
|
gint width = gimp_item_get_width (GIMP_ITEM (mask));
|
|
|
|
gint height = gimp_item_get_height (GIMP_ITEM (mask));
|
|
|
|
|
|
|
|
gimp_channel_combine_clear (
|
|
|
|
mask,
|
|
|
|
GEGL_RECTANGLE (0,
|
|
|
|
0,
|
|
|
|
width,
|
|
|
|
rect->y));
|
|
|
|
|
|
|
|
gimp_channel_combine_clear (
|
|
|
|
mask,
|
|
|
|
GEGL_RECTANGLE (0,
|
|
|
|
rect->y + rect->height,
|
|
|
|
width,
|
|
|
|
height - (rect->y + rect->height)));
|
|
|
|
|
|
|
|
gimp_channel_combine_clear (
|
|
|
|
mask,
|
|
|
|
GEGL_RECTANGLE (0,
|
|
|
|
rect->y,
|
|
|
|
rect->x,
|
|
|
|
rect->height));
|
|
|
|
|
|
|
|
gimp_channel_combine_clear (
|
|
|
|
mask,
|
|
|
|
GEGL_RECTANGLE (rect->x + rect->width,
|
|
|
|
rect->y,
|
|
|
|
width - (rect->x + rect->width),
|
|
|
|
rect->height));
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_channel_combine_start (GimpChannel *mask,
|
|
|
|
GimpChannelOps op,
|
|
|
|
const GeglRectangle *rect,
|
|
|
|
gboolean full_extent,
|
|
|
|
gboolean full_value,
|
|
|
|
GimpChannelCombineData *data)
|
|
|
|
{
|
|
|
|
GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
|
|
|
GeglRectangle extent;
|
|
|
|
gboolean intersects;
|
|
|
|
|
|
|
|
extent.x = 0;
|
|
|
|
extent.y = 0;
|
|
|
|
extent.width = gimp_item_get_width (GIMP_ITEM (mask));
|
|
|
|
extent.height = gimp_item_get_height (GIMP_ITEM (mask));
|
|
|
|
|
|
|
|
intersects = gegl_rectangle_intersect (&data->rect, rect, &extent);
|
|
|
|
|
|
|
|
data->bounds_known = mask->bounds_known;
|
|
|
|
data->empty = mask->empty;
|
|
|
|
|
|
|
|
data->bounds.x = mask->x1;
|
|
|
|
data->bounds.y = mask->y1;
|
|
|
|
data->bounds.width = mask->x2 - mask->x1;
|
|
|
|
data->bounds.height = mask->y2 - mask->y1;
|
|
|
|
|
|
|
|
gegl_buffer_freeze_changed (buffer);
|
|
|
|
|
|
|
|
/* Determine new boundary */
|
|
|
|
switch (op)
|
2009-10-10 15:46:31 +02:00
|
|
|
{
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
case GIMP_CHANNEL_OP_REPLACE:
|
|
|
|
gimp_channel_combine_clear (mask, NULL);
|
|
|
|
|
|
|
|
if (! intersects)
|
|
|
|
{
|
|
|
|
data->bounds_known = TRUE;
|
|
|
|
data->empty = TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->bounds_known = FALSE;
|
|
|
|
|
|
|
|
if (full_extent)
|
|
|
|
{
|
|
|
|
data->bounds_known = TRUE;
|
|
|
|
data->empty = FALSE;
|
|
|
|
data->bounds = data->rect;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_CHANNEL_OP_ADD:
|
|
|
|
if (! intersects)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
data->bounds_known = FALSE;
|
|
|
|
|
|
|
|
if (full_extent && (mask->bounds_known ||
|
|
|
|
gegl_rectangle_equal (&data->rect, &extent)))
|
|
|
|
{
|
|
|
|
data->bounds_known = TRUE;
|
|
|
|
data->empty = FALSE;
|
|
|
|
|
|
|
|
if (mask->bounds_known && ! mask->empty)
|
|
|
|
{
|
|
|
|
gegl_rectangle_bounding_box (&data->bounds,
|
|
|
|
&data->bounds, &data->rect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data->bounds = data->rect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_CHANNEL_OP_SUBTRACT:
|
|
|
|
if (intersects && mask->bounds_known)
|
|
|
|
{
|
|
|
|
if (mask->empty)
|
|
|
|
{
|
|
|
|
intersects = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
intersects = gegl_rectangle_intersect (&data->rect,
|
|
|
|
&data->rect,
|
|
|
|
&data->bounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! intersects)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (full_value &&
|
|
|
|
gegl_rectangle_contains (&data->rect,
|
|
|
|
mask->bounds_known ? &data->bounds :
|
|
|
|
&extent))
|
|
|
|
{
|
|
|
|
gimp_channel_combine_clear (mask, NULL);
|
|
|
|
|
|
|
|
data->bounds_known = TRUE;
|
|
|
|
data->empty = TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->bounds_known = FALSE;
|
|
|
|
|
|
|
|
gegl_buffer_set_abyss (buffer, &data->rect);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_CHANNEL_OP_INTERSECT:
|
|
|
|
if (intersects && mask->bounds_known)
|
|
|
|
{
|
|
|
|
if (mask->empty)
|
|
|
|
{
|
|
|
|
intersects = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
intersects = gegl_rectangle_intersect (&data->rect,
|
|
|
|
&data->rect,
|
|
|
|
&data->bounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! intersects)
|
|
|
|
{
|
|
|
|
gimp_channel_combine_clear (mask, NULL);
|
|
|
|
|
|
|
|
data->bounds_known = TRUE;
|
|
|
|
data->empty = TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (full_value && mask->bounds_known &&
|
|
|
|
gegl_rectangle_contains (&data->rect, &data->bounds))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->bounds_known = FALSE;
|
|
|
|
|
|
|
|
gimp_channel_combine_clear_complement (mask, &data->rect);
|
|
|
|
|
|
|
|
gegl_buffer_set_abyss (buffer, &data->rect);
|
|
|
|
break;
|
2009-10-10 15:46:31 +02:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_channel_combine_end (GimpChannel *mask,
|
|
|
|
GimpChannelCombineData *data)
|
|
|
|
{
|
|
|
|
GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
|
|
|
|
|
|
|
gegl_buffer_set_abyss (buffer, gegl_buffer_get_extent (buffer));
|
|
|
|
|
|
|
|
gegl_buffer_thaw_changed (buffer);
|
2003-10-06 12:17:11 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
mask->bounds_known = data->bounds_known;
|
|
|
|
|
|
|
|
if (data->bounds_known)
|
|
|
|
{
|
|
|
|
mask->empty = data->empty;
|
|
|
|
|
|
|
|
if (data->empty)
|
|
|
|
{
|
|
|
|
mask->x1 = 0;
|
|
|
|
mask->y1 = 0;
|
|
|
|
mask->x2 = gimp_item_get_width (GIMP_ITEM (mask));
|
|
|
|
mask->y2 = gimp_item_get_height (GIMP_ITEM (mask));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask->x1 = data->bounds.x;
|
|
|
|
mask->y1 = data->bounds.y;
|
|
|
|
mask->x2 = data->bounds.x + data->bounds.width;
|
|
|
|
mask->y2 = data->bounds.y + data->bounds.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (mask),
|
|
|
|
data->rect.x, data->rect.y,
|
|
|
|
data->rect.width, data->rect.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_channel_combine_rect (GimpChannel *mask,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h)
|
|
|
|
{
|
|
|
|
GimpChannelCombineData data;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
|
|
|
if (gimp_channel_combine_start (mask, op, GEGL_RECTANGLE (x, y, w, h),
|
|
|
|
TRUE, TRUE, &data))
|
|
|
|
{
|
|
|
|
GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
|
|
|
|
|
|
|
gimp_gegl_mask_combine_rect (buffer, op, x, y, w, h);
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_channel_combine_end (mask, &data);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-03-18 16:22:14 +00:00
|
|
|
gimp_channel_combine_ellipse (GimpChannel *mask,
|
2004-07-18 19:31:29 +00:00
|
|
|
GimpChannelOps op,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h,
|
|
|
|
gboolean antialias)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2006-10-18 18:54:28 +00:00
|
|
|
gimp_channel_combine_ellipse_rect (mask, op, x, y, w, h,
|
|
|
|
w / 2.0, h / 2.0, antialias);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_channel_combine_ellipse_rect (GimpChannel *mask,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h,
|
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 09:27:08 -04:00
|
|
|
gdouble rx,
|
|
|
|
gdouble ry,
|
2006-10-18 18:54:28 +00:00
|
|
|
gboolean antialias)
|
|
|
|
{
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
GimpChannelCombineData data;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2001-08-11 14:39:19 +00:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
2012-03-17 12:45:58 +01:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
if (gimp_channel_combine_start (mask, op, GEGL_RECTANGLE (x, y, w, h),
|
|
|
|
TRUE, FALSE, &data))
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
2012-03-17 12:45:58 +01:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
gimp_gegl_mask_combine_ellipse_rect (buffer, op, x, y, w, h,
|
|
|
|
rx, ry, antialias);
|
2004-07-19 14:25:59 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
gimp_channel_combine_end (mask, &data);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-03-18 16:22:14 +00:00
|
|
|
gimp_channel_combine_mask (GimpChannel *mask,
|
2006-04-12 12:49:29 +00:00
|
|
|
GimpChannel *add_on,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gint off_x,
|
|
|
|
gint off_y)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2013-04-08 21:54:46 +02:00
|
|
|
GeglBuffer *add_on_buffer;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2001-08-11 14:39:19 +00:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (add_on));
|
|
|
|
|
2012-03-21 00:42:44 +01:00
|
|
|
add_on_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (add_on));
|
2012-03-19 03:15:30 +01:00
|
|
|
|
2013-04-08 21:54:46 +02:00
|
|
|
gimp_channel_combine_buffer (mask, add_on_buffer,
|
|
|
|
op, off_x, off_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_channel_combine_buffer (GimpChannel *mask,
|
|
|
|
GeglBuffer *add_on_buffer,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gint off_x,
|
|
|
|
gint off_y)
|
|
|
|
{
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
GimpChannelCombineData data;
|
2012-03-19 03:15:30 +01:00
|
|
|
|
2013-04-08 21:54:46 +02:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
g_return_if_fail (GEGL_IS_BUFFER (add_on_buffer));
|
2012-03-19 03:15:30 +01:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
if (gimp_channel_combine_start (mask, op,
|
|
|
|
GEGL_RECTANGLE (
|
2020-02-03 19:57:41 +02:00
|
|
|
off_x + gegl_buffer_get_x (add_on_buffer),
|
|
|
|
off_y + gegl_buffer_get_y (add_on_buffer),
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
gegl_buffer_get_width (add_on_buffer),
|
|
|
|
gegl_buffer_get_height (add_on_buffer)),
|
|
|
|
FALSE, FALSE, &data))
|
|
|
|
{
|
|
|
|
GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
2001-01-29 02:45:02 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
gimp_gegl_mask_combine_buffer (buffer, add_on_buffer, op,
|
|
|
|
off_x, off_y);
|
|
|
|
}
|
2003-10-06 12:17:11 +00:00
|
|
|
|
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
d0ae244fe85a502446fe9c7b82afdf1b89498966), rendering the bounds-
recalculation code ineffective. This avoids manually recalculating
the bounds in many cases, speeding up selection operations.
2019-03-20 15:30:35 -04:00
|
|
|
gimp_channel_combine_end (mask, &data);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2020-05-20 18:16:30 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_channel_combine_items:
|
|
|
|
* @channel:
|
|
|
|
* @items:
|
|
|
|
* @op:
|
|
|
|
*
|
|
|
|
* Edit @channel with the given @items, according to the boolean @op.
|
|
|
|
* @items need to belong to the same image, but it doesn't have to be
|
|
|
|
* the owner image of @channel.
|
|
|
|
* If @items contain a single layer, it will be used as-is, without
|
|
|
|
* caring about opacity, mode or visibility.
|
|
|
|
* If @items contain several layers, they will be used composited using
|
|
|
|
* their opacity, mode, visibility, etc. properties within the image
|
|
|
|
* (similar as if a "merge visible" had been applied to the image then
|
|
|
|
* the resulting layer used alone).
|
|
|
|
* If @items contain channels or vectors, they will be added as a set
|
|
|
|
* (i.e. as a single item which is an union of other items). E.g. an
|
|
|
|
* combine in GIMP_CHANNEL_OP_INTERSECT mode does not intersect all
|
|
|
|
* @items with each other and @channel. It first adds-alike all @items
|
|
|
|
* together, then intersects the result with @channel.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gimp_channel_combine_items (GimpChannel *mask,
|
|
|
|
GList *items,
|
|
|
|
GimpChannelOps op)
|
|
|
|
{
|
|
|
|
GimpImage *image;
|
|
|
|
GimpImage *items_image = NULL;
|
|
|
|
GimpImage *temp_image = NULL;
|
|
|
|
|
|
|
|
GimpChannel *channel = NULL;
|
|
|
|
GList *layers = NULL;
|
|
|
|
GList *iter;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
g_return_if_fail (g_list_length (items) > 0);
|
|
|
|
|
|
|
|
for (iter = items; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (iter->data) ||
|
|
|
|
GIMP_IS_CHANNEL (iter->data) ||
|
|
|
|
GIMP_IS_VECTORS (iter->data));
|
|
|
|
|
|
|
|
if (items_image == NULL)
|
|
|
|
items_image = gimp_item_get_image (iter->data);
|
|
|
|
else
|
|
|
|
g_return_if_fail (items_image == gimp_item_get_image (iter->data));
|
|
|
|
|
|
|
|
if (GIMP_IS_LAYER (iter->data))
|
|
|
|
layers = g_list_prepend (layers, iter->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
image = gimp_item_get_image (GIMP_ITEM (mask));
|
|
|
|
if (g_list_length (layers) > 1)
|
|
|
|
{
|
|
|
|
GList *merged_layers;
|
|
|
|
|
app: rework and fix the logic for copy-pasting multiple drawables.
There were a lot of incertainty of what should happen when we copy layers being
descendant of each other (i.e. when you select a group layer and some of its
children), then when you paste such data. So we sat down with Aryeom and tried
to come up with some consistent behavior which is somewhat expectable, but also
which would allow the most use-case.
Otherwise it was making very weird result when pasting the data, duplicating
some layers and whatnot, which was obviously a buggy behavior and never the
expected result.
We decided that if you select one leaf item, then even if you also selected a
parent item, it would be as though the parent was not selected. This is very
often what you expect anyway when you select a whole bunch of layers and would
work well if, say, you shift-click over many layers in sub-groups. Then you
wouldn't have to manually ctrl-click to unselect every group.
Then what if you were instead expecting to copy many groups? Then you could
shift-click the group arrow, closing all same-level groups. Once they are all
closed, you can shift-click the groups to only select group layers, not their
contents.
This way, both use cases are still quite doable easily with this default choice.
2022-11-12 18:28:58 +01:00
|
|
|
temp_image = gimp_image_new_from_drawables (image->gimp, items, FALSE, FALSE);
|
2020-05-20 18:16:30 +02:00
|
|
|
merged_layers = gimp_image_merge_visible_layers (temp_image,
|
|
|
|
gimp_get_user_context (temp_image->gimp),
|
|
|
|
GIMP_CLIP_TO_IMAGE,
|
|
|
|
FALSE, TRUE, NULL);
|
|
|
|
g_return_if_fail (g_list_length (merged_layers) == 1);
|
|
|
|
gimp_item_to_selection (GIMP_ITEM (merged_layers->data),
|
|
|
|
GIMP_CHANNEL_OP_REPLACE,
|
|
|
|
TRUE, FALSE, 0.0, 0.0);
|
|
|
|
channel = gimp_image_get_mask (temp_image);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! channel)
|
|
|
|
{
|
|
|
|
channel = gimp_channel_new (image,
|
2020-07-06 23:15:12 +02:00
|
|
|
gimp_image_get_width (image),
|
|
|
|
gimp_image_get_height (image),
|
|
|
|
NULL, NULL);
|
2020-05-20 18:16:30 +02:00
|
|
|
gimp_channel_clear (channel, NULL, FALSE);
|
|
|
|
|
|
|
|
if (g_list_length (layers) == 1)
|
2020-07-06 23:15:12 +02:00
|
|
|
{
|
|
|
|
if (gimp_drawable_has_alpha (layers->data))
|
|
|
|
{
|
|
|
|
GimpChannel *alpha;
|
2020-10-21 17:36:58 +02:00
|
|
|
gint offset_x;
|
|
|
|
gint offset_y;
|
2020-07-06 23:15:12 +02:00
|
|
|
|
|
|
|
alpha = gimp_channel_new_from_alpha (image,
|
|
|
|
layers->data, NULL, NULL);
|
2020-10-21 17:36:58 +02:00
|
|
|
gimp_item_get_offset (layers->data, &offset_x, &offset_y);
|
2020-07-06 23:15:12 +02:00
|
|
|
gimp_channel_combine_mask (channel, alpha,
|
2020-10-21 17:36:58 +02:00
|
|
|
GIMP_CHANNEL_OP_REPLACE,
|
|
|
|
offset_x, offset_y);
|
2020-07-06 23:15:12 +02:00
|
|
|
g_object_unref (alpha);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_channel_all (channel, FALSE);
|
|
|
|
}
|
|
|
|
}
|
2020-05-20 18:16:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (iter = items; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
if (! GIMP_IS_LAYER (iter->data))
|
2020-11-26 16:18:04 +01:00
|
|
|
{
|
|
|
|
gint offset_x;
|
|
|
|
gint offset_y;
|
|
|
|
|
|
|
|
gimp_item_get_offset (iter->data, &offset_x, &offset_y);
|
|
|
|
gimp_channel_combine_buffer (channel,
|
|
|
|
gimp_drawable_get_buffer (GIMP_DRAWABLE (iter->data)),
|
|
|
|
GIMP_CHANNEL_OP_ADD, offset_x, offset_y);
|
|
|
|
}
|
2020-05-20 18:16:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gimp_channel_combine_buffer (mask,
|
|
|
|
gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
|
|
|
|
op, 0, 0);
|
|
|
|
|
|
|
|
if (temp_image)
|
|
|
|
g_object_unref (temp_image);
|
|
|
|
else
|
|
|
|
g_object_unref (channel);
|
|
|
|
|
|
|
|
g_list_free (layers);
|
|
|
|
}
|