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