app/display/gimpcanvas.c (gimp_canvas_set_custom_gc) do not drop the

2005-08-06  Sven Neumann  <sven@gimp.org>

	* 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.
This commit is contained in:
Sven Neumann 2005-08-06 11:18:26 +00:00 committed by Sven Neumann
parent 90d861bec2
commit d89f04d500
10 changed files with 162 additions and 32 deletions

View File

@ -1,3 +1,17 @@
2005-08-06 Sven Neumann <sven@gimp.org>
* 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 <sven@gimp.org>
* app/core/gimppalette-import.c:

View File

@ -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);
}
/**

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -39,7 +39,7 @@ struct _GimpForegroundSelectOptions
GimpSelectionOptions parent_instance;
gboolean background;
gdouble stroke_width;
gint stroke_width;
};

View File

@ -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,