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