Gimp/app/display/gimpdisplayshell-callbacks.c
CET 1999 Olof S Kylande ac6a5dae50 Fix of KDE/Kwm selection add/sub/inter problem NOTE: This is a workaround,
Thu Dec 16 20:15:25 CET 1999  Olof S Kylande <olof@gimp.org>

        Fix of KDE/Kwm  selection add/sub/inter problem
        NOTE: This is a workaround, not a real fix.
        Many Thanks to Matthias Ettrich

        * app/disp_callbacks.c

        Updated unsharp-mask to version 0.10

        * plug-ins/unsharp/dialog_f.c
        * plug-ins/unsharp/dialog_f.h
        * plug-ins/unsharp/dialog_i.c
        * plug-ins/unsharp/dialog_i.h
        * plug-ins/unsharp/unsharp.c

        Updated print plug-in to version 3.0.1

        * plug-ins/print/README (new file)
        * plug-ins/print/print-escp2.c
        * plug-ins/print/print-pcl.c
        * plug-ins/print/print-ps.c
        * plug-ins/print/print-util.c
        * plug-ins/print/print.c
        * plug-ins/print/print.h

        Updated all files in the help/C/dialogs dir. This is
        a first alpha glimpse of the help system. Please give
        me feedback of the content. However since it's in alpha
        stage it means that there is spell, grammatical, etc errors.
        There is may also be pure errors which I hope "you" will
        report to either olof@gimp.org or karin@gimp.org. Please
        don't report spell, grammatical, etc error at this stage in dev.

        If you have any plans to commit to the help system please write
        to olof@gimp.org. (This is mandatory not a please ;-).

        * help/C/welcome.html
        * help/C/dialogs/about.html ..............
1999-12-16 19:44:02 +00:00

892 lines
23 KiB
C

/* 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
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include "gdk/gdkkeysyms.h"
#include "appenv.h"
#include "bucket_fill.h"
#include "colormaps.h"
#include "cursorutil.h"
#include "devices.h"
#include "disp_callbacks.h"
#include "gdisplay.h"
#include "general.h"
#include "gimpcontext.h"
#include "gimprc.h"
#include "info_window.h"
#include "interface.h"
#include "layer_select.h"
#include "move.h"
#include "patterns.h"
#include "scale.h"
#include "scroll.h"
#include "tools.h"
#include "undo.h"
#include "gimage.h"
#include "dialog_handler.h"
#include "libgimp/gimpintl.h"
/* Function declarations */
static void gdisplay_check_device_cursor (GDisplay *gdisp);
static void
redraw (GDisplay *gdisp,
int x,
int y,
int w,
int h)
{
long x1, y1, x2, y2; /* coordinate of rectangle corners */
x1 = x;
y1 = y;
x2 = (x+w);
y2 = (y+h);
x1 = BOUNDS (x1, 0, gdisp->disp_width);
y1 = BOUNDS (y1, 0, gdisp->disp_height);
x2 = BOUNDS (x2, 0, gdisp->disp_width);
y2 = BOUNDS (y2, 0, gdisp->disp_height);
if ((x2 - x1) && (y2 - y1))
{
gdisplay_expose_area (gdisp, x1, y1, (x2 - x1), (y2 - y1));
gdisplay_flush_displays_only (gdisp);
}
}
static void
gdisplay_check_device_cursor (GDisplay *gdisp)
{
GList *list;
/* gdk_input_list_devices returns an internal list, so we shouldn't
free it afterwards */
for (list = gdk_input_list_devices(); list; list = g_list_next (list))
{
GdkDeviceInfo *info = (GdkDeviceInfo *) list->data;
if (info->deviceid == current_device)
{
gdisp->draw_cursor = !info->has_cursor;
break;
}
}
}
static int
key_to_state (int key)
{
switch (key)
{
case GDK_Alt_L: case GDK_Alt_R:
return GDK_MOD1_MASK;
case GDK_Shift_L: case GDK_Shift_R:
return GDK_SHIFT_MASK;
case GDK_Control_L: case GDK_Control_R:
return GDK_CONTROL_MASK;
default:
return 0;
}
}
gint
gdisplay_shell_events (GtkWidget *widget,
GdkEvent *event,
GDisplay *gdisp)
{
switch (event->type)
{
case GDK_BUTTON_PRESS:
case GDK_KEY_PRESS:
/* Setting the context's display automatically sets the image, too */
gimp_context_set_display (gimp_context_get_user (), gdisp);
break;
default:
break;
}
return FALSE;
}
gint
gdisplay_canvas_events (GtkWidget *canvas,
GdkEvent *event)
{
GDisplay *gdisp;
GdkEventExpose *eevent;
GdkEventMotion *mevent;
GdkEventButton *bevent;
GdkEventKey *kevent;
gdouble tx, ty;
guint state = 0;
gint return_val = FALSE;
static gboolean scrolled = FALSE;
static guint key_signal_id = 0;
int update_cursor = FALSE;
tx = ty = 0;
gdisp = (GDisplay *) gtk_object_get_user_data (GTK_OBJECT (canvas));
if (!canvas->window)
return FALSE;
/* If this is the first event... */
if (!gdisp->select)
{
/* create the selection object */
gdisp->select = selection_create (gdisp->canvas->window, gdisp,
gdisp->gimage->height,
gdisp->gimage->width, marching_speed);
gdisp->disp_width = gdisp->canvas->allocation.width;
gdisp->disp_height = gdisp->canvas->allocation.height;
/* create GC for scrolling */
gdisp->scroll_gc = gdk_gc_new (gdisp->canvas->window);
gdk_gc_set_exposures (gdisp->scroll_gc, TRUE);
/* set up the scrollbar observers */
gtk_signal_connect (GTK_OBJECT (gdisp->hsbdata), "value_changed",
(GtkSignalFunc) scrollbar_horz_update,
gdisp);
gtk_signal_connect (GTK_OBJECT (gdisp->vsbdata), "value_changed",
(GtkSignalFunc) scrollbar_vert_update,
gdisp);
/* setup scale properly */
setup_scale (gdisp);
}
/* Find out what device the event occurred upon */
if (devices_check_change (event))
gdisplay_check_device_cursor (gdisp);
switch (event->type)
{
case GDK_EXPOSE:
eevent = (GdkEventExpose *) event;
/*printf(" EXP:%d,%d(%dx%d) ",eevent->area.x, eevent->area.y,
eevent->area.width, eevent->area.height);fflush(stdout);*/
redraw (gdisp, eevent->area.x, eevent->area.y,
eevent->area.width, eevent->area.height);
break;
case GDK_CONFIGURE:
/*printf(" CNF ");fflush(stdout);*/
if ((gdisp->disp_width != gdisp->canvas->allocation.width) ||
(gdisp->disp_height != gdisp->canvas->allocation.height))
{
gdisp->disp_width = gdisp->canvas->allocation.width;
gdisp->disp_height = gdisp->canvas->allocation.height;
resize_display (gdisp, 0, FALSE);
}
break;
case GDK_LEAVE_NOTIFY:
if ( ( (GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL )
return TRUE;
gdisplay_update_cursor (gdisp, 0, 0);
gtk_label_set_text (GTK_LABEL (gdisp->cursor_label), "");
info_window_update_RGB (gdisp, -1, -1);
case GDK_PROXIMITY_OUT:
gdisp->proximity = FALSE;
break;
case GDK_ENTER_NOTIFY:
if ( ( (GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL )
return TRUE;
/* Actually, should figure out tx,ty here */
break;
case GDK_BUTTON_PRESS:
bevent = (GdkEventButton *) event;
state = bevent->state;
switch (bevent->button)
{
case 1:
state |= GDK_BUTTON1_MASK;
gtk_grab_add (canvas);
/* This is a hack to prevent other stuff being run in the middle of
a tool operation (like changing image types.... brrrr). We just
block all the keypress event. A better solution is to implement
some sort of locking for images.
Note that this is dependent on specific GTK behavior, and isn't
guaranteed to work in future versions of GTK.
-Yosh
*/
if (key_signal_id == 0)
key_signal_id = gtk_signal_connect (GTK_OBJECT (canvas),
"key_press_event",
GTK_SIGNAL_FUNC (gtk_true),
NULL);
if (active_tool && ((active_tool->type == MOVE) ||
!gimage_is_empty (gdisp->gimage)))
{
if (active_tool->auto_snap_to)
{
gdisplay_snap_point (gdisp, bevent->x, bevent->y, &tx, &ty);
bevent->x = tx;
bevent->y = ty;
update_cursor = TRUE;
}
/* reset the current tool if ... */
if ((/* it has no drawable */
! active_tool->drawable ||
/* or a drawable different from the current one */
(gimage_active_drawable (gdisp->gimage) !=
active_tool->drawable)) &&
/* and doesn't want to be preserved across drawable changes */
! active_tool->preserve)
{
tools_initialize (active_tool->type, gdisp);
}
/* otherwise set it's drawable if it has none */
else if (! active_tool->drawable)
{
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
(* active_tool->button_press_func) (active_tool, bevent, gdisp);
}
break;
case 2:
state |= GDK_BUTTON2_MASK;
scrolled = TRUE;
gtk_grab_add (canvas);
start_grab_and_scroll (gdisp, bevent);
break;
case 3:
state |= GDK_BUTTON3_MASK;
gtk_menu_popup (GTK_MENU (gdisp->popup),
NULL, NULL, NULL, NULL, 3, bevent->time);
return_val = TRUE;
break;
/* wheelmouse support */
case 4:
state |= GDK_BUTTON4_MASK;
if (state & GDK_SHIFT_MASK)
{
change_scale (gdisp, ZOOMIN);
}
else
{
GtkAdjustment *adj =
(state & GDK_CONTROL_MASK) ? gdisp->hsbdata : gdisp->vsbdata;
gfloat new_value = adj->value - adj->page_increment / 2;
new_value =
CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
gtk_adjustment_set_value (adj, new_value);
}
return_val = TRUE;
break;
case 5:
state |= GDK_BUTTON5_MASK;
if (state & GDK_SHIFT_MASK)
{
change_scale (gdisp, ZOOMOUT);
}
else
{
GtkAdjustment *adj =
(state & GDK_CONTROL_MASK) ? gdisp->hsbdata : gdisp->vsbdata;
gfloat new_value = adj->value + adj->page_increment / 2;
new_value = CLAMP (new_value,
adj->lower, adj->upper - adj->page_size);
gtk_adjustment_set_value (adj, new_value);
}
return_val = TRUE;
break;
default:
break;
}
break;
case GDK_BUTTON_RELEASE:
bevent = (GdkEventButton *) event;
state = bevent->state;
switch (bevent->button)
{
case 1:
state &= ~GDK_BUTTON1_MASK;
/* Lame hack. See above */
if (key_signal_id)
{
gtk_signal_disconnect (GTK_OBJECT (canvas), key_signal_id);
key_signal_id = 0;
}
gtk_grab_remove (canvas);
gdk_pointer_ungrab (bevent->time); /* fixes pointer grab bug */
if (active_tool && ((active_tool->type == MOVE) ||
!gimage_is_empty (gdisp->gimage)))
{
if (active_tool->state == ACTIVE)
{
if (active_tool->auto_snap_to)
{
gdisplay_snap_point (gdisp, bevent->x, bevent->y, &tx, &ty);
bevent->x = tx;
bevent->y = ty;
update_cursor = TRUE;
}
(* active_tool->button_release_func) (active_tool, bevent,
gdisp);
}
}
break;
case 2:
state &= ~GDK_BUTTON2_MASK;
scrolled = FALSE;
gtk_grab_remove (canvas);
end_grab_and_scroll (gdisp, bevent);
break;
case 3:
state &= ~GDK_BUTTON3_MASK;
break;
/* wheelmouse support */
case 4:
state &= ~GDK_BUTTON4_MASK;
return_val = TRUE;
break;
case 5:
state &= ~GDK_BUTTON5_MASK;
return_val = TRUE;
break;
default:
break;
}
break;
case GDK_MOTION_NOTIFY:
mevent = (GdkEventMotion *) event;
state = mevent->state;
/* Ask for the pointer position, but ignore it except for cursor
* handling, so motion events sync with the button press/release events */
if (mevent->is_hint)
gdk_input_window_get_pointer (canvas->window, current_device, &tx, &ty,
#ifdef GTK_HAVE_SIX_VALUATORS
NULL, NULL, NULL, NULL, NULL);
#else /* !GTK_HAVE_SIX_VALUATORS */
NULL, NULL, NULL, NULL);
#endif /* GTK_HAVE_SIX_VALUATORS */
else
{
tx = mevent->x;
ty = mevent->y;
}
update_cursor = TRUE;
if (!gdisp->proximity)
{
gdisp->proximity = TRUE;
gdisplay_check_device_cursor (gdisp);
}
if (active_tool && ((active_tool->type == MOVE) ||
!gimage_is_empty (gdisp->gimage)) &&
(mevent->state & GDK_BUTTON1_MASK))
{
if (active_tool->state == ACTIVE)
{
/* if the first mouse button is down, check for automatic
* scrolling...
*/
if ((mevent->state & GDK_BUTTON1_MASK) && !active_tool->scroll_lock)
{
if (mevent->x < 0 || mevent->y < 0 ||
mevent->x > gdisp->disp_width ||
mevent->y > gdisp->disp_height)
scroll_to_pointer_position (gdisp, mevent);
}
if (active_tool->auto_snap_to)
{
gdisplay_snap_point (gdisp, mevent->x, mevent->y, &tx, &ty);
mevent->x = tx;
mevent->y = ty;
update_cursor = TRUE;
}
(* active_tool->motion_func) (active_tool, mevent, gdisp);
}
}
else if ((mevent->state & GDK_BUTTON2_MASK) && scrolled)
{
grab_and_scroll (gdisp, mevent);
}
break;
case GDK_KEY_PRESS:
kevent = (GdkEventKey *) event;
state = kevent->state;
switch (kevent->keyval)
{
case GDK_Left: case GDK_Right:
case GDK_Up: case GDK_Down:
if (active_tool && !gimage_is_empty (gdisp->gimage))
(* active_tool->arrow_keys_func) (active_tool, kevent, gdisp);
return_val = TRUE;
break;
case GDK_Tab:
if (kevent->state & GDK_MOD1_MASK && !gimage_is_empty (gdisp->gimage))
layer_select_init (gdisp->gimage, 1, kevent->time);
if (kevent->state & GDK_CONTROL_MASK && !gimage_is_empty (gdisp->gimage))
layer_select_init (gdisp->gimage, -1, kevent->time);
/* Hide or show all dialogs */
if (!kevent->state)
dialog_toggle();
return_val = TRUE;
break;
/* Update the state based on modifiers being pressed */
case GDK_Alt_L: case GDK_Alt_R:
case GDK_Shift_L: case GDK_Shift_R:
case GDK_Control_L: case GDK_Control_R:
state |= key_to_state(kevent->keyval);
/* For all modifier keys: call the tools modifier_key_func */
if (active_tool && !gimage_is_empty (gdisp->gimage))
{
gdk_input_window_get_pointer (canvas->window, current_device,
#ifdef GTK_HAVE_SIX_VALUATORS
&tx, &ty, NULL, NULL, NULL, NULL, NULL);
#else /* !GTK_HAVE_SIX_VALUATORS */
&tx, &ty, NULL, NULL, NULL, NULL);
#endif /* GTK_HAVE_SIX_VALUATORS */
(* active_tool->modifier_key_func) (active_tool, kevent, gdisp);
return_val = TRUE;
}
break;
}
break;
case GDK_KEY_RELEASE:
kevent = (GdkEventKey *) event;
state = kevent->state;
switch (kevent->keyval)
{
case GDK_Alt_L: case GDK_Alt_R:
case GDK_Shift_L: case GDK_Shift_R:
case GDK_Control_L: case GDK_Control_R:
state &= ~key_to_state(kevent->keyval);
/* For all modifier keys: call the tools modifier_key_func */
if (active_tool && !gimage_is_empty (gdisp->gimage))
{
gdk_input_window_get_pointer (canvas->window, current_device,
#ifdef GTK_HAVE_SIX_VALUATORS
&tx, &ty, NULL, NULL, NULL, NULL, NULL);
#else /* !GTK_HAVE_SIX_VALUATORS */
&tx, &ty, NULL, NULL, NULL, NULL);
#endif /* GTK_HAVE_SIX_VALUATORS */
(* active_tool->modifier_key_func) (active_tool, kevent, gdisp);
return_val = TRUE;
}
break;
}
return_val = TRUE;
break;
default:
break;
}
if (no_cursor_updating == 0)
{
if (active_tool && !gimage_is_empty (gdisp->gimage) &&
!(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
{
GdkEventMotion me;
me.x = tx; me.y = ty;
me.state = state;
(* active_tool->cursor_update_func) (active_tool, &me, gdisp);
}
else if (gimage_is_empty (gdisp->gimage))
gdisplay_install_tool_cursor (gdisp, GDK_TOP_LEFT_ARROW);
}
if (update_cursor)
gdisplay_update_cursor (gdisp, tx, ty);
return return_val;
}
gint
gdisplay_hruler_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data)
{
GDisplay *gdisp;
if (event->button == 1)
{
gdisp = data;
gimp_context_set_tool (gimp_context_get_user (), MOVE);
move_tool_start_hguide (active_tool, gdisp);
gtk_grab_add (gdisp->canvas);
}
return FALSE;
}
gint
gdisplay_vruler_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data)
{
GDisplay *gdisp;
if (event->button == 1)
{
gdisp = data;
gimp_context_set_tool (gimp_context_get_user (), MOVE);
move_tool_start_vguide (active_tool, gdisp);
gtk_grab_add (gdisp->canvas);
}
return FALSE;
}
gint
gdisplay_origin_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data)
{
GDisplay *gdisp;
if (event->button == 1)
{
gdisp = data;
gtk_menu_popup (GTK_MENU (gdisp->popup),
NULL, NULL, NULL, NULL, 1, event->time);
}
/* Stop the signal emission so the button doesn't grab the
* pointer away from us */
gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "button_press_event");
return FALSE;
}
gboolean
gdisplay_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time,
gpointer data)
{
GDisplay *gdisp;
GtkWidget *src_widget;
gboolean return_val = FALSE;
gdisp = (GDisplay *) data;
if ((src_widget = gtk_drag_get_source_widget (context)))
{
GimpDrawable *drawable = NULL;
Layer *layer = NULL;
Channel *channel = NULL;
LayerMask *layer_mask = NULL;
GImage *component = NULL;
ChannelType component_type = -1;
layer = (Layer *) gtk_object_get_data (GTK_OBJECT (src_widget),
"gimp_layer");
channel = (Channel *) gtk_object_get_data (GTK_OBJECT (src_widget),
"gimp_channel");
layer_mask = (LayerMask *) gtk_object_get_data (GTK_OBJECT (src_widget),
"gimp_layer_mask");
component = (GImage *) gtk_object_get_data (GTK_OBJECT (src_widget),
"gimp_component");
if (layer)
{
drawable = GIMP_DRAWABLE (layer);
}
else if (channel)
{
drawable = GIMP_DRAWABLE (channel);
}
else if (layer_mask)
{
drawable = GIMP_DRAWABLE (layer_mask);
}
else if (component)
{
component_type =
(ChannelType) gtk_object_get_data (GTK_OBJECT (src_widget),
"gimp_component_type");
}
/* FIXME: implement special treatment of channel etc.
*/
if (drawable)
{
GImage *gimage;
Layer *new_layer;
GImage *dest_gimage;
gint width, height;
gint dest_width, dest_height;
gint off_x, off_y;
TileManager *tiles;
PixelRegion srcPR, destPR;
guchar bg[MAX_CHANNELS];
gint bytes, type;
gimage = gimp_drawable_gimage (drawable);
width = gimp_drawable_width (drawable);
height = gimp_drawable_height (drawable);
/* How many bytes in the temp buffer? */
switch (drawable_type (drawable))
{
case RGB_GIMAGE: case RGBA_GIMAGE:
bytes = 4; type = RGB;
break;
case GRAY_GIMAGE: case GRAYA_GIMAGE:
bytes = 2; type = GRAY;
break;
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
bytes = 4; type = INDEXED;
break;
default:
bytes = 3; type = RGB;
break;
}
gimage_get_background (gimage, drawable, bg);
tiles = tile_manager_new (width, height, bytes);
pixel_region_init (&srcPR, drawable_data (drawable),
0, 0, width, height, FALSE);
pixel_region_init (&destPR, tiles,
0, 0, width, height, TRUE);
if (type == INDEXED)
/* If the layer is indexed...we need to extract pixels */
extract_from_region (&srcPR, &destPR, NULL,
drawable_cmap (drawable), bg, type,
drawable_has_alpha (drawable), FALSE);
else if (bytes > srcPR.bytes)
/* If the layer doesn't have an alpha channel, add one */
add_alpha_region (&srcPR, &destPR);
else
/* Otherwise, do a straight copy */
copy_region (&srcPR, &destPR);
dest_gimage = gdisp->gimage;
dest_width = dest_gimage->width;
dest_height = dest_gimage->height;
new_layer =
layer_from_tiles (dest_gimage,
GIMP_DRAWABLE (gimage_get_active_layer (dest_gimage)),
tiles, _("Pasted Layer"),
OPAQUE_OPACITY, NORMAL_MODE);
tile_manager_destroy (tiles);
if (new_layer)
{
undo_push_group_start (dest_gimage, EDIT_PASTE_UNDO);
gimp_drawable_set_gimage (GIMP_DRAWABLE (new_layer), dest_gimage);
off_x = (dest_gimage->width - width) / 2;
off_y = (dest_gimage->height - height) / 2;
layer_translate (new_layer, off_x, off_y);
gimage_add_layer (dest_gimage, new_layer, -1);
gdisplays_flush ();
return_val = TRUE;
undo_push_group_end (dest_gimage);
}
}
}
gtk_drag_finish (context, return_val, FALSE, time);
if (return_val)
gimp_context_set_display (gimp_context_get_user (), gdisp);
return return_val;
}
static void
gdisplay_bucket_fill (GtkWidget *widget,
BucketFillMode fill_mode,
guchar orig_color[],
TempBuf *orig_pat_buf,
gpointer data)
{
GimpImage *gimage;
GimpDrawable *drawable;
TileManager *buf_tiles;
PixelRegion bufPR;
GimpContext *context;
gint x1, x2, y1, y2;
gint bytes;
gboolean has_alpha;
guchar color[3];
TempBuf *pat_buf = NULL;
gboolean new_buf = FALSE;
gimage = ((GDisplay *) data)->gimage;
drawable = gimage_active_drawable (gimage);
if (!drawable)
return;
gimp_add_busy_cursors ();
/* Get the bucket fill context */
if (! global_paint_options)
context = tool_info[BUCKET_FILL].tool_context;
else
context = gimp_context_get_user ();
/* Transform the passed data for the dest image */
if (fill_mode == FG_BUCKET_FILL)
{
gimp_image_transform_color (gimage, drawable, orig_color, color, RGB);
}
else
{
if (((orig_pat_buf->bytes == 3) && !drawable_color (drawable)) ||
((orig_pat_buf->bytes == 1) && !drawable_gray (drawable)))
{
guchar *d1, *d2;
gint size;
if ((orig_pat_buf->bytes == 1) && drawable_color (drawable))
pat_buf = temp_buf_new (orig_pat_buf->width, orig_pat_buf->height,
3, 0, 0, NULL);
else
pat_buf = temp_buf_new (orig_pat_buf->width, orig_pat_buf->height,
1, 0, 0, NULL);
d1 = temp_buf_data (orig_pat_buf);
d2 = temp_buf_data (pat_buf);
size = orig_pat_buf->width * orig_pat_buf->height;
while (size--)
{
gimage_transform_color (gimage, drawable, d1, d2,
(orig_pat_buf->bytes == 3) ? RGB : GRAY);
d1 += orig_pat_buf->bytes;
d2 += pat_buf->bytes;
}
new_buf = TRUE;
}
else
{
pat_buf = orig_pat_buf;
}
}
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
/* Fill the region */
buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
bucket_fill_region (fill_mode, &bufPR, NULL,
color, pat_buf, x1, y1, has_alpha);
/* Apply it to the image */
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
gimage_apply_image (gimage, drawable, &bufPR, TRUE,
gimp_context_get_opacity (context) * 255,
gimp_context_get_paint_mode (context),
NULL, x1, y1);
tile_manager_destroy (buf_tiles);
/* Update the displays */
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
gdisplays_flush ();
if (new_buf)
temp_buf_free (pat_buf);
gimp_remove_busy_cursors (NULL);
}
void
gdisplay_drop_color (GtkWidget *widget,
guchar r,
guchar g,
guchar b,
gpointer data)
{
guchar color[3];
color[0] = r;
color[1] = g;
color[2] = b;
gdisplay_bucket_fill (widget, FG_BUCKET_FILL, color, NULL, data);
}
void
gdisplay_drop_pattern (GtkWidget *widget,
GPattern *pattern,
gpointer data)
{
gdisplay_bucket_fill (widget, PATTERN_BUCKET_FILL, NULL, pattern->mask, data);
}