diff --git a/app/display/Makefile.am b/app/display/Makefile.am index 96526274ba..fa22ef9236 100644 --- a/app/display/Makefile.am +++ b/app/display/Makefile.am @@ -41,6 +41,8 @@ libappdisplay_a_sources = \ gimpcanvaslayerboundary.h \ gimpcanvasline.c \ gimpcanvasline.h \ + gimpcanvaspen.c \ + gimpcanvaspen.h \ gimpcanvaspolygon.c \ gimpcanvaspolygon.h \ gimpcanvasproxygroup.c \ diff --git a/app/display/gimpcanvaspen.c b/app/display/gimpcanvaspen.c new file mode 100644 index 0000000000..d77abaad5c --- /dev/null +++ b/app/display/gimpcanvaspen.c @@ -0,0 +1,237 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcanvaspen.c + * Copyright (C) 2010 Michael Natterer + * + * 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 3 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, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" + +#include "display-types.h" + +#include "core/gimpcontext.h" +#include "core/gimpparamspecs.h" + +#include "gimpcanvaspen.h" +#include "gimpdisplayshell.h" +#include "gimpdisplayshell-style.h" +#include "gimpdisplayshell-transform.h" + + +enum +{ + PROP_0, + PROP_COLOR, + PROP_WIDTH +}; + + +typedef struct _GimpCanvasPenPrivate GimpCanvasPenPrivate; + +struct _GimpCanvasPenPrivate +{ + GimpRGB color; + gint width; +}; + +#define GET_PRIVATE(pen) \ + G_TYPE_INSTANCE_GET_PRIVATE (pen, \ + GIMP_TYPE_CANVAS_PEN, \ + GimpCanvasPenPrivate) + + +/* local function prototypes */ + +static void gimp_canvas_pen_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_canvas_pen_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static GdkRegion * gimp_canvas_pen_get_extents (GimpCanvasItem *item, + GimpDisplayShell *shell); +static void gimp_canvas_pen_stroke (GimpCanvasItem *item, + GimpDisplayShell *shell, + cairo_t *cr); + + +G_DEFINE_TYPE (GimpCanvasPen, gimp_canvas_pen, + GIMP_TYPE_CANVAS_POLYGON) + +#define parent_class gimp_canvas_pen_parent_class + + +static void +gimp_canvas_pen_class_init (GimpCanvasPenClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpCanvasItemClass *item_class = GIMP_CANVAS_ITEM_CLASS (klass); + + object_class->set_property = gimp_canvas_pen_set_property; + object_class->get_property = gimp_canvas_pen_get_property; + + item_class->get_extents = gimp_canvas_pen_get_extents; + item_class->stroke = gimp_canvas_pen_stroke; + + g_object_class_install_property (object_class, PROP_COLOR, + gimp_param_spec_rgb ("color", NULL, NULL, + FALSE, NULL, + GIMP_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_WIDTH, + g_param_spec_int ("width", NULL, NULL, + 1, G_MAXINT, 1, + GIMP_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (GimpCanvasPenPrivate)); +} + +static void +gimp_canvas_pen_init (GimpCanvasPen *pen) +{ +} + +static void +gimp_canvas_pen_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpCanvasPenPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_COLOR: + gimp_value_get_rgb (value, &private->color); + break; + case PROP_WIDTH: + private->width = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_canvas_pen_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpCanvasPenPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_COLOR: + gimp_value_set_rgb (value, &private->color); + break; + case PROP_WIDTH: + g_value_set_int (value, private->width); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static GdkRegion * +gimp_canvas_pen_get_extents (GimpCanvasItem *item, + GimpDisplayShell *shell) +{ + GimpCanvasPenPrivate *private = GET_PRIVATE (item); + GdkRegion *region; + + region = GIMP_CANVAS_ITEM_CLASS (parent_class)->get_extents (item, shell); + + if (region) + { + GdkRectangle rectangle; + + gdk_region_get_clipbox (region, &rectangle); + + rectangle.x -= ceil (private->width / 2.0); + rectangle.y -= ceil (private->width / 2.0); + rectangle.width += private->width + 1; + rectangle.height += private->width + 1; + } + + return region; +} + +static void +gimp_canvas_pen_stroke (GimpCanvasItem *item, + GimpDisplayShell *shell, + cairo_t *cr) +{ + GimpCanvasPenPrivate *private = GET_PRIVATE (item); + + gimp_display_shell_set_pen_style (shell, cr, &private->color, private->width); + cairo_stroke (cr); +} + +GimpCanvasItem * +gimp_canvas_pen_new (GimpDisplayShell *shell, + const GimpVector2 *points, + gint n_points, + GimpContext *context, + GimpActiveColor color, + gint width) +{ + GimpCanvasItem *item; + GimpArray *array; + GimpRGB rgb; + + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL); + g_return_val_if_fail (points != NULL && n_points > 1, NULL); + g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + + array = gimp_array_new ((const guint8 *) points, + n_points * sizeof (GimpVector2), TRUE); + + switch (color) + { + case GIMP_ACTIVE_COLOR_FOREGROUND: + gimp_context_get_foreground (context, &rgb); + break; + + case GIMP_ACTIVE_COLOR_BACKGROUND: + gimp_context_get_background (context, &rgb); + break; + } + + item = g_object_new (GIMP_TYPE_CANVAS_PEN, + "shell", shell, + "points", array, + "color", &rgb, + "width", width, + NULL); + + gimp_array_free (array); + + return item; +} diff --git a/app/display/gimpcanvaspen.h b/app/display/gimpcanvaspen.h new file mode 100644 index 0000000000..251fc68892 --- /dev/null +++ b/app/display/gimpcanvaspen.h @@ -0,0 +1,60 @@ +/* GIMP - The GNU Image Manipulation Program Copyright (C) 1995 + * Spencer Kimball and Peter Mattis + * + * gimpcanvaspen.h + * Copyright (C) 2010 Michael Natterer + * + * 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 3 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, see . + */ + +#ifndef __GIMP_CANVAS_PEN_H__ +#define __GIMP_CANVAS_PEN_H__ + + +#include "gimpcanvaspolygon.h" + + +#define GIMP_TYPE_CANVAS_PEN (gimp_canvas_pen_get_type ()) +#define GIMP_CANVAS_PEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CANVAS_PEN, GimpCanvasPen)) +#define GIMP_CANVAS_PEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CANVAS_PEN, GimpCanvasPenClass)) +#define GIMP_IS_CANVAS_PEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CANVAS_PEN)) +#define GIMP_IS_CANVAS_PEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CANVAS_PEN)) +#define GIMP_CANVAS_PEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CANVAS_PEN, GimpCanvasPenClass)) + + +typedef struct _GimpCanvasPen GimpCanvasPen; +typedef struct _GimpCanvasPenClass GimpCanvasPenClass; + +struct _GimpCanvasPen +{ + GimpCanvasPolygon parent_instance; +}; + +struct _GimpCanvasPenClass +{ + GimpCanvasPolygonClass parent_class; +}; + + +GType gimp_canvas_pen_get_type (void) G_GNUC_CONST; + +GimpCanvasItem * gimp_canvas_pen_new (GimpDisplayShell *shell, + const GimpVector2 *points, + gint n_points, + GimpContext *context, + GimpActiveColor color, + gint width); + + +#endif /* __GIMP_CANVAS_PEN_H__ */ diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index 107d0e832c..99279b6fb8 100644 --- a/app/display/gimpdisplayshell-draw.c +++ b/app/display/gimpdisplayshell-draw.c @@ -29,7 +29,6 @@ #include "base/tile-manager.h" -#include "core/gimpcontext.h" #include "core/gimpdrawable.h" #include "core/gimpimage.h" #include "core/gimpprojection.h" @@ -118,50 +117,6 @@ gimp_display_shell_draw_get_scaled_image_size_for_scale (GimpDisplayShell *shell if (h) *h = PROJ_ROUND (level_height * (scale_y * (1 << level))); } -void -gimp_display_shell_draw_pen (GimpDisplayShell *shell, - cairo_t *cr, - const GimpVector2 *points, - gint n_points, - GimpContext *context, - GimpActiveColor color, - gint width) -{ - gint i; - gint x, y; - - g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); - g_return_if_fail (cr != NULL); - g_return_if_fail (GIMP_IS_CONTEXT (context)); - g_return_if_fail (n_points == 0 || points != NULL); - - if (n_points == 0) - return; - - gimp_display_shell_set_pen_style (shell, cr, context, color, width); - cairo_translate (cr, 0.5, 0.5); - - gimp_display_shell_transform_xy (shell, - points[0].x, points[0].y, - &x, &y); - - cairo_move_to (cr, x, y); - - for (i = 1; i < n_points; i++) - { - gimp_display_shell_transform_xy (shell, - points[i].x, points[i].y, - &x, &y); - - cairo_line_to (cr, x, y); - } - - if (i == 1) - cairo_line_to (cr, x, y); - - cairo_stroke (cr); -} - void gimp_display_shell_draw_selection_out (GimpDisplayShell *shell, cairo_t *cr, diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h index ef43e94663..876242db4f 100644 --- a/app/display/gimpdisplayshell-draw.h +++ b/app/display/gimpdisplayshell-draw.h @@ -28,13 +28,6 @@ void gimp_display_shell_draw_get_scaled_image_size_for_scale gint *w, gint *h); -void gimp_display_shell_draw_pen (GimpDisplayShell *shell, - cairo_t *cr, - const GimpVector2 *points, - gint n_points, - GimpContext *context, - GimpActiveColor color, - gint width); void gimp_display_shell_draw_selection_out (GimpDisplayShell *shell, cairo_t *cr, GdkSegment *segs, @@ -43,8 +36,10 @@ void gimp_display_shell_draw_selection_in (GimpDisplayShell *shell, cairo_t *cr, cairo_pattern_t *mask, gint index); + void gimp_display_shell_draw_vectors (GimpDisplayShell *shell, cairo_t *cr); + void gimp_display_shell_draw_image (GimpDisplayShell *shell, cairo_t *cr, gint x, diff --git a/app/display/gimpdisplayshell-style.c b/app/display/gimpdisplayshell-style.c index 4983fc839a..4220bc6c32 100644 --- a/app/display/gimpdisplayshell-style.c +++ b/app/display/gimpdisplayshell-style.c @@ -28,7 +28,6 @@ #include "display-types.h" -#include "core/gimpcontext.h" #include "core/gimpgrid.h" #include "core/gimplayer.h" #include "core/gimplayermask.h" @@ -174,33 +173,19 @@ gimp_display_shell_set_grid_style (GimpDisplayShell *shell, void gimp_display_shell_set_pen_style (GimpDisplayShell *shell, cairo_t *cr, - GimpContext *context, - GimpActiveColor active, + const GimpRGB *color, gint width) { - GimpRGB rgb; - g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (cr != NULL); - g_return_if_fail (GIMP_IS_CONTEXT (context)); + g_return_if_fail (color != NULL); cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width (cr, width); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - 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; - } - - cairo_set_source_rgb (cr, rgb.r, rgb.g, rgb.b); + gimp_cairo_set_source_rgb (cr, color); } void diff --git a/app/display/gimpdisplayshell-style.h b/app/display/gimpdisplayshell-style.h index 1b6431f91e..a8ba939347 100644 --- a/app/display/gimpdisplayshell-style.h +++ b/app/display/gimpdisplayshell-style.h @@ -33,8 +33,7 @@ void gimp_display_shell_set_grid_style (GimpDisplayShell *shell, GimpGrid *grid); void gimp_display_shell_set_pen_style (GimpDisplayShell *shell, cairo_t *cr, - GimpContext *context, - GimpActiveColor active, + const GimpRGB *color, gint width); void gimp_display_shell_set_layer_style (GimpDisplayShell *shell, cairo_t *cr, diff --git a/app/tools/gimpdrawtool.c b/app/tools/gimpdrawtool.c index b255a2ca02..893284b719 100644 --- a/app/tools/gimpdrawtool.c +++ b/app/tools/gimpdrawtool.c @@ -40,6 +40,7 @@ #include "display/gimpcanvasguide.h" #include "display/gimpcanvashandle.h" #include "display/gimpcanvasline.h" +#include "display/gimpcanvaspen.h" #include "display/gimpcanvaspolygon.h" #include "display/gimpcanvasrectangle.h" #include "display/gimpcanvassamplepoint.h" @@ -652,6 +653,30 @@ gimp_draw_tool_add_strokes (GimpDrawTool *draw_tool, return item; } +GimpCanvasItem * +gimp_draw_tool_add_pen (GimpDrawTool *draw_tool, + const GimpVector2 *points, + gint n_points, + GimpContext *context, + GimpActiveColor color, + gint width) +{ + GimpCanvasItem *item; + + g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL); + + if (points == NULL || n_points < 2) + return NULL; + + item = gimp_canvas_pen_new (gimp_display_get_shell (draw_tool->display), + points, n_points, context, color, width); + + gimp_draw_tool_add_item (draw_tool, item); + g_object_unref (item); + + return item; +} + /** * gimp_draw_tool_add_boundary: * @draw_tool: a #GimpDrawTool diff --git a/app/tools/gimpdrawtool.h b/app/tools/gimpdrawtool.h index c931035d28..433ddbedb0 100644 --- a/app/tools/gimpdrawtool.h +++ b/app/tools/gimpdrawtool.h @@ -131,6 +131,7 @@ GimpCanvasItem * gimp_draw_tool_add_corner (GimpDrawTool *draw_too gint width, gint height, GtkAnchorType anchor); + GimpCanvasItem * gimp_draw_tool_add_lines (GimpDrawTool *draw_tool, const GimpVector2 *points, gint n_points, @@ -141,6 +142,13 @@ GimpCanvasItem * gimp_draw_tool_add_strokes (GimpDrawTool *draw_too gint n_points, gboolean filled); +GimpCanvasItem * gimp_draw_tool_add_pen (GimpDrawTool *draw_tool, + const GimpVector2 *points, + gint n_points, + GimpContext *context, + GimpActiveColor color, + gint width); + GimpCanvasItem * gimp_draw_tool_add_boundary (GimpDrawTool *draw_tool, const BoundSeg *bound_segs, gint n_bound_segs, diff --git a/app/tools/gimpforegroundselecttool.c b/app/tools/gimpforegroundselecttool.c index 7236c3fdcf..71b3915267 100644 --- a/app/tools/gimpforegroundselecttool.c +++ b/app/tools/gimpforegroundselecttool.c @@ -44,7 +44,6 @@ #include "display/gimpdisplay.h" #include "display/gimpdisplayshell.h" -#include "display/gimpdisplayshell-draw.h" #include "gimpforegroundselecttool.h" #include "gimpforegroundselectoptions.h" @@ -571,18 +570,14 @@ gimp_foreground_select_tool_draw (GimpDrawTool *draw_tool) if (fg_select->stroke) { - GimpDisplayShell *shell = gimp_display_get_shell (draw_tool->display); - cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (shell->canvas)); - gimp_display_shell_draw_pen (gimp_display_get_shell (draw_tool->display), - cr, - (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); - cairo_destroy (cr); + gimp_draw_tool_add_pen (draw_tool, + (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)