1 /* $Id: freehand.c,v 1.3 2004/12/25 04:41:58 meffie Exp $
2 *
3 * GNU Paint
4 * Copyright 2000-2003, 2007 Li-Cheng (Andy) Tai
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied
13 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "freehand.h"
25 #include "debug.h"
26
27 typedef struct _gpaint_closed_freehand
28 {
29 gpaint_tool tool;
30 gpaint_point last;
31 gpaint_point anchor;
32 gpaint_point_array *points;
33 gboolean fill;
34 } gpaint_closed_freehand;
35
36 #define GPAINT_CFH(tool) ((gpaint_closed_freehand*)(tool))
37
38
39 static void freehand_destroy(gpaint_tool *tool);
40 static void freehand_select(gpaint_tool *tool);
41 static void freehand_deselect(gpaint_tool *tool);
42 static gboolean freehand_attribute(gpaint_tool *tool, gpaint_attribute attribute, gpointer data);
43 static void freehand_draw_line(gpaint_tool* tool, int x, int y);
44 static void freehand_button_release(gpaint_tool *tool, int x, int y);
45
46 static void freehand_button_press(gpaint_tool* tool, int x, int y);
47 static void freehand_button_release(gpaint_tool *tool, int x, int y);
48 static void freehand_fill_area(gpaint_drawing *drawing, gpaint_point_array *point);
49
50
51
52 /*
53 * Create closed freehand drawing tool.
54 */
closed_freehand_create(const char * name)55 gpaint_tool *closed_freehand_create(const char *name)
56 {
57 gpaint_closed_freehand *cfh = g_new0(gpaint_closed_freehand, 1);
58 g_assert(cfh);
59
60 GPAINT_TOOL(cfh)->name = name;
61 GPAINT_TOOL(cfh)->cursor = gdk_cursor_new(GDK_PENCIL);
62 GPAINT_TOOL(cfh)->destroy = freehand_destroy;
63 GPAINT_TOOL(cfh)->select = freehand_select;
64 GPAINT_TOOL(cfh)->deselect = freehand_deselect;
65 GPAINT_TOOL(cfh)->attribute = freehand_attribute;
66 GPAINT_TOOL(cfh)->button_press = freehand_button_press;
67 GPAINT_TOOL(cfh)->motion = freehand_draw_line;
68 GPAINT_TOOL(cfh)->button_release = freehand_button_release;
69
70 cfh->points = point_array_new();
71 return GPAINT_TOOL(cfh);
72 }
73
74 static void
freehand_destroy(gpaint_tool * tool)75 freehand_destroy(gpaint_tool *tool)
76 {
77 debug_fn();
78 point_array_delete(GPAINT_CFH(tool)->points);
79 gdk_cursor_destroy(tool->cursor);
80 g_free(tool);
81 }
82
83 static void
freehand_select(gpaint_tool * tool)84 freehand_select(gpaint_tool *tool)
85 {
86 debug_fn();
87 }
88
89 static void
freehand_deselect(gpaint_tool * tool)90 freehand_deselect(gpaint_tool *tool)
91 {
92 gpaint_closed_freehand *pen = GPAINT_CFH(tool);
93 debug_fn();
94 clear_point(&pen->last);
95 point_array_remove_all(pen->points);
96 }
97
98 static gboolean
freehand_attribute(gpaint_tool * tool,gpaint_attribute attribute,gpointer data)99 freehand_attribute(gpaint_tool *tool, gpaint_attribute attribute, gpointer data)
100 {
101 if (attribute==GpaintFillShape)
102 {
103 GPAINT_CFH(tool)->fill = *((gboolean*)data);
104 return TRUE;
105 }
106 return FALSE;
107 }
108
109 static void
freehand_draw_line(gpaint_tool * tool,int x,int y)110 freehand_draw_line(gpaint_tool* tool, int x, int y)
111 {
112 gpaint_closed_freehand *pen = GPAINT_CFH(tool);
113 if (!is_point_defined(&pen->last))
114 {
115 set_point(&pen->last, x, y);
116 }
117 gdk_draw_line(tool->drawing->backing_pixmap, tool->drawing->gc,
118 pen->last.x, pen->last.y, x, y);
119 gdk_draw_line(tool->drawing->window, tool->drawing->gc,
120 pen->last.x, pen->last.y, x, y);
121 drawing_modified(tool->drawing);
122 set_point(&pen->last, x, y);
123 point_array_append(pen->points, x, y);
124 }
125
126
127 static void
freehand_button_press(gpaint_tool * tool,int x,int y)128 freehand_button_press(gpaint_tool* tool, int x, int y)
129 {
130 set_point(&(GPAINT_CFH(tool)->anchor), x, y);
131 freehand_draw_line(tool, x, y);
132 }
133
134 static void
freehand_button_release(gpaint_tool * tool,int x,int y)135 freehand_button_release(gpaint_tool *tool, int x, int y)
136 {
137 gpaint_closed_freehand *pen = GPAINT_CFH(tool);
138 gdk_draw_line(tool->drawing->backing_pixmap, tool->drawing->gc,
139 x, y, pen->anchor.x, pen->anchor.y);
140 gdk_draw_line(tool->drawing->window, tool->drawing->gc,
141 x, y, pen->anchor.x, pen->anchor.y);
142 drawing_modified(tool->drawing);
143 point_array_append(pen->points, pen->anchor.x, pen->anchor.y);
144
145 if (pen->fill)
146 {
147 freehand_fill_area(tool->drawing, pen->points);
148 }
149
150 point_array_remove_all(pen->points);
151 clear_point(&pen->anchor);
152 clear_point(&pen->last);
153 }
154
155 static void
freehand_fill_area(gpaint_drawing * drawing,gpaint_point_array * points)156 freehand_fill_area(gpaint_drawing *drawing, gpaint_point_array *points)
157 {
158 if (point_array_size(points) > 2)
159 {
160 gdk_draw_polygon(
161 drawing->backing_pixmap,
162 drawing->gc,
163 TRUE,
164 point_array_data(points),
165 point_array_size(points));
166 gdk_draw_polygon(
167 drawing->window,
168 drawing->gc,
169 TRUE,
170 point_array_data(points),
171 point_array_size(points));
172 drawing_modified(drawing);
173 }
174 }
175