1997-11-25 06:05:25 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (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
|
|
|
|
* along with this program; if not, write to the Free Software
|
1998-04-13 13:44:11 +08:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
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 <stdlib.h>
|
|
|
|
#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
|
|
|
|
2000-12-29 23:22:01 +08:00
|
|
|
#include <gtk/gtk.h>
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2001-01-24 02:49:44 +08:00
|
|
|
#include "libgimpcolor/gimpcolor.h"
|
2001-01-24 07:56:18 +08:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
2001-05-21 21:58:46 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2001-01-24 02:49:44 +08:00
|
|
|
|
2001-05-10 06:34:59 +08:00
|
|
|
#include "tools-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2001-05-15 19:25:25 +08:00
|
|
|
#include "base/brush-scale.h"
|
|
|
|
#include "base/pixel-region.h"
|
|
|
|
#include "base/temp-buf.h"
|
|
|
|
#include "base/tile-manager.h"
|
|
|
|
#include "base/tile.h"
|
|
|
|
|
2001-04-07 23:58:26 +08:00
|
|
|
#include "paint-funcs/paint-funcs.h"
|
|
|
|
|
2001-07-07 20:17:23 +08:00
|
|
|
#include "core/gimp.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpbrushpipe.h"
|
|
|
|
#include "core/gimpcontext.h"
|
|
|
|
#include "core/gimpdrawable.h"
|
|
|
|
#include "core/gimpgradient.h"
|
|
|
|
#include "core/gimpimage.h"
|
|
|
|
#include "core/gimpimage-mask.h"
|
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
2001-07-24 Michael Natterer <mitch@gimp.org>
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
* configure.in: require glib/gtk+ >= 1.3.7, commented out the
gtkxmhtml stuff.
From now on, you will need glib, pango, atk and gtk+ HEAD from CVS
to hack or use GIMP HEAD.
Beware, it crashes randomly :)
* app/core/Makefile.am
* app/core/gimpmarshal.list: new file plus rules to generate
gimpmarshal.[ch] from it.
* app/core/*
* app/tools/*
* app/widgets/*
* libgimpwidgets/*: started to use the glib object system. All
core/ objects are still gtk objects however. All signals are
created using g_signal_new(). There are many gtk+ artefacts left.
Finally, we will _not_ use the gtk_signal_foo() wrappers and
friends any more.
* app/colormaps.c
* app/devices.[ch]
* app/disp_callbacks.c
* app/errorconsole.c
* app/file-save.[ch]
* app/interface.c
* app/module_db.c
* app/nav_window.c
* app/ops_buttons.c
* app/scroll.c
* app/user_install.c
* app/gui/about-dialog.c
* app/gui/brush-editor.c
* app/gui/brushes-commands.c
* app/gui/color-notebook.c
* app/gui/colormap-dialog.c
* app/gui/dialogs-commands.c
* app/gui/dialogs-constructors.c
* app/gui/file-commands.c
* app/gui/file-dialog-utils.c
* app/gui/file-new-dialog.c
* app/gui/file-open-dialog.[ch]
* app/gui/file-save-dialog.c
* app/gui/gradient-editor.c
* app/gui/gradients-commands.c
* app/gui/image-commands.c
* app/gui/info-dialog.[ch]
* app/gui/layer-select.c
* app/gui/layers-commands.c
* app/gui/menus.c
* app/gui/offset-dialog.c
* app/gui/palette-editor.c
* app/gui/palettes-commands.c
* app/gui/patterns-commands.c
* app/gui/preferences-dialog.c
* app/gui/resize-dialog.[ch]
* app/gui/splash.c
* app/gui/tips-dialog.c
* app/gui/tool-options-dialog.c
* app/gui/toolbox.c
* app/gui/tools-commands.c
* libgimp/gimpbrushmenu.c
* libgimp/gimpmenu.c
* libgimp/gimppatternmenu.c
* libgimp/gimpui.c
* libgimpbase/gimpenv.c: tons and tons of changes like "const
gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete
and currently disables), lots of s/gtk_signal/g_signal/,
removal/replacement of deprecated stuff,
s/GtkSignalFunc/GCallback/ and lots of small changes and fixes
while I was on it, zillions of warnings left...
* modules/Makefile.am: disabled the water color selector
temporarily (XInput issues).
* plug-ins/Makefile.am
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl: simply excluded all plug-ins
which did not build (including Script-Fu). They are trivial to
fix.
2001-07-25 05:27:11 +08:00
|
|
|
#include "core/gimpmarshal.h"
|
2001-12-02 05:02:34 +08:00
|
|
|
#include "core/gimptoolinfo.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
|
2001-09-26 07:23:09 +08:00
|
|
|
#include "display/gimpdisplay.h"
|
2001-10-13 20:52:30 +08:00
|
|
|
#include "display/gimpdisplay-foreach.h"
|
2001-11-01 05:20:09 +08:00
|
|
|
#include "display/gimpdisplayshell.h"
|
2001-09-26 07:23:09 +08:00
|
|
|
|
2001-03-08 09:07:03 +08:00
|
|
|
#include "gimpdrawtool.h"
|
2001-03-24 10:30:39 +08:00
|
|
|
#include "gimpdodgeburntool.h"
|
2001-03-12 12:40:17 +08:00
|
|
|
#include "gimperasertool.h"
|
2001-04-19 21:01:44 +08:00
|
|
|
#include "gimpconvolvetool.h"
|
2001-03-08 09:07:03 +08:00
|
|
|
#include "gimppainttool.h"
|
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
#include "app_procs.h"
|
2001-07-07 20:17:23 +08:00
|
|
|
#include "devices.h"
|
|
|
|
#include "gimprc.h"
|
|
|
|
#include "undo.h"
|
|
|
|
|
2000-03-05 08:06:11 +08:00
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
#include "gimppainttool_kernels.h"
|
2000-05-29 16:40:29 +08:00
|
|
|
|
2001-01-24 07:56:18 +08:00
|
|
|
|
2001-11-12 22:45:58 +08:00
|
|
|
#define TARGET_SIZE 15
|
1999-05-15 08:02:47 +08:00
|
|
|
|
1999-09-02 02:46:25 +08:00
|
|
|
#define EPSILON 0.00001
|
|
|
|
|
|
|
|
#define STATUSBAR_SIZE 128
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* local function prototypes */
|
2001-11-20 22:20:17 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void gimp_paint_tool_class_init (GimpPaintToolClass *klass);
|
|
|
|
static void gimp_paint_tool_init (GimpPaintTool *paint_tool);
|
|
|
|
|
|
|
|
static void gimp_paint_tool_control (GimpTool *tool,
|
|
|
|
ToolAction action,
|
2001-10-29 19:47:11 +08:00
|
|
|
GimpDisplay *gdisp);
|
2001-02-28 03:18:01 +08:00
|
|
|
static void gimp_paint_tool_button_press (GimpTool *tool,
|
2001-11-09 03:14:51 +08:00
|
|
|
GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
2001-10-29 19:47:11 +08:00
|
|
|
GimpDisplay *gdisp);
|
2001-02-28 03:18:01 +08:00
|
|
|
static void gimp_paint_tool_button_release (GimpTool *tool,
|
2001-11-09 03:14:51 +08:00
|
|
|
GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
2001-10-29 19:47:11 +08:00
|
|
|
GimpDisplay *gdisp);
|
2001-02-28 03:18:01 +08:00
|
|
|
static void gimp_paint_tool_motion (GimpTool *tool,
|
2001-11-09 03:14:51 +08:00
|
|
|
GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
2001-10-29 19:47:11 +08:00
|
|
|
GimpDisplay *gdisp);
|
2001-02-28 03:18:01 +08:00
|
|
|
static void gimp_paint_tool_cursor_update (GimpTool *tool,
|
2001-11-09 03:14:51 +08:00
|
|
|
GimpCoords *coords,
|
|
|
|
GdkModifierType state,
|
2001-10-29 19:47:11 +08:00
|
|
|
GimpDisplay *gdisp);
|
2001-02-28 03:18:01 +08:00
|
|
|
|
|
|
|
static void gimp_paint_tool_draw (GimpDrawTool *draw_tool);
|
|
|
|
|
|
|
|
|
|
|
|
static void gimp_paint_tool_sample_color (GimpDrawable *drawable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint state);
|
2001-02-27 13:21:12 +08:00
|
|
|
static void gimp_paint_tool_calculate_brush_size (MaskBuf *mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble scale,
|
|
|
|
gint *width,
|
|
|
|
gint *height);
|
2001-02-27 13:21:12 +08:00
|
|
|
static MaskBuf * gimp_paint_tool_subsample_mask (MaskBuf *mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble x,
|
|
|
|
gdouble y);
|
2001-02-27 13:21:12 +08:00
|
|
|
static MaskBuf * gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble x,
|
|
|
|
gdouble y,
|
|
|
|
gdouble pressure);
|
2001-02-27 13:21:12 +08:00
|
|
|
static MaskBuf * gimp_paint_tool_solidify_mask (MaskBuf *brush_mask);
|
|
|
|
static MaskBuf * gimp_paint_tool_scale_mask (MaskBuf *brush_mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble scale);
|
2001-02-27 13:21:12 +08:00
|
|
|
static MaskBuf * gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble scale);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
static MaskBuf * gimp_paint_tool_get_brush_mask (GimpPaintTool *gimp_paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
BrushApplicationMode brush_hardness,
|
|
|
|
gdouble scale);
|
2001-02-27 13:21:12 +08:00
|
|
|
static void gimp_paint_tool_paste (GimpPaintTool *gimp_paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
MaskBuf *brush_mask,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint brush_opacity,
|
|
|
|
gint image_opacity,
|
|
|
|
LayerModeEffects paint_mode,
|
|
|
|
PaintApplicationMode mode);
|
2001-02-27 13:21:12 +08:00
|
|
|
static void gimp_paint_tool_replace (GimpPaintTool *gimp_paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
MaskBuf *brush_mask,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint brush_opacity,
|
|
|
|
gint image_opacity,
|
|
|
|
PaintApplicationMode mode);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
static void brush_to_canvas_tiles (GimpPaintTool *gimp_paint_tool,
|
|
|
|
MaskBuf *brush_mask,
|
2000-06-06 06:08:45 +08:00
|
|
|
gint brush_opacity);
|
2001-02-27 13:21:12 +08:00
|
|
|
static void brush_to_canvas_buf (GimpPaintTool *gimp_paint_tool,
|
2000-06-06 06:08:45 +08:00
|
|
|
MaskBuf *brush_mask,
|
|
|
|
gint brush_opacity);
|
2001-02-27 13:21:12 +08:00
|
|
|
static void canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
static void set_undo_tiles (GimpDrawable *drawable,
|
2000-06-06 06:08:45 +08:00
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h);
|
|
|
|
static void set_canvas_tiles (gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h);
|
2001-02-27 13:21:12 +08:00
|
|
|
static void gimp_paint_tool_invalidate_cache (GimpBrush *brush,
|
2001-02-28 03:18:01 +08:00
|
|
|
gpointer data);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* paint buffers utility functions */
|
|
|
|
static void free_paint_buffers (void);
|
|
|
|
|
|
|
|
/* brush pipe utility functions */
|
|
|
|
static void paint_line_pixmap_mask (GimpImage *dest,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
TempBuf *pixmap_mask,
|
|
|
|
TempBuf *brush_mask,
|
|
|
|
guchar *d,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint bytes,
|
|
|
|
gint width,
|
|
|
|
BrushApplicationMode mode);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* undo blocks variables */
|
2000-06-06 06:08:45 +08:00
|
|
|
static TileManager *undo_tiles = NULL;
|
|
|
|
static TileManager *canvas_tiles = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* paint buffers variables */
|
2000-06-06 06:08:45 +08:00
|
|
|
static TempBuf *orig_buf = NULL;
|
|
|
|
static TempBuf *canvas_buf = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* brush buffers */
|
2000-06-06 06:08:45 +08:00
|
|
|
static MaskBuf *pressure_brush;
|
|
|
|
static MaskBuf *solid_brush;
|
|
|
|
static MaskBuf *scale_brush = NULL;
|
|
|
|
static MaskBuf *scale_pixmap = NULL;
|
|
|
|
static MaskBuf *kernel_brushes[SUBSAMPLE + 1][SUBSAMPLE + 1];
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
static MaskBuf *last_brush_mask = NULL;
|
|
|
|
static gboolean cache_invalid = FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static GimpDrawToolClass *parent_class = NULL;
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
|
2001-08-14 22:53:55 +08:00
|
|
|
GType
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_get_type (void)
|
|
|
|
{
|
2001-08-14 22:53:55 +08:00
|
|
|
static GType tool_type = 0;
|
2001-02-27 13:21:12 +08:00
|
|
|
|
|
|
|
if (! tool_type)
|
|
|
|
{
|
2001-08-14 22:53:55 +08:00
|
|
|
static const GTypeInfo tool_info =
|
2001-02-27 13:21:12 +08:00
|
|
|
{
|
|
|
|
sizeof (GimpPaintToolClass),
|
2001-08-14 22:53:55 +08:00
|
|
|
(GBaseInitFunc) NULL,
|
|
|
|
(GBaseFinalizeFunc) NULL,
|
|
|
|
(GClassInitFunc) gimp_paint_tool_class_init,
|
|
|
|
NULL, /* class_finalize */
|
|
|
|
NULL, /* class_data */
|
|
|
|
sizeof (GimpPaintTool),
|
|
|
|
0, /* n_preallocs */
|
|
|
|
(GInstanceInitFunc) gimp_paint_tool_init,
|
2001-02-27 13:21:12 +08:00
|
|
|
};
|
|
|
|
|
2001-08-14 22:53:55 +08:00
|
|
|
tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
|
|
|
|
"GimpPaintTool",
|
|
|
|
&tool_info, 0);
|
2001-02-27 13:21:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return tool_type;
|
|
|
|
}
|
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
|
|
|
gimp_paint_tool_class_init (GimpPaintToolClass *klass)
|
2001-02-27 13:21:12 +08:00
|
|
|
{
|
2001-02-28 03:18:01 +08:00
|
|
|
GimpToolClass *tool_class;
|
|
|
|
GimpDrawToolClass *draw_tool_class;
|
|
|
|
|
2001-08-14 22:53:55 +08:00
|
|
|
tool_class = GIMP_TOOL_CLASS (klass);
|
|
|
|
draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
|
2001-02-28 03:18:01 +08:00
|
|
|
|
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
2001-07-24 Michael Natterer <mitch@gimp.org>
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
* configure.in: require glib/gtk+ >= 1.3.7, commented out the
gtkxmhtml stuff.
From now on, you will need glib, pango, atk and gtk+ HEAD from CVS
to hack or use GIMP HEAD.
Beware, it crashes randomly :)
* app/core/Makefile.am
* app/core/gimpmarshal.list: new file plus rules to generate
gimpmarshal.[ch] from it.
* app/core/*
* app/tools/*
* app/widgets/*
* libgimpwidgets/*: started to use the glib object system. All
core/ objects are still gtk objects however. All signals are
created using g_signal_new(). There are many gtk+ artefacts left.
Finally, we will _not_ use the gtk_signal_foo() wrappers and
friends any more.
* app/colormaps.c
* app/devices.[ch]
* app/disp_callbacks.c
* app/errorconsole.c
* app/file-save.[ch]
* app/interface.c
* app/module_db.c
* app/nav_window.c
* app/ops_buttons.c
* app/scroll.c
* app/user_install.c
* app/gui/about-dialog.c
* app/gui/brush-editor.c
* app/gui/brushes-commands.c
* app/gui/color-notebook.c
* app/gui/colormap-dialog.c
* app/gui/dialogs-commands.c
* app/gui/dialogs-constructors.c
* app/gui/file-commands.c
* app/gui/file-dialog-utils.c
* app/gui/file-new-dialog.c
* app/gui/file-open-dialog.[ch]
* app/gui/file-save-dialog.c
* app/gui/gradient-editor.c
* app/gui/gradients-commands.c
* app/gui/image-commands.c
* app/gui/info-dialog.[ch]
* app/gui/layer-select.c
* app/gui/layers-commands.c
* app/gui/menus.c
* app/gui/offset-dialog.c
* app/gui/palette-editor.c
* app/gui/palettes-commands.c
* app/gui/patterns-commands.c
* app/gui/preferences-dialog.c
* app/gui/resize-dialog.[ch]
* app/gui/splash.c
* app/gui/tips-dialog.c
* app/gui/tool-options-dialog.c
* app/gui/toolbox.c
* app/gui/tools-commands.c
* libgimp/gimpbrushmenu.c
* libgimp/gimpmenu.c
* libgimp/gimppatternmenu.c
* libgimp/gimpui.c
* libgimpbase/gimpenv.c: tons and tons of changes like "const
gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete
and currently disables), lots of s/gtk_signal/g_signal/,
removal/replacement of deprecated stuff,
s/GtkSignalFunc/GCallback/ and lots of small changes and fixes
while I was on it, zillions of warnings left...
* modules/Makefile.am: disabled the water color selector
temporarily (XInput issues).
* plug-ins/Makefile.am
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl: simply excluded all plug-ins
which did not build (including Script-Fu). They are trivial to
fix.
2001-07-25 05:27:11 +08:00
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
2001-02-28 03:18:01 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
tool_class->control = gimp_paint_tool_control;
|
2001-02-28 03:18:01 +08:00
|
|
|
tool_class->button_press = gimp_paint_tool_button_press;
|
|
|
|
tool_class->button_release = gimp_paint_tool_button_release;
|
|
|
|
tool_class->motion = gimp_paint_tool_motion;
|
|
|
|
tool_class->cursor_update = gimp_paint_tool_cursor_update;
|
|
|
|
|
|
|
|
draw_tool_class->draw = gimp_paint_tool_draw;
|
|
|
|
|
|
|
|
klass->paint = NULL;
|
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
|
|
|
|
gimp_paint_tool_init (GimpPaintTool *tool)
|
|
|
|
{
|
|
|
|
tool->pick_colors = FALSE;
|
|
|
|
tool->flags = 0;
|
|
|
|
tool->context_id = 0;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
2001-10-29 19:47:11 +08:00
|
|
|
gimp_paint_tool_control (GimpTool *tool,
|
|
|
|
ToolAction action,
|
|
|
|
GimpDisplay *gdisp)
|
2001-02-28 03:18:01 +08:00
|
|
|
{
|
|
|
|
GimpPaintTool *paint_tool;
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
|
|
|
|
paint_tool = GIMP_PAINT_TOOL (tool);
|
|
|
|
drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
|
|
|
|
|
|
switch (action)
|
1999-05-13 19:12:32 +08:00
|
|
|
{
|
2001-02-28 03:18:01 +08:00
|
|
|
case PAUSE:
|
|
|
|
break;
|
2001-01-15 09:48:53 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
case RESUME:
|
|
|
|
break;
|
2000-02-28 10:40:44 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
case HALT:
|
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, FINISH_PAINT);
|
|
|
|
gimp_paint_tool_cleanup ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
1999-05-13 19:12:32 +08:00
|
|
|
}
|
|
|
|
|
2001-12-02 06:59:48 +08:00
|
|
|
GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
|
2001-02-28 03:18:01 +08:00
|
|
|
}
|
1999-05-13 19:12:32 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
2001-11-09 03:14:51 +08:00
|
|
|
gimp_paint_tool_button_press (GimpTool *tool,
|
|
|
|
GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *gdisp)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-11-01 05:20:09 +08:00
|
|
|
GimpPaintTool *paint_tool;
|
|
|
|
GimpDisplayShell *shell;
|
|
|
|
GimpBrush *current_brush;
|
|
|
|
gboolean draw_line;
|
|
|
|
GimpDrawable *drawable;
|
2001-11-09 03:14:51 +08:00
|
|
|
gdouble x, y;
|
|
|
|
gint off_x, off_y;
|
2001-02-27 13:21:12 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
paint_tool = GIMP_PAINT_TOOL (tool);
|
Jens Lautenbacher <jtl@gimp.org>
2000-12-18 Sven Neumann <sven@gimp.org>
Jens Lautenbacher <jtl@gimp.org>
* app/Makefile.am
* app/gimpbrushlistP.h
* app/gimpbrushpipeP.h
* app/gimpobjectP.h: removed these three files
* app/parasitelistP.h
* app/channels_dialog.c
* app/docindex.c
* app/gimpdrawable.c
* app/gimpdrawableP.h
* app/gimpimage.c
* app/gimpimageP.h
* app/gimplist.[ch]
* app/gimpobject.c
* app/gimpobject.h
* app/gimpsetP.h: changed according to header removal
* app/airbrush.c
* app/brush_select.[ch]
* app/brushes_cmds.c
* app/gimpbrush.[ch]
* app/gimpbrushgenerated.[ch]
* app/gimpbrushlist.[ch]
* app/gimpbrushpipe.[ch]
* app/gimpcontextpreview.c
* app/paint_core.c
* app/paintbrush.c
* app/pencil.c
* tools/pdbgen/pdb/brushes.pdb: Big Brushes Cleanup.
The GimpBrush* object hierarchy and the file formats were broken by
"design". This made it overly difficult to read and write pixmap
brushes and brush pipes, leading to the situation that The GIMP was
not able to read it's very own file formats. Since the GimpBrush
format did support arbitrary color depths, the introduction of a
file format for pixmap brushes was unnecessary.
The GimpBrushPixmap object is dead. GimpBrush has an additional
pixmap temp_buf and handles pixmap brushes transparently. The file
format of pixmap brushes is not any longer a grayscale brush plus
a pattern, but a simple brush with RGBA data. The old brushes can
still be loaded, but the .gpb format is deprecated.
GimpBrushPipe derives from GimpBrush. The fileformat is still a text
header, followed by a number of brushes, but those brushes are stored
in the new GimpBrush format (no pattern anymore). The pipe does not
care about the depth of the contained GimpBrushes, so we get
grayscale BrushPipes for free. Since the brush loader still loads the
old format, old .gih files can also still be loaded.
Since the brushes in the GimpBrushPipe do not any longer contain a
pointer to the pipe object, we do only temporarily switch brushes
in the paint_core routines. This is not very elegant, but the best
we can do without a major redesign.
* app/patterns.[ch]: changed the loader to work with a filedescriptor
instead of a filehandle to make it work with the new brush loading
code.
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/gih.c: new plug-in that saves GIH files in the
new format (loader will follow soon)
* plug-ins/common/gpb.c: removed since Pixmap Brushes are no longer
supported as a special file format.
* plug-ins/common/gbr.c: load and save brushes in the new brush format
which allows RGBA brushes too.
* plug-ins/common/pat.c: load and save grayscale patterns too
2000-12-18 23:14:08 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
|
2000-12-29 23:22:01 +08:00
|
|
|
drawable = gimp_image_active_drawable (gdisp->gimage);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
gimp_drawable_offsets (drawable, &off_x, &off_y);
|
|
|
|
|
|
|
|
x = coords->x - off_x;
|
|
|
|
y = coords->y - off_y;
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (! gimp_paint_tool_start (paint_tool, drawable, x, y))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
1999-06-03 23:02:48 +08:00
|
|
|
draw_line = FALSE;
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
{
|
|
|
|
gdouble save_x, save_y;
|
|
|
|
|
|
|
|
save_x = paint_tool->cur_coords.x;
|
|
|
|
save_y = paint_tool->cur_coords.y;
|
|
|
|
|
|
|
|
paint_tool->cur_coords = *coords;
|
|
|
|
paint_tool->state = state;
|
|
|
|
|
|
|
|
paint_tool->cur_coords.x = save_x;
|
|
|
|
paint_tool->cur_coords.y = save_y;
|
|
|
|
}
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
if (gdisp != tool->gdisp || paint_tool->context_id < 1)
|
1999-09-02 02:46:25 +08:00
|
|
|
{
|
|
|
|
/* initialize the statusbar display */
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->context_id =
|
2001-11-01 05:20:09 +08:00
|
|
|
gtk_statusbar_get_context_id (GTK_STATUSBAR (shell->statusbar), "paint");
|
1999-09-02 02:46:25 +08:00
|
|
|
}
|
2000-03-05 08:06:11 +08:00
|
|
|
|
|
|
|
/* if this is a new image, reinit the core vals */
|
2001-11-09 03:14:51 +08:00
|
|
|
if ((gdisp != tool->gdisp) || ! (state & GDK_SHIFT_MASK))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* initialize some values */
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x = x;
|
|
|
|
paint_tool->cur_coords.y = y;
|
|
|
|
|
|
|
|
paint_tool->start_coords = paint_tool->cur_coords;
|
|
|
|
paint_tool->last_coords = paint_tool->cur_coords;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
1999-08-14 20:34:08 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* If shift is down and this is not the first paint
|
|
|
|
* stroke, then draw a line from the last coords to the pointer
|
|
|
|
*/
|
2001-11-09 03:14:51 +08:00
|
|
|
else if (state & GDK_SHIFT_MASK)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-03 23:02:48 +08:00
|
|
|
draw_line = TRUE;
|
2001-11-14 00:21:34 +08:00
|
|
|
|
2001-12-02 06:59:48 +08:00
|
|
|
paint_tool->start_coords = paint_tool->last_coords;
|
1999-06-18 04:34:50 +08:00
|
|
|
|
1999-11-25 09:59:14 +08:00
|
|
|
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
2001-11-09 03:14:51 +08:00
|
|
|
if (state & GDK_CONTROL_MASK)
|
1999-06-18 04:34:50 +08:00
|
|
|
{
|
2000-03-05 08:06:11 +08:00
|
|
|
gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 };
|
|
|
|
gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 };
|
|
|
|
gint dx, dy, i, radius, frac;
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
dx = paint_tool->cur_coords.x - paint_tool->last_coords.x;
|
|
|
|
dy = paint_tool->cur_coords.y - paint_tool->last_coords.y;
|
2000-03-05 08:06:11 +08:00
|
|
|
|
1999-11-25 09:59:14 +08:00
|
|
|
if (dy)
|
1999-06-18 04:34:50 +08:00
|
|
|
{
|
1999-11-25 09:59:14 +08:00
|
|
|
radius = sqrt (SQR (dx) + SQR (dy));
|
|
|
|
frac = abs ((dx << 8) / dy);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
if (frac < tangens2[i])
|
2001-02-27 13:21:12 +08:00
|
|
|
break;
|
1999-11-25 09:59:14 +08:00
|
|
|
}
|
|
|
|
dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8);
|
2000-06-06 06:08:45 +08:00
|
|
|
dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8);
|
1999-06-18 04:34:50 +08:00
|
|
|
}
|
2001-11-14 00:21:34 +08:00
|
|
|
|
|
|
|
paint_tool->cur_coords.x = paint_tool->last_coords.x + dx;
|
|
|
|
paint_tool->cur_coords.y = paint_tool->last_coords.y + dy;
|
1999-06-18 04:34:50 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
tool->state = ACTIVE;
|
2000-12-31 12:07:42 +08:00
|
|
|
tool->gdisp = gdisp;
|
1997-11-25 06:05:25 +08:00
|
|
|
tool->paused_count = 0;
|
|
|
|
|
|
|
|
/* pause the current selection and grab the pointer */
|
2001-09-26 01:44:03 +08:00
|
|
|
gimp_image_selection_control (gdisp->gimage, GIMP_SELECTION_PAUSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-05-05 17:10:35 +08:00
|
|
|
/* add motion memory if perfectmouse is set */
|
2001-11-09 03:14:51 +08:00
|
|
|
if (gimprc.perfectmouse)
|
|
|
|
{
|
|
|
|
gdk_pointer_grab (shell->canvas->window, FALSE,
|
|
|
|
GDK_BUTTON1_MOTION_MASK |
|
|
|
|
GDK_BUTTON_RELEASE_MASK,
|
|
|
|
NULL, NULL, time);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
2001-11-09 03:14:51 +08:00
|
|
|
{
|
|
|
|
gdk_pointer_grab (shell->canvas->window, FALSE,
|
|
|
|
GDK_POINTER_MOTION_HINT_MASK |
|
|
|
|
GDK_BUTTON1_MOTION_MASK |
|
|
|
|
GDK_BUTTON_RELEASE_MASK,
|
|
|
|
NULL, NULL, time);
|
|
|
|
}
|
2000-03-05 08:06:11 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Let the specific painting function initialize itself */
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, INIT_PAINT);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
if (paint_tool->pick_colors &&
|
|
|
|
! (state & GDK_SHIFT_MASK) &&
|
|
|
|
(state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)))
|
1999-08-14 20:34:08 +08:00
|
|
|
{
|
2001-11-09 03:14:51 +08:00
|
|
|
gimp_paint_tool_sample_color (drawable, coords->x, coords->y, state);
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->pick_state = TRUE;
|
1999-08-14 20:34:08 +08:00
|
|
|
return;
|
|
|
|
}
|
1999-05-13 19:12:32 +08:00
|
|
|
else
|
2001-11-09 03:14:51 +08:00
|
|
|
{
|
|
|
|
paint_tool->pick_state = FALSE;
|
|
|
|
}
|
1999-05-13 19:12:32 +08:00
|
|
|
|
Jens Lautenbacher <jtl@gimp.org>
2000-12-18 Sven Neumann <sven@gimp.org>
Jens Lautenbacher <jtl@gimp.org>
* app/Makefile.am
* app/gimpbrushlistP.h
* app/gimpbrushpipeP.h
* app/gimpobjectP.h: removed these three files
* app/parasitelistP.h
* app/channels_dialog.c
* app/docindex.c
* app/gimpdrawable.c
* app/gimpdrawableP.h
* app/gimpimage.c
* app/gimpimageP.h
* app/gimplist.[ch]
* app/gimpobject.c
* app/gimpobject.h
* app/gimpsetP.h: changed according to header removal
* app/airbrush.c
* app/brush_select.[ch]
* app/brushes_cmds.c
* app/gimpbrush.[ch]
* app/gimpbrushgenerated.[ch]
* app/gimpbrushlist.[ch]
* app/gimpbrushpipe.[ch]
* app/gimpcontextpreview.c
* app/paint_core.c
* app/paintbrush.c
* app/pencil.c
* tools/pdbgen/pdb/brushes.pdb: Big Brushes Cleanup.
The GimpBrush* object hierarchy and the file formats were broken by
"design". This made it overly difficult to read and write pixmap
brushes and brush pipes, leading to the situation that The GIMP was
not able to read it's very own file formats. Since the GimpBrush
format did support arbitrary color depths, the introduction of a
file format for pixmap brushes was unnecessary.
The GimpBrushPixmap object is dead. GimpBrush has an additional
pixmap temp_buf and handles pixmap brushes transparently. The file
format of pixmap brushes is not any longer a grayscale brush plus
a pattern, but a simple brush with RGBA data. The old brushes can
still be loaded, but the .gpb format is deprecated.
GimpBrushPipe derives from GimpBrush. The fileformat is still a text
header, followed by a number of brushes, but those brushes are stored
in the new GimpBrush format (no pattern anymore). The pipe does not
care about the depth of the contained GimpBrushes, so we get
grayscale BrushPipes for free. Since the brush loader still loads the
old format, old .gih files can also still be loaded.
Since the brushes in the GimpBrushPipe do not any longer contain a
pointer to the pipe object, we do only temporarily switch brushes
in the paint_core routines. This is not very elegant, but the best
we can do without a major redesign.
* app/patterns.[ch]: changed the loader to work with a filedescriptor
instead of a filehandle to make it work with the new brush loading
code.
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/gih.c: new plug-in that saves GIH files in the
new format (loader will follow soon)
* plug-ins/common/gpb.c: removed since Pixmap Brushes are no longer
supported as a special file format.
* plug-ins/common/gbr.c: load and save brushes in the new brush format
which allows RGBA brushes too.
* plug-ins/common/pat.c: load and save grayscale patterns too
2000-12-18 23:14:08 +08:00
|
|
|
/* store the current brush pointer */
|
2001-02-27 13:21:12 +08:00
|
|
|
current_brush = paint_tool->brush;
|
Jens Lautenbacher <jtl@gimp.org>
2000-12-18 Sven Neumann <sven@gimp.org>
Jens Lautenbacher <jtl@gimp.org>
* app/Makefile.am
* app/gimpbrushlistP.h
* app/gimpbrushpipeP.h
* app/gimpobjectP.h: removed these three files
* app/parasitelistP.h
* app/channels_dialog.c
* app/docindex.c
* app/gimpdrawable.c
* app/gimpdrawableP.h
* app/gimpimage.c
* app/gimpimageP.h
* app/gimplist.[ch]
* app/gimpobject.c
* app/gimpobject.h
* app/gimpsetP.h: changed according to header removal
* app/airbrush.c
* app/brush_select.[ch]
* app/brushes_cmds.c
* app/gimpbrush.[ch]
* app/gimpbrushgenerated.[ch]
* app/gimpbrushlist.[ch]
* app/gimpbrushpipe.[ch]
* app/gimpcontextpreview.c
* app/paint_core.c
* app/paintbrush.c
* app/pencil.c
* tools/pdbgen/pdb/brushes.pdb: Big Brushes Cleanup.
The GimpBrush* object hierarchy and the file formats were broken by
"design". This made it overly difficult to read and write pixmap
brushes and brush pipes, leading to the situation that The GIMP was
not able to read it's very own file formats. Since the GimpBrush
format did support arbitrary color depths, the introduction of a
file format for pixmap brushes was unnecessary.
The GimpBrushPixmap object is dead. GimpBrush has an additional
pixmap temp_buf and handles pixmap brushes transparently. The file
format of pixmap brushes is not any longer a grayscale brush plus
a pattern, but a simple brush with RGBA data. The old brushes can
still be loaded, but the .gpb format is deprecated.
GimpBrushPipe derives from GimpBrush. The fileformat is still a text
header, followed by a number of brushes, but those brushes are stored
in the new GimpBrush format (no pattern anymore). The pipe does not
care about the depth of the contained GimpBrushes, so we get
grayscale BrushPipes for free. Since the brush loader still loads the
old format, old .gih files can also still be loaded.
Since the brushes in the GimpBrushPipe do not any longer contain a
pointer to the pipe object, we do only temporarily switch brushes
in the paint_core routines. This is not very elegant, but the best
we can do without a major redesign.
* app/patterns.[ch]: changed the loader to work with a filedescriptor
instead of a filehandle to make it work with the new brush loading
code.
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/gih.c: new plug-in that saves GIH files in the
new format (loader will follow soon)
* plug-ins/common/gpb.c: removed since Pixmap Brushes are no longer
supported as a special file format.
* plug-ins/common/gbr.c: load and save brushes in the new brush format
which allows RGBA brushes too.
* plug-ins/common/pat.c: load and save grayscale patterns too
2000-12-18 23:14:08 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Paint to the image */
|
|
|
|
if (draw_line)
|
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_draw_tool_pause (GIMP_DRAW_TOOL(paint_tool));
|
2001-11-09 03:14:51 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_interpolate (paint_tool, drawable);
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->last_coords = paint_tool->cur_coords;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
Overhaul of pixmap brushes and pipes: No separate pixmap pipe
brush tool any longer. The paintbrush, airbrush and pencil
tools, which already knew how to handle the single-pixmap
brushes now also handle the pipes as well.
* app/pixmapbrush.{h,c}
* app/gimpbrushpixmap.{h,c}: Removed these files.
* app/Makefile.am
* app/makefile.{cygwin,msc}: Remove from here, too.
* app/gimpbrushpipe.{h,c}: Total overhaul.
* app/paint_core.h
* app/apptypes.h: Some more types moved to apptypes.h
* app/context_manager.c
* app/tool_options.c
* app/tools.c
* app/toolsF.h: Remove PIXMAPBRUSH tool.
* app/gimpbrush.h: New method: select_brush. Used to change the
brush in paint_core, for pipe brushes.
* app/gimpbrush.c: Add gimp_brush_select_brush, which is dummy for
the normal brushes (returns the same brush).
* app/paint_core.c: Call the brush's select_brush method to get a
potential new brush before calling the paint_func.
* app/gimpbrushlist.c: Various changes related to the pixmap and
pipe overhaul.
* app/airbrush.c
* app/pencil.c: Reorder code a bit in the tool motion function to
avoid executing unnecessary code in the case of a pixmap brush.
Other changes in the same commit:
* app/install.c: Make quote_spaces extern.
* app/appenv.h: Declare it.
* libgimp/gimpui.def: Add missing entry points.
* libgimp/makefile.{cygwin,msc}: Add missing objects to gimpui.
1999-08-26 08:54:30 +08:00
|
|
|
{
|
1999-08-31 05:24:13 +08:00
|
|
|
/* If we current point == last point, check if the brush
|
|
|
|
* wants to be painted in that case. (Direction dependent
|
|
|
|
* pixmap brush pipes don't, as they don't know which
|
|
|
|
* pixmap to select.)
|
|
|
|
*/
|
2001-11-14 00:21:34 +08:00
|
|
|
if (paint_tool->last_coords.x != paint_tool->cur_coords.x ||
|
2001-12-02 06:59:48 +08:00
|
|
|
paint_tool->last_coords.y != paint_tool->cur_coords.y ||
|
|
|
|
gimp_brush_want_null_motion (paint_tool->brush,
|
|
|
|
&paint_tool->last_coords,
|
|
|
|
&paint_tool->cur_coords))
|
1999-08-31 05:24:13 +08:00
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH)
|
2001-08-14 22:53:55 +08:00
|
|
|
{
|
|
|
|
paint_tool->brush =
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_brush_select_brush (paint_tool->brush,
|
|
|
|
&paint_tool->last_coords,
|
|
|
|
&paint_tool->cur_coords);
|
2001-08-14 22:53:55 +08:00
|
|
|
}
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, MOTION_PAINT);
|
1999-08-31 05:24:13 +08:00
|
|
|
}
|
Overhaul of pixmap brushes and pipes: No separate pixmap pipe
brush tool any longer. The paintbrush, airbrush and pencil
tools, which already knew how to handle the single-pixmap
brushes now also handle the pipes as well.
* app/pixmapbrush.{h,c}
* app/gimpbrushpixmap.{h,c}: Removed these files.
* app/Makefile.am
* app/makefile.{cygwin,msc}: Remove from here, too.
* app/gimpbrushpipe.{h,c}: Total overhaul.
* app/paint_core.h
* app/apptypes.h: Some more types moved to apptypes.h
* app/context_manager.c
* app/tool_options.c
* app/tools.c
* app/toolsF.h: Remove PIXMAPBRUSH tool.
* app/gimpbrush.h: New method: select_brush. Used to change the
brush in paint_core, for pipe brushes.
* app/gimpbrush.c: Add gimp_brush_select_brush, which is dummy for
the normal brushes (returns the same brush).
* app/paint_core.c: Call the brush's select_brush method to get a
potential new brush before calling the paint_func.
* app/gimpbrushlist.c: Various changes related to the pixmap and
pipe overhaul.
* app/airbrush.c
* app/pencil.c: Reorder code a bit in the tool motion function to
avoid executing unnecessary code in the case of a pixmap brush.
Other changes in the same commit:
* app/install.c: Make quote_spaces extern.
* app/appenv.h: Declare it.
* libgimp/gimpui.def: Add missing entry points.
* libgimp/makefile.{cygwin,msc}: Add missing objects to gimpui.
1999-08-26 08:54:30 +08:00
|
|
|
}
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->flags & TOOL_TRACES_ON_WINDOW)
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, PRETRACE_PAINT);
|
2000-12-31 12:07:42 +08:00
|
|
|
|
2001-11-11 07:03:22 +08:00
|
|
|
gimp_display_flush_now (gdisp);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->flags & TOOL_TRACES_ON_WINDOW)
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, POSTTRACE_PAINT);
|
Jens Lautenbacher <jtl@gimp.org>
2000-12-18 Sven Neumann <sven@gimp.org>
Jens Lautenbacher <jtl@gimp.org>
* app/Makefile.am
* app/gimpbrushlistP.h
* app/gimpbrushpipeP.h
* app/gimpobjectP.h: removed these three files
* app/parasitelistP.h
* app/channels_dialog.c
* app/docindex.c
* app/gimpdrawable.c
* app/gimpdrawableP.h
* app/gimpimage.c
* app/gimpimageP.h
* app/gimplist.[ch]
* app/gimpobject.c
* app/gimpobject.h
* app/gimpsetP.h: changed according to header removal
* app/airbrush.c
* app/brush_select.[ch]
* app/brushes_cmds.c
* app/gimpbrush.[ch]
* app/gimpbrushgenerated.[ch]
* app/gimpbrushlist.[ch]
* app/gimpbrushpipe.[ch]
* app/gimpcontextpreview.c
* app/paint_core.c
* app/paintbrush.c
* app/pencil.c
* tools/pdbgen/pdb/brushes.pdb: Big Brushes Cleanup.
The GimpBrush* object hierarchy and the file formats were broken by
"design". This made it overly difficult to read and write pixmap
brushes and brush pipes, leading to the situation that The GIMP was
not able to read it's very own file formats. Since the GimpBrush
format did support arbitrary color depths, the introduction of a
file format for pixmap brushes was unnecessary.
The GimpBrushPixmap object is dead. GimpBrush has an additional
pixmap temp_buf and handles pixmap brushes transparently. The file
format of pixmap brushes is not any longer a grayscale brush plus
a pattern, but a simple brush with RGBA data. The old brushes can
still be loaded, but the .gpb format is deprecated.
GimpBrushPipe derives from GimpBrush. The fileformat is still a text
header, followed by a number of brushes, but those brushes are stored
in the new GimpBrush format (no pattern anymore). The pipe does not
care about the depth of the contained GimpBrushes, so we get
grayscale BrushPipes for free. Since the brush loader still loads the
old format, old .gih files can also still be loaded.
Since the brushes in the GimpBrushPipe do not any longer contain a
pointer to the pipe object, we do only temporarily switch brushes
in the paint_core routines. This is not very elegant, but the best
we can do without a major redesign.
* app/patterns.[ch]: changed the loader to work with a filedescriptor
instead of a filehandle to make it work with the new brush loading
code.
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/gih.c: new plug-in that saves GIH files in the
new format (loader will follow soon)
* plug-ins/common/gpb.c: removed since Pixmap Brushes are no longer
supported as a special file format.
* plug-ins/common/gbr.c: load and save brushes in the new brush format
which allows RGBA brushes too.
* plug-ins/common/pat.c: load and save grayscale patterns too
2000-12-18 23:14:08 +08:00
|
|
|
|
|
|
|
/* restore the current brush pointer */
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->brush = current_brush;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
2001-11-09 03:14:51 +08:00
|
|
|
gimp_paint_tool_button_release (GimpTool *tool,
|
|
|
|
GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *gdisp)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
GimpPaintTool *paint_tool;
|
2001-12-02 06:59:48 +08:00
|
|
|
GimpDrawable *drawable;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
paint_tool = GIMP_PAINT_TOOL (tool);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-12-02 06:59:48 +08:00
|
|
|
drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* resume the current selection and ungrab the pointer */
|
2001-09-26 01:44:03 +08:00
|
|
|
gimp_image_selection_control (gdisp->gimage, GIMP_SELECTION_RESUME);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
gdk_pointer_ungrab (time);
|
1997-11-25 06:05:25 +08:00
|
|
|
gdk_flush ();
|
|
|
|
|
|
|
|
/* Let the specific painting function finish up */
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, FINISH_PAINT);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_draw_tool_stop (GIMP_DRAW_TOOL (paint_tool));
|
2001-12-02 06:59:48 +08:00
|
|
|
|
|
|
|
/* Set tool state to inactive -- no longer painting */
|
1997-11-25 06:05:25 +08:00
|
|
|
tool->state = INACTIVE;
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->pick_state = FALSE;
|
1999-05-13 19:12:32 +08:00
|
|
|
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_paint_tool_finish (paint_tool, drawable);
|
2001-02-28 03:18:01 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
gdisplays_flush ();
|
|
|
|
}
|
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
2001-11-09 03:14:51 +08:00
|
|
|
gimp_paint_tool_motion (GimpTool *tool,
|
|
|
|
GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *gdisp)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
GimpPaintTool *paint_tool;
|
2001-12-02 06:59:48 +08:00
|
|
|
GimpDrawable *drawable;
|
2001-11-09 03:14:51 +08:00
|
|
|
gint off_x, off_y;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
paint_tool = GIMP_PAINT_TOOL (tool);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-12-02 06:59:48 +08:00
|
|
|
drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
|
|
|
|
|
|
gimp_drawable_offsets (drawable, &off_x, &off_y);
|
2001-11-09 03:14:51 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords = *coords;
|
|
|
|
paint_tool->state = state;
|
|
|
|
|
|
|
|
paint_tool->cur_coords.x -= off_x;
|
|
|
|
paint_tool->cur_coords.y -= off_y;
|
1999-05-13 19:12:32 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->pick_state)
|
2000-03-05 08:06:11 +08:00
|
|
|
{
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_paint_tool_sample_color (drawable,
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x,
|
|
|
|
paint_tool->cur_coords.y,
|
2001-11-09 03:14:51 +08:00
|
|
|
state);
|
2000-03-05 08:06:11 +08:00
|
|
|
return;
|
|
|
|
}
|
1999-05-13 19:12:32 +08:00
|
|
|
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_paint_tool_interpolate (paint_tool, drawable);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->flags & TOOL_TRACES_ON_WINDOW)
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, PRETRACE_PAINT);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-11-11 07:03:22 +08:00
|
|
|
gimp_display_flush_now (gdisp);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->flags & TOOL_TRACES_ON_WINDOW)
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, POSTTRACE_PAINT);
|
2001-11-14 00:21:34 +08:00
|
|
|
|
|
|
|
paint_tool->last_coords = paint_tool->cur_coords;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
|
|
|
|
/* FIXME: this belongs in the individual tools */
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
2001-11-09 03:14:51 +08:00
|
|
|
gimp_paint_tool_cursor_update (GimpTool *tool,
|
|
|
|
GimpCoords *coords,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *gdisp)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-11-01 05:20:09 +08:00
|
|
|
GimpPaintTool *paint_tool;
|
|
|
|
GimpDrawTool *draw_tool;
|
|
|
|
GimpDisplayShell *shell;
|
|
|
|
GimpLayer *layer;
|
|
|
|
gchar status_str[STATUSBAR_SIZE];
|
2000-06-14 18:59:16 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
GdkCursorType ctype = GIMP_MOUSE_CURSOR;
|
2001-02-25 03:29:47 +08:00
|
|
|
GimpCursorModifier cmodifier = GIMP_CURSOR_MODIFIER_NONE;
|
2001-02-28 03:18:01 +08:00
|
|
|
gboolean ctoggle = FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
paint_tool = GIMP_PAINT_TOOL (tool);
|
|
|
|
draw_tool = GIMP_DRAW_TOOL (tool);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
/* undraw the current tool */
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_draw_tool_pause (draw_tool);
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (gdisp != tool->gdisp || paint_tool->context_id < 1)
|
2000-03-05 08:06:11 +08:00
|
|
|
{
|
|
|
|
/* initialize the statusbar display */
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->context_id =
|
2001-11-01 05:20:09 +08:00
|
|
|
gtk_statusbar_get_context_id (GTK_STATUSBAR (shell->statusbar), "paint");
|
2000-03-05 08:06:11 +08:00
|
|
|
}
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->context_id)
|
2001-11-01 05:20:09 +08:00
|
|
|
gtk_statusbar_pop (GTK_STATUSBAR (shell->statusbar), paint_tool->context_id);
|
1999-05-15 08:02:47 +08:00
|
|
|
|
2001-03-12 01:24:47 +08:00
|
|
|
#ifdef __GNUC__
|
|
|
|
#warning this doesnt belong here
|
|
|
|
#endif
|
2001-02-28 03:18:01 +08:00
|
|
|
/* Set toggle cursors for various paint tools */
|
|
|
|
if (tool->toggled)
|
|
|
|
{
|
2001-12-02 06:59:48 +08:00
|
|
|
if (GIMP_IS_ERASER_TOOL (tool))
|
2001-02-28 03:18:01 +08:00
|
|
|
{
|
|
|
|
cmodifier = GIMP_CURSOR_MODIFIER_MINUS;
|
|
|
|
}
|
2001-12-02 06:59:48 +08:00
|
|
|
else if (GIMP_IS_CONVOLVE_TOOL (tool))
|
2001-02-28 03:18:01 +08:00
|
|
|
{
|
|
|
|
cmodifier = GIMP_CURSOR_MODIFIER_MINUS;
|
|
|
|
}
|
2001-12-02 06:59:48 +08:00
|
|
|
else if (GIMP_IS_DODGEBURN_TOOL (tool))
|
2001-02-28 03:18:01 +08:00
|
|
|
{
|
|
|
|
ctoggle = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-12-29 23:22:01 +08:00
|
|
|
if ((layer = gimp_image_get_active_layer (gdisp->gimage)))
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2001-11-14 00:21:34 +08:00
|
|
|
gint off_x, off_y;
|
|
|
|
|
|
|
|
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
|
|
|
|
|
1999-05-15 08:02:47 +08:00
|
|
|
/* If shift is down and this is not the first paint stroke, draw a line */
|
2001-11-09 03:14:51 +08:00
|
|
|
if (gdisp == tool->gdisp && (state & GDK_SHIFT_MASK))
|
2001-02-27 13:21:12 +08:00
|
|
|
{
|
1999-09-02 02:46:25 +08:00
|
|
|
gdouble dx, dy, d;
|
1999-08-21 21:16:20 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
/* Get the current coordinates */
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x = coords->x - off_x;
|
|
|
|
paint_tool->cur_coords.y = coords->y - off_y;
|
1999-05-15 08:36:42 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
dx = paint_tool->cur_coords.x - paint_tool->last_coords.x;
|
|
|
|
dy = paint_tool->cur_coords.y - paint_tool->last_coords.y;
|
2000-03-05 08:06:11 +08:00
|
|
|
|
1999-11-25 09:59:14 +08:00
|
|
|
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
2001-11-09 03:14:51 +08:00
|
|
|
if (state & GDK_CONTROL_MASK)
|
1999-06-18 04:34:50 +08:00
|
|
|
{
|
2000-03-05 08:06:11 +08:00
|
|
|
gint idx = dx;
|
|
|
|
gint idy = dy;
|
|
|
|
gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 };
|
|
|
|
gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 };
|
|
|
|
gint i, radius, frac;
|
2000-12-31 12:07:42 +08:00
|
|
|
|
1999-11-25 09:59:14 +08:00
|
|
|
if (idy)
|
1999-06-18 04:34:50 +08:00
|
|
|
{
|
1999-11-25 09:59:14 +08:00
|
|
|
radius = sqrt (SQR (idx) + SQR (idy));
|
|
|
|
frac = abs ((idx << 8) / idy);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
if (frac < tangens2[i])
|
2001-02-27 13:21:12 +08:00
|
|
|
break;
|
1999-11-25 09:59:14 +08:00
|
|
|
}
|
2001-11-09 03:14:51 +08:00
|
|
|
|
1999-11-25 09:59:14 +08:00
|
|
|
dx = idx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8);
|
|
|
|
dy = idy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8);
|
1999-06-18 04:34:50 +08:00
|
|
|
}
|
1999-11-25 09:59:14 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x = paint_tool->last_coords.x + dx;
|
|
|
|
paint_tool->cur_coords.y = paint_tool->last_coords.y + dy;
|
1999-06-18 04:34:50 +08:00
|
|
|
}
|
|
|
|
|
1999-09-02 02:46:25 +08:00
|
|
|
/* show distance in statusbar */
|
|
|
|
if (gdisp->dot_for_dot)
|
|
|
|
{
|
|
|
|
d = sqrt (SQR (dx) + SQR (dy));
|
2001-11-12 22:45:58 +08:00
|
|
|
g_snprintf (status_str, sizeof (status_str), "%.1f %s",
|
|
|
|
d, _("pixels"));
|
1999-09-02 02:46:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-03-05 08:06:11 +08:00
|
|
|
gchar *format_str =
|
|
|
|
g_strdup_printf ("%%.%df %s",
|
|
|
|
gimp_unit_get_digits (gdisp->gimage->unit),
|
|
|
|
gimp_unit_get_symbol (gdisp->gimage->unit));
|
2001-02-27 13:21:12 +08:00
|
|
|
d = (gimp_unit_get_factor (gdisp->gimage->unit) *
|
2000-03-05 08:06:11 +08:00
|
|
|
sqrt (SQR (dx / gdisp->gimage->xresolution) +
|
|
|
|
SQR (dy / gdisp->gimage->yresolution)));
|
|
|
|
|
2001-11-12 22:45:58 +08:00
|
|
|
g_snprintf (status_str, sizeof (status_str), format_str, d);
|
1999-09-02 02:46:25 +08:00
|
|
|
g_free (format_str);
|
|
|
|
}
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
gtk_statusbar_push (GTK_STATUSBAR (shell->statusbar),
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->context_id, status_str);
|
1999-09-02 02:46:25 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (draw_tool->gc == NULL)
|
2000-06-14 18:59:16 +08:00
|
|
|
{
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_draw_tool_start (draw_tool, shell->canvas->window);
|
2000-06-14 18:59:16 +08:00
|
|
|
}
|
1999-05-15 08:02:47 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* is this a bad hack ? */
|
2001-02-27 13:21:12 +08:00
|
|
|
draw_tool->paused_count = 0;
|
|
|
|
gimp_draw_tool_resume (draw_tool);
|
1999-05-15 08:02:47 +08:00
|
|
|
}
|
2001-02-27 13:21:12 +08:00
|
|
|
}
|
|
|
|
/* If Ctrl or Mod1 is pressed, pick colors */
|
|
|
|
else if (paint_tool->pick_colors &&
|
2001-11-09 03:14:51 +08:00
|
|
|
! (state & GDK_SHIFT_MASK) &&
|
|
|
|
(state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)))
|
1999-06-08 06:38:20 +08:00
|
|
|
{
|
|
|
|
ctype = GIMP_COLOR_PICKER_CURSOR;
|
|
|
|
}
|
1999-06-03 23:02:48 +08:00
|
|
|
/* Normal operation -- no modifier pressed or first stroke */
|
2001-02-27 13:21:12 +08:00
|
|
|
else
|
1999-06-03 23:02:48 +08:00
|
|
|
{
|
2001-11-09 03:14:51 +08:00
|
|
|
if (coords->x >= off_x &&
|
|
|
|
coords->y >= off_y &&
|
|
|
|
coords->x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) &&
|
|
|
|
coords->y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer))))
|
1999-06-03 23:02:48 +08:00
|
|
|
{
|
|
|
|
/* One more test--is there a selected region?
|
|
|
|
* if so, is cursor inside?
|
|
|
|
*/
|
2001-11-29 06:42:19 +08:00
|
|
|
if (gimp_image_mask_is_empty (gdisp->gimage))
|
2000-06-14 18:59:16 +08:00
|
|
|
ctype = GIMP_MOUSE_CURSOR;
|
2001-11-29 06:42:19 +08:00
|
|
|
else if (gimp_image_mask_value (gdisp->gimage,
|
|
|
|
coords->x, coords->y))
|
2000-06-14 18:59:16 +08:00
|
|
|
ctype = GIMP_MOUSE_CURSOR;
|
1999-06-03 23:02:48 +08:00
|
|
|
}
|
1999-05-15 08:02:47 +08:00
|
|
|
}
|
2001-02-25 03:29:47 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_display_shell_install_tool_cursor (shell,
|
|
|
|
ctype,
|
|
|
|
ctype == GIMP_COLOR_PICKER_CURSOR ?
|
|
|
|
GIMP_COLOR_PICKER_TOOL_CURSOR :
|
|
|
|
ctoggle ?
|
|
|
|
tool->toggle_cursor : tool->tool_cursor,
|
|
|
|
cmodifier);
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
static void
|
|
|
|
gimp_paint_tool_draw (GimpDrawTool *draw_tool)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-11-12 22:45:58 +08:00
|
|
|
GimpPaintTool *paint_tool;
|
2001-02-27 13:21:12 +08:00
|
|
|
|
|
|
|
/* if shift was never used, draw_tool->gc is NULL
|
2001-11-01 05:20:09 +08:00
|
|
|
* and we don't care about a redraw
|
|
|
|
*/
|
2001-11-12 22:45:58 +08:00
|
|
|
if (! draw_tool->gc)
|
|
|
|
return;
|
2000-02-10 12:16:52 +08:00
|
|
|
|
2001-11-12 22:45:58 +08:00
|
|
|
paint_tool = GIMP_PAINT_TOOL (draw_tool);
|
2001-11-09 03:14:51 +08:00
|
|
|
|
2001-11-12 22:45:58 +08:00
|
|
|
/* Draw start target */
|
2001-11-16 05:17:36 +08:00
|
|
|
gimp_draw_tool_draw_handle (draw_tool,
|
|
|
|
GIMP_HANDLE_CROSS,
|
|
|
|
floor (paint_tool->last_coords.x) + 0.5,
|
|
|
|
floor (paint_tool->last_coords.y) + 0.5,
|
|
|
|
TARGET_SIZE,
|
|
|
|
TARGET_SIZE,
|
|
|
|
GTK_ANCHOR_CENTER,
|
|
|
|
TRUE);
|
2001-11-12 22:45:58 +08:00
|
|
|
|
|
|
|
/* Draw end target */
|
2001-11-16 05:17:36 +08:00
|
|
|
gimp_draw_tool_draw_handle (draw_tool,
|
|
|
|
GIMP_HANDLE_CROSS,
|
|
|
|
floor (paint_tool->cur_coords.x) + 0.5,
|
|
|
|
floor (paint_tool->cur_coords.y) + 0.5,
|
|
|
|
TARGET_SIZE,
|
|
|
|
TARGET_SIZE,
|
|
|
|
GTK_ANCHOR_CENTER,
|
|
|
|
TRUE);
|
2001-11-12 22:45:58 +08:00
|
|
|
|
|
|
|
/* Draw the line between the start and end coords */
|
|
|
|
gimp_draw_tool_draw_line (draw_tool,
|
2001-11-14 00:21:34 +08:00
|
|
|
floor (paint_tool->last_coords.x) + 0.5,
|
|
|
|
floor (paint_tool->last_coords.y) + 0.5,
|
|
|
|
floor (paint_tool->cur_coords.x) + 0.5,
|
|
|
|
floor (paint_tool->cur_coords.y) + 0.5,
|
2001-11-12 22:45:58 +08:00
|
|
|
TRUE);
|
2001-11-09 03:14:51 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
/***********************************************************************/
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
static void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_sample_color (GimpDrawable *drawable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint state)
|
2001-02-27 13:21:12 +08:00
|
|
|
{
|
2001-02-28 03:18:01 +08:00
|
|
|
GimpRGB color;
|
|
|
|
guchar *col;
|
1999-05-15 20:13:43 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
if( x >= 0 && x < gimp_drawable_width (drawable) &&
|
|
|
|
y >= 0 && y < gimp_drawable_height (drawable))
|
|
|
|
{
|
|
|
|
if ((col = gimp_drawable_get_color_at (drawable, x, y)))
|
|
|
|
{
|
2001-07-07 20:17:23 +08:00
|
|
|
Gimp *gimp;
|
|
|
|
|
|
|
|
gimp = gimp_drawable_gimage (drawable)->gimp;
|
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_rgba_set_uchar (&color,
|
|
|
|
col[RED_PIX],
|
|
|
|
col[GREEN_PIX],
|
|
|
|
col[BLUE_PIX],
|
|
|
|
255);
|
1999-06-26 19:16:47 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
if ((state & GDK_CONTROL_MASK))
|
2001-07-07 20:17:23 +08:00
|
|
|
gimp_context_set_foreground (gimp_get_user_context (gimp), &color);
|
2001-02-28 03:18:01 +08:00
|
|
|
else
|
2001-07-07 20:17:23 +08:00
|
|
|
gimp_context_set_background (gimp_get_user_context (gimp), &color);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-28 03:18:01 +08:00
|
|
|
g_free (col);
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-11-20 22:20:17 +08:00
|
|
|
gimp_paint_tool_paint (GimpPaintTool *paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
GimpDrawable *drawable,
|
|
|
|
PaintState state)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-11-20 22:20:17 +08:00
|
|
|
GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->paint (paint_tool, drawable, state);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2000-03-05 08:06:11 +08:00
|
|
|
gboolean
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_start (GimpPaintTool *paint_tool,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gdouble x,
|
|
|
|
gdouble y)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-11-14 18:50:19 +08:00
|
|
|
static GimpBrush *brush = NULL;
|
2001-02-27 13:21:12 +08:00
|
|
|
|
2001-07-07 20:17:23 +08:00
|
|
|
GimpContext *context;
|
|
|
|
|
2001-10-22 20:13:44 +08:00
|
|
|
context = gimp_get_current_context (gimp_drawable_gimage (drawable)->gimp);
|
2001-07-07 20:17:23 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x = x;
|
|
|
|
paint_tool->cur_coords.y = y;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-03-12 01:24:47 +08:00
|
|
|
#ifdef __GNUC__
|
|
|
|
#warning (FIX non-gui paint tools)
|
|
|
|
#endif
|
2001-02-28 03:18:01 +08:00
|
|
|
#if 0
|
1998-06-06 11:49:01 +08:00
|
|
|
/* Set up some defaults for non-gui use */
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool == &non_gui_paint_tool)
|
1999-09-02 04:16:18 +08:00
|
|
|
{
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.pressure = 1.0;
|
|
|
|
paint_tool->cur_coords.xtilt = 0.5;
|
|
|
|
paint_tool->cur_coords.ytilt = 0.5;
|
|
|
|
paint_tool->cur_coords.wheel = 0.5;
|
|
|
|
|
|
|
|
paint_tool->start_coords = paint_tool->cur_coords;
|
|
|
|
paint_tool->last_coords = paint_tool->cur_coords;
|
1999-09-02 04:16:18 +08:00
|
|
|
}
|
2001-02-28 03:18:01 +08:00
|
|
|
#endif
|
1998-06-06 11:49:01 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Each buffer is the same size as the maximum bounds of the active brush... */
|
2001-07-07 20:17:23 +08:00
|
|
|
if (brush && brush != gimp_context_get_brush (context))
|
1999-10-27 02:27:27 +08:00
|
|
|
{
|
2001-07-25 08:27:41 +08:00
|
|
|
g_signal_handlers_disconnect_by_func (G_OBJECT (brush),
|
|
|
|
G_CALLBACK (gimp_paint_tool_invalidate_cache),
|
|
|
|
NULL);
|
|
|
|
g_object_unref (G_OBJECT (brush));
|
1999-10-27 02:27:27 +08:00
|
|
|
}
|
2001-07-07 20:17:23 +08:00
|
|
|
if (!(brush = gimp_context_get_brush (context)))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1998-12-16 08:37:09 +08:00
|
|
|
g_message (_("No brushes available for use with this tool."));
|
1997-11-25 06:05:25 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-07-25 08:27:41 +08:00
|
|
|
g_object_ref (G_OBJECT (brush));
|
|
|
|
g_signal_connect (G_OBJECT (brush), "invalidate_preview",
|
|
|
|
G_CALLBACK (gimp_paint_tool_invalidate_cache),
|
|
|
|
NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->spacing = (double) gimp_brush_get_spacing (brush) / 100.0;
|
1999-07-26 15:24:47 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->brush = brush;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* free the block structures */
|
|
|
|
if (undo_tiles)
|
|
|
|
tile_manager_destroy (undo_tiles);
|
|
|
|
if (canvas_tiles)
|
|
|
|
tile_manager_destroy (canvas_tiles);
|
|
|
|
|
|
|
|
/* Allocate the undo structure */
|
2001-01-15 05:11:52 +08:00
|
|
|
undo_tiles = tile_manager_new (gimp_drawable_width (drawable),
|
|
|
|
gimp_drawable_height (drawable),
|
|
|
|
gimp_drawable_bytes (drawable));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Allocate the canvas blocks structure */
|
2001-01-15 05:11:52 +08:00
|
|
|
canvas_tiles = tile_manager_new (gimp_drawable_width (drawable),
|
|
|
|
gimp_drawable_height (drawable), 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Get the initial undo extents */
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->x1 = paint_tool->x2 = paint_tool->cur_coords.x;
|
|
|
|
paint_tool->y1 = paint_tool->y2 = paint_tool->cur_coords.y;
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->distance = 0.0;
|
|
|
|
paint_tool->pixel_dist = 0.0;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_interpolate (GimpPaintTool *paint_tool,
|
|
|
|
GimpDrawable *drawable)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-02-28 03:18:01 +08:00
|
|
|
GimpBrush *current_brush;
|
2001-11-14 00:21:34 +08:00
|
|
|
GimpCoords delta;
|
1999-09-26 03:49:58 +08:00
|
|
|
/* double spacing; */
|
|
|
|
/* double lastscale, curscale; */
|
2000-06-06 06:08:45 +08:00
|
|
|
gdouble n;
|
2000-02-15 02:09:33 +08:00
|
|
|
gdouble left;
|
|
|
|
gdouble t;
|
|
|
|
gdouble initial;
|
|
|
|
gdouble dist;
|
|
|
|
gdouble total;
|
|
|
|
gdouble pixel_dist;
|
|
|
|
gdouble pixel_initial;
|
|
|
|
gdouble xd, yd;
|
|
|
|
gdouble mag;
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
delta.x = paint_tool->cur_coords.x - paint_tool->last_coords.x;
|
|
|
|
delta.y = paint_tool->cur_coords.y - paint_tool->last_coords.y;
|
|
|
|
delta.pressure = paint_tool->cur_coords.pressure - paint_tool->last_coords.pressure;
|
|
|
|
delta.xtilt = paint_tool->cur_coords.xtilt - paint_tool->last_coords.xtilt;
|
|
|
|
delta.ytilt = paint_tool->cur_coords.ytilt - paint_tool->last_coords.ytilt;
|
|
|
|
delta.wheel = paint_tool->cur_coords.wheel - paint_tool->last_coords.wheel;
|
2001-03-31 00:39:14 +08:00
|
|
|
|
|
|
|
/* return if there has been no motion */
|
2001-11-14 00:21:34 +08:00
|
|
|
if (! delta.x &&
|
|
|
|
! delta.y &&
|
|
|
|
! delta.pressure &&
|
|
|
|
! delta.xtilt &&
|
|
|
|
! delta.ytilt &&
|
|
|
|
! delta.wheel)
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
1999-07-23 07:11:46 +08:00
|
|
|
|
2000-12-31 12:07:42 +08:00
|
|
|
/* calculate the distance traveled in the coordinate space of the brush */
|
2001-02-27 13:21:12 +08:00
|
|
|
mag = gimp_vector2_length (&(paint_tool->brush->x_axis));
|
2001-11-14 00:21:34 +08:00
|
|
|
xd = gimp_vector2_inner_product ((GimpVector2 *) &delta,
|
2001-02-27 13:21:12 +08:00
|
|
|
&(paint_tool->brush->x_axis)) / (mag*mag);
|
1998-07-24 16:56:18 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
mag = gimp_vector2_length (&(paint_tool->brush->y_axis));
|
2001-11-14 00:21:34 +08:00
|
|
|
yd = gimp_vector2_inner_product ((GimpVector2 *) &delta,
|
2001-02-27 13:21:12 +08:00
|
|
|
&(paint_tool->brush->y_axis)) / (mag*mag);
|
1998-07-24 16:56:18 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
dist = 0.5 * sqrt (xd*xd + yd*yd);
|
|
|
|
total = dist + paint_tool->distance;
|
|
|
|
initial = paint_tool->distance;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
pixel_dist = gimp_vector2_length ((GimpVector2 *) &delta);
|
2001-02-27 13:21:12 +08:00
|
|
|
pixel_initial = paint_tool->pixel_dist;
|
1999-09-26 03:49:58 +08:00
|
|
|
|
|
|
|
/* FIXME: need to adapt the spacing to the size */
|
2001-02-27 13:21:12 +08:00
|
|
|
/* lastscale = MIN (gimp_paint_tool->lastpressure, 1/256); */
|
|
|
|
/* curscale = MIN (gimp_paint_tool->curpressure, 1/256); */
|
|
|
|
/* spacing = gimp_paint_tool->spacing * sqrt (0.5 * (lastscale + curscale)); */
|
1999-09-09 09:47:54 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
while (paint_tool->distance < total)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
n = (gint) (paint_tool->distance / paint_tool->spacing + 1.0 + EPSILON);
|
|
|
|
left = n * paint_tool->spacing - paint_tool->distance;
|
2000-12-31 12:07:42 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->distance += left;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
if (paint_tool->distance <= (total + EPSILON))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
t = (paint_tool->distance - initial) / dist;
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x = (paint_tool->last_coords.x +
|
|
|
|
delta.x * t);
|
|
|
|
paint_tool->cur_coords.y = (paint_tool->last_coords.y +
|
|
|
|
delta.y * t);
|
|
|
|
paint_tool->cur_coords.pressure = (paint_tool->last_coords.pressure +
|
|
|
|
delta.pressure * t);
|
|
|
|
paint_tool->cur_coords.xtilt = (paint_tool->last_coords.xtilt +
|
|
|
|
delta.xtilt * t);
|
|
|
|
paint_tool->cur_coords.ytilt = (paint_tool->last_coords.ytilt +
|
|
|
|
delta.ytilt * t);
|
|
|
|
paint_tool->cur_coords.wheel = (paint_tool->last_coords.wheel +
|
|
|
|
delta.ytilt * t);
|
|
|
|
|
|
|
|
paint_tool->pixel_dist = pixel_initial + pixel_dist * t;
|
Jens Lautenbacher <jtl@gimp.org>
2000-12-18 Sven Neumann <sven@gimp.org>
Jens Lautenbacher <jtl@gimp.org>
* app/Makefile.am
* app/gimpbrushlistP.h
* app/gimpbrushpipeP.h
* app/gimpobjectP.h: removed these three files
* app/parasitelistP.h
* app/channels_dialog.c
* app/docindex.c
* app/gimpdrawable.c
* app/gimpdrawableP.h
* app/gimpimage.c
* app/gimpimageP.h
* app/gimplist.[ch]
* app/gimpobject.c
* app/gimpobject.h
* app/gimpsetP.h: changed according to header removal
* app/airbrush.c
* app/brush_select.[ch]
* app/brushes_cmds.c
* app/gimpbrush.[ch]
* app/gimpbrushgenerated.[ch]
* app/gimpbrushlist.[ch]
* app/gimpbrushpipe.[ch]
* app/gimpcontextpreview.c
* app/paint_core.c
* app/paintbrush.c
* app/pencil.c
* tools/pdbgen/pdb/brushes.pdb: Big Brushes Cleanup.
The GimpBrush* object hierarchy and the file formats were broken by
"design". This made it overly difficult to read and write pixmap
brushes and brush pipes, leading to the situation that The GIMP was
not able to read it's very own file formats. Since the GimpBrush
format did support arbitrary color depths, the introduction of a
file format for pixmap brushes was unnecessary.
The GimpBrushPixmap object is dead. GimpBrush has an additional
pixmap temp_buf and handles pixmap brushes transparently. The file
format of pixmap brushes is not any longer a grayscale brush plus
a pattern, but a simple brush with RGBA data. The old brushes can
still be loaded, but the .gpb format is deprecated.
GimpBrushPipe derives from GimpBrush. The fileformat is still a text
header, followed by a number of brushes, but those brushes are stored
in the new GimpBrush format (no pattern anymore). The pipe does not
care about the depth of the contained GimpBrushes, so we get
grayscale BrushPipes for free. Since the brush loader still loads the
old format, old .gih files can also still be loaded.
Since the brushes in the GimpBrushPipe do not any longer contain a
pointer to the pipe object, we do only temporarily switch brushes
in the paint_core routines. This is not very elegant, but the best
we can do without a major redesign.
* app/patterns.[ch]: changed the loader to work with a filedescriptor
instead of a filehandle to make it work with the new brush loading
code.
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/gih.c: new plug-in that saves GIH files in the
new format (loader will follow soon)
* plug-ins/common/gpb.c: removed since Pixmap Brushes are no longer
supported as a special file format.
* plug-ins/common/gbr.c: load and save brushes in the new brush format
which allows RGBA brushes too.
* plug-ins/common/pat.c: load and save grayscale patterns too
2000-12-18 23:14:08 +08:00
|
|
|
|
|
|
|
/* save the current brush */
|
2001-02-27 13:21:12 +08:00
|
|
|
current_brush = paint_tool->brush;
|
Jens Lautenbacher <jtl@gimp.org>
2000-12-18 Sven Neumann <sven@gimp.org>
Jens Lautenbacher <jtl@gimp.org>
* app/Makefile.am
* app/gimpbrushlistP.h
* app/gimpbrushpipeP.h
* app/gimpobjectP.h: removed these three files
* app/parasitelistP.h
* app/channels_dialog.c
* app/docindex.c
* app/gimpdrawable.c
* app/gimpdrawableP.h
* app/gimpimage.c
* app/gimpimageP.h
* app/gimplist.[ch]
* app/gimpobject.c
* app/gimpobject.h
* app/gimpsetP.h: changed according to header removal
* app/airbrush.c
* app/brush_select.[ch]
* app/brushes_cmds.c
* app/gimpbrush.[ch]
* app/gimpbrushgenerated.[ch]
* app/gimpbrushlist.[ch]
* app/gimpbrushpipe.[ch]
* app/gimpcontextpreview.c
* app/paint_core.c
* app/paintbrush.c
* app/pencil.c
* tools/pdbgen/pdb/brushes.pdb: Big Brushes Cleanup.
The GimpBrush* object hierarchy and the file formats were broken by
"design". This made it overly difficult to read and write pixmap
brushes and brush pipes, leading to the situation that The GIMP was
not able to read it's very own file formats. Since the GimpBrush
format did support arbitrary color depths, the introduction of a
file format for pixmap brushes was unnecessary.
The GimpBrushPixmap object is dead. GimpBrush has an additional
pixmap temp_buf and handles pixmap brushes transparently. The file
format of pixmap brushes is not any longer a grayscale brush plus
a pattern, but a simple brush with RGBA data. The old brushes can
still be loaded, but the .gpb format is deprecated.
GimpBrushPipe derives from GimpBrush. The fileformat is still a text
header, followed by a number of brushes, but those brushes are stored
in the new GimpBrush format (no pattern anymore). The pipe does not
care about the depth of the contained GimpBrushes, so we get
grayscale BrushPipes for free. Since the brush loader still loads the
old format, old .gih files can also still be loaded.
Since the brushes in the GimpBrushPipe do not any longer contain a
pointer to the pipe object, we do only temporarily switch brushes
in the paint_core routines. This is not very elegant, but the best
we can do without a major redesign.
* app/patterns.[ch]: changed the loader to work with a filedescriptor
instead of a filehandle to make it work with the new brush loading
code.
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/gih.c: new plug-in that saves GIH files in the
new format (loader will follow soon)
* plug-ins/common/gpb.c: removed since Pixmap Brushes are no longer
supported as a special file format.
* plug-ins/common/gbr.c: load and save brushes in the new brush format
which allows RGBA brushes too.
* plug-ins/common/pat.c: load and save grayscale patterns too
2000-12-18 23:14:08 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH)
|
2001-08-14 22:53:55 +08:00
|
|
|
{
|
|
|
|
paint_tool->brush =
|
2001-12-02 06:59:48 +08:00
|
|
|
gimp_brush_select_brush (paint_tool->brush,
|
|
|
|
&paint_tool->last_coords,
|
|
|
|
&paint_tool->cur_coords);
|
2001-08-14 22:53:55 +08:00
|
|
|
}
|
2001-12-02 06:59:48 +08:00
|
|
|
|
|
|
|
gimp_paint_tool_paint (paint_tool, drawable, MOTION_PAINT);
|
Jens Lautenbacher <jtl@gimp.org>
2000-12-18 Sven Neumann <sven@gimp.org>
Jens Lautenbacher <jtl@gimp.org>
* app/Makefile.am
* app/gimpbrushlistP.h
* app/gimpbrushpipeP.h
* app/gimpobjectP.h: removed these three files
* app/parasitelistP.h
* app/channels_dialog.c
* app/docindex.c
* app/gimpdrawable.c
* app/gimpdrawableP.h
* app/gimpimage.c
* app/gimpimageP.h
* app/gimplist.[ch]
* app/gimpobject.c
* app/gimpobject.h
* app/gimpsetP.h: changed according to header removal
* app/airbrush.c
* app/brush_select.[ch]
* app/brushes_cmds.c
* app/gimpbrush.[ch]
* app/gimpbrushgenerated.[ch]
* app/gimpbrushlist.[ch]
* app/gimpbrushpipe.[ch]
* app/gimpcontextpreview.c
* app/paint_core.c
* app/paintbrush.c
* app/pencil.c
* tools/pdbgen/pdb/brushes.pdb: Big Brushes Cleanup.
The GimpBrush* object hierarchy and the file formats were broken by
"design". This made it overly difficult to read and write pixmap
brushes and brush pipes, leading to the situation that The GIMP was
not able to read it's very own file formats. Since the GimpBrush
format did support arbitrary color depths, the introduction of a
file format for pixmap brushes was unnecessary.
The GimpBrushPixmap object is dead. GimpBrush has an additional
pixmap temp_buf and handles pixmap brushes transparently. The file
format of pixmap brushes is not any longer a grayscale brush plus
a pattern, but a simple brush with RGBA data. The old brushes can
still be loaded, but the .gpb format is deprecated.
GimpBrushPipe derives from GimpBrush. The fileformat is still a text
header, followed by a number of brushes, but those brushes are stored
in the new GimpBrush format (no pattern anymore). The pipe does not
care about the depth of the contained GimpBrushes, so we get
grayscale BrushPipes for free. Since the brush loader still loads the
old format, old .gih files can also still be loaded.
Since the brushes in the GimpBrushPipe do not any longer contain a
pointer to the pipe object, we do only temporarily switch brushes
in the paint_core routines. This is not very elegant, but the best
we can do without a major redesign.
* app/patterns.[ch]: changed the loader to work with a filedescriptor
instead of a filehandle to make it work with the new brush loading
code.
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl
* plug-ins/common/gih.c: new plug-in that saves GIH files in the
new format (loader will follow soon)
* plug-ins/common/gpb.c: removed since Pixmap Brushes are no longer
supported as a special file format.
* plug-ins/common/gbr.c: load and save brushes in the new brush format
which allows RGBA brushes too.
* plug-ins/common/pat.c: load and save grayscale patterns too
2000-12-18 23:14:08 +08:00
|
|
|
|
|
|
|
/* restore the current brush pointer */
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->brush = current_brush;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
2000-12-31 12:07:42 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x = (paint_tool->last_coords.x +
|
|
|
|
delta.x);
|
|
|
|
paint_tool->cur_coords.y = (paint_tool->last_coords.y +
|
|
|
|
delta.y);
|
|
|
|
paint_tool->cur_coords.pressure = (paint_tool->last_coords.pressure +
|
|
|
|
delta.pressure);
|
|
|
|
paint_tool->cur_coords.xtilt = (paint_tool->last_coords.xtilt +
|
|
|
|
delta.xtilt);
|
|
|
|
paint_tool->cur_coords.ytilt = (paint_tool->last_coords.ytilt +
|
|
|
|
delta.ytilt);
|
|
|
|
paint_tool->cur_coords.wheel = (paint_tool->last_coords.wheel +
|
|
|
|
delta.wheel);
|
|
|
|
|
|
|
|
paint_tool->distance = total;
|
|
|
|
paint_tool->pixel_dist = pixel_initial + pixel_dist;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_finish (GimpPaintTool *paint_tool,
|
|
|
|
GimpDrawable *drawable)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-03-08 10:01:52 +08:00
|
|
|
GimpImage *gimage;
|
1997-11-25 06:05:25 +08:00
|
|
|
PaintUndo *pu;
|
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
if (! (gimage = gimp_drawable_gimage (drawable)))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Determine if any part of the image has been altered--
|
|
|
|
* if nothing has, then just return...
|
|
|
|
*/
|
1998-06-06 11:49:01 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if ((paint_tool->x2 == paint_tool->x1) ||
|
|
|
|
(paint_tool->y2 == paint_tool->y1))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
undo_push_group_start (gimage, PAINT_CORE_UNDO);
|
|
|
|
|
2001-04-01 01:46:59 +08:00
|
|
|
pu = g_new0 (PaintUndo, 1);
|
|
|
|
pu->tool_ID = GIMP_TOOL (paint_tool)->ID;
|
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
2001-07-24 Michael Natterer <mitch@gimp.org>
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
* configure.in: require glib/gtk+ >= 1.3.7, commented out the
gtkxmhtml stuff.
From now on, you will need glib, pango, atk and gtk+ HEAD from CVS
to hack or use GIMP HEAD.
Beware, it crashes randomly :)
* app/core/Makefile.am
* app/core/gimpmarshal.list: new file plus rules to generate
gimpmarshal.[ch] from it.
* app/core/*
* app/tools/*
* app/widgets/*
* libgimpwidgets/*: started to use the glib object system. All
core/ objects are still gtk objects however. All signals are
created using g_signal_new(). There are many gtk+ artefacts left.
Finally, we will _not_ use the gtk_signal_foo() wrappers and
friends any more.
* app/colormaps.c
* app/devices.[ch]
* app/disp_callbacks.c
* app/errorconsole.c
* app/file-save.[ch]
* app/interface.c
* app/module_db.c
* app/nav_window.c
* app/ops_buttons.c
* app/scroll.c
* app/user_install.c
* app/gui/about-dialog.c
* app/gui/brush-editor.c
* app/gui/brushes-commands.c
* app/gui/color-notebook.c
* app/gui/colormap-dialog.c
* app/gui/dialogs-commands.c
* app/gui/dialogs-constructors.c
* app/gui/file-commands.c
* app/gui/file-dialog-utils.c
* app/gui/file-new-dialog.c
* app/gui/file-open-dialog.[ch]
* app/gui/file-save-dialog.c
* app/gui/gradient-editor.c
* app/gui/gradients-commands.c
* app/gui/image-commands.c
* app/gui/info-dialog.[ch]
* app/gui/layer-select.c
* app/gui/layers-commands.c
* app/gui/menus.c
* app/gui/offset-dialog.c
* app/gui/palette-editor.c
* app/gui/palettes-commands.c
* app/gui/patterns-commands.c
* app/gui/preferences-dialog.c
* app/gui/resize-dialog.[ch]
* app/gui/splash.c
* app/gui/tips-dialog.c
* app/gui/tool-options-dialog.c
* app/gui/toolbox.c
* app/gui/tools-commands.c
* libgimp/gimpbrushmenu.c
* libgimp/gimpmenu.c
* libgimp/gimppatternmenu.c
* libgimp/gimpui.c
* libgimpbase/gimpenv.c: tons and tons of changes like "const
gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete
and currently disables), lots of s/gtk_signal/g_signal/,
removal/replacement of deprecated stuff,
s/GtkSignalFunc/GCallback/ and lots of small changes and fixes
while I was on it, zillions of warnings left...
* modules/Makefile.am: disabled the water color selector
temporarily (XInput issues).
* plug-ins/Makefile.am
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl: simply excluded all plug-ins
which did not build (including Script-Fu). They are trivial to
fix.
2001-07-25 05:27:11 +08:00
|
|
|
pu->tool_type = G_TYPE_FROM_CLASS (G_OBJECT_GET_CLASS (paint_tool));
|
2001-11-14 00:21:34 +08:00
|
|
|
pu->last_coords = paint_tool->start_coords;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Push a paint undo */
|
|
|
|
undo_push_paint (gimage, pu);
|
|
|
|
|
|
|
|
/* push an undo */
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_apply_image (drawable, paint_tool->x1, paint_tool->y1,
|
|
|
|
paint_tool->x2, paint_tool->y2, undo_tiles, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
undo_tiles = NULL;
|
|
|
|
|
|
|
|
/* push the group end */
|
|
|
|
undo_push_group_end (gimage);
|
|
|
|
|
|
|
|
/* invalidate the drawable--have to do it here, because
|
|
|
|
* it is not done during the actual painting.
|
|
|
|
*/
|
2001-02-05 06:10:54 +08:00
|
|
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_cleanup (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* CLEANUP */
|
|
|
|
/* If the undo tiles exist, nuke them */
|
|
|
|
if (undo_tiles)
|
|
|
|
{
|
|
|
|
tile_manager_destroy (undo_tiles);
|
|
|
|
undo_tiles = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the canvas blocks exist, nuke them */
|
|
|
|
if (canvas_tiles)
|
|
|
|
{
|
|
|
|
tile_manager_destroy (canvas_tiles);
|
|
|
|
canvas_tiles = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the temporary buffers if they exist */
|
|
|
|
free_paint_buffers ();
|
|
|
|
}
|
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_get_color_from_gradient (GimpPaintTool *paint_tool,
|
2001-10-22 20:13:44 +08:00
|
|
|
GimpGradient *gradient,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble gradient_length,
|
|
|
|
GimpRGB *color,
|
|
|
|
GradientPaintMode mode)
|
2000-06-06 06:08:45 +08:00
|
|
|
{
|
2001-10-22 20:13:44 +08:00
|
|
|
gdouble distance; /* distance in current brush stroke */
|
|
|
|
gdouble y;
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
distance = paint_tool->pixel_dist;
|
2001-10-22 20:13:44 +08:00
|
|
|
y = (gdouble) distance / gradient_length;
|
2000-06-06 06:08:45 +08:00
|
|
|
|
|
|
|
/* for the once modes, set y close to 1.0 after the first chunk */
|
2001-10-22 20:13:44 +08:00
|
|
|
if ((mode == ONCE_FORWARD || mode == ONCE_BACKWARDS) && y >= 1.0)
|
2001-02-27 13:21:12 +08:00
|
|
|
y = 0.9999999;
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-10-22 20:13:44 +08:00
|
|
|
if ((((gint) y & 1) && mode != LOOP_SAWTOOTH) || mode == ONCE_BACKWARDS )
|
|
|
|
y = 1.0 - (y - (gint) y);
|
2000-06-06 06:08:45 +08:00
|
|
|
else
|
2001-10-22 20:13:44 +08:00
|
|
|
y = y - (gint) y;
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-10-22 20:13:44 +08:00
|
|
|
gimp_gradient_get_color_at (gradient, y, color);
|
2000-06-06 06:08:45 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/************************/
|
|
|
|
/* Painting functions */
|
|
|
|
/************************/
|
|
|
|
|
|
|
|
TempBuf *
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_get_paint_area (GimpPaintTool *paint_tool,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gdouble scale)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-03-05 08:06:11 +08:00
|
|
|
gint x, y;
|
|
|
|
gint x1, y1, x2, y2;
|
|
|
|
gint bytes;
|
|
|
|
gint dwidth, dheight;
|
|
|
|
gint bwidth, bheight;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
bytes = gimp_drawable_has_alpha (drawable) ?
|
|
|
|
gimp_drawable_bytes (drawable) : gimp_drawable_bytes (drawable) + 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_calculate_brush_size (paint_tool->brush->mask, scale,
|
1999-09-09 09:47:54 +08:00
|
|
|
&bwidth, &bheight);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* adjust the x and y coordinates to the upper left corner of the brush */
|
2001-11-14 00:21:34 +08:00
|
|
|
x = (gint) floor (paint_tool->cur_coords.x) - (bwidth >> 1);
|
|
|
|
y = (gint) floor (paint_tool->cur_coords.y) - (bheight >> 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
dwidth = gimp_drawable_width (drawable);
|
|
|
|
dheight = gimp_drawable_height (drawable);
|
1998-07-25 02:52:03 +08:00
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
x1 = CLAMP (x - 1, 0, dwidth);
|
|
|
|
y1 = CLAMP (y - 1, 0, dheight);
|
|
|
|
x2 = CLAMP (x + bwidth + 1, 0, dwidth);
|
|
|
|
y2 = CLAMP (y + bheight + 1, 0, dheight);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* configure the canvas buffer */
|
|
|
|
if ((x2 - x1) && (y2 - y1))
|
|
|
|
canvas_buf = temp_buf_resize (canvas_buf, bytes, x1, y1,
|
|
|
|
(x2 - x1), (y2 - y1));
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return canvas_buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
TempBuf *
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_get_orig_image (GimpPaintTool *paint_tool,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint x1,
|
|
|
|
gint y1,
|
|
|
|
gint x2,
|
|
|
|
gint y2)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion destPR;
|
|
|
|
Tile *undo_tile;
|
|
|
|
gint h;
|
|
|
|
gint refd;
|
|
|
|
gint pixelwidth;
|
|
|
|
gint dwidth;
|
|
|
|
gint dheight;
|
|
|
|
guchar *s;
|
|
|
|
guchar *d;
|
|
|
|
gpointer pr;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
orig_buf = temp_buf_resize (orig_buf, gimp_drawable_bytes (drawable),
|
1997-11-25 06:05:25 +08:00
|
|
|
x1, y1, (x2 - x1), (y2 - y1));
|
1998-07-25 02:52:03 +08:00
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
dwidth = gimp_drawable_width (drawable);
|
|
|
|
dheight = gimp_drawable_height (drawable);
|
1998-07-25 02:52:03 +08:00
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
x1 = CLAMP (x1, 0, dwidth);
|
|
|
|
y1 = CLAMP (y1, 0, dheight);
|
|
|
|
x2 = CLAMP (x2, 0, dwidth);
|
|
|
|
y2 = CLAMP (y2, 0, dheight);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* configure the pixel regions */
|
2001-01-15 05:11:52 +08:00
|
|
|
pixel_region_init (&srcPR, gimp_drawable_data (drawable), x1, y1,
|
1998-07-25 02:52:03 +08:00
|
|
|
(x2 - x1), (y2 - y1), FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
destPR.bytes = orig_buf->bytes;
|
|
|
|
destPR.x = 0; destPR.y = 0;
|
|
|
|
destPR.w = (x2 - x1); destPR.h = (y2 - y1);
|
|
|
|
destPR.rowstride = orig_buf->bytes * orig_buf->width;
|
|
|
|
destPR.data = temp_buf_data (orig_buf) +
|
|
|
|
(y1 - orig_buf->y) * destPR.rowstride + (x1 - orig_buf->x) * destPR.bytes;
|
|
|
|
|
1998-07-25 02:52:03 +08:00
|
|
|
for (pr = pixel_regions_register (2, &srcPR, &destPR);
|
|
|
|
pr != NULL;
|
|
|
|
pr = pixel_regions_process (pr))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* If the undo tile corresponding to this location is valid, use it */
|
1998-07-25 02:52:03 +08:00
|
|
|
undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y,
|
1998-08-16 03:17:36 +08:00
|
|
|
FALSE, FALSE);
|
1998-08-12 01:35:34 +08:00
|
|
|
if (tile_is_valid (undo_tile) == TRUE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1998-07-10 12:33:21 +08:00
|
|
|
refd = 1;
|
1998-07-25 02:52:03 +08:00
|
|
|
undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y,
|
1998-08-16 03:17:36 +08:00
|
|
|
TRUE, FALSE);
|
1998-10-25 13:55:36 +08:00
|
|
|
s = (unsigned char*)tile_data_pointer (undo_tile, 0, 0) +
|
1998-08-12 01:35:34 +08:00
|
|
|
srcPR.rowstride * (srcPR.y % TILE_HEIGHT) +
|
|
|
|
srcPR.bytes * (srcPR.x % TILE_WIDTH); /* dubious... */
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-07-11 22:00:55 +08:00
|
|
|
refd = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
s = srcPR.data;
|
|
|
|
}
|
|
|
|
|
|
|
|
d = destPR.data;
|
|
|
|
pixelwidth = srcPR.w * srcPR.bytes;
|
|
|
|
h = srcPR.h;
|
|
|
|
while (h --)
|
|
|
|
{
|
|
|
|
memcpy (d, s, pixelwidth);
|
|
|
|
s += srcPR.rowstride;
|
|
|
|
d += destPR.rowstride;
|
|
|
|
}
|
|
|
|
|
1998-07-10 12:33:21 +08:00
|
|
|
if (refd)
|
|
|
|
tile_release (undo_tile, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return orig_buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_paste_canvas (GimpPaintTool *paint_tool,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint brush_opacity,
|
|
|
|
gint image_opacity,
|
|
|
|
LayerModeEffects paint_mode,
|
|
|
|
BrushApplicationMode brush_hardness,
|
|
|
|
gdouble brush_scale,
|
|
|
|
PaintApplicationMode mode)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
MaskBuf *brush_mask;
|
|
|
|
|
|
|
|
/* get the brush mask */
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_mask = gimp_paint_tool_get_brush_mask (paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
brush_hardness, brush_scale);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* paste the canvas buf */
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_paste (paint_tool, brush_mask, drawable,
|
2001-02-28 03:18:01 +08:00
|
|
|
brush_opacity, image_opacity, paint_mode, mode);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
/* Similar to gimp_paint_tool_paste_canvas, but replaces the alpha channel
|
1997-12-08 09:13:10 +08:00
|
|
|
rather than using it to composite (i.e. transparent over opaque
|
|
|
|
becomes transparent rather than opauqe. */
|
|
|
|
void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_replace_canvas (GimpPaintTool *paint_tool,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint brush_opacity,
|
|
|
|
gint image_opacity,
|
|
|
|
BrushApplicationMode brush_hardness,
|
|
|
|
gdouble brush_scale,
|
|
|
|
PaintApplicationMode mode)
|
1997-12-08 09:13:10 +08:00
|
|
|
{
|
|
|
|
MaskBuf *brush_mask;
|
|
|
|
|
|
|
|
/* get the brush mask */
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_mask =
|
|
|
|
gimp_paint_tool_get_brush_mask (paint_tool, brush_hardness, brush_scale);
|
1997-12-08 09:13:10 +08:00
|
|
|
|
|
|
|
/* paste the canvas buf */
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_replace (paint_tool, brush_mask, drawable,
|
2001-02-28 03:18:01 +08:00
|
|
|
brush_opacity, image_opacity, mode);
|
1997-12-08 09:13:10 +08:00
|
|
|
}
|
|
|
|
|
1998-07-09 13:31:06 +08:00
|
|
|
|
1999-10-27 02:27:27 +08:00
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_invalidate_cache (GimpBrush *brush,
|
2001-02-28 03:18:01 +08:00
|
|
|
gpointer data)
|
2001-02-27 13:21:12 +08:00
|
|
|
{
|
1999-10-27 02:27:27 +08:00
|
|
|
/* Make sure we don't cache data for a brush that has changed */
|
1998-07-10 16:59:55 +08:00
|
|
|
if (last_brush_mask == brush->mask)
|
1999-10-27 02:27:27 +08:00
|
|
|
cache_invalid = TRUE;
|
1998-07-09 13:31:06 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/************************************************************
|
|
|
|
* LOCAL FUNCTION DEFINITIONS *
|
|
|
|
************************************************************/
|
|
|
|
|
1999-09-09 09:47:54 +08:00
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_calculate_brush_size (MaskBuf *mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble scale,
|
|
|
|
gint *width,
|
|
|
|
gint *height)
|
1999-09-09 09:47:54 +08:00
|
|
|
{
|
2000-12-12 03:30:22 +08:00
|
|
|
scale = CLAMP (scale, 0.0, 1.0);
|
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
if (devices_get_current (the_gimp) == gdk_device_get_core_pointer ())
|
1999-09-09 09:47:54 +08:00
|
|
|
{
|
|
|
|
*width = mask->width;
|
|
|
|
*height = mask->height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-03-05 08:06:11 +08:00
|
|
|
gdouble ratio;
|
1999-09-09 09:47:54 +08:00
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
if (scale < 1 / 256)
|
|
|
|
ratio = 1 / 16;
|
1999-09-09 09:47:54 +08:00
|
|
|
else
|
|
|
|
ratio = sqrt (scale);
|
2000-12-31 12:07:42 +08:00
|
|
|
|
|
|
|
*width = MAX ((gint) (mask->width * ratio + 0.5), 1);
|
|
|
|
*height = MAX ((gint) (mask->height * ratio + 0.5), 1);
|
1999-09-09 09:47:54 +08:00
|
|
|
}
|
2001-02-27 13:21:12 +08:00
|
|
|
}
|
1999-09-09 09:47:54 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static MaskBuf *
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_subsample_mask (MaskBuf *mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble x,
|
|
|
|
gdouble y)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
MaskBuf *dest;
|
|
|
|
gdouble left;
|
|
|
|
guchar *m;
|
|
|
|
guchar *d;
|
2000-03-05 08:06:11 +08:00
|
|
|
const gint *k;
|
2000-06-06 06:08:45 +08:00
|
|
|
gint index1;
|
|
|
|
gint index2;
|
2000-03-05 08:06:11 +08:00
|
|
|
const gint *kernel;
|
2000-06-06 06:08:45 +08:00
|
|
|
gint new_val;
|
|
|
|
gint i, j;
|
|
|
|
gint r, s;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
x += (x < 0) ? mask->width : 0;
|
2000-12-31 12:07:42 +08:00
|
|
|
left = x - floor (x);
|
|
|
|
index1 = (gint) (left * (gdouble) (SUBSAMPLE + 1));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
y += (y < 0) ? mask->height : 0;
|
2000-12-31 12:07:42 +08:00
|
|
|
left = y - floor (y);
|
|
|
|
index2 = (gint) (left * (gdouble) (SUBSAMPLE + 1));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
kernel = subsample[index2][index1];
|
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
if (mask == last_brush_mask && !cache_invalid)
|
|
|
|
{
|
|
|
|
if (kernel_brushes[index2][index1])
|
|
|
|
return kernel_brushes[index2][index1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i <= SUBSAMPLE; i++)
|
|
|
|
for (j = 0; j <= SUBSAMPLE; j++)
|
|
|
|
{
|
|
|
|
if (kernel_brushes[i][j])
|
|
|
|
mask_buf_free (kernel_brushes[i][j]);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
kernel_brushes[i][j] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
last_brush_mask = mask;
|
|
|
|
cache_invalid = FALSE;
|
|
|
|
}
|
2000-12-31 12:07:42 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
dest = kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2,
|
2000-06-06 06:08:45 +08:00
|
|
|
mask->height + 2);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
m = mask_buf_data (mask);
|
|
|
|
for (i = 0; i < mask->height; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < mask->width; j++)
|
|
|
|
{
|
|
|
|
k = kernel;
|
|
|
|
for (r = 0; r < KERNEL_HEIGHT; r++)
|
|
|
|
{
|
|
|
|
d = mask_buf_data (dest) + (i+r) * dest->width + j;
|
|
|
|
s = KERNEL_WIDTH;
|
|
|
|
while (s--)
|
|
|
|
{
|
1999-07-27 16:47:31 +08:00
|
|
|
new_val = *d + ((*m * *k++ + 128) >> 8);
|
2000-01-26 07:06:12 +08:00
|
|
|
*d++ = MIN (new_val, 255);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
m++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
1998-06-15 06:42:36 +08:00
|
|
|
/* #define FANCY_PRESSURE */
|
|
|
|
|
1998-06-06 11:49:01 +08:00
|
|
|
static MaskBuf *
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble x,
|
|
|
|
gdouble y,
|
|
|
|
gdouble pressure)
|
1998-06-06 11:49:01 +08:00
|
|
|
{
|
|
|
|
static MaskBuf *last_brush = NULL;
|
2000-06-06 06:08:45 +08:00
|
|
|
static guchar mapi[256];
|
|
|
|
guchar *source;
|
|
|
|
guchar *dest;
|
1998-06-06 11:49:01 +08:00
|
|
|
MaskBuf *subsample_mask;
|
2000-06-06 06:08:45 +08:00
|
|
|
gint i;
|
1998-06-15 06:42:36 +08:00
|
|
|
#ifdef FANCY_PRESSURE
|
2000-03-05 08:06:11 +08:00
|
|
|
static gdouble map[256];
|
2000-06-06 06:08:45 +08:00
|
|
|
gdouble ds, s, c;
|
1998-06-15 06:42:36 +08:00
|
|
|
#endif
|
1998-06-06 11:49:01 +08:00
|
|
|
|
|
|
|
/* Get the raw subsampled mask */
|
2001-02-27 13:21:12 +08:00
|
|
|
subsample_mask = gimp_paint_tool_subsample_mask (brush_mask, x, y);
|
1998-06-06 11:49:01 +08:00
|
|
|
|
|
|
|
/* Special case pressure = 0.5 */
|
2000-06-06 06:08:45 +08:00
|
|
|
if ((int)(pressure * 100 + 0.5) == 50)
|
1998-06-06 11:49:01 +08:00
|
|
|
return subsample_mask;
|
|
|
|
|
|
|
|
/* Make sure we have the right sized buffer */
|
|
|
|
if (brush_mask != last_brush)
|
|
|
|
{
|
|
|
|
if (pressure_brush)
|
|
|
|
mask_buf_free (pressure_brush);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
|
|
|
pressure_brush = mask_buf_new (brush_mask->width + 2,
|
|
|
|
brush_mask->height + 2);
|
1998-06-06 11:49:01 +08:00
|
|
|
}
|
|
|
|
|
1998-06-15 06:42:36 +08:00
|
|
|
#ifdef FANCY_PRESSURE
|
1998-06-06 11:49:01 +08:00
|
|
|
/* Create the pressure profile
|
|
|
|
|
|
|
|
It is: I'(I) = tanh(20*(pressure-0.5)*I) : pressure > 0.5
|
|
|
|
I'(I) = 1 - tanh(20*(0.5-pressure)*(1-I)) : pressure < 0.5
|
|
|
|
|
|
|
|
It looks like:
|
|
|
|
|
|
|
|
low pressure medium pressure high pressure
|
|
|
|
|
|
|
|
| / --
|
|
|
|
| / /
|
|
|
|
/ / |
|
|
|
|
-- / |
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
ds = (pressure - 0.5)*(20./256.);
|
|
|
|
s = 0;
|
|
|
|
c = 1.0;
|
|
|
|
|
|
|
|
if (ds > 0)
|
|
|
|
{
|
|
|
|
for (i=0;i<256;i++)
|
|
|
|
{
|
|
|
|
map[i] = s/c;
|
|
|
|
s += c*ds;
|
|
|
|
c += s*ds;
|
|
|
|
}
|
|
|
|
for (i=0;i<256;i++)
|
|
|
|
mapi[i] = (int)(255*map[i]/map[255]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ds = -ds;
|
|
|
|
for (i=255;i>=0;i--)
|
|
|
|
{
|
|
|
|
map[i] = s/c;
|
|
|
|
s += c*ds;
|
|
|
|
c += s*ds;
|
|
|
|
}
|
|
|
|
for (i=0;i<256;i++)
|
|
|
|
mapi[i] = (int)(255*(1-map[i]/map[0]));
|
|
|
|
}
|
1998-06-15 06:42:36 +08:00
|
|
|
#else /* ! FANCY_PRESSURE */
|
|
|
|
|
2000-12-31 12:07:42 +08:00
|
|
|
for (i = 0; i < 256; i++)
|
1998-06-15 06:42:36 +08:00
|
|
|
{
|
2000-12-31 12:07:42 +08:00
|
|
|
gint tmp = (pressure / 0.5) * i;
|
|
|
|
|
1998-06-15 06:42:36 +08:00
|
|
|
if (tmp > 255)
|
|
|
|
mapi[i] = 255;
|
|
|
|
else
|
|
|
|
mapi[i] = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* FANCY_PRESSURE */
|
1998-06-06 11:49:01 +08:00
|
|
|
|
|
|
|
/* Now convert the brush */
|
|
|
|
|
|
|
|
source = mask_buf_data (subsample_mask);
|
2000-12-31 12:07:42 +08:00
|
|
|
dest = mask_buf_data (pressure_brush);
|
1998-06-06 11:49:01 +08:00
|
|
|
|
|
|
|
i = subsample_mask->width * subsample_mask->height;
|
|
|
|
while (i--)
|
|
|
|
{
|
|
|
|
*dest++ = mapi[(*source++)];
|
|
|
|
}
|
|
|
|
|
|
|
|
return pressure_brush;
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static MaskBuf *
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_solidify_mask (MaskBuf *brush_mask)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
static MaskBuf *last_brush = NULL;
|
2001-02-28 03:18:01 +08:00
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
gint i;
|
|
|
|
gint j;
|
|
|
|
guchar *data;
|
|
|
|
guchar *src;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-09-09 09:47:54 +08:00
|
|
|
if (brush_mask == last_brush && !cache_invalid)
|
1997-11-25 06:05:25 +08:00
|
|
|
return solid_brush;
|
2000-06-06 06:08:45 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
last_brush = brush_mask;
|
1999-09-09 09:47:54 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (solid_brush)
|
|
|
|
mask_buf_free (solid_brush);
|
1999-07-02 00:52:50 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
solid_brush = mask_buf_new (brush_mask->width + 2, brush_mask->height + 2);
|
|
|
|
|
|
|
|
/* get the data and advance one line into it */
|
|
|
|
data = mask_buf_data (solid_brush) + solid_brush->width;
|
2000-06-06 06:08:45 +08:00
|
|
|
src = mask_buf_data (brush_mask);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
for (i = 0; i < brush_mask->height; i++)
|
|
|
|
{
|
|
|
|
data++;
|
|
|
|
for (j = 0; j < brush_mask->width; j++)
|
|
|
|
{
|
1998-01-25 09:24:46 +08:00
|
|
|
*data++ = (*src++) ? OPAQUE_OPACITY : TRANSPARENT_OPACITY;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
data++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return solid_brush;
|
|
|
|
}
|
|
|
|
|
1999-09-09 09:47:54 +08:00
|
|
|
static MaskBuf *
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_scale_mask (MaskBuf *brush_mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble scale)
|
1999-09-09 09:47:54 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
static MaskBuf *last_brush = NULL;
|
2001-02-27 13:21:12 +08:00
|
|
|
static gint last_width = 0.0;
|
|
|
|
static gint last_height = 0.0;
|
2000-06-06 06:08:45 +08:00
|
|
|
gint dest_width;
|
|
|
|
gint dest_height;
|
1999-09-09 09:47:54 +08:00
|
|
|
|
2000-12-12 03:30:22 +08:00
|
|
|
scale = CLAMP (scale, 0.0, 1.0);
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (scale == 0.0)
|
1999-09-09 09:47:54 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (scale == 1.0)
|
|
|
|
return brush_mask;
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_calculate_brush_size (brush_mask, scale,
|
1999-09-09 09:47:54 +08:00
|
|
|
&dest_width, &dest_height);
|
|
|
|
|
1999-09-10 03:11:38 +08:00
|
|
|
if (brush_mask == last_brush && !cache_invalid &&
|
1999-09-09 09:47:54 +08:00
|
|
|
dest_width == last_width && dest_height == last_height)
|
|
|
|
return scale_brush;
|
|
|
|
|
|
|
|
if (scale_brush)
|
|
|
|
mask_buf_free (scale_brush);
|
|
|
|
|
|
|
|
last_brush = brush_mask;
|
|
|
|
last_width = dest_width;
|
|
|
|
last_height = dest_height;
|
2000-03-05 08:06:11 +08:00
|
|
|
|
1999-09-09 09:47:54 +08:00
|
|
|
scale_brush = brush_scale_mask (brush_mask, dest_width, dest_height);
|
|
|
|
cache_invalid = TRUE;
|
|
|
|
|
|
|
|
return scale_brush;
|
|
|
|
}
|
|
|
|
|
1999-09-10 03:11:38 +08:00
|
|
|
static MaskBuf *
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask,
|
2001-02-28 03:18:01 +08:00
|
|
|
gdouble scale)
|
1999-09-10 03:11:38 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
static MaskBuf *last_brush = NULL;
|
2001-02-27 13:21:12 +08:00
|
|
|
static gint last_width = 0.0;
|
|
|
|
static gint last_height = 0.0;
|
2000-06-06 06:08:45 +08:00
|
|
|
gint dest_width;
|
|
|
|
gint dest_height;
|
1999-09-10 03:11:38 +08:00
|
|
|
|
2000-12-12 03:30:22 +08:00
|
|
|
scale = CLAMP (scale, 0.0, 1.0);
|
|
|
|
|
2000-12-31 12:07:42 +08:00
|
|
|
if (scale == 0.0)
|
1999-09-10 03:11:38 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (scale == 1.0)
|
|
|
|
return brush_mask;
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_calculate_brush_size (brush_mask, scale,
|
1999-09-10 03:11:38 +08:00
|
|
|
&dest_width, &dest_height);
|
|
|
|
|
|
|
|
if (brush_mask == last_brush && !cache_invalid &&
|
|
|
|
dest_width == last_width && dest_height == last_height)
|
|
|
|
return scale_pixmap;
|
|
|
|
|
|
|
|
if (scale_pixmap)
|
|
|
|
mask_buf_free (scale_pixmap);
|
|
|
|
|
|
|
|
last_brush = brush_mask;
|
|
|
|
last_width = dest_width;
|
|
|
|
last_height = dest_height;
|
2000-03-05 08:06:11 +08:00
|
|
|
|
1999-09-10 03:11:38 +08:00
|
|
|
scale_pixmap = brush_scale_pixmap (brush_mask, dest_width, dest_height);
|
|
|
|
cache_invalid = TRUE;
|
|
|
|
|
|
|
|
return scale_pixmap;
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static MaskBuf *
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_get_brush_mask (GimpPaintTool *paint_tool,
|
|
|
|
BrushApplicationMode brush_hardness,
|
|
|
|
gdouble scale)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-12-02 05:02:34 +08:00
|
|
|
GimpTool *tool;
|
|
|
|
MaskBuf *mask;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
tool = GIMP_TOOL (paint_tool);
|
|
|
|
|
|
|
|
if (devices_get_current (tool->tool_info->gimp) == gdk_device_get_core_pointer ())
|
2001-02-27 13:21:12 +08:00
|
|
|
mask = paint_tool->brush->mask;
|
1999-09-09 09:47:54 +08:00
|
|
|
else
|
2001-02-27 13:21:12 +08:00
|
|
|
mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale);
|
2000-03-05 08:06:11 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
switch (brush_hardness)
|
|
|
|
{
|
|
|
|
case SOFT:
|
2001-02-27 13:21:12 +08:00
|
|
|
mask = gimp_paint_tool_subsample_mask (mask,
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x,
|
|
|
|
paint_tool->cur_coords.y);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
case HARD:
|
2001-02-27 13:21:12 +08:00
|
|
|
mask = gimp_paint_tool_solidify_mask (mask);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
1998-06-06 11:49:01 +08:00
|
|
|
case PRESSURE:
|
2001-02-27 13:21:12 +08:00
|
|
|
mask = gimp_paint_tool_pressurize_mask (mask,
|
2001-11-14 00:21:34 +08:00
|
|
|
paint_tool->cur_coords.x,
|
|
|
|
paint_tool->cur_coords.y,
|
|
|
|
paint_tool->cur_coords.pressure);
|
1998-06-06 11:49:01 +08:00
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-09-09 09:47:54 +08:00
|
|
|
return mask;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_paste (GimpPaintTool *paint_tool,
|
|
|
|
MaskBuf *brush_mask,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint brush_opacity,
|
|
|
|
gint image_opacity,
|
|
|
|
LayerModeEffects paint_mode,
|
|
|
|
PaintApplicationMode mode)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
GimpImage *gimage;
|
|
|
|
PixelRegion srcPR;
|
1997-11-25 06:05:25 +08:00
|
|
|
TileManager *alt = NULL;
|
2000-06-06 06:08:45 +08:00
|
|
|
gint offx;
|
|
|
|
gint offy;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
if (! (gimage = gimp_drawable_gimage (drawable)))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* set undo blocks */
|
1998-01-22 15:02:57 +08:00
|
|
|
set_undo_tiles (drawable,
|
1997-11-25 06:05:25 +08:00
|
|
|
canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height);
|
|
|
|
|
|
|
|
/* If the mode is CONSTANT:
|
|
|
|
* combine the canvas buf, the brush mask to the canvas tiles
|
|
|
|
*/
|
|
|
|
if (mode == CONSTANT)
|
|
|
|
{
|
|
|
|
/* initialize any invalid canvas tiles */
|
|
|
|
set_canvas_tiles (canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height);
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity);
|
|
|
|
canvas_tiles_to_canvas_buf (paint_tool);
|
1997-11-25 06:05:25 +08:00
|
|
|
alt = undo_tiles;
|
|
|
|
}
|
|
|
|
/* Otherwise:
|
|
|
|
* combine the canvas buf and the brush mask to the canvas buf
|
|
|
|
*/
|
2000-12-31 12:07:42 +08:00
|
|
|
else
|
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_to_canvas_buf (paint_tool, brush_mask, brush_opacity);
|
2000-12-31 12:07:42 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* intialize canvas buf source pixel regions */
|
|
|
|
srcPR.bytes = canvas_buf->bytes;
|
|
|
|
srcPR.x = 0; srcPR.y = 0;
|
|
|
|
srcPR.w = canvas_buf->width;
|
|
|
|
srcPR.h = canvas_buf->height;
|
|
|
|
srcPR.rowstride = canvas_buf->width * canvas_buf->bytes;
|
|
|
|
srcPR.data = temp_buf_data (canvas_buf);
|
|
|
|
|
|
|
|
/* apply the paint area to the gimage */
|
2000-12-29 23:22:01 +08:00
|
|
|
gimp_image_apply_image (gimage, drawable, &srcPR,
|
|
|
|
FALSE, image_opacity, paint_mode,
|
|
|
|
alt, /* specify an alternative src1 */
|
|
|
|
canvas_buf->x, canvas_buf->y);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Update the undo extents */
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x);
|
|
|
|
paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y);
|
|
|
|
paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width));
|
|
|
|
paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
/* Update the gimage--it is important to call gimp_image_update
|
1997-12-08 09:13:10 +08:00
|
|
|
* instead of drawable_update because we don't want the drawable
|
|
|
|
* preview to be constantly invalidated
|
|
|
|
*/
|
2001-01-15 05:11:52 +08:00
|
|
|
gimp_drawable_offsets (drawable, &offx, &offy);
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_image_update (gimage,
|
|
|
|
canvas_buf->x + offx,
|
|
|
|
canvas_buf->y + offy,
|
|
|
|
canvas_buf->width,
|
|
|
|
canvas_buf->height);
|
1997-12-08 09:13:10 +08:00
|
|
|
}
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
/* This works similarly to gimp_paint_tool_paste. However, instead of combining
|
1997-12-08 09:13:10 +08:00
|
|
|
the canvas to the paint core drawable using one of the combination
|
2001-02-27 13:21:12 +08:00
|
|
|
modes, it uses a "replace" mode (i.e. transparent pixels in the
|
1997-12-08 09:13:10 +08:00
|
|
|
canvas erase the paint core drawable).
|
|
|
|
|
|
|
|
When not drawing on alpha-enabled images, it just paints using NORMAL
|
|
|
|
mode.
|
|
|
|
*/
|
|
|
|
static void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_replace (GimpPaintTool *paint_tool,
|
|
|
|
MaskBuf *brush_mask,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint brush_opacity,
|
|
|
|
gint image_opacity,
|
|
|
|
PaintApplicationMode mode)
|
1997-12-08 09:13:10 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
GimpImage *gimage;
|
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion maskPR;
|
1999-07-02 00:52:50 +08:00
|
|
|
TileManager *alt = NULL;
|
2000-06-06 06:08:45 +08:00
|
|
|
gint offx;
|
|
|
|
gint offy;
|
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
|
|
|
{
|
2001-02-27 13:21:12 +08:00
|
|
|
gimp_paint_tool_paste (paint_tool, brush_mask, drawable,
|
2001-02-28 03:18:01 +08:00
|
|
|
brush_opacity, image_opacity, NORMAL_MODE,
|
|
|
|
mode);
|
1997-12-08 09:13:10 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-01-15 05:11:52 +08:00
|
|
|
if (! (gimage = gimp_drawable_gimage (drawable)))
|
1997-12-08 09:13:10 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* set undo blocks */
|
1998-01-22 15:02:57 +08:00
|
|
|
set_undo_tiles (drawable,
|
1997-12-08 09:13:10 +08:00
|
|
|
canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height);
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (mode == CONSTANT)
|
2000-03-05 08:06:11 +08:00
|
|
|
{
|
|
|
|
/* initialize any invalid canvas tiles */
|
|
|
|
set_canvas_tiles (canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height);
|
|
|
|
|
|
|
|
/* combine the brush mask and the canvas tiles */
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity);
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
/* set the alt source as the unaltered undo_tiles */
|
2000-03-05 08:06:11 +08:00
|
|
|
alt = undo_tiles;
|
|
|
|
|
|
|
|
/* initialize the maskPR from the canvas tiles */
|
|
|
|
pixel_region_init (&maskPR, canvas_tiles,
|
|
|
|
canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height, FALSE);
|
|
|
|
}
|
2000-12-31 12:07:42 +08:00
|
|
|
else
|
2000-03-05 08:06:11 +08:00
|
|
|
{
|
|
|
|
/* The mask is just the brush mask */
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.bytes = 1;
|
2001-02-27 13:21:12 +08:00
|
|
|
maskPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.y = 0;
|
|
|
|
maskPR.w = canvas_buf->width;
|
|
|
|
maskPR.h = canvas_buf->height;
|
2000-03-05 08:06:11 +08:00
|
|
|
maskPR.rowstride = maskPR.bytes * brush_mask->width;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.data = mask_buf_data (brush_mask);
|
2000-03-05 08:06:11 +08:00
|
|
|
}
|
2000-12-31 12:07:42 +08:00
|
|
|
|
1997-12-08 09:13:10 +08:00
|
|
|
/* intialize canvas buf source pixel regions */
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.bytes = canvas_buf->bytes;
|
2001-02-27 13:21:12 +08:00
|
|
|
srcPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.y = 0;
|
|
|
|
srcPR.w = canvas_buf->width;
|
|
|
|
srcPR.h = canvas_buf->height;
|
1997-12-08 09:13:10 +08:00
|
|
|
srcPR.rowstride = canvas_buf->width * canvas_buf->bytes;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.data = temp_buf_data (canvas_buf);
|
1997-12-08 09:13:10 +08:00
|
|
|
|
|
|
|
/* apply the paint area to the gimage */
|
2000-12-29 23:22:01 +08:00
|
|
|
gimp_image_replace_image (gimage, drawable, &srcPR,
|
|
|
|
FALSE, image_opacity,
|
2001-02-27 13:21:12 +08:00
|
|
|
&maskPR,
|
2000-12-29 23:22:01 +08:00
|
|
|
canvas_buf->x, canvas_buf->y);
|
1997-12-08 09:13:10 +08:00
|
|
|
|
|
|
|
/* Update the undo extents */
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x);
|
|
|
|
paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y);
|
|
|
|
paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width));
|
|
|
|
paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height));
|
1997-12-08 09:13:10 +08:00
|
|
|
|
2001-11-01 05:20:09 +08:00
|
|
|
/* Update the gimage--it is important to call gimp_image_update
|
1997-11-25 06:05:25 +08:00
|
|
|
* instead of drawable_update because we don't want the drawable
|
|
|
|
* preview to be constantly invalidated
|
|
|
|
*/
|
2001-01-15 05:11:52 +08:00
|
|
|
gimp_drawable_offsets (drawable, &offx, &offy);
|
2001-11-01 05:20:09 +08:00
|
|
|
gimp_image_update (gimage,
|
|
|
|
canvas_buf->x + offx,
|
|
|
|
canvas_buf->y + offy,
|
|
|
|
canvas_buf->width,
|
|
|
|
canvas_buf->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
1999-07-02 00:52:50 +08:00
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool)
|
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
|
|
|
|
|
|
|
/* combine the canvas tiles and the canvas buf */
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.bytes = canvas_buf->bytes;
|
2001-02-27 13:21:12 +08:00
|
|
|
srcPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.y = 0;
|
|
|
|
srcPR.w = canvas_buf->width;
|
|
|
|
srcPR.h = canvas_buf->height;
|
1999-07-02 00:52:50 +08:00
|
|
|
srcPR.rowstride = canvas_buf->width * canvas_buf->bytes;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.data = temp_buf_data (canvas_buf);
|
1999-07-02 00:52:50 +08:00
|
|
|
|
|
|
|
pixel_region_init (&maskPR, canvas_tiles,
|
|
|
|
canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height, FALSE);
|
|
|
|
|
|
|
|
/* apply the canvas tiles to the canvas buf */
|
|
|
|
apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_to_canvas_tiles (GimpPaintTool *paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
MaskBuf *brush_mask,
|
|
|
|
gint brush_opacity)
|
1999-07-02 00:52:50 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion maskPR;
|
2001-02-28 03:18:01 +08:00
|
|
|
gint x;
|
|
|
|
gint y;
|
|
|
|
gint xoff;
|
|
|
|
gint yoff;
|
1999-07-02 00:52:50 +08:00
|
|
|
|
|
|
|
/* combine the brush mask and the canvas tiles */
|
|
|
|
pixel_region_init (&srcPR, canvas_tiles,
|
|
|
|
canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height, TRUE);
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
x = (gint) floor (paint_tool->cur_coords.x) - (brush_mask->width >> 1);
|
|
|
|
y = (gint) floor (paint_tool->cur_coords.y) - (brush_mask->height >> 1);
|
1999-07-02 00:52:50 +08:00
|
|
|
xoff = (x < 0) ? -x : 0;
|
|
|
|
yoff = (y < 0) ? -y : 0;
|
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.bytes = 1;
|
2001-02-27 13:21:12 +08:00
|
|
|
maskPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.y = 0;
|
|
|
|
maskPR.w = srcPR.w;
|
|
|
|
maskPR.h = srcPR.h;
|
1999-07-02 00:52:50 +08:00
|
|
|
maskPR.rowstride = maskPR.bytes * brush_mask->width;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes;
|
1999-07-02 00:52:50 +08:00
|
|
|
|
|
|
|
/* combine the mask to the canvas tiles */
|
|
|
|
combine_mask_and_region (&srcPR, &maskPR, brush_opacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_to_canvas_buf (GimpPaintTool *paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
MaskBuf *brush_mask,
|
|
|
|
gint brush_opacity)
|
1999-07-02 00:52:50 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion maskPR;
|
2001-02-28 03:18:01 +08:00
|
|
|
gint x;
|
|
|
|
gint y;
|
|
|
|
gint xoff;
|
|
|
|
gint yoff;
|
2000-06-06 06:08:45 +08:00
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
x = (gint) floor (paint_tool->cur_coords.x) - (brush_mask->width >> 1);
|
|
|
|
y = (gint) floor (paint_tool->cur_coords.y) - (brush_mask->height >> 1);
|
1999-07-02 00:52:50 +08:00
|
|
|
xoff = (x < 0) ? -x : 0;
|
|
|
|
yoff = (y < 0) ? -y : 0;
|
|
|
|
|
|
|
|
/* combine the canvas buf and the brush mask to the canvas buf */
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.bytes = canvas_buf->bytes;
|
2001-02-27 13:21:12 +08:00
|
|
|
srcPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.y = 0;
|
|
|
|
srcPR.w = canvas_buf->width;
|
|
|
|
srcPR.h = canvas_buf->height;
|
1999-07-02 00:52:50 +08:00
|
|
|
srcPR.rowstride = canvas_buf->width * canvas_buf->bytes;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.data = temp_buf_data (canvas_buf);
|
1999-07-02 00:52:50 +08:00
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.bytes = 1;
|
2001-02-27 13:21:12 +08:00
|
|
|
maskPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.y = 0;
|
|
|
|
maskPR.w = srcPR.w;
|
|
|
|
maskPR.h = srcPR.h;
|
1999-07-02 00:52:50 +08:00
|
|
|
maskPR.rowstride = maskPR.bytes * brush_mask->width;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes;
|
1999-07-02 00:52:50 +08:00
|
|
|
|
|
|
|
/* apply the mask */
|
|
|
|
apply_mask_to_region (&srcPR, &maskPR, brush_opacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
1997-11-25 06:05:25 +08:00
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_to_canvas_tiles (GimpPaintTool *paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
MaskBuf *brush_mask,
|
|
|
|
gint brush_opacity)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion maskPR;
|
|
|
|
gint x;
|
|
|
|
gint y;
|
|
|
|
gint xoff;
|
|
|
|
gint yoff;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* combine the brush mask and the canvas tiles */
|
|
|
|
pixel_region_init (&srcPR, canvas_tiles,
|
|
|
|
canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height, TRUE);
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
x = (gint) floor (paint_tool->cur_coords.x) - (brush_mask->width >> 1);
|
|
|
|
y = (gint) floor (paint_tool->cur_coords.y) - (brush_mask->height >> 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
xoff = (x < 0) ? -x : 0;
|
|
|
|
yoff = (y < 0) ? -y : 0;
|
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.bytes = 1;
|
2001-02-27 13:21:12 +08:00
|
|
|
maskPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.y = 0;
|
|
|
|
maskPR.w = srcPR.w;
|
|
|
|
maskPR.h = srcPR.h;
|
1997-11-25 06:05:25 +08:00
|
|
|
maskPR.rowstride = maskPR.bytes * brush_mask->width;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* combine the mask and canvas tiles */
|
|
|
|
combine_mask_and_region (&srcPR, &maskPR, brush_opacity);
|
|
|
|
|
|
|
|
/* combine the canvas tiles and the canvas buf */
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.bytes = canvas_buf->bytes;
|
2001-02-27 13:21:12 +08:00
|
|
|
srcPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.y = 0;
|
|
|
|
srcPR.w = canvas_buf->width;
|
|
|
|
srcPR.h = canvas_buf->height;
|
1997-11-25 06:05:25 +08:00
|
|
|
srcPR.rowstride = canvas_buf->width * canvas_buf->bytes;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.data = temp_buf_data (canvas_buf);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
pixel_region_init (&maskPR, canvas_tiles,
|
|
|
|
canvas_buf->x, canvas_buf->y,
|
|
|
|
canvas_buf->width, canvas_buf->height, FALSE);
|
|
|
|
|
|
|
|
/* apply the canvas tiles to the canvas buf */
|
1998-01-25 09:24:46 +08:00
|
|
|
apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
paint_to_canvas_buf (GimpPaintTool *paint_tool,
|
2001-02-28 03:18:01 +08:00
|
|
|
MaskBuf *brush_mask,
|
|
|
|
gint brush_opacity)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
PixelRegion srcPR;
|
|
|
|
PixelRegion maskPR;
|
|
|
|
gint x;
|
|
|
|
gint y;
|
|
|
|
gint xoff;
|
|
|
|
gint yoff;
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
x = (gint) floor (paint_tool->cur_coords.x) - (brush_mask->width >> 1);
|
|
|
|
y = (gint) floor (paint_tool->cur_coords.y) - (brush_mask->height >> 1);
|
1998-03-27 16:13:45 +08:00
|
|
|
xoff = (x < 0) ? -x : 0;
|
|
|
|
yoff = (y < 0) ? -y : 0;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* combine the canvas buf and the brush mask to the canvas buf */
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.bytes = canvas_buf->bytes;
|
2001-02-27 13:21:12 +08:00
|
|
|
srcPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.y = 0;
|
|
|
|
srcPR.w = canvas_buf->width;
|
|
|
|
srcPR.h = canvas_buf->height;
|
1997-11-25 06:05:25 +08:00
|
|
|
srcPR.rowstride = canvas_buf->width * canvas_buf->bytes;
|
2000-06-06 06:08:45 +08:00
|
|
|
srcPR.data = temp_buf_data (canvas_buf);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.bytes = 1;
|
2001-02-27 13:21:12 +08:00
|
|
|
maskPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.y = 0;
|
|
|
|
maskPR.w = srcPR.w;
|
|
|
|
maskPR.h = srcPR.h;
|
1997-11-25 06:05:25 +08:00
|
|
|
maskPR.rowstride = maskPR.bytes * brush_mask->width;
|
2000-06-06 06:08:45 +08:00
|
|
|
maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* apply the mask */
|
|
|
|
apply_mask_to_region (&srcPR, &maskPR, brush_opacity);
|
|
|
|
}
|
1999-07-02 00:52:50 +08:00
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
static void
|
2001-02-27 13:21:12 +08:00
|
|
|
set_undo_tiles (GimpDrawable *drawable,
|
2000-03-05 08:06:11 +08:00
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
gint i;
|
|
|
|
gint j;
|
1997-11-25 06:05:25 +08:00
|
|
|
Tile *src_tile;
|
|
|
|
Tile *dest_tile;
|
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
if (undo_tiles == NULL)
|
1998-08-16 03:17:36 +08:00
|
|
|
{
|
1999-11-23 06:38:02 +08:00
|
|
|
g_warning ("set_undo_tiles: undo_tiles is null");
|
1998-08-16 03:17:36 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT)))
|
|
|
|
{
|
|
|
|
for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH)))
|
|
|
|
{
|
1998-08-16 03:17:36 +08:00
|
|
|
dest_tile = tile_manager_get_tile (undo_tiles, j, i, FALSE, FALSE);
|
1998-08-12 01:35:34 +08:00
|
|
|
if (tile_is_valid (dest_tile) == FALSE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-01-15 05:11:52 +08:00
|
|
|
src_tile = tile_manager_get_tile (gimp_drawable_data (drawable),
|
|
|
|
j, i, TRUE, FALSE);
|
1998-08-16 03:17:36 +08:00
|
|
|
tile_manager_map_tile (undo_tiles, j, i, src_tile);
|
1998-07-10 10:43:12 +08:00
|
|
|
tile_release (src_tile, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-03-05 08:06:11 +08:00
|
|
|
set_canvas_tiles (gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
gint i;
|
|
|
|
gint j;
|
1997-11-25 06:05:25 +08:00
|
|
|
Tile *tile;
|
|
|
|
|
|
|
|
for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT)))
|
|
|
|
{
|
|
|
|
for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH)))
|
|
|
|
{
|
1998-08-16 03:17:36 +08:00
|
|
|
tile = tile_manager_get_tile (canvas_tiles, j, i, FALSE, FALSE);
|
1998-08-12 01:35:34 +08:00
|
|
|
if (tile_is_valid (tile) == FALSE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1998-08-16 03:17:36 +08:00
|
|
|
tile = tile_manager_get_tile (canvas_tiles, j, i, TRUE, TRUE);
|
2000-06-06 06:08:45 +08:00
|
|
|
memset (tile_data_pointer (tile, 0, 0), 0, tile_size (tile));
|
1998-07-10 10:43:12 +08:00
|
|
|
tile_release (tile, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************/
|
|
|
|
/* Paint buffers utility functions */
|
|
|
|
/*****************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2000-03-05 08:06:11 +08:00
|
|
|
free_paint_buffers (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
if (orig_buf)
|
|
|
|
temp_buf_free (orig_buf);
|
|
|
|
orig_buf = NULL;
|
|
|
|
|
|
|
|
if (canvas_buf)
|
|
|
|
temp_buf_free (canvas_buf);
|
|
|
|
canvas_buf = NULL;
|
|
|
|
}
|
1999-09-10 03:11:38 +08:00
|
|
|
|
|
|
|
|
|
|
|
/**************************************************/
|
|
|
|
/* Brush pipe utility functions */
|
|
|
|
/**************************************************/
|
|
|
|
|
|
|
|
void
|
2001-02-28 03:18:01 +08:00
|
|
|
gimp_paint_tool_color_area_with_pixmap (GimpPaintTool *paint_tool,
|
|
|
|
GimpImage *dest,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
TempBuf *area,
|
|
|
|
gdouble scale,
|
|
|
|
BrushApplicationMode mode)
|
1999-09-10 03:11:38 +08:00
|
|
|
{
|
|
|
|
PixelRegion destPR;
|
2000-06-06 06:08:45 +08:00
|
|
|
void *pr;
|
|
|
|
guchar *d;
|
|
|
|
gint ulx;
|
|
|
|
gint uly;
|
|
|
|
gint offsetx;
|
|
|
|
gint offsety;
|
|
|
|
gint y;
|
1999-09-10 03:11:38 +08:00
|
|
|
TempBuf *pixmap_mask;
|
|
|
|
TempBuf *brush_mask;
|
2000-03-05 08:06:11 +08:00
|
|
|
|
2001-02-27 13:21:12 +08:00
|
|
|
g_return_if_fail (GIMP_IS_BRUSH (paint_tool->brush));
|
|
|
|
g_return_if_fail (paint_tool->brush->pixmap != NULL);
|
|
|
|
|
1999-09-10 03:11:38 +08:00
|
|
|
/* scale the brushes */
|
2001-02-27 13:21:12 +08:00
|
|
|
pixmap_mask = gimp_paint_tool_scale_pixmap (paint_tool->brush->pixmap, scale);
|
2000-06-06 06:08:45 +08:00
|
|
|
|
1999-09-10 03:11:38 +08:00
|
|
|
if (mode == SOFT)
|
2001-02-27 13:21:12 +08:00
|
|
|
brush_mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale);
|
1999-09-10 03:11:38 +08:00
|
|
|
else
|
|
|
|
brush_mask = NULL;
|
|
|
|
|
2000-06-06 06:08:45 +08:00
|
|
|
destPR.bytes = area->bytes;
|
2001-02-27 13:21:12 +08:00
|
|
|
destPR.x = 0;
|
2000-06-06 06:08:45 +08:00
|
|
|
destPR.y = 0;
|
|
|
|
destPR.w = area->width;
|
|
|
|
destPR.h = area->height;
|
1999-09-10 03:11:38 +08:00
|
|
|
destPR.rowstride = destPR.bytes * area->width;
|
2000-06-06 06:08:45 +08:00
|
|
|
destPR.data = temp_buf_data (area);
|
1999-09-10 03:11:38 +08:00
|
|
|
|
|
|
|
pr = pixel_regions_register (1, &destPR);
|
|
|
|
|
|
|
|
/* Calculate upper left corner of brush as in
|
2001-02-27 13:21:12 +08:00
|
|
|
* gimp_paint_tool_get_paint_area. Ugly to have to do this here, too.
|
1999-09-10 03:11:38 +08:00
|
|
|
*/
|
|
|
|
|
2001-11-14 00:21:34 +08:00
|
|
|
ulx = (gint) floor (paint_tool->cur_coords.x) - (pixmap_mask->width >> 1);
|
|
|
|
uly = (gint) floor (paint_tool->cur_coords.y) - (pixmap_mask->height >> 1);
|
1999-09-10 03:11:38 +08:00
|
|
|
|
|
|
|
offsetx = area->x - ulx;
|
|
|
|
offsety = area->y - uly;
|
|
|
|
|
|
|
|
for (; pr != NULL; pr = pixel_regions_process (pr))
|
|
|
|
{
|
|
|
|
d = destPR.data;
|
|
|
|
for (y = 0; y < destPR.h; y++)
|
|
|
|
{
|
|
|
|
paint_line_pixmap_mask (dest, drawable, pixmap_mask, brush_mask,
|
|
|
|
d, offsetx, y + offsety,
|
|
|
|
destPR.bytes, destPR.w, mode);
|
|
|
|
d += destPR.rowstride;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-06-06 06:08:45 +08:00
|
|
|
paint_line_pixmap_mask (GimpImage *dest,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
TempBuf *pixmap_mask,
|
|
|
|
TempBuf *brush_mask,
|
|
|
|
guchar *d,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint bytes,
|
|
|
|
gint width,
|
|
|
|
BrushApplicationMode mode)
|
1999-09-10 03:11:38 +08:00
|
|
|
{
|
2000-06-06 06:08:45 +08:00
|
|
|
guchar *b;
|
|
|
|
guchar *p;
|
|
|
|
guchar *mask;
|
|
|
|
gdouble alpha;
|
|
|
|
gdouble factor = 0.00392156986; /* 1.0 / 255.0 */
|
|
|
|
gint x_index;
|
2000-06-28 05:26:59 +08:00
|
|
|
gint i,byte_loop;
|
1999-09-10 03:11:38 +08:00
|
|
|
|
|
|
|
/* Make sure x, y are positive */
|
|
|
|
while (x < 0)
|
|
|
|
x += pixmap_mask->width;
|
|
|
|
while (y < 0)
|
|
|
|
y += pixmap_mask->height;
|
|
|
|
|
|
|
|
/* Point to the approriate scanline */
|
|
|
|
b = temp_buf_data (pixmap_mask) +
|
|
|
|
(y % pixmap_mask->height) * pixmap_mask->width * pixmap_mask->bytes;
|
|
|
|
|
|
|
|
if (mode == SOFT && brush_mask)
|
|
|
|
{
|
|
|
|
/* ditto, except for the brush mask, so we can pre-multiply the alpha value */
|
|
|
|
mask = temp_buf_data (brush_mask) +
|
|
|
|
(y % brush_mask->height) * brush_mask->width;
|
|
|
|
for (i = 0; i < width; i++)
|
|
|
|
{
|
|
|
|
/* attempt to avoid doing this calc twice in the loop */
|
|
|
|
x_index = ((i + x) % pixmap_mask->width);
|
|
|
|
p = b + x_index * pixmap_mask->bytes;
|
|
|
|
d[bytes-1] = mask[x_index];
|
|
|
|
|
|
|
|
/* multiply alpha into the pixmap data */
|
|
|
|
/* maybe we could do this at tool creation or brush switch time? */
|
|
|
|
/* and compute it for the whole brush at once and cache it? */
|
|
|
|
alpha = d[bytes-1] * factor;
|
2000-06-28 05:26:59 +08:00
|
|
|
if(alpha)
|
|
|
|
for (byte_loop = 0; byte_loop < bytes - 1; byte_loop++)
|
|
|
|
d[byte_loop] *= alpha;
|
|
|
|
|
1999-09-10 03:11:38 +08:00
|
|
|
/* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */
|
2000-12-29 23:22:01 +08:00
|
|
|
gimp_image_transform_color (dest, drawable, p, d, RGB);
|
1999-09-10 03:11:38 +08:00
|
|
|
d += bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < width; i++)
|
|
|
|
{
|
|
|
|
/* attempt to avoid doing this calc twice in the loop */
|
|
|
|
x_index = ((i + x) % pixmap_mask->width);
|
|
|
|
p = b + x_index * pixmap_mask->bytes;
|
|
|
|
d[bytes-1] = 255;
|
|
|
|
|
|
|
|
/* multiply alpha into the pixmap data */
|
|
|
|
/* maybe we could do this at tool creation or brush switch time? */
|
|
|
|
/* and compute it for the whole brush at once and cache it? */
|
2000-12-29 23:22:01 +08:00
|
|
|
gimp_image_transform_color (dest, drawable, p, d, RGB);
|
1999-09-10 03:11:38 +08:00
|
|
|
d += bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|