home *** CD-ROM | disk | FTP | other *** search
- /* The GIMP -- an image manipulation program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * GimpContextPreview Widget
- * Copyright (C) 1999 Sven Neumann
- *
- * 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 <string.h>
-
- #include <gtk/gtk.h>
-
- #include "apptypes.h"
-
- #include "appenv.h"
- #include "brush_scale.h"
- #include "gimpbrush.h"
- #include "gimpbrushpipe.h"
- #include "gimpcontextpreview.h"
- #include "gimpdnd.h"
- #include "gradient_header.h"
- #include "patterns.h"
- #include "temp_buf.h"
-
- #include "libgimp/gimplimits.h"
-
- /* the pixmaps for the [scale|pipe]_indicators */
- #define indicator_width 7
- #define indicator_height 7
-
- #define WHT {255, 255, 255}
- #define BLK { 0, 0, 0}
- #define RED {255, 127, 127}
-
- static unsigned char scale_indicator_bits[7][7][3] =
- {
- { WHT, WHT, WHT, WHT, WHT, WHT, WHT },
- { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
- { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
- { WHT, BLK, BLK, BLK, BLK, BLK, WHT },
- { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
- { WHT, WHT, WHT, BLK, WHT, WHT, WHT },
- { WHT, WHT, WHT, WHT, WHT, WHT, WHT }
- };
-
- static unsigned char pipe_indicator_bits[7][7][3] =
- {
- { WHT, WHT, WHT, WHT, WHT, WHT, WHT },
- { WHT, WHT, WHT, WHT, WHT, WHT, RED },
- { WHT, WHT, WHT, WHT, WHT, RED, RED },
- { WHT, WHT, WHT, WHT, RED, RED, RED },
- { WHT, WHT, WHT, RED, RED, RED, RED },
- { WHT, WHT, RED, RED, RED, RED, RED },
- { WHT, RED, RED, RED, RED, RED, RED }
- };
-
- static unsigned char scale_pipe_indicator_bits[7][7][3] =
- {
- { WHT, WHT, WHT, WHT, WHT, WHT, WHT },
- { WHT, WHT, WHT, BLK, WHT, WHT, RED },
- { WHT, WHT, WHT, BLK, WHT, RED, RED },
- { WHT, BLK, BLK, BLK, BLK, BLK, RED },
- { WHT, WHT, WHT, BLK, RED, RED, RED },
- { WHT, WHT, RED, BLK, RED, RED, RED },
- { WHT, RED, RED, RED, RED, RED, RED }
- };
-
-
- /* how long to wait after mouse-down before showing popup */
- #define POPUP_DELAY_MS 150
-
- /* size of the gradient popup */
- #define GRADIENT_POPUP_WIDTH 128
- #define GRADIENT_POPUP_HEIGHT 32
-
- #define DRAG_PREVIEW_SIZE 32
-
- /* event mask for the context_preview */
- #define CONTEXT_PREVIEW_EVENT_MASK (GDK_BUTTON_PRESS_MASK | \
- GDK_BUTTON_RELEASE_MASK | \
- GDK_ENTER_NOTIFY_MASK | \
- GDK_LEAVE_NOTIFY_MASK)
-
- /* shared widgets for the popups */
- /* XXX: It is pretty dangerous making these variables statics,
- * I'd feel safer if they were per-instance and private. -- austin */
- static GtkWidget *gcp_popup = NULL;
- static GtkWidget *gcp_popup_preview = NULL;
- static guint gcp_pipe_timer = 0;
- static guint gcp_pipe_index = 0;
- static guint gcp_popup_timer = 0;
-
- /* dnd stuff */
- static GtkTargetEntry context_preview_target_table[3][1] =
- {
- { GIMP_TARGET_BRUSH },
- { GIMP_TARGET_PATTERN },
- { GIMP_TARGET_GRADIENT }
- };
- static guint n_targets = 1;
-
- /* signals */
- enum
- {
- CLICKED,
- LAST_SIGNAL
- };
-
- static guint gimp_context_preview_signals[LAST_SIGNAL] = { 0 };
- static GtkPreviewClass *parent_class = NULL;
-
- static gpointer gimp_context_preview_get_data (GimpContextPreview *,
- gpointer);
- static gint gimp_context_preview_button_press_event (GtkWidget *,
- GdkEventButton *);
- static gint gimp_context_preview_button_release_event (GtkWidget *,
- GdkEventButton *);
- static void gimp_context_preview_popup_open (GimpContextPreview *,
- gint, gint);
- static void gimp_context_preview_popup_close (void);
- static gboolean gimp_context_preview_data_matches_type (GimpContextPreview *,
- gpointer);
- static void gimp_context_preview_draw_brush (GimpContextPreview *);
- static void gimp_context_preview_draw_brush_popup (GimpContextPreview *);
- static gint gimp_context_preview_animate_pipe (GimpContextPreview *);
- static void gimp_context_preview_draw_pattern (GimpContextPreview *);
- static void gimp_context_preview_draw_pattern_popup (GimpContextPreview *);
- static void gimp_context_preview_draw_gradient (GimpContextPreview *);
- static void gimp_context_preview_draw_gradient_popup (GimpContextPreview *);
-
- static gint brush_dirty_callback (GimpBrush *, GimpContextPreview *);
- static gint brush_rename_callback (GimpBrush *, GimpContextPreview *);
-
- static void
- gimp_context_preview_destroy (GtkObject *object)
- {
- g_return_if_fail (GIMP_IS_CONTEXT_PREVIEW (object));
-
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
- }
-
- static void
- gimp_context_preview_class_init (GimpContextPreviewClass *class)
- {
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- object_class = (GtkObjectClass*) class;
- widget_class = (GtkWidgetClass*) class;
-
- parent_class = gtk_type_class (gtk_preview_get_type ());
-
- gimp_context_preview_signals[CLICKED] =
- gtk_signal_new ("clicked",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (GimpContextPreviewClass, clicked),
- gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
- gtk_object_class_add_signals (object_class, gimp_context_preview_signals,
- LAST_SIGNAL);
-
- class->clicked = NULL;
-
- widget_class->button_press_event = gimp_context_preview_button_press_event;
- widget_class->button_release_event = gimp_context_preview_button_release_event;
-
- object_class->destroy = gimp_context_preview_destroy;
- }
-
- static void
- gimp_context_preview_init (GimpContextPreview *gcp)
- {
- gcp->data = NULL;
- gcp->type = GCP_LAST;
- gcp->width = 0;
- gcp->height = 0;
- gcp->popup_width = 0;
- gcp->popup_height = 0;
- gcp->show_popup = FALSE;
- gcp->show_tooltips = FALSE;
-
- GTK_PREVIEW (gcp)->type = GTK_PREVIEW_COLOR;
- GTK_PREVIEW (gcp)->bpp = 3;
- GTK_PREVIEW (gcp)->dither = GDK_RGB_DITHER_NORMAL;
-
- gtk_widget_set_events (GTK_WIDGET (gcp), CONTEXT_PREVIEW_EVENT_MASK);
- }
-
- GtkType
- gimp_context_preview_get_type (void)
- {
- static GtkType gcp_type = 0;
-
- if (!gcp_type)
- {
- GtkTypeInfo gcp_info =
- {
- "GimpContextPreview",
- sizeof (GimpContextPreview),
- sizeof (GimpContextPreviewClass),
- (GtkClassInitFunc) gimp_context_preview_class_init,
- (GtkObjectInitFunc) gimp_context_preview_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL
- };
-
- gcp_type = gtk_type_unique (gtk_preview_get_type (), &gcp_info);
- }
-
- return gcp_type;
- }
-
- GtkWidget *
- gimp_context_preview_new (GimpContextPreviewType type,
- gint width,
- gint height,
- gboolean show_popup,
- gboolean show_tooltips,
- GtkSignalFunc drop_data_callback,
- gpointer drop_data_data)
- {
- GimpContextPreview *gcp;
-
- g_return_val_if_fail (type >= 0 && type < GCP_LAST, NULL);
- g_return_val_if_fail (width > 0 && height > 0, NULL);
-
- gcp = gtk_type_new (gimp_context_preview_get_type ());
-
- gcp->type = type;
- gcp->width = width;
- gcp->height = height;
- gcp->show_popup = show_popup;
- gcp->show_tooltips = show_tooltips;
-
- gtk_preview_size (GTK_PREVIEW (gcp), width, height);
-
- /* drag dest */
- gtk_drag_dest_set (GTK_WIDGET (gcp),
- GTK_DEST_DEFAULT_HIGHLIGHT |
- GTK_DEST_DEFAULT_MOTION |
- GTK_DEST_DEFAULT_DROP,
- context_preview_target_table[type], n_targets,
- GDK_ACTION_COPY);
-
- switch (type)
- {
- case GCP_BRUSH:
- gimp_dnd_brush_dest_set (GTK_WIDGET (gcp),
- (GimpDndDropBrushFunc) drop_data_callback,
- drop_data_data);
- break;
- case GCP_PATTERN:
- gimp_dnd_pattern_dest_set (GTK_WIDGET (gcp),
- (GimpDndDropPatternFunc) drop_data_callback,
- drop_data_data);
- break;
- case GCP_GRADIENT:
- gimp_dnd_gradient_dest_set (GTK_WIDGET (gcp),
- (GimpDndDropGradientFunc) drop_data_callback,
- drop_data_data);
- break;
- default:
- break;
- }
-
- return GTK_WIDGET (gcp);
- }
-
- void
- gimp_context_preview_update (GimpContextPreview *gcp,
- gpointer data)
- {
- g_return_if_fail (GIMP_IS_CONTEXT_PREVIEW (gcp));
- g_return_if_fail (gimp_context_preview_data_matches_type (gcp, data));
-
- if (!gcp->data)
- {
- if (gcp->show_popup)
- gtk_drag_source_set (GTK_WIDGET (gcp),
- GDK_BUTTON2_MASK,
- context_preview_target_table[gcp->type], n_targets,
- GDK_ACTION_COPY);
- else
- gtk_drag_source_set (GTK_WIDGET (gcp),
- GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
- context_preview_target_table[gcp->type], n_targets,
- GDK_ACTION_COPY);
-
- switch (gcp->type)
- {
- case GCP_BRUSH:
- gimp_dnd_brush_source_set
- (GTK_WIDGET (gcp),
- (GimpDndDragBrushFunc) gimp_context_preview_get_data,
- NULL);
- break;
- case GCP_PATTERN:
- gimp_dnd_pattern_source_set
- (GTK_WIDGET (gcp),
- (GimpDndDragPatternFunc) gimp_context_preview_get_data,
- NULL);
- break;
- case GCP_GRADIENT:
- gimp_dnd_gradient_source_set
- (GTK_WIDGET (gcp),
- (GimpDndDragGradientFunc) gimp_context_preview_get_data,
- NULL);
- break;
- default:
- break;
- }
- }
-
- if (gcp->data && gcp->type == GCP_BRUSH)
- gtk_signal_disconnect_by_data (GTK_OBJECT (gcp->data), gcp);
-
- gcp->data = data;
- if (GTK_IS_OBJECT (gcp->data))
- gtk_signal_connect (GTK_OBJECT (gcp->data), "destroy",
- gtk_widget_destroyed, &gcp->data);
- switch (gcp->type)
- {
- case GCP_BRUSH:
- gimp_context_preview_draw_brush (gcp);
- gtk_signal_connect (GTK_OBJECT (gcp->data), "dirty",
- GTK_SIGNAL_FUNC (brush_dirty_callback), gcp);
- gtk_signal_connect (GTK_OBJECT (gcp->data), "rename",
- GTK_SIGNAL_FUNC (brush_rename_callback), gcp);
- break;
- case GCP_PATTERN:
- gimp_context_preview_draw_pattern (gcp);
- break;
- case GCP_GRADIENT:
- gimp_context_preview_draw_gradient (gcp);
- break;
- default:
- break;
- }
- gtk_widget_queue_draw (GTK_WIDGET (gcp));
-
- if (gcp->show_tooltips)
- {
- gchar *name = NULL;
-
- switch (gcp->type)
- {
- case GCP_BRUSH:
- {
- GimpBrush *brush = GIMP_BRUSH (gcp->data);
- name = brush->name;
- }
- break;
- case GCP_PATTERN:
- {
- GPattern *pattern = (GPattern *) (gcp->data);
- name = pattern->name;
- }
- break;
- case GCP_GRADIENT:
- {
- gradient_t *gradient = (gradient_t *) (gcp->data);
- name = gradient->name;
- }
- break;
- default:
- break;
- }
- gimp_help_set_help_data (GTK_WIDGET (gcp), name, NULL);
- }
- }
-
- static gpointer
- gimp_context_preview_get_data (GimpContextPreview *gcp,
- gpointer data)
- {
- g_return_val_if_fail (GIMP_IS_CONTEXT_PREVIEW (gcp), NULL);
-
- return gcp->data;
- }
-
- static gint
- gimp_context_preview_button_press_event (GtkWidget *widget,
- GdkEventButton *bevent)
- {
- if (bevent->button == 1)
- {
- if (GIMP_CONTEXT_PREVIEW (widget)->show_popup)
- {
- gdk_pointer_grab (widget->window, FALSE, GDK_BUTTON_RELEASE_MASK,
- NULL, NULL, bevent->time);
- gimp_context_preview_popup_open (GIMP_CONTEXT_PREVIEW (widget),
- bevent->x, bevent->y);
- }
- }
- return FALSE;
- }
-
- static gint
- gimp_context_preview_button_release_event (GtkWidget *widget,
- GdkEventButton *bevent)
- {
- gboolean fast_click = TRUE;
-
- if (bevent->button == 1)
- {
- if (GIMP_CONTEXT_PREVIEW (widget)->show_popup)
- {
- gdk_pointer_ungrab (bevent->time);
-
- /* user clicked quickly if the timeout is still running */
- fast_click = gcp_popup_timer;
-
- gimp_context_preview_popup_close ();
- }
-
- if (fast_click)
- gtk_signal_emit_by_name (GTK_OBJECT (widget), "clicked");
- }
- return FALSE;
- }
-
-
- typedef struct {
- GimpContextPreview *gcp;
- gint x;
- gint y;
- } popup_timeout_args_t;
-
-
- static gboolean
- gimp_context_preview_popup_timeout (gpointer data)
- {
- popup_timeout_args_t *popup_timeout_args = data;
- GimpContextPreview *gcp;
- gint x, y;
- gint x_org, y_org;
- gint scr_w, scr_h;
-
- gcp_popup_timer = 0;
-
- g_return_val_if_fail (popup_timeout_args != NULL, FALSE);
-
- gcp = popup_timeout_args->gcp;
- x = popup_timeout_args->x;
- y = popup_timeout_args->y;
-
- g_return_val_if_fail (gcp != NULL, FALSE);
- if (!gcp->data)
- return FALSE;
-
- switch (gcp->type)
- {
- case GCP_BRUSH:
- {
- GimpBrush *brush = GIMP_BRUSH (gcp->data);
- gcp->popup_width = brush->mask->width;
- gcp->popup_height = brush->mask->height;
-
- if (GIMP_IS_BRUSH_PIPE (brush))
- {
- GimpBrushPipe *pipe = GIMP_BRUSH_PIPE (brush);
- gint i;
-
- for (i = 1; i < pipe->nbrushes; i++)
- {
- brush = GIMP_BRUSH (pipe->brushes[i]);
- gcp->popup_width = MAX (gcp->popup_width, brush->mask->width);
- gcp->popup_height = MAX (gcp->popup_height, brush->mask->height);
- }
- }
- else if (gcp->popup_width <= gcp->width && gcp->popup_height <= gcp->height)
- return FALSE;
- }
- break;
- case GCP_PATTERN:
- {
- GPattern *pattern = (GPattern*)gcp->data;
- gcp->popup_width = pattern->mask->width;
- gcp->popup_height = pattern->mask->height;
- if (gcp->popup_width <= gcp->width && gcp->popup_height <= gcp->height)
- return FALSE;
- }
- break;
- case GCP_GRADIENT:
- gcp->popup_width = GRADIENT_POPUP_WIDTH;
- gcp->popup_height = GRADIENT_POPUP_HEIGHT;
- if (gcp->popup_width <= gcp->width && gcp->popup_height <= gcp->height)
- return FALSE;
- break;
- default:
- return FALSE;
- }
-
- /* make sure the popup exists and is not visible */
- if (gcp_popup == NULL)
- {
- GtkWidget *frame;
-
- gcp_popup = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_window_set_policy (GTK_WINDOW (gcp_popup), FALSE, FALSE, TRUE);
- gtk_signal_connect (GTK_OBJECT (gcp_popup), "destroy",
- gtk_widget_destroyed, &gcp_popup);
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
- gtk_container_add (GTK_CONTAINER (gcp_popup), frame);
- gtk_widget_show (frame);
- gcp_popup_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
- gtk_signal_connect (GTK_OBJECT (gcp_popup_preview), "destroy",
- gtk_widget_destroyed, &gcp_popup_preview);
- gtk_container_add (GTK_CONTAINER (frame), gcp_popup_preview);
- gtk_widget_show (gcp_popup_preview);
- }
- else
- {
- gtk_widget_hide (gcp_popup);
- }
-
- /* decide where to put the popup */
- gdk_window_get_origin (GTK_WIDGET (gcp)->window, &x_org, &y_org);
- scr_w = gdk_screen_width ();
- scr_h = gdk_screen_height ();
- x = x_org + x - (gcp->popup_width >> 1);
- y = y_org + y - (gcp->popup_height >> 1);
- x = (x < 0) ? 0 : x;
- y = (y < 0) ? 0 : y;
- x = (x + gcp->popup_width > scr_w) ? scr_w - gcp->popup_width : x;
- y = (y + gcp->popup_height > scr_h) ? scr_h - gcp->popup_height : y;
- gtk_preview_size (GTK_PREVIEW (gcp_popup_preview), gcp->popup_width, gcp->popup_height);
- gtk_widget_popup (gcp_popup, x, y);
-
- switch (gcp->type)
- {
- case GCP_BRUSH:
- gimp_context_preview_draw_brush_popup (gcp);
- if (GIMP_IS_BRUSH_PIPE (gcp->data) && gcp_pipe_timer == 0)
- {
- gcp_pipe_index = 0;
- gcp_pipe_timer =
- gtk_timeout_add (300,
- (GtkFunction) gimp_context_preview_animate_pipe,
- gcp);
- }
- break;
-
- case GCP_PATTERN:
- gimp_context_preview_draw_pattern_popup (gcp);
- break;
-
- case GCP_GRADIENT:
- gimp_context_preview_draw_gradient_popup (gcp);
- break;
-
- default:
- break;
- }
- gtk_widget_queue_draw (gcp_popup_preview);
-
- return FALSE;
- }
-
-
- static void
- gimp_context_preview_popup_open (GimpContextPreview *gcp,
- gint x,
- gint y)
- {
- static popup_timeout_args_t popup_timeout_args;
-
- if (gcp_popup_timer != 0)
- return;
-
- popup_timeout_args.gcp = gcp;
- popup_timeout_args.x = x;
- popup_timeout_args.y = y;
- gcp_popup_timer = gtk_timeout_add (POPUP_DELAY_MS,
- gimp_context_preview_popup_timeout,
- &popup_timeout_args);
- }
-
-
- static void
- gimp_context_preview_popup_close (void)
- {
- if (gcp_pipe_timer > 0)
- gtk_timeout_remove (gcp_pipe_timer);
- gcp_pipe_timer = 0;
-
- if (gcp_popup_timer)
- gtk_timeout_remove (gcp_popup_timer);
- gcp_popup_timer = 0;
-
- if (gcp_popup != NULL)
- gtk_widget_hide (gcp_popup);
- }
-
- static gboolean
- gimp_context_preview_data_matches_type (GimpContextPreview *gcp,
- gpointer data)
- {
- gboolean match = FALSE;
-
- g_return_val_if_fail (GIMP_IS_CONTEXT_PREVIEW (gcp), FALSE);
-
- switch (gcp->type)
- {
- case GCP_BRUSH:
- match = GIMP_IS_BRUSH (data);
- break;
- case GCP_PATTERN:
- case GCP_GRADIENT:
- match = data != NULL; /* would be nicer if these were real gtk_objects */
- break;
- default:
- break;
- }
- return (match);
- }
-
- /* brush draw functions */
-
- void
- draw_brush (GtkPreview *preview,
- GimpBrush *brush,
- gint width,
- gint height,
- gboolean is_popup)
- {
- gboolean scale = FALSE;
- gint brush_width, brush_height;
- gint offset_x, offset_y;
- TempBuf *mask_buf, *pixmap_buf = NULL;
- guchar *mask, *buf, *b;
- guchar bg;
- gint x, y;
-
- mask_buf = gimp_brush_get_mask (brush);
- pixmap_buf = gimp_brush_get_pixmap (brush);
- brush_width = mask_buf->width;
- brush_height = mask_buf->height;
-
- if (brush_width > width || brush_height > height)
- {
- gdouble ratio_x = (gdouble)brush_width / width;
- gdouble ratio_y = (gdouble)brush_height / height;
-
- brush_width = (gdouble)brush_width / MAX (ratio_x, ratio_y) + 0.5;
- brush_height = (gdouble)brush_height / MAX (ratio_x, ratio_y) + 0.5;
-
- mask_buf = brush_scale_mask (mask_buf, brush_width, brush_height);
- if (pixmap_buf)
- {
- /* TODO: the scale function should scale the pixmap
- and the mask in one run */
- pixmap_buf = brush_scale_pixmap (pixmap_buf, brush_width, brush_height);
- }
- scale = TRUE;
- }
-
- offset_x = (width - brush_width) / 2;
- offset_y = (height - brush_height) / 2;
-
- mask = temp_buf_data (mask_buf);
- buf = g_new (guchar, 3 * width);
- memset (buf, 255, 3 * width);
-
- if (pixmap_buf)
- {
- guchar *pixmap = temp_buf_data (pixmap_buf);
-
- for (y = 0; y < offset_y; y++)
- gtk_preview_draw_row (preview, buf, 0, y, width);
- for (y = offset_y; y < brush_height + offset_y; y++)
- {
- b = buf + 3 * offset_x;
- for (x = 0; x < brush_width ; x++)
- {
- bg = (255 - *mask);
- *b++ = bg + (*mask * *pixmap++) / 255;
- *b++ = bg + (*mask * *pixmap++) / 255;
- *b++ = bg + (*mask * *pixmap++) / 255;
- mask++;
- }
- gtk_preview_draw_row (preview, buf, 0, y, width);
- }
- memset (buf, 255, 3 * width);
- for (y = brush_height + offset_y; y < height; y++)
- gtk_preview_draw_row (preview, buf, 0, y, width);
- }
- else
- {
- for (y = 0; y < offset_y; y++)
- gtk_preview_draw_row (preview, buf, 0, y, width);
- for (y = offset_y; y < brush_height + offset_y; y++)
- {
- b = buf + 3 * offset_x;
- for (x = 0; x < brush_width ; x++)
- {
- bg = 255 - *mask++;
- memset (b, bg, 3);
- b += 3;
- }
- gtk_preview_draw_row (preview, buf, 0, y, width);
- }
- memset (buf, 255, 3 * width);
- for (y = brush_height + offset_y; y < height; y++)
- gtk_preview_draw_row (preview, buf, 0, y, width);
- }
-
- if (scale)
- {
- offset_x = width - indicator_width;
- offset_y = height - indicator_height;
- for (y = 0; y < indicator_height; y++)
- (GIMP_IS_BRUSH_PIPE (brush)) ?
- gtk_preview_draw_row (preview, scale_pipe_indicator_bits[y][0],
- offset_x, offset_y + y, indicator_width) :
- gtk_preview_draw_row (preview, scale_indicator_bits[y][0],
- offset_x, offset_y + y, indicator_width);
- temp_buf_free (mask_buf);
- if (pixmap_buf)
- temp_buf_free (pixmap_buf);
- }
- else if (!is_popup && GIMP_IS_BRUSH_PIPE (brush))
- {
- offset_x = width - indicator_width;
- offset_y = height - indicator_height;
- for (y = 0; y < indicator_height; y++)
- gtk_preview_draw_row (preview, pipe_indicator_bits[y][0],
- offset_x, offset_y + y, indicator_width);
- }
-
- g_free (buf);
- }
-
- static void
- gimp_context_preview_draw_brush_popup (GimpContextPreview *gcp)
- {
- GimpBrush *brush;
-
- g_return_if_fail (gcp != NULL && GIMP_IS_BRUSH (gcp->data));
-
- brush = GIMP_BRUSH (gcp->data);
- draw_brush (GTK_PREVIEW (gcp_popup_preview), brush,
- gcp->popup_width, gcp->popup_height, TRUE);
- }
-
- static void
- gimp_context_preview_draw_brush (GimpContextPreview *gcp)
- {
- GimpBrush *brush;
-
- g_return_if_fail (gcp != NULL && GIMP_IS_BRUSH (gcp->data));
-
- brush = GIMP_BRUSH (gcp->data);
- draw_brush (GTK_PREVIEW (gcp), brush, gcp->width, gcp->height, FALSE);
- }
-
-
- static gint
- gimp_context_preview_animate_pipe (GimpContextPreview *gcp)
- {
- GimpBrushPipe *pipe;
- GimpBrush *brush;
-
- g_return_val_if_fail (gcp != NULL &&
- GIMP_IS_BRUSH_PIPE (gcp->data), FALSE);
- if (gcp_popup != NULL && !GTK_WIDGET_VISIBLE (gcp_popup))
- {
- gcp_pipe_timer = 0;
- return (FALSE);
- }
-
- pipe = GIMP_BRUSH_PIPE (gcp->data);
- if (++gcp_pipe_index >= pipe->nbrushes)
- gcp_pipe_index = 0;
- brush = GIMP_BRUSH (pipe->brushes[gcp_pipe_index]);
- draw_brush (GTK_PREVIEW (gcp_popup_preview), brush,
- gcp->popup_width, gcp->popup_height, TRUE);
- gtk_widget_queue_draw (gcp_popup_preview);
-
- return (TRUE);
- }
-
- /* brush callbacks */
- static gint
- brush_dirty_callback (GimpBrush *brush,
- GimpContextPreview *gcp)
- {
- gimp_context_preview_draw_brush (gcp);
- gtk_widget_queue_draw (GTK_WIDGET (gcp));
-
- return TRUE;
- }
-
- static gint
- brush_rename_callback (GimpBrush *brush,
- GimpContextPreview *gcp)
- {
- if (gcp->show_tooltips)
- gimp_help_set_help_data (GTK_WIDGET (gcp), brush->name, NULL);
-
- return TRUE;
- }
-
-
- /* pattern draw functions */
-
- void
- draw_pattern (GtkPreview *preview,
- GPattern *pattern,
- gint width,
- gint height)
- {
- gint pattern_width, pattern_height;
- guchar *mask, *src, *buf, *b;
- gint x, y;
-
- pattern_width = pattern->mask->width;
- pattern_height = pattern->mask->height;
-
- mask = temp_buf_data (pattern->mask);
- buf = g_new (guchar, 3 * width);
- if (pattern->mask->bytes == 1)
- {
- for (y = 0; y < height; y++)
- {
- b = buf;
- src = mask + (pattern_width * (y % pattern_height));
- for (x = 0; x < width ; x++)
- {
- memset (b, src[x % pattern_width], 3);
- b += 3;
- }
- gtk_preview_draw_row (preview, buf, 0, y, width);
- }
- }
- else
- {
- for (y = 0; y < height; y++)
- {
- b = buf;
- src = mask + 3 * (pattern_width * (y % pattern_height));
- for (x = 0; x < width ; x++)
- {
- memcpy (b, src + 3 * (x % pattern_width), 3);
- b += 3;
- }
- gtk_preview_draw_row (preview, buf, 0, y, width);
- }
- }
- g_free(buf);
- }
-
- static void
- gimp_context_preview_draw_pattern_popup (GimpContextPreview *gcp)
- {
- GPattern *pattern;
-
- g_return_if_fail (gcp != NULL && gcp->data != NULL);
-
- pattern = (GPattern*)(gcp->data);
- draw_pattern (GTK_PREVIEW (gcp_popup_preview), pattern,
- gcp->popup_width, gcp->popup_height);
- }
-
- static void
- gimp_context_preview_draw_pattern (GimpContextPreview *gcp)
- {
- GPattern *pattern;
-
- g_return_if_fail (gcp != NULL && gcp->data != NULL);
-
- pattern = (GPattern*)(gcp->data);
- draw_pattern (GTK_PREVIEW (gcp), pattern, gcp->width, gcp->height);
- }
-
-
- /* gradient draw functions */
-
- void
- draw_gradient (GtkPreview *preview,
- gradient_t *gradient,
- gint width,
- gint height)
- {
- guchar *p0, *p1, *even, *odd;
- gint x, y;
- gdouble dx, cur_x;
- gdouble r, g, b, a;
- gdouble c0, c1;
-
- dx = 1.0 / (width - 1);
- cur_x = 0.0;
- p0 = even = g_new (guchar, 3 * width);
- p1 = odd = g_new (guchar, 3 * width);
-
- for (x = 0; x < width; x++)
- {
- gradient_get_color_at (gradient, cur_x, &r, &g, &b, &a);
-
- if ((x / GIMP_CHECK_SIZE_SM) & 1)
- {
- c0 = GIMP_CHECK_LIGHT;
- c1 = GIMP_CHECK_DARK;
- }
- else
- {
- c0 = GIMP_CHECK_DARK;
- c1 = GIMP_CHECK_LIGHT;
- }
-
- *p0++ = (c0 + (r - c0) * a) * 255.0;
- *p0++ = (c0 + (g - c0) * a) * 255.0;
- *p0++ = (c0 + (b - c0) * a) * 255.0;
-
- *p1++ = (c1 + (r - c1) * a) * 255.0;
- *p1++ = (c1 + (g - c1) * a) * 255.0;
- *p1++ = (c1 + (b - c1) * a) * 255.0;
-
- cur_x += dx;
- }
-
- for (y = 0; y < height; y++)
- {
- if ((y / GIMP_CHECK_SIZE_SM) & 1)
- gtk_preview_draw_row (preview, odd, 0, y, width);
- else
- gtk_preview_draw_row (preview, even, 0, y, width);
- }
-
- g_free (odd);
- g_free (even);
- }
-
- static void
- gimp_context_preview_draw_gradient_popup (GimpContextPreview *gcp)
- {
- gradient_t *gradient;
-
- g_return_if_fail (gcp != NULL && gcp->data != NULL);
-
- gradient = (gradient_t*)(gcp->data);
- draw_gradient (GTK_PREVIEW (gcp_popup_preview), gradient,
- gcp->popup_width, gcp->popup_height);
- }
-
- static void
- gimp_context_preview_draw_gradient (GimpContextPreview *gcp)
- {
- gradient_t *gradient;
-
- g_return_if_fail (gcp != NULL && gcp->data != NULL);
-
- gradient = (gradient_t*)(gcp->data);
- draw_gradient (GTK_PREVIEW (gcp), gradient, gcp->width, gcp->height);
- }
-