diff --git a/ChangeLog b/ChangeLog index e16508c3f7..268ec1fa60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2005-08-06 Sven Neumann + + * app/display/gimpcanvas.c (gimp_canvas_set_custom_gc) do not + drop the reference if the same custom GC is being set again. + + * app/display/gimpdisplayshell-draw.[ch] + * app/display/gimpdisplayshell-handlers.c + * app/display/gimpdisplayshell.[ch]: added GC and methods to draw + on the canvas with a solid pen. + + * app/tools/gimpforegroundselectoptions.[ch] + * app/tools/gimpforegroundselecttool.c: draw using the new pen + functions. Scale the stroke width with the display scale. + 2005-08-06 Sven Neumann * app/core/gimppalette-import.c: diff --git a/app/display/gimpcanvas.c b/app/display/gimpcanvas.c index f12369c944..b5b27a8a97 100644 --- a/app/display/gimpcanvas.c +++ b/app/display/gimpcanvas.c @@ -823,13 +823,13 @@ void gimp_canvas_set_custom_gc (GimpCanvas *canvas, GdkGC *gc) { + if (gc) + g_object_ref (gc); + if (canvas->gc[GIMP_CANVAS_STYLE_CUSTOM]) g_object_unref (canvas->gc[GIMP_CANVAS_STYLE_CUSTOM]); canvas->gc[GIMP_CANVAS_STYLE_CUSTOM] = gc; - - if (gc) - g_object_ref (gc); } /** diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index b739c3734d..11cf66fb0f 100644 --- a/app/display/gimpdisplayshell-draw.c +++ b/app/display/gimpdisplayshell-draw.c @@ -23,6 +23,7 @@ #include "display-types.h" #include "core/gimp-utils.h" +#include "core/gimpcontext.h" #include "core/gimpgrid.h" #include "core/gimpimage.h" #include "core/gimpimage-guides.h" @@ -48,6 +49,10 @@ static GdkGC * gimp_display_shell_get_grid_gc (GimpDisplayShell *shell, GimpGrid *grid); +static GdkGC * gimp_display_shell_get_pen_gc (GimpDisplayShell *shell, + GimpContext *context, + GimpActiveColor active, + gint width); /* public functions */ @@ -293,6 +298,42 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell, } } +void +gimp_display_shell_draw_pen (GimpDisplayShell *shell, + const GimpVector2 *points, + gint num_points, + GimpContext *context, + GimpActiveColor color, + gint width) +{ + GimpCanvas *canvas; + GdkGC *gc; + GdkPoint *coords; + gint i; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + g_return_if_fail (GIMP_IS_CONTEXT (context)); + g_return_if_fail (num_points == 0 || points != NULL); + + canvas = GIMP_CANVAS (shell->canvas); + + coords = g_new (GdkPoint, num_points); + + for (i = 0; i < num_points ; i++) + gimp_display_shell_transform_xy (shell, + points[i].x, points[i].y, + &coords[i].x, &coords[i].y, + FALSE); + + gc = gimp_display_shell_get_pen_gc (shell, context, color, width); + + gimp_canvas_set_custom_gc (canvas, gc); + gimp_canvas_draw_lines (canvas, GIMP_CANVAS_STYLE_CUSTOM, coords, num_points); + gimp_canvas_set_custom_gc (canvas, NULL); + + g_free (coords); +} + void gimp_display_shell_draw_sample_point (GimpDisplayShell *shell, GimpSamplePoint *sample_point, @@ -568,10 +609,58 @@ gimp_display_shell_get_grid_gc (GimpDisplayShell *shell, GDK_GC_JOIN_STYLE)); gimp_rgb_get_gdk_color (&grid->fgcolor, &fg); - gimp_rgb_get_gdk_color (&grid->bgcolor, &bg); - gdk_gc_set_rgb_fg_color (shell->grid_gc, &fg); + + gimp_rgb_get_gdk_color (&grid->bgcolor, &bg); gdk_gc_set_rgb_bg_color (shell->grid_gc, &bg); return shell->grid_gc; } + +static GdkGC * +gimp_display_shell_get_pen_gc (GimpDisplayShell *shell, + GimpContext *context, + GimpActiveColor active, + gint width) +{ + GdkGCValues values; + GimpRGB rgb; + GdkColor color; + + if (shell->pen_gc) + return shell->pen_gc; + + values.line_width = MAX (1, width); + values.line_style = GDK_LINE_SOLID; + values.cap_style = GDK_CAP_ROUND; + values.join_style = GDK_JOIN_MITER; + + shell->pen_gc = gdk_gc_new_with_values (shell->canvas->window, + &values, (GDK_GC_LINE_WIDTH | + GDK_GC_LINE_STYLE | + GDK_GC_CAP_STYLE | + GDK_GC_JOIN_STYLE)); + + switch (active) + { + case GIMP_ACTIVE_COLOR_FOREGROUND: + gimp_context_get_foreground (context, &rgb); + break; + + case GIMP_ACTIVE_COLOR_BACKGROUND: + gimp_context_get_background (context, &rgb); + break; + } + + gimp_rgb_get_gdk_color (&rgb, &color); + gdk_gc_set_rgb_fg_color (shell->pen_gc, &color); + + g_object_add_weak_pointer (G_OBJECT (shell->pen_gc), + (gpointer *) &shell->pen_gc); + + g_signal_connect_object (context, "notify", + G_CALLBACK (g_object_unref), + shell->pen_gc, G_CONNECT_SWAPPED); + + return shell->pen_gc; +} diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h index 0ae1496700..d99fb15150 100644 --- a/app/display/gimpdisplayshell-draw.h +++ b/app/display/gimpdisplayshell-draw.h @@ -26,6 +26,12 @@ void gimp_display_shell_draw_guide (GimpDisplayShell *shell, void gimp_display_shell_draw_guides (GimpDisplayShell *shell); void gimp_display_shell_draw_grid (GimpDisplayShell *shell, const GdkRectangle *area); +void gimp_display_shell_draw_pen (GimpDisplayShell *shell, + const GimpVector2 *points, + gint num_points, + GimpContext *context, + GimpActiveColor color, + gint width); void gimp_display_shell_draw_sample_point (GimpDisplayShell *shell, GimpSamplePoint *sample_point, gboolean active); diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c index 45a57e222f..3ac366872d 100644 --- a/app/display/gimpdisplayshell-handlers.c +++ b/app/display/gimpdisplayshell-handlers.c @@ -273,6 +273,12 @@ gimp_display_shell_disconnect (GimpDisplayShell *shell) shell->grid_gc = NULL; } + if (shell->pen_gc) + { + g_object_unref (shell->pen_gc); + shell->pen_gc = NULL; + } + g_signal_handlers_disconnect_by_func (gimage->gimp->config, gimp_display_shell_ants_speed_notify_handler, shell); diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 40f1cc31bf..8aa9153310 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -254,6 +254,7 @@ gimp_display_shell_init (GimpDisplayShell *shell) shell->canvas = NULL; shell->grid_gc = NULL; + shell->pen_gc = NULL; shell->hsbdata = NULL; shell->vsbdata = NULL; @@ -271,9 +272,9 @@ gimp_display_shell_init (GimpDisplayShell *shell) shell->menubar = NULL; shell->statusbar = NULL; - shell->render_buf = g_malloc (GIMP_RENDER_BUF_WIDTH * - GIMP_RENDER_BUF_HEIGHT * - 3); + shell->render_buf = g_new (guchar, + GIMP_RENDER_BUF_WIDTH * + GIMP_RENDER_BUF_HEIGHT * 3); shell->title_idle_id = 0; diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h index 8b1d5a9c9e..60db12d5b3 100644 --- a/app/display/gimpdisplayshell.h +++ b/app/display/gimpdisplayshell.h @@ -96,6 +96,7 @@ struct _GimpDisplayShell GtkWidget *canvas; /* GimpCanvas widget */ GdkGC *grid_gc; /* GC for grid drawing */ + GdkGC *pen_gc; /* GC for felt pen drawing */ GtkAdjustment *hsbdata; /* adjustments */ GtkAdjustment *vsbdata; diff --git a/app/tools/gimpforegroundselectoptions.c b/app/tools/gimpforegroundselectoptions.c index 4044d450b7..94ca8268ce 100644 --- a/app/tools/gimpforegroundselectoptions.c +++ b/app/tools/gimpforegroundselectoptions.c @@ -93,10 +93,10 @@ gimp_foreground_select_options_class_init (GimpForegroundSelectOptionsClass *kla "background", NULL, FALSE, 0); - GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_STROKE_WIDTH, - "stroke-width", NULL, - 0.0, 2000.0, 6.0, - 0); + GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_STROKE_WIDTH, + "stroke-width", NULL, + 1, 100, 6, + 0); } static void @@ -113,7 +113,7 @@ gimp_foreground_select_options_set_property (GObject *object, options->background = g_value_get_boolean (value); break; case PROP_STROKE_WIDTH: - options->stroke_width = g_value_get_double (value); + options->stroke_width = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -135,7 +135,7 @@ gimp_foreground_select_options_get_property (GObject *object, g_value_set_boolean (value, options->background); break; case PROP_STROKE_WIDTH: - g_value_set_double (value, options->stroke_width); + g_value_set_int (value, options->stroke_width); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); diff --git a/app/tools/gimpforegroundselectoptions.h b/app/tools/gimpforegroundselectoptions.h index 941c9d384d..6d919a2b6c 100644 --- a/app/tools/gimpforegroundselectoptions.h +++ b/app/tools/gimpforegroundselectoptions.h @@ -39,7 +39,7 @@ struct _GimpForegroundSelectOptions GimpSelectionOptions parent_instance; gboolean background; - gdouble stroke_width; + gint stroke_width; }; diff --git a/app/tools/gimpforegroundselecttool.c b/app/tools/gimpforegroundselecttool.c index abd9c7b7d5..ac337aaa6d 100644 --- a/app/tools/gimpforegroundselecttool.c +++ b/app/tools/gimpforegroundselecttool.c @@ -42,6 +42,7 @@ #include "display/gimpdisplay.h" #include "display/gimpdisplayshell.h" +#include "display/gimpdisplayshell-draw.h" #include "gimpforegroundselecttool.h" #include "gimpforegroundselectoptions.h" @@ -52,7 +53,7 @@ typedef struct { - gdouble width; + gint width; gboolean background; gint num_points; GimpVector2 *points; @@ -105,6 +106,7 @@ static void gimp_foreground_select_tool_apply (GimpForegroundSelectTool *fg GimpDisplay *gdisp); static void gimp_foreground_select_tool_stroke (GimpChannel *mask, + GimpDisplay *gdisp, FgSelectStroke *stroke); static void gimp_foreground_select_tool_push_stroke (GimpForegroundSelectTool *fg_select, @@ -123,7 +125,7 @@ gimp_foreground_select_tool_register (GimpToolRegisterCallback callback, (* callback) (GIMP_TYPE_FOREGROUND_SELECT_TOOL, GIMP_TYPE_FOREGROUND_SELECT_OPTIONS, gimp_foreground_select_options_gui, - 0, + GIMP_CONTEXT_FOREGROUND_MASK | GIMP_CONTEXT_BACKGROUND_MASK, "gimp-foreground-select-tool", _("Foreground Select"), _("Extract foreground using SIOX algorithm"), @@ -443,7 +445,7 @@ gimp_foreground_select_tool_motion (GimpTool *tool, GimpVector2, fg_select->stroke->len - 1); - if (last->x != coords->x || last->y != coords->y) + if (last->x != (gint) coords->x || last->y != (gint) coords->y) { GimpVector2 point = gimp_vector2_new (coords->x, coords->y); @@ -468,10 +470,19 @@ gimp_foreground_select_tool_draw (GimpDrawTool *draw_tool) if (fg_select->stroke) { - const gdouble *points = (const gdouble *) fg_select->stroke->data; + GimpTool *tool = GIMP_TOOL (draw_tool); + GimpForegroundSelectOptions *options; - gimp_draw_tool_draw_lines (draw_tool, - points, fg_select->stroke->len, FALSE, FALSE); + options = GIMP_FOREGROUND_SELECT_OPTIONS (tool->tool_info->tool_options); + + gimp_display_shell_draw_pen (GIMP_DISPLAY_SHELL (draw_tool->gdisp->shell), + (const GimpVector2 *)fg_select->stroke->data, + fg_select->stroke->len, + GIMP_CONTEXT (options), + (options->background ? + GIMP_ACTIVE_COLOR_BACKGROUND : + GIMP_ACTIVE_COLOR_FOREGROUND), + options->stroke_width); } if (! fg_select->mask) @@ -516,16 +527,16 @@ gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel, width = x2 - x; height = y2 - y; + /* apply foreground and background markers */ + for (list = fg_select->strokes; list; list = list->next) + gimp_foreground_select_tool_stroke (mask, gdisp, list->data); + /* restrict working area to double the size of the bounding box */ x = MAX (0, x - width / 2); y = MAX (0, y - height / 2); width = MIN (width * 2, gimp_item_width (GIMP_ITEM (mask)) - x); height = MIN (height * 2, gimp_item_height (GIMP_ITEM (mask)) - y); - /* apply foreground and background markers */ - for (list = fg_select->strokes; list; list = list->next) - gimp_foreground_select_tool_stroke (mask, list->data); - gimp_drawable_foreground_extract_rect (drawable, GIMP_FOREGROUND_EXTRACT_SIOX, GIMP_DRAWABLE (mask), @@ -615,14 +626,16 @@ gimp_foreground_select_tool_apply (GimpForegroundSelectTool *fg_select, static void gimp_foreground_select_tool_stroke (GimpChannel *mask, + GimpDisplay *gdisp, FgSelectStroke *stroke) { - GimpScanConvert *scan_convert = gimp_scan_convert_new (); - GimpItem *item = GIMP_ITEM (mask); - GimpChannel *channel = gimp_channel_new (gimp_item_get_image (item), - gimp_item_width (item), - gimp_item_height (item), - "tmp", NULL); + GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (gdisp->shell); + GimpScanConvert *scan_convert = gimp_scan_convert_new (); + GimpItem *item = GIMP_ITEM (mask); + GimpChannel *channel = gimp_channel_new (gimp_item_get_image (item), + gimp_item_width (item), + gimp_item_height (item), + "tmp", NULL); /* FIXME: We should be able to get away w/o a temporary drawable * by doing some changes to GimpScanConvert. @@ -631,7 +644,7 @@ gimp_foreground_select_tool_stroke (GimpChannel *mask, gimp_scan_convert_add_polyline (scan_convert, stroke->num_points, stroke->points, FALSE); gimp_scan_convert_stroke (scan_convert, - stroke->width, + SCALEFACTOR_Y (shell) * stroke->width, GIMP_JOIN_MITER, GIMP_CAP_ROUND, 10.0, 0.0, NULL); gimp_scan_convert_render (scan_convert,