1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpcanvaspen.c
5 * Copyright (C) 2010 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25
26 #include "libgimpbase/gimpbase.h"
27 #include "libgimpcolor/gimpcolor.h"
28 #include "libgimpmath/gimpmath.h"
29
30 #include "display-types.h"
31
32 #include "core/gimpcontext.h"
33 #include "core/gimpparamspecs.h"
34
35 #include "gimpcanvas-style.h"
36 #include "gimpcanvaspen.h"
37 #include "gimpdisplayshell.h"
38
39
40 enum
41 {
42 PROP_0,
43 PROP_COLOR,
44 PROP_WIDTH
45 };
46
47
48 typedef struct _GimpCanvasPenPrivate GimpCanvasPenPrivate;
49
50 struct _GimpCanvasPenPrivate
51 {
52 GimpRGB color;
53 gint width;
54 };
55
56 #define GET_PRIVATE(pen) \
57 ((GimpCanvasPenPrivate *) gimp_canvas_pen_get_instance_private ((GimpCanvasPen *) (pen)))
58
59
60 /* local function prototypes */
61
62 static void gimp_canvas_pen_set_property (GObject *object,
63 guint property_id,
64 const GValue *value,
65 GParamSpec *pspec);
66 static void gimp_canvas_pen_get_property (GObject *object,
67 guint property_id,
68 GValue *value,
69 GParamSpec *pspec);
70 static cairo_region_t * gimp_canvas_pen_get_extents (GimpCanvasItem *item);
71 static void gimp_canvas_pen_stroke (GimpCanvasItem *item,
72 cairo_t *cr);
73
74
G_DEFINE_TYPE_WITH_PRIVATE(GimpCanvasPen,gimp_canvas_pen,GIMP_TYPE_CANVAS_POLYGON)75 G_DEFINE_TYPE_WITH_PRIVATE (GimpCanvasPen, gimp_canvas_pen,
76 GIMP_TYPE_CANVAS_POLYGON)
77
78 #define parent_class gimp_canvas_pen_parent_class
79
80
81 static void
82 gimp_canvas_pen_class_init (GimpCanvasPenClass *klass)
83 {
84 GObjectClass *object_class = G_OBJECT_CLASS (klass);
85 GimpCanvasItemClass *item_class = GIMP_CANVAS_ITEM_CLASS (klass);
86
87 object_class->set_property = gimp_canvas_pen_set_property;
88 object_class->get_property = gimp_canvas_pen_get_property;
89
90 item_class->get_extents = gimp_canvas_pen_get_extents;
91 item_class->stroke = gimp_canvas_pen_stroke;
92
93 g_object_class_install_property (object_class, PROP_COLOR,
94 gimp_param_spec_rgb ("color", NULL, NULL,
95 FALSE, NULL,
96 GIMP_PARAM_READWRITE));
97
98 g_object_class_install_property (object_class, PROP_WIDTH,
99 g_param_spec_int ("width", NULL, NULL,
100 1, G_MAXINT, 1,
101 GIMP_PARAM_READWRITE));
102 }
103
104 static void
gimp_canvas_pen_init(GimpCanvasPen * pen)105 gimp_canvas_pen_init (GimpCanvasPen *pen)
106 {
107 }
108
109 static void
gimp_canvas_pen_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)110 gimp_canvas_pen_set_property (GObject *object,
111 guint property_id,
112 const GValue *value,
113 GParamSpec *pspec)
114 {
115 GimpCanvasPenPrivate *private = GET_PRIVATE (object);
116
117 switch (property_id)
118 {
119 case PROP_COLOR:
120 gimp_value_get_rgb (value, &private->color);
121 break;
122 case PROP_WIDTH:
123 private->width = g_value_get_int (value);
124 break;
125
126 default:
127 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
128 break;
129 }
130 }
131
132 static void
gimp_canvas_pen_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)133 gimp_canvas_pen_get_property (GObject *object,
134 guint property_id,
135 GValue *value,
136 GParamSpec *pspec)
137 {
138 GimpCanvasPenPrivate *private = GET_PRIVATE (object);
139
140 switch (property_id)
141 {
142 case PROP_COLOR:
143 gimp_value_set_rgb (value, &private->color);
144 break;
145 case PROP_WIDTH:
146 g_value_set_int (value, private->width);
147 break;
148
149 default:
150 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
151 break;
152 }
153 }
154
155 static cairo_region_t *
gimp_canvas_pen_get_extents(GimpCanvasItem * item)156 gimp_canvas_pen_get_extents (GimpCanvasItem *item)
157 {
158 GimpCanvasPenPrivate *private = GET_PRIVATE (item);
159 cairo_region_t *region;
160
161 region = GIMP_CANVAS_ITEM_CLASS (parent_class)->get_extents (item);
162
163 if (region)
164 {
165 cairo_rectangle_int_t rectangle;
166
167 cairo_region_get_extents (region, &rectangle);
168
169 rectangle.x -= ceil (private->width / 2.0);
170 rectangle.y -= ceil (private->width / 2.0);
171 rectangle.width += private->width + 1;
172 rectangle.height += private->width + 1;
173
174 cairo_region_union_rectangle (region, &rectangle);
175 }
176
177 return region;
178 }
179
180 static void
gimp_canvas_pen_stroke(GimpCanvasItem * item,cairo_t * cr)181 gimp_canvas_pen_stroke (GimpCanvasItem *item,
182 cairo_t *cr)
183 {
184 GimpCanvasPenPrivate *private = GET_PRIVATE (item);
185
186 gimp_canvas_set_pen_style (gimp_canvas_item_get_canvas (item), cr,
187 &private->color, private->width);
188 cairo_stroke (cr);
189 }
190
191 GimpCanvasItem *
gimp_canvas_pen_new(GimpDisplayShell * shell,const GimpVector2 * points,gint n_points,GimpContext * context,GimpActiveColor color,gint width)192 gimp_canvas_pen_new (GimpDisplayShell *shell,
193 const GimpVector2 *points,
194 gint n_points,
195 GimpContext *context,
196 GimpActiveColor color,
197 gint width)
198 {
199 GimpCanvasItem *item;
200 GimpArray *array;
201 GimpRGB rgb;
202
203 g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
204 g_return_val_if_fail (points != NULL && n_points > 1, NULL);
205 g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
206
207 array = gimp_array_new ((const guint8 *) points,
208 n_points * sizeof (GimpVector2), TRUE);
209
210 switch (color)
211 {
212 case GIMP_ACTIVE_COLOR_FOREGROUND:
213 gimp_context_get_foreground (context, &rgb);
214 break;
215
216 case GIMP_ACTIVE_COLOR_BACKGROUND:
217 gimp_context_get_background (context, &rgb);
218 break;
219 }
220
221 item = g_object_new (GIMP_TYPE_CANVAS_PEN,
222 "shell", shell,
223 "points", array,
224 "color", &rgb,
225 "width", width,
226 NULL);
227
228 gimp_array_free (array);
229
230 return item;
231 }
232