2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-25 06:05:25 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-25 06:05:25 +08: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
|
2009-01-18 06:28:01 +08:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-17 05:37:03 +08: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-02 04:30:56 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <string.h>
|
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-02 04:30:56 +08:00
|
|
|
|
2008-10-10 04:24:04 +08:00
|
|
|
#include <gegl.h>
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2008-12-28 00:04:43 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2009-04-23 03:22:08 +08:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
2008-12-28 00:04:43 +08:00
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
#include "paint-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2001-05-15 19:25:25 +08:00
|
|
|
#include "base/pixel-region.h"
|
|
|
|
#include "base/temp-buf.h"
|
|
|
|
|
2001-04-07 23:58:26 +08:00
|
|
|
#include "paint-funcs/paint-funcs.h"
|
|
|
|
|
2012-03-22 21:13:17 +08:00
|
|
|
#include "gegl/gimp-gegl-utils.h"
|
|
|
|
|
2003-02-14 22:14:29 +08:00
|
|
|
#include "core/gimp.h"
|
2009-04-23 03:22:08 +08:00
|
|
|
#include "core/gimp-utils.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpdrawable.h"
|
|
|
|
#include "core/gimpimage.h"
|
2003-02-13 19:23:50 +08:00
|
|
|
#include "core/gimpimage-undo.h"
|
2005-08-29 03:17:44 +08:00
|
|
|
#include "core/gimppickable.h"
|
2008-08-14 01:30:08 +08:00
|
|
|
#include "core/gimpprojection.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
#include "gimppaintcore.h"
|
2007-02-04 02:48:00 +08:00
|
|
|
#include "gimppaintcoreundo.h"
|
2002-06-17 18:34:28 +08:00
|
|
|
#include "gimppaintoptions.h"
|
2001-03-08 09:07:03 +08:00
|
|
|
|
2004-06-06 00:21:41 +08:00
|
|
|
#include "gimpairbrush.h"
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2004-06-06 00:21:41 +08:00
|
|
|
#include "gimp-intl.h"
|
2000-05-29 16:40:29 +08:00
|
|
|
|
2011-01-08 02:45:29 +08:00
|
|
|
#define STROKE_BUFFER_INIT_SIZE 2000
|
2004-07-19 22:37:40 +08:00
|
|
|
|
2006-09-03 21:16:58 +08:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
PROP_UNDO_DESC
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-05-26 04:41:09 +08:00
|
|
|
/* local function prototypes */
|
2001-01-24 07:56:18 +08:00
|
|
|
|
2004-05-26 20:55:10 +08:00
|
|
|
static void gimp_paint_core_finalize (GObject *object);
|
2006-09-03 21:16:58 +08:00
|
|
|
static void gimp_paint_core_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void gimp_paint_core_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec);
|
2004-05-26 20:55:10 +08:00
|
|
|
|
|
|
|
static gboolean gimp_paint_core_real_start (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
2009-04-18 04:29:25 +08:00
|
|
|
const GimpCoords *coords,
|
2006-09-27 04:55:40 +08:00
|
|
|
GError **error);
|
2004-05-26 20:55:10 +08:00
|
|
|
static gboolean gimp_paint_core_real_pre_paint (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *options,
|
2004-07-19 22:37:40 +08:00
|
|
|
GimpPaintState paint_state,
|
2004-05-27 00:13:53 +08:00
|
|
|
guint32 time);
|
2004-05-26 20:55:10 +08:00
|
|
|
static void gimp_paint_core_real_paint (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *options,
|
2009-05-03 18:08:21 +08:00
|
|
|
const GimpCoords *coords,
|
2004-07-19 22:37:40 +08:00
|
|
|
GimpPaintState paint_state,
|
2004-05-27 00:13:53 +08:00
|
|
|
guint32 time);
|
2004-06-14 20:52:33 +08:00
|
|
|
static void gimp_paint_core_real_post_paint (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *options,
|
2004-07-19 22:37:40 +08:00
|
|
|
GimpPaintState paint_state,
|
2004-06-14 20:52:33 +08:00
|
|
|
guint32 time);
|
2004-05-26 20:55:10 +08:00
|
|
|
static void gimp_paint_core_real_interpolate (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
2004-05-27 00:13:53 +08:00
|
|
|
GimpPaintOptions *options,
|
|
|
|
guint32 time);
|
2012-04-02 03:20:12 +08:00
|
|
|
static GeglBuffer *
|
|
|
|
gimp_paint_core_real_get_paint_buffer (GimpPaintCore *core,
|
2004-05-26 20:55:10 +08:00
|
|
|
GimpDrawable *drawable,
|
2009-05-18 04:45:06 +08:00
|
|
|
GimpPaintOptions *options,
|
2012-04-02 03:20:12 +08:00
|
|
|
const GimpCoords *coords,
|
|
|
|
gint *paint_buffer_x,
|
|
|
|
gint *paint_buffer_y);
|
2007-02-04 02:48:00 +08:00
|
|
|
static GimpUndo* gimp_paint_core_real_push_undo (GimpPaintCore *core,
|
|
|
|
GimpImage *image,
|
|
|
|
const gchar *undo_desc);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2012-03-31 23:00:48 +08:00
|
|
|
static void paint_mask_to_canvas_buffer (GimpPaintCore *core,
|
2004-05-28 17:34:13 +08:00
|
|
|
PixelRegion *paint_maskPR,
|
|
|
|
gdouble paint_opacity);
|
2012-03-31 23:00:48 +08:00
|
|
|
static void paint_mask_to_paint_area (GimpPaintCore *core,
|
2004-05-28 17:34:13 +08:00
|
|
|
PixelRegion *paint_maskPR,
|
|
|
|
gdouble paint_opacity);
|
2012-03-31 23:00:48 +08:00
|
|
|
static void canvas_buffer_to_paint_area (GimpPaintCore *core);
|
2004-05-26 04:41:09 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-05-15 17:46:31 +08:00
|
|
|
G_DEFINE_TYPE (GimpPaintCore, gimp_paint_core, GIMP_TYPE_OBJECT)
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-12-08 05:11:53 +08:00
|
|
|
#define parent_class gimp_paint_core_parent_class
|
2001-02-28 03:18:01 +08:00
|
|
|
|
2005-12-08 05:11:53 +08:00
|
|
|
static gint global_core_ID = 1;
|
2001-02-27 13:21:12 +08:00
|
|
|
|
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
2002-02-15 03:31:16 +08:00
|
|
|
gimp_paint_core_class_init (GimpPaintCoreClass *klass)
|
2001-02-27 13:21:12 +08:00
|
|
|
{
|
2004-05-26 04:41:09 +08:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2001-02-28 03:18:01 +08:00
|
|
|
|
2006-09-03 21:16:58 +08:00
|
|
|
object_class->finalize = gimp_paint_core_finalize;
|
|
|
|
object_class->set_property = gimp_paint_core_set_property;
|
|
|
|
object_class->get_property = gimp_paint_core_get_property;
|
|
|
|
|
|
|
|
klass->start = gimp_paint_core_real_start;
|
|
|
|
klass->pre_paint = gimp_paint_core_real_pre_paint;
|
|
|
|
klass->paint = gimp_paint_core_real_paint;
|
|
|
|
klass->post_paint = gimp_paint_core_real_post_paint;
|
|
|
|
klass->interpolate = gimp_paint_core_real_interpolate;
|
2012-04-02 03:20:12 +08:00
|
|
|
klass->get_paint_buffer = gimp_paint_core_real_get_paint_buffer;
|
2006-09-03 21:16:58 +08:00
|
|
|
klass->push_undo = gimp_paint_core_real_push_undo;
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_UNDO_DESC,
|
|
|
|
g_param_spec_string ("undo-desc", NULL, NULL,
|
|
|
|
_("Paint"),
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
2001-02-27 13:21:12 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
2002-02-15 03:31:16 +08:00
|
|
|
gimp_paint_core_init (GimpPaintCore *core)
|
2001-02-28 03:18:01 +08:00
|
|
|
{
|
2012-03-30 22:24:09 +08:00
|
|
|
core->ID = global_core_ID++;
|
2002-02-13 22:50:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2002-02-15 03:31:16 +08:00
|
|
|
gimp_paint_core_finalize (GObject *object)
|
2002-02-13 22:50:37 +08:00
|
|
|
{
|
2004-05-26 04:41:09 +08:00
|
|
|
GimpPaintCore *core = GIMP_PAINT_CORE (object);
|
2002-02-13 22:50:37 +08:00
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
gimp_paint_core_cleanup (core);
|
2002-02-13 22:50:37 +08:00
|
|
|
|
2006-09-03 21:16:58 +08:00
|
|
|
g_free (core->undo_desc);
|
|
|
|
core->undo_desc = NULL;
|
|
|
|
|
2012-02-07 21:06:12 +08:00
|
|
|
if (core->stroke_buffer)
|
|
|
|
{
|
|
|
|
g_array_free (core->stroke_buffer, TRUE);
|
|
|
|
core->stroke_buffer = NULL;
|
|
|
|
}
|
|
|
|
|
2002-02-13 22:50:37 +08:00
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2001-02-28 03:18:01 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-09-03 21:16:58 +08:00
|
|
|
static void
|
|
|
|
gimp_paint_core_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpPaintCore *core = GIMP_PAINT_CORE (object);
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_UNDO_DESC:
|
|
|
|
g_free (core->undo_desc);
|
|
|
|
core->undo_desc = g_value_dup_string (value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_paint_core_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpPaintCore *core = GIMP_PAINT_CORE (object);
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_UNDO_DESC:
|
|
|
|
g_value_set_string (value, core->undo_desc);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-26 20:55:10 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_paint_core_real_start (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
2009-04-18 04:29:25 +08:00
|
|
|
const GimpCoords *coords,
|
2006-09-27 04:55:40 +08:00
|
|
|
GError **error)
|
2004-05-26 20:55:10 +08:00
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2004-07-19 22:37:40 +08:00
|
|
|
gimp_paint_core_real_pre_paint (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
GimpPaintState paint_state,
|
|
|
|
guint32 time)
|
2004-05-26 20:55:10 +08:00
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-07-19 22:37:40 +08:00
|
|
|
gimp_paint_core_real_paint (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
2009-05-03 18:08:21 +08:00
|
|
|
const GimpCoords *coords,
|
2004-07-19 22:37:40 +08:00
|
|
|
GimpPaintState paint_state,
|
|
|
|
guint32 time)
|
2004-05-26 20:55:10 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2004-06-14 20:52:33 +08:00
|
|
|
static void
|
2004-07-19 22:37:40 +08:00
|
|
|
gimp_paint_core_real_post_paint (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
GimpPaintState paint_state,
|
|
|
|
guint32 time)
|
2004-06-14 20:52:33 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2004-05-26 20:55:10 +08:00
|
|
|
static void
|
|
|
|
gimp_paint_core_real_interpolate (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
2004-05-27 00:13:53 +08:00
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
guint32 time)
|
2004-05-26 20:55:10 +08:00
|
|
|
{
|
2004-05-27 00:13:53 +08:00
|
|
|
gimp_paint_core_paint (core, drawable, paint_options,
|
2004-07-19 22:37:40 +08:00
|
|
|
GIMP_PAINT_STATE_MOTION, time);
|
2004-05-26 20:55:10 +08:00
|
|
|
|
|
|
|
core->last_coords = core->cur_coords;
|
|
|
|
}
|
|
|
|
|
2012-04-02 03:20:12 +08:00
|
|
|
static GeglBuffer *
|
|
|
|
gimp_paint_core_real_get_paint_buffer (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
gint *paint_buffer_x,
|
|
|
|
gint *paint_buffer_y)
|
2004-05-26 20:55:10 +08:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-04 02:48:00 +08:00
|
|
|
static GimpUndo *
|
|
|
|
gimp_paint_core_real_push_undo (GimpPaintCore *core,
|
|
|
|
GimpImage *image,
|
|
|
|
const gchar *undo_desc)
|
|
|
|
{
|
|
|
|
return gimp_image_undo_push (image, GIMP_TYPE_PAINT_CORE_UNDO,
|
|
|
|
GIMP_UNDO_PAINT, undo_desc,
|
|
|
|
0,
|
|
|
|
"paint-core", core,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
2007-04-01 00:43:41 +08:00
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2004-07-19 22:37:40 +08:00
|
|
|
gimp_paint_core_paint (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
GimpPaintState paint_state,
|
|
|
|
guint32 time)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-06-14 20:52:33 +08:00
|
|
|
GimpPaintCoreClass *core_class;
|
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-05-26 04:41:09 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
2003-03-04 02:43:11 +08:00
|
|
|
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options));
|
2002-02-15 03:31:16 +08:00
|
|
|
|
2004-06-14 20:52:33 +08:00
|
|
|
core_class = GIMP_PAINT_CORE_GET_CLASS (core);
|
|
|
|
|
|
|
|
if (core_class->pre_paint (core, drawable,
|
|
|
|
paint_options,
|
|
|
|
paint_state, time))
|
2002-02-16 01:44:05 +08:00
|
|
|
{
|
2011-04-21 03:00:35 +08:00
|
|
|
|
2011-09-12 03:31:59 +08:00
|
|
|
if (paint_state == GIMP_PAINT_STATE_MOTION)
|
|
|
|
{
|
|
|
|
/* Save coordinates for gimp_paint_core_interpolate() */
|
|
|
|
core->last_paint.x = core->cur_coords.x;
|
|
|
|
core->last_paint.y = core->cur_coords.y;
|
|
|
|
}
|
|
|
|
|
2004-06-14 20:52:33 +08:00
|
|
|
core_class->paint (core, drawable,
|
|
|
|
paint_options,
|
2009-05-03 18:08:21 +08:00
|
|
|
&core->cur_coords,
|
2004-06-14 20:52:33 +08:00
|
|
|
paint_state, time);
|
|
|
|
|
|
|
|
core_class->post_paint (core, drawable,
|
|
|
|
paint_options,
|
|
|
|
paint_state, time);
|
2004-05-26 04:41:09 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2000-03-05 08:06:11 +08:00
|
|
|
gboolean
|
2006-09-27 04:55:40 +08:00
|
|
|
gimp_paint_core_start (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
2009-04-18 04:29:25 +08:00
|
|
|
const GimpCoords *coords,
|
2006-09-27 04:55:40 +08:00
|
|
|
GError **error)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-05-26 20:55:10 +08:00
|
|
|
GimpItem *item;
|
2001-07-07 20:17:23 +08:00
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE);
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
|
2004-05-26 04:41:09 +08:00
|
|
|
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
|
2003-03-04 02:43:11 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE);
|
2002-02-15 03:31:16 +08:00
|
|
|
g_return_val_if_fail (coords != NULL, FALSE);
|
2006-09-27 04:55:40 +08:00
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-05-26 04:41:09 +08:00
|
|
|
item = GIMP_ITEM (drawable);
|
2011-01-08 02:45:29 +08:00
|
|
|
|
2011-01-09 05:18:56 +08:00
|
|
|
if (core->stroke_buffer)
|
|
|
|
{
|
|
|
|
g_array_free (core->stroke_buffer, TRUE);
|
|
|
|
core->stroke_buffer = NULL;
|
|
|
|
}
|
2011-01-08 02:45:29 +08:00
|
|
|
|
|
|
|
core->stroke_buffer = g_array_sized_new (TRUE, TRUE,
|
2011-01-09 05:18:56 +08:00
|
|
|
sizeof (GimpCoords),
|
2011-01-08 02:45:29 +08:00
|
|
|
STROKE_BUFFER_INIT_SIZE);
|
2002-02-26 01:58:50 +08:00
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
core->cur_coords = *coords;
|
1998-06-06 11:49:01 +08:00
|
|
|
|
2004-05-26 20:55:10 +08:00
|
|
|
if (! GIMP_PAINT_CORE_GET_CLASS (core)->start (core, drawable,
|
|
|
|
paint_options,
|
2006-09-27 04:55:40 +08:00
|
|
|
coords, error))
|
1999-10-27 02:27:27 +08:00
|
|
|
{
|
2004-05-26 04:41:09 +08:00
|
|
|
return FALSE;
|
2003-07-25 00:35:25 +08:00
|
|
|
}
|
2002-02-13 22:50:37 +08:00
|
|
|
|
2002-02-07 19:33:01 +08:00
|
|
|
/* Allocate the undo structure */
|
2012-03-22 23:29:33 +08:00
|
|
|
if (core->undo_buffer)
|
|
|
|
g_object_unref (core->undo_buffer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2012-03-22 23:29:33 +08:00
|
|
|
core->undo_buffer = gimp_gegl_buffer_dup (gimp_drawable_get_buffer (drawable));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-08-29 03:17:44 +08:00
|
|
|
/* Allocate the saved proj structure */
|
2012-03-30 22:24:09 +08:00
|
|
|
if (core->saved_proj_buffer)
|
|
|
|
{
|
|
|
|
g_object_unref (core->saved_proj_buffer);
|
|
|
|
core->saved_proj_buffer = NULL;
|
|
|
|
}
|
2007-04-01 00:43:41 +08:00
|
|
|
|
2005-08-29 03:17:44 +08:00
|
|
|
if (core->use_saved_proj)
|
|
|
|
{
|
2008-11-04 20:07:17 +08:00
|
|
|
GimpImage *image = gimp_item_get_image (item);
|
|
|
|
GimpPickable *pickable = GIMP_PICKABLE (gimp_image_get_projection (image));
|
2012-03-30 22:24:09 +08:00
|
|
|
GeglBuffer *buffer = gimp_pickable_get_buffer (pickable);
|
2005-08-29 03:17:44 +08:00
|
|
|
|
2012-03-30 22:24:09 +08:00
|
|
|
core->saved_proj_buffer = gimp_gegl_buffer_dup (buffer);
|
2005-08-29 03:17:44 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Allocate the canvas blocks structure */
|
2012-03-30 22:38:52 +08:00
|
|
|
if (core->canvas_buffer)
|
|
|
|
g_object_unref (core->canvas_buffer);
|
2002-02-07 19:33:01 +08:00
|
|
|
|
2012-03-30 22:38:52 +08:00
|
|
|
core->canvas_buffer =
|
|
|
|
gimp_gegl_buffer_new (GIMP_GEGL_RECT (0, 0,
|
|
|
|
gimp_item_get_width (item),
|
|
|
|
gimp_item_get_height (item)),
|
|
|
|
babl_format ("Y u8"));
|
|
|
|
gegl_buffer_clear (core->canvas_buffer, NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Get the initial undo extents */
|
|
|
|
|
2009-05-03 18:19:07 +08:00
|
|
|
core->x1 = core->x2 = core->cur_coords.x;
|
|
|
|
core->y1 = core->y2 = core->cur_coords.y;
|
2002-06-13 03:18:34 +08:00
|
|
|
|
|
|
|
core->last_paint.x = -1e6;
|
|
|
|
core->last_paint.y = -1e6;
|
2003-07-10 20:13:21 +08:00
|
|
|
|
2007-11-13 18:59:32 +08:00
|
|
|
/* Freeze the drawable preview so that it isn't constantly updated. */
|
|
|
|
gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable));
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-02-16 01:44:05 +08:00
|
|
|
void
|
|
|
|
gimp_paint_core_finish (GimpPaintCore *core,
|
2008-10-25 19:59:03 +08:00
|
|
|
GimpDrawable *drawable,
|
|
|
|
gboolean push_undo)
|
2002-02-16 01:44:05 +08:00
|
|
|
{
|
2006-09-03 21:16:58 +08:00
|
|
|
GimpImage *image;
|
2002-02-16 01:44:05 +08:00
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-05-26 04:41:09 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
2011-01-08 02:45:29 +08:00
|
|
|
|
2011-01-09 05:18:56 +08:00
|
|
|
if (core->stroke_buffer)
|
|
|
|
{
|
|
|
|
g_array_free (core->stroke_buffer, TRUE);
|
|
|
|
core->stroke_buffer = NULL;
|
|
|
|
}
|
2002-02-16 01:44:05 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
2002-02-26 01:58:50 +08:00
|
|
|
|
2002-02-16 01:44:05 +08:00
|
|
|
/* Determine if any part of the image has been altered--
|
|
|
|
* if nothing has, then just return...
|
|
|
|
*/
|
2003-02-14 22:14:29 +08:00
|
|
|
if ((core->x2 == core->x1) || (core->y2 == core->y1))
|
2010-02-20 03:59:25 +08:00
|
|
|
{
|
|
|
|
gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable));
|
|
|
|
return;
|
|
|
|
}
|
2002-02-16 01:44:05 +08:00
|
|
|
|
2008-10-25 19:59:03 +08:00
|
|
|
if (push_undo)
|
|
|
|
{
|
2012-03-22 21:13:17 +08:00
|
|
|
GeglBuffer *buffer;
|
2012-03-23 10:04:14 +08:00
|
|
|
gint x, y, width, height;
|
|
|
|
|
|
|
|
gimp_rectangle_intersect (core->x1, core->y1,
|
|
|
|
core->x2 - core->x1, core->y2 - core->y1,
|
|
|
|
0, 0,
|
|
|
|
gimp_item_get_width (GIMP_ITEM (drawable)),
|
|
|
|
gimp_item_get_height (GIMP_ITEM (drawable)),
|
|
|
|
&x, &y, &width, &height);
|
2012-03-22 21:13:17 +08:00
|
|
|
|
2008-10-25 19:59:03 +08:00
|
|
|
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT,
|
|
|
|
core->undo_desc);
|
|
|
|
|
|
|
|
GIMP_PAINT_CORE_GET_CLASS (core)->push_undo (core, image, NULL);
|
2002-02-16 01:44:05 +08:00
|
|
|
|
2012-03-23 10:04:14 +08:00
|
|
|
buffer = gimp_gegl_buffer_new (GIMP_GEGL_RECT (0, 0, width, height),
|
2012-03-22 21:13:17 +08:00
|
|
|
gimp_drawable_get_format (drawable));
|
|
|
|
|
2012-03-22 23:29:33 +08:00
|
|
|
gegl_buffer_copy (core->undo_buffer,
|
2012-03-23 10:04:14 +08:00
|
|
|
GIMP_GEGL_RECT (x, y, width, height),
|
2012-03-22 21:13:17 +08:00
|
|
|
buffer,
|
|
|
|
GIMP_GEGL_RECT (0, 0, 0, 0));
|
|
|
|
|
2008-10-25 19:59:03 +08:00
|
|
|
gimp_drawable_push_undo (drawable, NULL,
|
2012-03-23 10:04:14 +08:00
|
|
|
buffer, x, y, width, height);
|
2012-03-22 21:13:17 +08:00
|
|
|
|
|
|
|
g_object_unref (buffer);
|
2002-02-16 01:44:05 +08:00
|
|
|
|
2008-10-25 19:59:03 +08:00
|
|
|
gimp_image_undo_group_end (image);
|
|
|
|
}
|
2003-05-27 01:02:06 +08:00
|
|
|
|
2012-03-22 23:29:33 +08:00
|
|
|
g_object_unref (core->undo_buffer);
|
|
|
|
core->undo_buffer = NULL;
|
2002-02-16 01:44:05 +08:00
|
|
|
|
2012-03-30 22:24:09 +08:00
|
|
|
if (core->saved_proj_buffer)
|
2005-08-29 03:17:44 +08:00
|
|
|
{
|
2012-03-30 22:24:09 +08:00
|
|
|
g_object_unref (core->saved_proj_buffer);
|
|
|
|
core->saved_proj_buffer = NULL;
|
2005-08-29 03:17:44 +08:00
|
|
|
}
|
|
|
|
|
2007-11-13 18:59:32 +08:00
|
|
|
gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable));
|
2002-02-16 01:44:05 +08:00
|
|
|
}
|
|
|
|
|
2003-09-17 20:05:11 +08:00
|
|
|
void
|
|
|
|
gimp_paint_core_cancel (GimpPaintCore *core,
|
2006-04-12 20:49:29 +08:00
|
|
|
GimpDrawable *drawable)
|
2003-09-17 20:05:11 +08:00
|
|
|
{
|
2009-06-17 04:09:48 +08:00
|
|
|
gint x, y;
|
|
|
|
gint width, height;
|
|
|
|
|
2003-09-17 20:05:11 +08:00
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-05-26 04:41:09 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
2003-09-17 20:05:11 +08:00
|
|
|
|
|
|
|
/* Determine if any part of the image has been altered--
|
|
|
|
* if nothing has, then just return...
|
|
|
|
*/
|
|
|
|
if ((core->x2 == core->x1) || (core->y2 == core->y1))
|
|
|
|
return;
|
|
|
|
|
2009-06-17 04:09:48 +08:00
|
|
|
if (gimp_rectangle_intersect (core->x1, core->y1,
|
|
|
|
core->x2 - core->x1,
|
|
|
|
core->y2 - core->y1,
|
|
|
|
0, 0,
|
|
|
|
gimp_item_get_width (GIMP_ITEM (drawable)),
|
|
|
|
gimp_item_get_height (GIMP_ITEM (drawable)),
|
|
|
|
&x, &y, &width, &height))
|
|
|
|
{
|
2012-03-22 23:29:33 +08:00
|
|
|
gegl_buffer_copy (core->undo_buffer,
|
|
|
|
GIMP_GEGL_RECT (x, y, width, height),
|
|
|
|
gimp_drawable_get_buffer (drawable),
|
|
|
|
GIMP_GEGL_RECT (x, y, width, height));
|
2009-06-17 04:09:48 +08:00
|
|
|
}
|
2003-09-17 20:05:11 +08:00
|
|
|
|
2012-03-22 23:29:33 +08:00
|
|
|
g_object_unref (core->undo_buffer);
|
|
|
|
core->undo_buffer = NULL;
|
2003-09-17 20:05:11 +08:00
|
|
|
|
2012-03-30 22:24:09 +08:00
|
|
|
if (core->saved_proj_buffer)
|
2005-08-29 03:17:44 +08:00
|
|
|
{
|
2012-03-30 22:24:09 +08:00
|
|
|
g_object_unref (core->saved_proj_buffer);
|
|
|
|
core->saved_proj_buffer = NULL;
|
2005-08-29 03:17:44 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 04:09:48 +08:00
|
|
|
gimp_drawable_update (drawable, x, y, width, height);
|
2007-11-13 18:59:32 +08:00
|
|
|
|
|
|
|
gimp_viewable_preview_thaw (GIMP_VIEWABLE (drawable));
|
2003-09-17 20:05:11 +08:00
|
|
|
}
|
|
|
|
|
2002-02-16 01:44:05 +08:00
|
|
|
void
|
|
|
|
gimp_paint_core_cleanup (GimpPaintCore *core)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
|
2012-03-22 23:29:33 +08:00
|
|
|
if (core->undo_buffer)
|
2002-02-16 01:44:05 +08:00
|
|
|
{
|
2012-03-22 23:29:33 +08:00
|
|
|
g_object_unref (core->undo_buffer);
|
|
|
|
core->undo_buffer = NULL;
|
2002-02-16 01:44:05 +08:00
|
|
|
}
|
|
|
|
|
2012-03-30 22:24:09 +08:00
|
|
|
if (core->saved_proj_buffer)
|
2005-08-29 03:17:44 +08:00
|
|
|
{
|
2012-03-30 22:24:09 +08:00
|
|
|
g_object_unref (core->saved_proj_buffer);
|
|
|
|
core->saved_proj_buffer = NULL;
|
2005-08-29 03:17:44 +08:00
|
|
|
}
|
|
|
|
|
2012-03-30 22:38:52 +08:00
|
|
|
if (core->canvas_buffer)
|
2002-02-16 01:44:05 +08:00
|
|
|
{
|
2012-03-30 22:38:52 +08:00
|
|
|
g_object_unref (core->canvas_buffer);
|
|
|
|
core->canvas_buffer = NULL;
|
2002-02-16 01:44:05 +08:00
|
|
|
}
|
|
|
|
|
2012-03-31 23:00:48 +08:00
|
|
|
if (core->paint_area)
|
2002-02-16 01:44:05 +08:00
|
|
|
{
|
2012-03-31 23:00:48 +08:00
|
|
|
temp_buf_free (core->paint_area);
|
|
|
|
core->paint_area = NULL;
|
2002-02-16 01:44:05 +08:00
|
|
|
}
|
2012-04-01 00:28:18 +08:00
|
|
|
|
|
|
|
if (core->paint_buffer)
|
|
|
|
{
|
|
|
|
g_object_unref (core->paint_buffer);
|
|
|
|
core->paint_buffer = NULL;
|
|
|
|
}
|
2002-02-16 01:44:05 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2002-02-22 00:02:30 +08:00
|
|
|
gimp_paint_core_interpolate (GimpPaintCore *core,
|
2004-05-28 17:34:13 +08:00
|
|
|
GimpDrawable *drawable,
|
2004-05-27 00:13:53 +08:00
|
|
|
GimpPaintOptions *paint_options,
|
2009-05-26 02:49:34 +08:00
|
|
|
const GimpCoords *coords,
|
2004-05-27 00:13:53 +08:00
|
|
|
guint32 time)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2002-02-15 03:31:16 +08:00
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
2004-05-26 04:41:09 +08:00
|
|
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
2003-03-04 02:43:11 +08:00
|
|
|
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options));
|
2009-05-26 02:49:34 +08:00
|
|
|
g_return_if_fail (coords != NULL);
|
|
|
|
|
|
|
|
core->cur_coords = *coords;
|
2002-02-15 03:31:16 +08:00
|
|
|
|
2004-05-26 20:55:10 +08:00
|
|
|
GIMP_PAINT_CORE_GET_CLASS (core)->interpolate (core, drawable,
|
2004-05-27 00:13:53 +08:00
|
|
|
paint_options, time);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2009-05-03 18:08:21 +08:00
|
|
|
void
|
|
|
|
gimp_paint_core_set_current_coords (GimpPaintCore *core,
|
|
|
|
const GimpCoords *coords)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (coords != NULL);
|
|
|
|
|
|
|
|
core->cur_coords = *coords;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-03-17 04:06:39 +08:00
|
|
|
gimp_paint_core_get_current_coords (GimpPaintCore *core,
|
|
|
|
GimpCoords *coords)
|
2009-05-03 18:08:21 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (coords != NULL);
|
|
|
|
|
|
|
|
*coords = core->cur_coords;
|
2011-03-17 04:06:39 +08:00
|
|
|
|
2009-05-03 18:08:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_paint_core_set_last_coords (GimpPaintCore *core,
|
|
|
|
const GimpCoords *coords)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (coords != NULL);
|
|
|
|
|
|
|
|
core->last_coords = *coords;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_paint_core_get_last_coords (GimpPaintCore *core,
|
|
|
|
GimpCoords *coords)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (coords != NULL);
|
|
|
|
|
|
|
|
*coords = core->last_coords;
|
|
|
|
}
|
|
|
|
|
2009-04-23 03:22:08 +08:00
|
|
|
/**
|
|
|
|
* gimp_paint_core_round_line:
|
|
|
|
* @core: the #GimpPaintCore
|
|
|
|
* @options: the #GimpPaintOptions to use
|
|
|
|
* @constrain_15_degrees: the modifier state
|
|
|
|
*
|
|
|
|
* Adjusts core->last_coords and core_cur_coords in preparation to
|
|
|
|
* drawing a straight line. If @center_pixels is TRUE the endpoints
|
|
|
|
* get pushed to the center of the pixels. This avoids artefacts
|
|
|
|
* for e.g. the hard mode. The rounding of the slope to 15 degree
|
|
|
|
* steps if ctrl is pressed happens, as does rounding the start and
|
|
|
|
* end coordinates (which may be fractional in high zoom modes) to
|
|
|
|
* the center of pixels.
|
|
|
|
**/
|
|
|
|
void
|
|
|
|
gimp_paint_core_round_line (GimpPaintCore *core,
|
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
gboolean constrain_15_degrees)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
|
|
|
g_return_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options));
|
|
|
|
|
|
|
|
if (gimp_paint_options_get_brush_mode (paint_options) == GIMP_BRUSH_HARD)
|
|
|
|
{
|
|
|
|
core->last_coords.x = floor (core->last_coords.x) + 0.5;
|
|
|
|
core->last_coords.y = floor (core->last_coords.y) + 0.5;
|
|
|
|
core->cur_coords.x = floor (core->cur_coords.x ) + 0.5;
|
|
|
|
core->cur_coords.y = floor (core->cur_coords.y ) + 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (constrain_15_degrees)
|
|
|
|
gimp_constrain_line (core->last_coords.x, core->last_coords.y,
|
|
|
|
&core->cur_coords.x, &core->cur_coords.y,
|
|
|
|
GIMP_CONSTRAIN_LINE_15_DEGREES);
|
|
|
|
}
|
|
|
|
|
1998-06-06 11:49:01 +08:00
|
|
|
|
2002-02-16 01:44:05 +08:00
|
|
|
/* protected functions */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2012-04-01 00:28:18 +08:00
|
|
|
GeglBuffer *
|
|
|
|
gimp_paint_core_get_paint_buffer (GimpPaintCore *core,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
gint *paint_buffer_x,
|
|
|
|
gint *paint_buffer_y)
|
|
|
|
{
|
2012-04-02 03:20:12 +08:00
|
|
|
GeglBuffer *paint_buffer;
|
|
|
|
|
2012-04-01 00:28:18 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
|
|
|
|
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), NULL);
|
|
|
|
g_return_val_if_fail (coords != NULL, NULL);
|
|
|
|
g_return_val_if_fail (paint_buffer_x != NULL, NULL);
|
|
|
|
g_return_val_if_fail (paint_buffer_y != NULL, NULL);
|
|
|
|
|
2012-04-02 03:20:12 +08:00
|
|
|
paint_buffer =
|
|
|
|
GIMP_PAINT_CORE_GET_CLASS (core)->get_paint_buffer (core, drawable,
|
|
|
|
paint_options,
|
|
|
|
coords,
|
|
|
|
paint_buffer_x,
|
|
|
|
paint_buffer_y);
|
2012-04-01 00:28:18 +08:00
|
|
|
|
2012-04-02 03:20:12 +08:00
|
|
|
core->paint_buffer_x = *paint_buffer_x;
|
|
|
|
core->paint_buffer_y = *paint_buffer_y;
|
2012-04-01 00:28:18 +08:00
|
|
|
|
2012-04-02 03:20:12 +08:00
|
|
|
return paint_buffer;
|
2012-04-01 00:28:18 +08:00
|
|
|
}
|
|
|
|
|
2012-03-31 07:36:10 +08:00
|
|
|
GeglBuffer *
|
2012-03-31 21:40:21 +08:00
|
|
|
gimp_paint_core_get_orig_image (GimpPaintCore *core)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2006-09-26 17:59:13 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL);
|
2012-03-31 07:36:10 +08:00
|
|
|
g_return_val_if_fail (core->undo_buffer != NULL, NULL);
|
2006-09-26 17:59:13 +08:00
|
|
|
|
2012-03-31 21:40:21 +08:00
|
|
|
return core->undo_buffer;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2012-03-31 07:36:10 +08:00
|
|
|
GeglBuffer *
|
2012-03-31 21:40:21 +08:00
|
|
|
gimp_paint_core_get_orig_proj (GimpPaintCore *core)
|
2005-08-29 03:17:44 +08:00
|
|
|
{
|
2006-09-26 17:59:13 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL);
|
2012-03-30 22:24:09 +08:00
|
|
|
g_return_val_if_fail (core->saved_proj_buffer != NULL, NULL);
|
2005-08-29 03:17:44 +08:00
|
|
|
|
2012-03-31 21:40:21 +08:00
|
|
|
return core->saved_proj_buffer;
|
2005-08-29 03:17:44 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2002-03-19 23:05:38 +08:00
|
|
|
gimp_paint_core_paste (GimpPaintCore *core,
|
2006-04-12 20:49:29 +08:00
|
|
|
PixelRegion *paint_maskPR,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gdouble paint_opacity,
|
|
|
|
gdouble image_opacity,
|
|
|
|
GimpLayerModeEffects paint_mode,
|
|
|
|
GimpPaintApplicationMode mode)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2012-03-23 07:12:13 +08:00
|
|
|
GeglBuffer *base_buffer = NULL;
|
2012-04-01 00:28:18 +08:00
|
|
|
gint width, height;
|
2007-06-27 06:41:06 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* If the mode is CONSTANT:
|
2012-03-31 23:00:48 +08:00
|
|
|
* combine the canvas buf, the paint mask to the canvas buffer
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2002-03-19 23:05:38 +08:00
|
|
|
if (mode == GIMP_PAINT_CONSTANT)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2012-03-31 23:00:48 +08:00
|
|
|
/* Some tools (ink) paint the mask to paint_core->canvas_buffer
|
2004-05-26 19:37:23 +08:00
|
|
|
* directly. Don't need to copy it in this case.
|
|
|
|
*/
|
2012-03-30 22:38:52 +08:00
|
|
|
if (paint_maskPR->tiles !=
|
|
|
|
gimp_gegl_buffer_get_tiles (core->canvas_buffer))
|
2004-05-26 19:37:23 +08:00
|
|
|
{
|
2012-03-31 23:00:48 +08:00
|
|
|
paint_mask_to_canvas_buffer (core, paint_maskPR, paint_opacity);
|
2004-05-26 19:37:23 +08:00
|
|
|
}
|
|
|
|
|
2012-03-31 23:00:48 +08:00
|
|
|
canvas_buffer_to_paint_area (core);
|
2012-03-23 07:12:13 +08:00
|
|
|
|
|
|
|
base_buffer = core->undo_buffer;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
/* Otherwise:
|
2004-05-26 04:41:09 +08:00
|
|
|
* combine the canvas buf and the paint mask to the canvas buf
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-31 12:07:42 +08:00
|
|
|
else
|
|
|
|
{
|
2012-03-31 23:00:48 +08:00
|
|
|
paint_mask_to_paint_area (core, paint_maskPR, paint_opacity);
|
2000-12-31 12:07:42 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2012-04-01 00:28:18 +08:00
|
|
|
width = gegl_buffer_get_width (core->paint_buffer);
|
|
|
|
height = gegl_buffer_get_height (core->paint_buffer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
/* apply the paint area to the image */
|
2012-04-01 00:28:18 +08:00
|
|
|
gimp_drawable_apply_buffer (drawable,
|
|
|
|
core->paint_buffer,
|
|
|
|
GIMP_GEGL_RECT (0, 0, width, height),
|
2003-10-06 22:40:12 +08:00
|
|
|
FALSE, NULL,
|
|
|
|
image_opacity, paint_mode,
|
2012-03-23 07:12:13 +08:00
|
|
|
base_buffer, /* specify an alternative src1 */
|
2012-04-01 00:28:18 +08:00
|
|
|
core->paint_buffer_x,
|
|
|
|
core->paint_buffer_y,
|
2008-11-09 03:52:18 +08:00
|
|
|
NULL,
|
2012-04-01 00:28:18 +08:00
|
|
|
core->paint_buffer_x,
|
|
|
|
core->paint_buffer_y);
|
2012-03-23 05:47:56 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Update the undo extents */
|
2012-04-01 00:28:18 +08:00
|
|
|
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
|
|
|
core->y1 = MIN (core->y1, core->paint_buffer_y);
|
|
|
|
core->x2 = MAX (core->x2, core->paint_buffer_x + width);
|
|
|
|
core->y2 = MAX (core->y2, core->paint_buffer_y + height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-11-13 18:59:32 +08:00
|
|
|
/* Update the drawable */
|
|
|
|
gimp_drawable_update (drawable,
|
2012-04-01 00:28:18 +08:00
|
|
|
core->paint_buffer_x,
|
|
|
|
core->paint_buffer_y,
|
|
|
|
width, height);
|
1997-12-08 09:13:10 +08:00
|
|
|
}
|
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
/* This works similarly to gimp_paint_core_paste. However, instead of
|
|
|
|
* combining the canvas to the paint core drawable using one of the
|
|
|
|
* combination modes, it uses a "replace" mode (i.e. transparent
|
|
|
|
* pixels in the canvas erase the paint core drawable).
|
1997-12-08 09:13:10 +08:00
|
|
|
|
2002-02-15 03:31:16 +08:00
|
|
|
* When not drawing on alpha-enabled images, it just paints using
|
|
|
|
* NORMAL mode.
|
|
|
|
*/
|
2004-05-26 04:41:09 +08:00
|
|
|
void
|
2002-03-19 23:05:38 +08:00
|
|
|
gimp_paint_core_replace (GimpPaintCore *core,
|
2004-05-28 17:34:13 +08:00
|
|
|
PixelRegion *paint_maskPR,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gdouble paint_opacity,
|
|
|
|
gdouble image_opacity,
|
|
|
|
GimpPaintApplicationMode mode)
|
1997-12-08 09:13:10 +08:00
|
|
|
{
|
2012-04-01 00:28:18 +08:00
|
|
|
gint width, height;
|
1997-12-08 09:13:10 +08:00
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
if (! gimp_drawable_has_alpha (drawable))
|
1997-12-08 09:13:10 +08:00
|
|
|
{
|
2004-05-26 19:37:23 +08:00
|
|
|
gimp_paint_core_paste (core, paint_maskPR, drawable,
|
2004-05-28 17:34:13 +08:00
|
|
|
paint_opacity,
|
2002-03-04 01:38:12 +08:00
|
|
|
image_opacity, GIMP_NORMAL_MODE,
|
2004-05-28 17:34:13 +08:00
|
|
|
mode);
|
1997-12-08 09:13:10 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-01 00:28:18 +08:00
|
|
|
width = gegl_buffer_get_width (core->paint_buffer);
|
|
|
|
height = gegl_buffer_get_height (core->paint_buffer);
|
|
|
|
|
2002-03-19 23:05:38 +08:00
|
|
|
if (mode == GIMP_PAINT_CONSTANT)
|
2000-03-05 08:06:11 +08:00
|
|
|
{
|
2012-03-30 22:38:52 +08:00
|
|
|
/* Some tools (ink) paint the mask to paint_core->canvas_buffer
|
2004-05-26 19:37:23 +08:00
|
|
|
* directly. Don't need to copy it in this case.
|
|
|
|
*/
|
2012-03-30 22:38:52 +08:00
|
|
|
if (paint_maskPR->tiles !=
|
|
|
|
gimp_gegl_buffer_get_tiles (core->canvas_buffer))
|
2004-05-26 19:37:23 +08:00
|
|
|
{
|
2012-03-31 23:00:48 +08:00
|
|
|
/* combine the paint mask and the canvas buffer */
|
|
|
|
paint_mask_to_canvas_buffer (core, paint_maskPR, paint_opacity);
|
2004-05-26 19:37:23 +08:00
|
|
|
|
2012-03-31 23:00:48 +08:00
|
|
|
/* initialize the maskPR from the canvas buffer */
|
2012-03-30 22:38:52 +08:00
|
|
|
pixel_region_init (paint_maskPR,
|
|
|
|
gimp_gegl_buffer_get_tiles (core->canvas_buffer),
|
2012-04-01 00:28:18 +08:00
|
|
|
core->paint_buffer_x,
|
|
|
|
core->paint_buffer_y,
|
|
|
|
width, height,
|
2004-05-26 19:37:23 +08:00
|
|
|
FALSE);
|
|
|
|
}
|
2000-03-05 08:06:11 +08:00
|
|
|
}
|
2000-12-31 12:07:42 +08:00
|
|
|
else
|
2000-03-05 08:06:11 +08:00
|
|
|
{
|
2004-05-26 19:37:23 +08:00
|
|
|
/* The mask is just the paint_maskPR */
|
2000-03-05 08:06:11 +08:00
|
|
|
}
|
2000-12-31 12:07:42 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
/* apply the paint area to the image */
|
2012-04-01 00:28:18 +08:00
|
|
|
gimp_drawable_replace_buffer (drawable, core->paint_buffer,
|
|
|
|
GIMP_GEGL_RECT (0, 0, width, height),
|
2003-10-06 22:40:12 +08:00
|
|
|
FALSE, NULL,
|
|
|
|
image_opacity,
|
2004-05-26 19:37:23 +08:00
|
|
|
paint_maskPR,
|
2012-04-01 00:28:18 +08:00
|
|
|
core->paint_buffer_x,
|
|
|
|
core->paint_buffer_y);
|
2012-03-23 19:31:21 +08:00
|
|
|
|
1997-12-08 09:13:10 +08:00
|
|
|
/* Update the undo extents */
|
2012-04-01 00:28:18 +08:00
|
|
|
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
|
|
|
core->y1 = MIN (core->y1, core->paint_buffer_y);
|
|
|
|
core->x2 = MAX (core->x2, core->paint_buffer_x + width);
|
|
|
|
core->y2 = MAX (core->y2, core->paint_buffer_y + height);
|
1997-12-08 09:13:10 +08:00
|
|
|
|
2007-11-13 18:59:32 +08:00
|
|
|
/* Update the drawable */
|
|
|
|
gimp_drawable_update (drawable,
|
2012-04-01 00:28:18 +08:00
|
|
|
core->paint_buffer_x,
|
|
|
|
core->paint_buffer_y,
|
|
|
|
width, height);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2011-09-15 01:42:52 +08:00
|
|
|
/**
|
|
|
|
* Smooth and store coords in the stroke buffer
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_paint_core_smooth_coords (GimpPaintCore *core,
|
|
|
|
GimpPaintOptions *paint_options,
|
|
|
|
GimpCoords *coords)
|
|
|
|
{
|
|
|
|
GimpSmoothingOptions *smoothing_options = paint_options->smoothing_options;
|
|
|
|
GArray *history = core->stroke_buffer;
|
|
|
|
|
|
|
|
if (core->stroke_buffer == NULL)
|
|
|
|
return; /* Paint core has not initalized yet */
|
|
|
|
|
|
|
|
if (smoothing_options->use_smoothing &&
|
|
|
|
smoothing_options->smoothing_quality > 0)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
guint length;
|
|
|
|
gint min_index;
|
|
|
|
gdouble gaussian_weight = 0.0;
|
|
|
|
gdouble gaussian_weight2 = SQR (smoothing_options->smoothing_factor);
|
|
|
|
gdouble velocity_sum = 0.0;
|
|
|
|
gdouble scale_sum = 0.0;
|
|
|
|
|
|
|
|
g_array_append_val (history, *coords);
|
|
|
|
|
|
|
|
if (history->len < 2)
|
|
|
|
return; /* Just dont bother, nothing to do */
|
|
|
|
|
|
|
|
coords->x = coords->y = 0.0;
|
|
|
|
|
|
|
|
length = MIN (smoothing_options->smoothing_quality, history->len);
|
|
|
|
|
|
|
|
min_index = history->len - length;
|
|
|
|
|
|
|
|
if (gaussian_weight2 != 0.0)
|
|
|
|
gaussian_weight = 1 / (sqrt (2 * G_PI) * smoothing_options->smoothing_factor);
|
|
|
|
|
|
|
|
for (i = history->len - 1; i >= min_index; i--)
|
|
|
|
{
|
|
|
|
gdouble rate = 0.0;
|
|
|
|
GimpCoords *next_coords = &g_array_index (history,
|
|
|
|
GimpCoords, i);
|
|
|
|
|
|
|
|
if (gaussian_weight2 != 0.0)
|
|
|
|
{
|
|
|
|
/* We use gaussian function with velocity as a window function */
|
|
|
|
velocity_sum += next_coords->velocity * 100;
|
|
|
|
rate = gaussian_weight * exp (-velocity_sum*velocity_sum / (2 * gaussian_weight2));
|
|
|
|
}
|
|
|
|
|
|
|
|
scale_sum += rate;
|
|
|
|
coords->x += rate * next_coords->x;
|
|
|
|
coords->y += rate * next_coords->y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scale_sum != 0.0)
|
|
|
|
{
|
|
|
|
coords->x /= scale_sum;
|
|
|
|
coords->y /= scale_sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-07-02 00:52:50 +08:00
|
|
|
static void
|
2012-03-31 23:00:48 +08:00
|
|
|
canvas_buffer_to_paint_area (GimpPaintCore *core)
|
1999-07-02 00:52:50 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion maskPR;
|
1999-07-02 00:52:50 +08:00
|
|
|
|
2012-03-31 23:00:48 +08:00
|
|
|
/* combine the canvas buffer and the paint area */
|
|
|
|
pixel_region_init_temp_buf (&srcPR, core->paint_area,
|
2005-09-04 01:16:58 +08:00
|
|
|
0, 0,
|
2012-03-31 23:00:48 +08:00
|
|
|
core->paint_area->width,
|
|
|
|
core->paint_area->height);
|
2002-02-15 03:31:16 +08:00
|
|
|
|
2012-03-30 22:38:52 +08:00
|
|
|
pixel_region_init (&maskPR,
|
|
|
|
gimp_gegl_buffer_get_tiles (core->canvas_buffer),
|
2012-03-31 23:00:48 +08:00
|
|
|
core->paint_area->x,
|
|
|
|
core->paint_area->y,
|
|
|
|
core->paint_area->width,
|
|
|
|
core->paint_area->height,
|
2002-02-13 22:50:37 +08:00
|
|
|
FALSE);
|
1999-07-02 00:52:50 +08:00
|
|
|
|
2012-03-31 23:00:48 +08:00
|
|
|
/* apply the canvas buffer to the paint area */
|
1999-07-02 00:52:50 +08:00
|
|
|
apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-31 23:00:48 +08:00
|
|
|
paint_mask_to_canvas_buffer (GimpPaintCore *core,
|
|
|
|
PixelRegion *paint_maskPR,
|
|
|
|
gdouble paint_opacity)
|
1999-07-02 00:52:50 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
1999-07-02 00:52:50 +08:00
|
|
|
|
2012-03-31 23:00:48 +08:00
|
|
|
/* combine the paint mask and the canvas buffer */
|
2012-03-30 22:38:52 +08:00
|
|
|
pixel_region_init (&srcPR,
|
|
|
|
gimp_gegl_buffer_get_tiles (core->canvas_buffer),
|
2012-03-31 23:00:48 +08:00
|
|
|
core->paint_area->x,
|
|
|
|
core->paint_area->y,
|
|
|
|
core->paint_area->width,
|
|
|
|
core->paint_area->height,
|
2002-02-13 22:50:37 +08:00
|
|
|
TRUE);
|
1999-07-02 00:52:50 +08:00
|
|
|
|
|
|
|
/* combine the mask to the canvas tiles */
|
2004-06-06 00:21:41 +08:00
|
|
|
combine_mask_and_region (&srcPR, paint_maskPR,
|
|
|
|
paint_opacity * 255.999, GIMP_IS_AIRBRUSH (core));
|
1999-07-02 00:52:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-31 23:00:48 +08:00
|
|
|
paint_mask_to_paint_area (GimpPaintCore *core,
|
2004-05-26 19:37:23 +08:00
|
|
|
PixelRegion *paint_maskPR,
|
2004-05-26 04:41:09 +08:00
|
|
|
gdouble paint_opacity)
|
1999-07-02 00:52:50 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
1999-07-02 00:52:50 +08:00
|
|
|
|
2004-05-26 04:41:09 +08:00
|
|
|
/* combine the canvas buf and the paint mask to the canvas buf */
|
2012-03-31 23:00:48 +08:00
|
|
|
pixel_region_init_temp_buf (&srcPR, core->paint_area,
|
2005-09-04 01:16:58 +08:00
|
|
|
0, 0,
|
2012-03-31 23:00:48 +08:00
|
|
|
core->paint_area->width,
|
|
|
|
core->paint_area->height);
|
1999-07-02 00:52:50 +08:00
|
|
|
|
|
|
|
/* apply the mask */
|
2004-05-26 19:37:23 +08:00
|
|
|
apply_mask_to_region (&srcPR, paint_maskPR, paint_opacity * 255.999);
|
1999-07-02 00:52:50 +08:00
|
|
|
}
|