1 /*
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * This is a plug-in for GIMP.
5 *
6 * Generates images containing vector type drawings.
7 *
8 * Copyright (C) 1997 Andy Thomas alt@picnic.demon.co.uk
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 *
23 */
24
25 #include "config.h"
26
27 #include <libgimp/gimp.h>
28 #include <libgimp/gimpui.h>
29
30 #include "gfig.h"
31 #include "gfig-dobject.h"
32 #include "gfig-rectangle.h"
33
34 #include "libgimp/stdplugins-intl.h"
35
36 static void d_draw_rectangle (GfigObject *obj,
37 cairo_t *cr);
38 static void d_paint_rectangle (GfigObject *obj);
39 static GfigObject *d_copy_rectangle (GfigObject *obj);
40
41 static void d_update_rectangle (GdkPoint *pnt);
42
43 static void
d_draw_rectangle(GfigObject * obj,cairo_t * cr)44 d_draw_rectangle (GfigObject *obj,
45 cairo_t *cr)
46 {
47 DobjPoints *first_pnt;
48 DobjPoints *second_pnt;
49 gint xmin, ymin;
50 gint xmax, ymax;
51
52 first_pnt = obj->points;
53
54 if (!first_pnt)
55 return; /* End-of-line */
56
57 draw_sqr (&first_pnt->pnt, obj == gfig_context->selected_obj, cr);
58
59 second_pnt = first_pnt->next;
60
61 if (!second_pnt)
62 return;
63
64 if (obj == obj_creating)
65 draw_circle (&second_pnt->pnt, TRUE, cr);
66 else
67 draw_sqr (&second_pnt->pnt, obj == gfig_context->selected_obj, cr);
68
69 xmin = MIN (gfig_scale_x (first_pnt->pnt.x),
70 gfig_scale_x (second_pnt->pnt.x));
71 ymin = MIN (gfig_scale_y (first_pnt->pnt.y),
72 gfig_scale_y (second_pnt->pnt.y));
73 xmax = MAX (gfig_scale_x (first_pnt->pnt.x),
74 gfig_scale_x (second_pnt->pnt.x));
75 ymax = MAX (gfig_scale_y (first_pnt->pnt.y),
76 gfig_scale_y (second_pnt->pnt.y));
77
78 cairo_rectangle (cr, xmin + .5, ymin + .5, xmax - xmin, ymax - ymin);
79 draw_item (cr, FALSE);
80 }
81
82 static void
d_paint_rectangle(GfigObject * obj)83 d_paint_rectangle (GfigObject *obj)
84 {
85 DobjPoints *first_pnt;
86 DobjPoints *second_pnt;
87 gdouble dpnts[4];
88
89 g_assert (obj != NULL);
90
91 /* Drawing rectangles is hard .
92 * 1) select rectangle
93 * 2) stroke it
94 */
95 first_pnt = obj->points;
96
97 if (!first_pnt)
98 return; /* End-of-line */
99
100 second_pnt = first_pnt->next;
101
102 if (!second_pnt)
103 {
104 g_error ("Internal error - rectangle no second pnt");
105 }
106
107 dpnts[0] = (gdouble) MIN (first_pnt->pnt.x, second_pnt->pnt.x);
108 dpnts[1] = (gdouble) MIN (first_pnt->pnt.y, second_pnt->pnt.y);
109 dpnts[2] = (gdouble) MAX (first_pnt->pnt.x, second_pnt->pnt.x);
110 dpnts[3] = (gdouble) MAX (first_pnt->pnt.y, second_pnt->pnt.y);
111
112 /* Scale before drawing */
113 if (selvals.scaletoimage)
114 scale_to_original_xy (&dpnts[0], 2);
115 else
116 scale_to_xy (&dpnts[0], 2);
117
118 if (gfig_context_get_current_style ()->fill_type != FILL_NONE)
119 {
120 gimp_context_push ();
121 gimp_context_set_feather (selopt.feather);
122 gimp_context_set_feather_radius (selopt.feather_radius, selopt.feather_radius);
123 gimp_image_select_rectangle (gfig_context->image_id,
124 selopt.type,
125 dpnts[0], dpnts[1],
126 dpnts[2] - dpnts[0],
127 dpnts[3] - dpnts[1]);
128 gimp_context_pop ();
129
130 paint_layer_fill (dpnts[0], dpnts[1], dpnts[2], dpnts[3]);
131 gimp_selection_none (gfig_context->image_id);
132 }
133
134 if (obj->style.paint_type == PAINT_BRUSH_TYPE)
135 {
136 gdouble line_pnts[] = { dpnts[0], dpnts[1], dpnts[2], dpnts[1],
137 dpnts[2], dpnts[3], dpnts[0], dpnts[3],
138 dpnts[0], dpnts[1] };
139
140 gfig_paint (selvals.brshtype, gfig_context->drawable_id, 10, line_pnts);
141 }
142 }
143
144 static GfigObject *
d_copy_rectangle(GfigObject * obj)145 d_copy_rectangle (GfigObject * obj)
146 {
147 GfigObject *new_rectangle;
148
149 g_assert (obj->type == RECTANGLE);
150
151 new_rectangle = d_new_object (RECTANGLE,
152 obj->points->pnt.x, obj->points->pnt.y);
153 new_rectangle->points->next = d_copy_dobjpoints (obj->points->next);
154
155 return new_rectangle;
156 }
157
158 void
d_rectangle_object_class_init(void)159 d_rectangle_object_class_init (void)
160 {
161 GfigObjectClass *class = &dobj_class[RECTANGLE];
162
163 class->type = RECTANGLE;
164 class->name = "RECTANGLE";
165 class->drawfunc = d_draw_rectangle;
166 class->paintfunc = d_paint_rectangle;
167 class->copyfunc = d_copy_rectangle;
168 class->update = d_update_rectangle;
169 }
170
171 static void
d_update_rectangle(GdkPoint * pnt)172 d_update_rectangle (GdkPoint *pnt)
173 {
174 DobjPoints *first_pnt;
175 DobjPoints *second_pnt;
176
177 first_pnt = obj_creating->points;
178
179 if (!first_pnt)
180 return; /* No points */
181
182 if ((second_pnt = first_pnt->next))
183 {
184 second_pnt->pnt.x = pnt->x;
185 second_pnt->pnt.y = pnt->y;
186 }
187 else
188 {
189 second_pnt = new_dobjpoint (pnt->x, pnt->y);
190 first_pnt->next = second_pnt;
191 }
192 }
193
194 void
d_rectangle_start(GdkPoint * pnt,gboolean shift_down)195 d_rectangle_start (GdkPoint *pnt,
196 gboolean shift_down)
197 {
198 obj_creating = d_new_object (RECTANGLE, pnt->x, pnt->y);
199 }
200
201 void
d_rectangle_end(GdkPoint * pnt,gboolean shift_down)202 d_rectangle_end (GdkPoint *pnt,
203 gboolean shift_down)
204 {
205 /* Under control point */
206 if (!obj_creating->points->next)
207 {
208 /* No circle created */
209 free_one_obj (obj_creating);
210 }
211 else
212 {
213 add_to_all_obj (gfig_context->current_obj, obj_creating);
214 }
215
216 obj_creating = NULL;
217 }
218
219