1 /*
2 light.c
3
4 Light Magic Tool Plugin
5 Tux Paint - A simple drawing program for children.
6
7 Copyright (c) 2002-2008 by Bill Kendrick and others; see AUTHORS.txt
8 bill@newbreedsoftware.com
9 http://www.tuxpaint.org/
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 (See COPYING.txt)
25
26 Last updated: July 8, 2008
27 $Id$
28 */
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include "tp_magic_api.h"
34 #include "SDL_image.h"
35 #include "SDL_mixer.h"
36
37 #include "math.h"
38
39 /* Our globals: */
40
41 static Mix_Chunk *light1_snd, *light2_snd;
42 static float light_h, light_s, light_v;
43 Uint32 light_api_version(void);
44 int light_init(magic_api * api);
45 int light_get_tool_count(magic_api * api);
46 SDL_Surface *light_get_icon(magic_api * api, int which);
47 char *light_get_name(magic_api * api, int which);
48 char *light_get_description(magic_api * api, int which, int mode);
49 static void do_light(void *ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y);
50 void light_drag(magic_api * api, int which, SDL_Surface * canvas,
51 SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect);
52 void light_click(magic_api * api, int which, int mode,
53 SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
54 void light_release(magic_api * api, int which,
55 SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
56 void light_shutdown(magic_api * api);
57 void light_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
58 int light_requires_colors(magic_api * api, int which);
59 void light_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas);
60 void light_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas);
61 int light_modes(magic_api * api, int which);
62
63
light_api_version(void)64 Uint32 light_api_version(void)
65 {
66 return (TP_MAGIC_API_VERSION);
67 }
68
69
70 // No setup required:
light_init(magic_api * api)71 int light_init(magic_api * api)
72 {
73 char fname[1024];
74
75 snprintf(fname, sizeof(fname), "%s/sounds/magic/light1.ogg", api->data_directory);
76 light1_snd = Mix_LoadWAV(fname);
77
78 snprintf(fname, sizeof(fname), "%s/sounds/magic/light2.ogg", api->data_directory);
79 light2_snd = Mix_LoadWAV(fname);
80
81 return (1);
82 }
83
84 // We have multiple tools:
light_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)85 int light_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
86 {
87 return (1);
88 }
89
90 // Load our icons:
light_get_icon(magic_api * api,int which ATTRIBUTE_UNUSED)91 SDL_Surface *light_get_icon(magic_api * api, int which ATTRIBUTE_UNUSED)
92 {
93 char fname[1024];
94
95 snprintf(fname, sizeof(fname), "%s/images/magic/light.png", api->data_directory);
96
97 return (IMG_Load(fname));
98 }
99
100 // Return our names, localized:
light_get_name(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)101 char *light_get_name(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
102 {
103 return (strdup(gettext_noop("Light")));
104 }
105
106 // Return our descriptions, localized:
light_get_description(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED)107 char *light_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
108 {
109 return (strdup(gettext_noop("Click and drag to draw a beam of light on your picture.")));
110 }
111
112 // Do the effect:
113
do_light(void * ptr,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last ATTRIBUTE_UNUSED,int x,int y)114 static void do_light(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas, SDL_Surface * last ATTRIBUTE_UNUSED,
115 int x, int y)
116 {
117 magic_api *api = (magic_api *) ptr;
118 int xx, yy;
119 Uint32 pix;
120 Uint8 r, g, b;
121 float h, s, v, new_h, new_s, new_v;
122 float adj;
123
124 for (yy = -8; yy < 8; yy++)
125 {
126 for (xx = -8; xx < 8; xx++)
127 {
128 if (api->in_circle(xx, yy, 8))
129 {
130 pix = api->getpixel(canvas, x + xx, y + yy);
131
132 SDL_GetRGB(pix, canvas->format, &r, &g, &b);
133
134 adj = (7.99 - sqrt(abs(xx * yy))) / 128.0;
135
136 api->rgbtohsv(r, g, b, &h, &s, &v);
137
138 v = min((float)1.0, v + adj);
139
140 if (light_h == -1 && h == -1)
141 {
142 new_h = -1;
143 new_s = 0;
144 new_v = v;
145 }
146 else if (light_h == -1)
147 {
148 new_h = h;
149 new_s = max(0.0, s - adj / 2.0);
150 new_v = v;
151 }
152 else if (h == -1)
153 {
154 new_h = light_h;
155 new_s = max(0.0, light_s - adj / 2.0);
156 new_v = v;
157 }
158 else
159 {
160 new_h = (light_h + h) / 2;
161 new_s = max(0.0, s - adj / 2.0);
162 new_v = v;
163 }
164
165 api->hsvtorgb(new_h, new_s, new_v, &r, &g, &b);
166
167 api->putpixel(canvas, x + xx, y + yy, SDL_MapRGB(canvas->format, r, g, b));
168 }
169 }
170 }
171 }
172
173 // Affect the canvas on drag:
light_drag(magic_api * api,int which,SDL_Surface * canvas,SDL_Surface * last,int ox,int oy,int x,int y,SDL_Rect * update_rect)174 void light_drag(magic_api * api, int which, SDL_Surface * canvas,
175 SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect)
176 {
177 api->line((void *)api, which, canvas, last, ox, oy, x, y, 1, do_light);
178
179 if (ox > x)
180 {
181 int tmp = ox;
182
183 ox = x;
184 x = tmp;
185 }
186 if (oy > y)
187 {
188 int tmp = oy;
189
190 oy = y;
191 y = tmp;
192 }
193
194 update_rect->x = ox - 8;
195 update_rect->y = oy - 8;
196 update_rect->w = (x + 8) - update_rect->x;
197 update_rect->h = (y + 8) - update_rect->h;
198
199 api->playsound(light1_snd, (x * 255) / canvas->w, 255);
200 }
201
202 // Affect the canvas on click:
light_click(magic_api * api,int which,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last,int x,int y,SDL_Rect * update_rect)203 void light_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
204 SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect)
205 {
206 light_drag(api, which, canvas, last, x, y, x, y, update_rect);
207 }
208
209 // Affect the canvas on release:
light_release(magic_api * api,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last ATTRIBUTE_UNUSED,int x,int y ATTRIBUTE_UNUSED,SDL_Rect * update_rect ATTRIBUTE_UNUSED)210 void light_release(magic_api * api, int which ATTRIBUTE_UNUSED,
211 SDL_Surface * canvas, SDL_Surface * last ATTRIBUTE_UNUSED,
212 int x, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
213 {
214 api->playsound(light2_snd, (x * 255) / canvas->w, 255);
215 }
216
217 // No setup happened:
light_shutdown(magic_api * api ATTRIBUTE_UNUSED)218 void light_shutdown(magic_api * api ATTRIBUTE_UNUSED)
219 {
220 if (light1_snd != NULL)
221 Mix_FreeChunk(light1_snd);
222 if (light2_snd != NULL)
223 Mix_FreeChunk(light2_snd);
224 }
225
226 // Record the color from Tux Paint:
light_set_color(magic_api * api,Uint8 r,Uint8 g,Uint8 b)227 void light_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
228 {
229 api->rgbtohsv(r, g, b, &light_h, &light_s, &light_v);
230 }
231
232 // Use colors:
light_requires_colors(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)233 int light_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
234 {
235 return 1;
236 }
237
light_switchin(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED)238 void light_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
239 SDL_Surface * canvas ATTRIBUTE_UNUSED)
240 {
241 }
242
light_switchout(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED)243 void light_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
244 SDL_Surface * canvas ATTRIBUTE_UNUSED)
245 {
246 }
247
light_modes(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)248 int light_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
249 {
250 return (MODE_PAINT);
251 }
252