1 /*
2   toothpaste.c
3 
4   toothpaste, Add a toothpaste effect to the image
5   Tux Paint - A simple drawing program for children.
6 
7   Credits: Andrew Corcoran <akanewbie@gmail.com>
8 
9   Copyright (c) 2002-2007 by Bill Kendrick and others; see AUTHORS.txt
10   bill@newbreedsoftware.com
11   http://www.tuxpaint.org/
12 
13   This program is free software; you can redistribute it and/or modify
14   it under the terms of the GNU General Public License as published by
15   the Free Software Foundation; either version 2 of the License, or
16   (at your option) any later version.
17 
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22 
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26   (See COPYING.txt)
27 
28   Last updated: June 6, 2008
29   $Id$
30 */
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <libintl.h>
35 #include "tp_magic_api.h"
36 #include "SDL_image.h"
37 #include "SDL_mixer.h"
38 #include <math.h>
39 #include <limits.h>
40 #include <time.h>
41 
42 #ifndef gettext_noop
43 #define gettext_noop(String) String
44 #endif
45 
46 double pi;
47 static Uint8 toothpaste_r, toothpaste_g, toothpaste_b;
48 static const int toothpaste_RADIUS = 10;
49 double *toothpaste_weights = NULL;
50 
51 enum
52 {
53   TOOL_toothpaste,
54   toothpaste_NUM_TOOLS
55 };
56 
57 static Mix_Chunk *toothpaste_snd_effect[toothpaste_NUM_TOOLS];
58 
59 const char *toothpaste_snd_filenames[toothpaste_NUM_TOOLS] = {
60   "toothpaste.ogg",
61 };
62 
63 const char *toothpaste_icon_filenames[toothpaste_NUM_TOOLS] = {
64   "toothpaste.png",
65 };
66 
67 const char *toothpaste_names[toothpaste_NUM_TOOLS] = {
68   gettext_noop("Toothpaste"),
69 };
70 
71 const char *toothpaste_descs[toothpaste_NUM_TOOLS] = {
72   gettext_noop("Click and drag to squirt toothpaste onto your picture."),
73 };
74 
75 
76 Uint32 toothpaste_api_version(void);
77 int toothpaste_init(magic_api * api);
78 int toothpaste_get_tool_count(magic_api * api);
79 SDL_Surface *toothpaste_get_icon(magic_api * api, int which);
80 char *toothpaste_get_name(magic_api * api, int which);
81 char *toothpaste_get_description(magic_api * api, int which, int mode);
82 static void do_toothpaste(void *ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y);
83 void toothpaste_drag(magic_api * api, int which, SDL_Surface * canvas,
84                      SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect);
85 void toothpaste_click(magic_api * api, int which, int mode,
86                       SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
87 void toothpaste_release(magic_api * api, int which,
88                         SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
89 void toothpaste_shutdown(magic_api * api);
90 void toothpaste_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
91 int toothpaste_requires_colors(magic_api * api, int which);
92 void toothpaste_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas);
93 void toothpaste_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas);
94 int toothpaste_modes(magic_api * api, int which);
95 
toothpaste_api_version(void)96 Uint32 toothpaste_api_version(void)
97 {
98   return (TP_MAGIC_API_VERSION);
99 }
100 
101 
toothpaste_init(magic_api * api)102 int toothpaste_init(magic_api * api)
103 {
104 
105   int i;
106   char fname[1024];
107   int k, j;
108 
109   //Load sounds
110   for (i = 0; i < toothpaste_NUM_TOOLS; i++)
111     {
112       snprintf(fname, sizeof(fname), "%s/sounds/magic/%s", api->data_directory, toothpaste_snd_filenames[i]);
113       toothpaste_snd_effect[i] = Mix_LoadWAV(fname);
114     }
115 
116   //Set up weights
117   pi = acos(0.0) * 2;
118   toothpaste_weights = (double *)malloc(toothpaste_RADIUS * 2 * toothpaste_RADIUS * 2 * sizeof(double));
119   if (toothpaste_weights == NULL)
120     {
121       return (0);
122     }
123 
124   for (k = -toothpaste_RADIUS; k < +toothpaste_RADIUS; k++)
125     {
126       for (j = -toothpaste_RADIUS; j < +toothpaste_RADIUS; j++)
127         {
128           if (api->in_circle(j, k, toothpaste_RADIUS))
129             {
130               toothpaste_weights[(k + toothpaste_RADIUS) * ((toothpaste_RADIUS * 2) - 1) + (j + toothpaste_RADIUS)] =
131                 ((fabs(atan2((double)(j), (double)(k)))) / pi);
132             }
133         }
134     }
135 
136   return (1);
137 }
138 
toothpaste_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)139 int toothpaste_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
140 {
141   return (toothpaste_NUM_TOOLS);
142 }
143 
144 // Load our icons:
toothpaste_get_icon(magic_api * api,int which ATTRIBUTE_UNUSED)145 SDL_Surface *toothpaste_get_icon(magic_api * api, int which ATTRIBUTE_UNUSED)
146 {
147   char fname[1024];
148 
149   snprintf(fname, sizeof(fname), "%simages/magic/%s", api->data_directory, toothpaste_icon_filenames[which]);
150   return (IMG_Load(fname));
151 }
152 
153 // Return our names, localized:
toothpaste_get_name(magic_api * api ATTRIBUTE_UNUSED,int which)154 char *toothpaste_get_name(magic_api * api ATTRIBUTE_UNUSED, int which)
155 {
156   return (strdup(gettext_noop(toothpaste_names[which])));
157 }
158 
159 // Return our descriptions, localized:
toothpaste_get_description(magic_api * api ATTRIBUTE_UNUSED,int which,int mode ATTRIBUTE_UNUSED)160 char *toothpaste_get_description(magic_api * api ATTRIBUTE_UNUSED, int which, int mode ATTRIBUTE_UNUSED)
161 {
162   return (strdup(gettext_noop(toothpaste_descs[which])));
163 }
164 
165 // Do the effect:
do_toothpaste(void * ptr,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last ATTRIBUTE_UNUSED,int x,int y)166 static void do_toothpaste(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas,
167                           SDL_Surface * last ATTRIBUTE_UNUSED, int x, int y)
168 {
169   magic_api *api = (magic_api *) ptr;
170 
171   int xx, yy;
172 
173   // double colr;
174   float h, s, v;
175   Uint8 r, g, b;
176 
177   for (yy = y - toothpaste_RADIUS; yy < y + toothpaste_RADIUS; yy++)
178     {
179       for (xx = x - toothpaste_RADIUS; xx < x + toothpaste_RADIUS; xx++)
180         {
181           if (api->in_circle(xx - x, yy - y, toothpaste_RADIUS) && !api->touched(xx, yy))
182             {
183 
184               api->rgbtohsv(toothpaste_r, toothpaste_g, toothpaste_b, &h, &s, &v);
185               api->hsvtorgb(h, s,
186                             toothpaste_weights[(yy - y + toothpaste_RADIUS) * ((toothpaste_RADIUS * 2) - 1) +
187                                                (xx - x + toothpaste_RADIUS)], &r, &g, &b);
188               api->putpixel(canvas, xx, yy, SDL_MapRGB(canvas->format, r, g, b));
189 
190             }
191         }
192     }
193 
194 }
195 
196 // Affect the canvas on drag:
toothpaste_drag(magic_api * api,int which,SDL_Surface * canvas,SDL_Surface * last,int ox,int oy,int x,int y,SDL_Rect * update_rect)197 void toothpaste_drag(magic_api * api, int which, SDL_Surface * canvas,
198                      SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect)
199 {
200 
201   api->line((void *)api, which, canvas, last, ox, oy, x, y, 1, do_toothpaste);
202 
203   api->playsound(toothpaste_snd_effect[which], (x * 255) / canvas->w, 255);
204 
205   update_rect->x = 0;
206   update_rect->y = 0;
207   update_rect->w = canvas->w;
208   update_rect->h = canvas->h;
209 
210 }
211 
212 // Affect the canvas on click:
toothpaste_click(magic_api * api,int which,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last,int x,int y,SDL_Rect * update_rect)213 void toothpaste_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
214                       SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect)
215 {
216 
217   toothpaste_drag(api, which, canvas, last, x, y, x, y, update_rect);
218 }
219 
220 // Affect the canvas on release:
toothpaste_release(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED,SDL_Surface * last ATTRIBUTE_UNUSED,int x ATTRIBUTE_UNUSED,int y ATTRIBUTE_UNUSED,SDL_Rect * update_rect ATTRIBUTE_UNUSED)221 void toothpaste_release(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
222                         SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED,
223                         int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
224 {
225 }
226 
227 // No setup happened:
toothpaste_shutdown(magic_api * api ATTRIBUTE_UNUSED)228 void toothpaste_shutdown(magic_api * api ATTRIBUTE_UNUSED)
229 {
230   //Clean up sounds
231   int i;
232 
233   for (i = 0; i < toothpaste_NUM_TOOLS; i++)
234     {
235       if (toothpaste_snd_effect[i] != NULL)
236         {
237           Mix_FreeChunk(toothpaste_snd_effect[i]);
238         }
239     }
240   if (toothpaste_weights != NULL)
241     {
242       free(toothpaste_weights);
243       toothpaste_weights = NULL;
244     }
245 }
246 
247 // Record the color from Tux Paint:
toothpaste_set_color(magic_api * api ATTRIBUTE_UNUSED,Uint8 r,Uint8 g,Uint8 b)248 void toothpaste_set_color(magic_api * api ATTRIBUTE_UNUSED, Uint8 r, Uint8 g, Uint8 b)
249 {
250   toothpaste_r = r;
251   toothpaste_g = g;
252   toothpaste_b = b;
253 }
254 
255 // Use colors:
toothpaste_requires_colors(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)256 int toothpaste_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
257 {
258   return 1;
259 }
260 
261 
toothpaste_switchin(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED)262 void toothpaste_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
263                          SDL_Surface * canvas ATTRIBUTE_UNUSED)
264 {
265 }
266 
toothpaste_switchout(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED)267 void toothpaste_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
268                           SDL_Surface * canvas ATTRIBUTE_UNUSED)
269 {
270 }
271 
toothpaste_modes(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)272 int toothpaste_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
273 {
274   return (MODE_PAINT);
275 }
276