1
2 /*
3 * Diverse Bristol audio routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 #include <math.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "brightoninternals.h"
27
28 #define S_D 6
29 #define S_D2 20
30 #define S_D3 23
31 #define S_D4 8
32 /*#define S_DEPTH * 4 / 5 */
33 /*#define S_DEPTH2 / 2 */
34
35 /*
36 * For now we only have cheap shading - puts a fixed shape of reduced intensity
37 * pixels into the shadow layer. nc - 17/04/02.
38 * Extended intensity gradients for smoother shadow. nc - 03/06/06.
39 */
40 int
brightonRenderShadow(brightonDevice * dev,int flags)41 brightonRenderShadow(brightonDevice *dev, int flags)
42 {
43 register int x, y, pf, py, po = 0, ys, xs, wr = 0, sfact = 0;
44 register brightonWindow *bwin = dev->bwin;
45 register brightonPalette *palette = bwin->display->palette;
46
47 /* printf("brightonRenderShadow(%x, %i, %i, %i, %i, %i, %i)\n", dev, */
48 /* dev->x, dev->y, dev->width, dev->height, */
49 /* dev->bwin->app->resources[dev->panel].sx, */
50 /* dev->bwin->app->resources[dev->panel].sy); */
51
52 if ((bwin->app->resources[dev->panel].flags & BRIGHTON_WITHDRAWN)
53 || (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
54 & BRIGHTON_NOSHADOW)
55 || (dev->device == -1))
56 return(0);
57
58 if (dev->device == -1)
59 return(0);
60
61 /*
62 * If it is a rotary:
63 */
64 if (dev->device == 0)
65 {
66 int th, tw, xo = 0, salt;
67 float yo, cy = 0, dy2 = dev->height / 4;
68
69 ys = dev->y + dev->bwin->app->resources[dev->panel].sy;
70 xs = dev->x + dev->bwin->app->resources[dev->panel].sx;
71
72 /* tw = dev->width * 4/3; */
73 /* th = dev->height * 4/3; */
74
75 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
76 & BRIGHTON_HALFSHADOW)
77 {
78 tw = dev->width * 7 / 8;
79 th = dev->height * 7 / 8;
80 } else {
81 tw = dev->width;
82 th = dev->height;
83 }
84
85 th = tw = sqrtf(th * th / 2) + 1;
86
87 /*
88 * Rotary. This needs to be changed. I want to take an angle of 45
89 * degrees from the pot, full width, and tailor the shadow at both
90 * ends. At the moment this only tails downwards.
91 */
92 yo = th;
93
94 for (x = 0; x < tw; x++)
95 {
96 for (y = 0; y < th - dy2; y++)
97 {
98 if (y < cy)
99 sfact = 1;
100 else if ((sfact = y - cy) < 2)
101 sfact = 1;
102 else if (sfact >= S_D4)
103 sfact = S_D4 - 1;
104
105 /*
106 * As y reaches the end of the shadow we need to tail it off.
107 * S_D4 - (th - y - 1)
108 * Salt graduates the tip
109 */
110 if ((salt = S_D4 - (th - y + 1)) < 2)
111 salt = 1;
112 else if (salt > S_D4)
113 salt = S_D4 - 1;
114
115 if (salt > sfact)
116 sfact = salt;
117
118 if ((x < 2) && (y < 2))
119 sfact = S_D4 - 1;
120 if ((x < 2) && (y < 3))
121 sfact = S_D4 - 2;
122 else if (((x == tw) || (x == tw - 1)) && (y == 0))
123 sfact = S_D4 - 1;
124
125 pf = (ys + y + yo + 1) * bwin->slayer->width
126 + xs + x + 2 + xo;
127
128 bwin->slayer->pixels[pf]
129 = brightonGetGC(bwin,
130 palette[bwin->canvas->pixels[pf]].red *sfact/S_D4,
131 palette[bwin->canvas->pixels[pf]].green *sfact/S_D4,
132 palette[bwin->canvas->pixels[pf]].blue *sfact/S_D4);
133
134 if (x != tw - 1)
135 {
136 bwin->slayer->pixels[pf + 1]
137 = brightonGetGC(bwin,
138 palette[bwin->canvas->pixels[pf + 1]].red *sfact/S_D4,
139 palette[bwin->canvas->pixels[pf + 1]].green *sfact/S_D4,
140 palette[bwin->canvas->pixels[pf + 1]].blue *sfact/S_D4);
141 }
142 xo++;
143 }
144
145 yo--;
146 xo = 0;
147
148 /*
149 * This triangulates the shadow.
150 */
151 if (x < tw / 2)
152 cy+=2;
153 else if (x > tw / 2)
154 cy-=2;
155
156 /*
157 * This shortens the outer edges
158 */
159 if (x > tw * 5 / 8)
160 dy2 += 1.0;
161 else if ((dy2 -= 1.0) < 0)
162 dy2 = 0;
163 }
164 } else if (dev->device == 2) {
165 int height = dev->height;
166 int width = dev->width;
167
168 if ((width < 5) || (height < 5))
169 return(0);
170
171 /*
172 * Buttons. These give their real size and shape but want light
173 * shading as they are not really supposed to have a high profile.
174 */
175
176 /*
177 * for a brightonScale we have to cater for vertical and horizontal
178 * movements.
179 */
180 ys = dev->y + dev->bwin->app->resources[dev->panel].sy;
181 xs = dev->x + dev->bwin->app->resources[dev->panel].sx;
182
183 for (y = ys; y < ys + height; y++)
184 {
185 py = y * bwin->slayer->width;
186
187 sfact = S_D;
188
189 /* for (x = xs; x < xs + width + po; x++) */
190 for (x = xs + width + po; x != xs + 4; x--)
191 {
192 if (--sfact < 0)
193 sfact = 0;
194
195 pf = py + x;
196 /*
197 * Take whatever is in the canvas area, reduce its brightness,
198 * put that into the shadow area.
199 */
200 if (flags)
201 bwin->slayer->pixels[pf] = -1;
202 else
203 bwin->slayer->pixels[pf]
204 = brightonGetGC(bwin,
205 palette[bwin->canvas->pixels[pf]].red *sfact/S_D,
206 palette[bwin->canvas->pixels[pf]].green *sfact/S_D,
207 palette[bwin->canvas->pixels[pf]].blue *sfact/S_D);
208 }
209 if (po < width / 6)
210 po++;
211 }
212
213 for (; y < ys + height + width / 5; y++)
214 {
215 py = y * bwin->slayer->width;
216
217 sfact = S_D;
218
219 for (x = xs + width + po - wr; x != xs; x--)
220 {
221 if (--sfact < 0)
222 sfact = 0;
223
224 if (y == (ys + height + width / 5) - 3)
225 sfact = S_D - 3;
226 else if (y == (ys + height + width / 5) - 2)
227 sfact = S_D - 2;
228
229 if (y == (ys + height + width / 5) - 1)
230 sfact = S_D - 1;
231 else if (x == (xs + width + po - wr))
232 sfact = S_D - 1;
233 else if (x == (xs + width + po - wr) - 1)
234 sfact = S_D - 2;
235
236 pf = py + x + wr;
237 /*
238 * Take whatever is in the canvas area, reduce its brightness,
239 * put that into the shadow area.
240 */
241 if (flags)
242 bwin->slayer->pixels[pf] = -1;
243 else
244 bwin->slayer->pixels[pf]
245 = brightonGetGC(bwin,
246 palette[bwin->canvas->pixels[pf]].red *sfact/S_D,
247 palette[bwin->canvas->pixels[pf]].green *sfact/S_D,
248 palette[bwin->canvas->pixels[pf]].blue *sfact/S_D);
249 }
250 wr++;
251 }
252 } else {
253 int height = dev->height;
254 int width = dev->width;
255 int div = 4;
256
257 if ((width < 5) || (height < 5))
258 return(0);
259
260 /*
261 * for a brightonScale we have to cater for vertical and horizontal
262 * movements.
263 */
264 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
265 & BRIGHTON_VERTICAL)
266 {
267 height = dev->width * 2 / 3;
268 width = dev->height * 2 / 3;
269 xs = dev->x + dev->bwin->app->resources[dev->panel].sx
270 + (int) dev->position;
271 ys = dev->y + dev->bwin->app->resources[dev->panel].sy;
272 } else {
273 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
274 & BRIGHTON_HALFSHADOW)
275 {
276 ys = dev->y + dev->bwin->app->resources[dev->panel].sy
277 + dev->height / 16
278 + (int) dev->position;
279 div = 8;
280 xs = dev->x + dev->bwin->app->resources[dev->panel].sx;
281 } else {
282 ys = dev->y + dev->bwin->app->resources[dev->panel].sy
283 + (int) dev->position;
284 xs = dev->x + dev->bwin->app->resources[dev->panel].sx;
285 }
286 }
287
288 for (y = ys; y < ys + height / div - 1; y++)
289 {
290 py = y * bwin->slayer->width;
291
292 sfact = S_D;
293
294 /* for (x = xs; x < xs + width + po; x++) */
295 for (x = xs + width + po; x != xs + 4; x--)
296 {
297 if (--sfact < 0)
298 sfact = 0;
299
300 pf = py + x;
301 /*
302 * Take whatever is in the canvas area, reduce its brightness,
303 * put that into the shadow area.
304 */
305 if (flags)
306 bwin->slayer->pixels[pf] = -1;
307 else
308 bwin->slayer->pixels[pf]
309 = brightonGetGC(bwin,
310 palette[bwin->canvas->pixels[pf]].red *sfact/S_D,
311 palette[bwin->canvas->pixels[pf]].green *sfact/S_D,
312 palette[bwin->canvas->pixels[pf]].blue *sfact/S_D);
313 }
314 if (po < width / 2)
315 po++;
316 }
317
318 for (; y < ys + height / div + width / 2; y++)
319 {
320 py = y * bwin->slayer->width;
321
322 sfact = S_D;
323
324 /* for (x = xs; x < xs + width + po - wr; x++) */
325 for (x = xs + width + po - wr; x != xs; x--)
326 {
327 if (--sfact < 0)
328 sfact = 0;
329
330 if (y == (ys + height / div + width / 2) - 4)
331 sfact = S_D - 4;
332 else if (y == (ys + height / div + width / 2) - 3)
333 sfact = S_D - 3;
334 else if (y == (ys + height / div + width / 2) - 2)
335 sfact = S_D - 2;
336
337 if (y == (ys + height / div + width / 2) - 1)
338 sfact = S_D - 1;
339 else if (x == (xs + width + po - wr))
340 sfact = S_D - 1;
341 else if (x == (xs + width + po - wr) - 1)
342 sfact = S_D - 2;
343
344 pf = py + x + wr;
345 /*
346 * Take whatever is in the canvas area, reduce its brightness,
347 * put that into the shadow area.
348 */
349 if (flags)
350 bwin->slayer->pixels[pf] = -1;
351 else
352 bwin->slayer->pixels[pf]
353 = brightonGetGC(bwin,
354 palette[bwin->canvas->pixels[pf]].red *sfact/S_D,
355 palette[bwin->canvas->pixels[pf]].green *sfact/S_D,
356 palette[bwin->canvas->pixels[pf]].blue *sfact/S_D);
357 }
358 wr++;
359 }
360
361 }
362 return(0);
363 }
364
365