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 "brightoninternals.h"
23
24 extern void bvgRenderInt(brightonWindow *, char *, brightonBitmap *);
25
26 #define MY_CALL 0x01
27 struct {
28 unsigned int flags;
29 int px, py;
30 brightonBitmap frame;
31 brightonPanel *panel;
32 } window;
33
34 void
brightonCreatePanel(int x,int y,char * image)35 brightonCreatePanel(int x, int y, char *image)
36 {
37 window.px = x;
38 window.py = y;
39
40 window.flags |= MY_CALL;
41 }
42
43 int
brightonDevUndraw(brightonWindow * bwin,brightonBitmap * dest,int ix,int iy,int w,int h)44 brightonDevUndraw(brightonWindow *bwin, brightonBitmap *dest, int ix, int iy,
45 int w, int h)
46 {
47 int x, y, z, dy, s = dest->width * dest->height;
48
49 /*printf("undraw %x %x %x, %i %i %i %i\n", */
50 /*bwin, dest, dest->pixels, ix, iy, w, h); */
51
52 for (y = iy; y <= (iy + h - 1); y++)
53 {
54 dy = y * dest->width;
55
56 for (x = ix; x <= (ix + w - 1); x++)
57 {
58 if (((z = dy + x) < 0) || (z > s))
59 continue;
60 dest->pixels[z] = -1;
61 }
62 }
63 return(0);
64 }
65
66 void
brightonPanelLocation(brightonWindow * bwin,int panel,int index,int x,int y,int width,int height)67 brightonPanelLocation(brightonWindow *bwin, int panel, int index,
68 int x, int y, int width, int height)
69 {
70 bwin->app->resources[panel].devlocn[index].ax = x;
71 bwin->app->resources[panel].devlocn[index].ay = y;
72 bwin->app->resources[panel].devlocn[index].aw = width;
73 bwin->app->resources[panel].devlocn[index].ah = height;
74 }
75
76 static brightonILocations *ldid = 0;
77
78 static int
configurePanel(brightonWindow * bwin,brightonIResource * panel,brightonEvent * event)79 configurePanel(brightonWindow *bwin, brightonIResource *panel,
80 brightonEvent *event)
81 {
82 int dev;
83 brightonILocations *device;
84
85 /* printf("configure panel: %i\n", event->command); */
86
87 if (event->command == BRIGHTON_PARAMCHANGE)
88 {
89 if (event->type == BRIGHTON_EXPOSE)
90 {
91 if (event->intvalue)
92 {
93 //printf(" REQ EXPOSE %x %x\n", (size_t) event, (size_t) panel);
94 panel->flags &= ~BRIGHTON_WITHDRAWN;
95
96 event->command = BRIGHTON_RESIZE;
97
98 event->x = panel->sx;
99 event->y = panel->sy;
100 event->w = panel->sw;
101 event->h = panel->sh;
102
103 brightonDevUndraw(bwin, bwin->dlayer,
104 event->x, event->y, event->w, event->h);
105 brightonDevUndraw(bwin, bwin->slayer,
106 event->x, event->y, event->w, event->h);
107
108 /*
109 * We should also go through all the tools in the panel and
110 * rerender their shadow.
111 */
112 for (dev = 0; dev < panel->ndevices; dev++)
113 {
114 if (panel->devlocn[dev].type == 0)
115 brightonRenderShadow(
116 (brightonDevice *) panel->devlocn[dev].dev, 0);
117 }
118 } else {
119 //printf(" REQ UNEXPOSE %x %x\n", (size_t) event, (size_t) panel);
120 panel->flags |= BRIGHTON_WITHDRAWN;
121 /*
122 * On unexpose events we dont do any redraws? Conceptually we
123 * only have overlapping panels, and EXPOSE/UNEXPOSE go in
124 * pairs - the next event on another panel will draw over the
125 * top of me.
126 */
127 return(0);
128 }
129 } else
130 return(0);
131 }
132
133 if (event->command == BRIGHTON_RESIZE)
134 {
135 panel->sx = event->x;
136 panel->sy = event->y;
137 panel->sw = event->w;
138 panel->sh = event->h;
139
140 /*
141 * We need to configure our size and render any image and blueprints for
142 * this panel. Then we need to call all our devices and make sure they
143 * are also configured for their location within this panel.
144 */
145 if (panel->canvas)
146 brightonFreeBitmap(bwin, panel->canvas);
147
148 panel->canvas = brightonCreateBitmap(bwin, event->w, event->h);
149
150 if (panel->flags & BRIGHTON_WITHDRAWN)
151 {
152 /*
153 * NOTE:
154 * this was a fix for incorrect shadow rendering if panels are
155 * resized whilst withdrawn.
156 */
157 for (dev = 0; dev < panel->ndevices; dev++)
158 {
159 if (panel->devlocn[dev].type == -1)
160 continue;
161
162 event->x = (int) panel->devlocn[dev].x * panel->sw / 1000;
163 event->y = (int) panel->devlocn[dev].y * panel->sh / 1000;
164 event->w = (int) panel->devlocn[dev].width * panel->sw / 1000;
165 event->h = (int) panel->devlocn[dev].height * panel->sh / 1000;
166
167 brightonPanelLocation(bwin,
168 panel->devlocn[dev].panel, panel->devlocn[dev].index,
169 event->x, event->y, event->w, event->h);
170
171 ((brightonDevice *) panel->devlocn[dev].dev)->configure(
172 panel->devlocn[dev].dev, event);
173 }
174 return(0);
175 }
176
177 /*
178 * Render our panel canvas.
179 */
180 if (panel->surface == NULL) {
181 /*
182 * A few panels do not use a surface. This works, it gets filled as
183 * 'Blue' and never gets rendered. It caused problems with the
184 * prealiasing code since unless a surface is rendered then we
185 * cannot do the antialiasing. To overcome this we paint the actual
186 * content of the parent into the panel surface.
187 * This is not as trivial as it seems as we actually want a window
188 * into the backing store, most of which can be resolved by correct
189 * placement of these elements in the image stacking order.
190 */
191 brightonTesselate(bwin, bwin->canvas, panel->canvas, 0, 0,
192 panel->sw, panel->sh, panel->flags);
193 } else {
194 if (panel->flags & BRIGHTON_STRETCH)
195 brightonStretch(bwin, panel->surface, panel->canvas, 0, 0,
196 panel->sw, panel->sh, panel->flags);
197 else
198 brightonTesselate(bwin, panel->surface, panel->canvas, 0, 0,
199 panel->sw, panel->sh, panel->flags);
200 }
201
202 /*
203 * This should be done with antialiasing since when it is scaled it
204 * can look rather grizzly. Also, if we don't have a surface then we
205 * should create a dummy one to allow for antialiasing.
206 */
207 if ((bwin->display->flags & BRIGHTON_ANTIALIAS_5)
208 || (bwin->display->flags & BRIGHTON_ANTIALIAS_2))
209 brightonStretchAlias(bwin, panel->image, panel->canvas, 0, 0,
210 panel->sw, panel->sh, 0.2);
211 else
212 brightonStretch(bwin, panel->image, panel->canvas, 0, 0,
213 panel->sw, panel->sh, 0);
214
215 if (panel->image)
216 bvgRenderInt(bwin, rindex(panel->image->name, '/'), panel->canvas);
217
218 /*
219 * And then render it onto the window cavas area
220 */
221 brightonStretch(bwin, panel->canvas, bwin->canvas, panel->sx, panel->sy,
222 panel->sw, panel->sh, BRIGHTON_ANTIALIAS);
223
224 brightonFinalRender(bwin, panel->sx, panel->sy, panel->sw, panel->sh);
225
226 for (dev = 0; dev < panel->ndevices; dev++)
227 {
228 if (panel->devlocn[dev].type == -1)
229 continue;
230
231 event->x = (int) panel->devlocn[dev].x * panel->sw / 1000;
232 event->y = (int) panel->devlocn[dev].y * panel->sh / 1000;
233 event->w = (int) panel->devlocn[dev].width * panel->sw / 1000;
234 event->h = (int) panel->devlocn[dev].height * panel->sh / 1000;
235
236 brightonPanelLocation(bwin,
237 panel->devlocn[dev].panel, panel->devlocn[dev].index,
238 event->x, event->y, event->w, event->h);
239
240 ((brightonDevice *) panel->devlocn[dev].dev)->configure(
241 panel->devlocn[dev].dev, event);
242 }
243
244 return(0);
245 }
246
247 device = brightonDeviceLocator(panel,
248 event->x - panel->sx, event->y - panel->sy);
249
250 if ((panel->flags & BRIGHTON_KEY_PANEL) || ldid)
251 {
252 brightonEvent nEv;
253
254 //printf("keypanel\n");
255 /*
256 * We may have to reinterpret some events. We want to have motion
257 * tracking to move from key to key which means if the device ID changes
258 * then send a BUTTONRELEASE on the previous ID and a BUTTONPRESS on
259 * the new one.
260 */
261 if (device != ldid)
262 {
263 //printf("release button\n");
264 memcpy(&nEv, event, sizeof(brightonEvent));
265
266 nEv.command = BRIGHTON_BUTTONRELEASE;
267
268 nEv.x -= panel->sx;
269 nEv.y -= panel->sy;
270
271 if (bwin->activedev)
272 ((brightonDevice *) bwin->activedev->dev)->configure
273 (bwin->activedev->dev, &nEv);
274 }
275 if ((panel->flags & BRIGHTON_KEY_PANEL) && device)
276 {
277 if (ldid != device)
278 {
279 //printf("press button\n");
280 memcpy(&nEv, event, sizeof(brightonEvent));
281
282 nEv.command = BRIGHTON_BUTTONPRESS;
283
284 nEv.x = event->x - panel->sx;
285 nEv.y = event->y - panel->sy;
286
287 ldid = bwin->activedev = device;
288
289 ((brightonDevice *) device->dev)->configure
290 (device->dev, &nEv);
291
292 return(0);
293 }
294 } else {
295 ldid = 0;
296 bwin->activedev = 0;
297 }
298 }
299
300 if (event->command == BRIGHTON_BUTTONRELEASE)
301 {
302 /*printf("panel button release: %i\n", bwin->activedev); */
303
304 if (bwin->activedev == 0)
305 return(0);
306
307 /* This should be simplified to Deliver the Event */
308 if ((bwin->app->resources[bwin->activedev->panel].devlocn[
309 bwin->activedev->index].flags & BRIGHTON_CENTER)
310 || (bwin->app->resources[bwin->activedev->panel].devlocn[
311 bwin->activedev->index].type == 5))
312 {
313 /*
314 * Deliver the event.
315 */
316 event->x -= panel->sx;
317 event->y -= panel->sy;
318
319 ((brightonDevice *) bwin->activedev->dev)->configure
320 (bwin->activedev->dev, event);
321 } else if (device == bwin->activedev) {
322 /*
323 * Deliver the event.
324 */
325 event->x -= panel->sx;
326 event->y -= panel->sy;
327
328 ((brightonDevice *) bwin->activedev->dev)->configure
329 (bwin->activedev->dev, event);
330 } else {
331 /*
332 * Deliver the event.
333 */
334 event->x -= panel->sx;
335 event->y -= panel->sy;
336
337 ((brightonDevice *) bwin->activedev->dev)->configure
338 (bwin->activedev->dev, event);
339 }
340
341 bwin->activedev = 0;
342
343 return(0);
344 }
345
346 if ((event->command == BRIGHTON_BUTTONPRESS)
347 || (event->command == BRIGHTON_BUTTONRELEASE))
348 {
349 /*printf("panel button press\n"); */
350
351 if ((bwin->activedev = device) == 0)
352 return(0);
353
354 /*
355 * Deliver the event.
356 */
357 event->x -= panel->sx;
358 event->y -= panel->sy;
359
360 ((brightonDevice *) bwin->activedev->dev)->configure
361 (bwin->activedev->dev, event);
362
363 return(0);
364 }
365
366 if (event->command == BRIGHTON_MOTION)
367 {
368 if (bwin->activedev)
369 {
370 /*
371 * Deliver the event.
372 */
373 event->x -= panel->sx;
374 event->y -= panel->sy;
375
376 if (bwin->activedev->flags & BRIGHTON_CHECKBUTTON)
377 {
378 if (device != bwin->activedev)
379 {
380 event->command = BRIGHTON_LEAVE;
381 ((brightonDevice *) bwin->activedev->dev)->configure
382 (bwin->activedev->dev, event);
383 } else {
384 event->command = BRIGHTON_ENTER;
385 ((brightonDevice *) bwin->activedev->dev)->configure
386 (bwin->activedev->dev, event);
387 }
388 } else {
389 ((brightonDevice *) bwin->activedev->dev)->configure
390 (bwin->activedev->dev, event);
391 }
392 }
393 /*
394 else {
395 if (device->flags & BRIGHTON_TRACKING)
396 {
397 event->command = BRIGHTON_ENTER;
398 device->configure(device, event);
399 }
400 }
401 */
402 return(0);
403 }
404
405 if (event->command == BRIGHTON_KEYRELEASE)
406 {
407 /*
408 * Deliver the event.
409 */
410 event->x -= panel->sx;
411 event->y -= panel->sy;
412
413 if (bwin->activedev)
414 {
415 ((brightonDevice *) bwin->activedev->dev)->configure
416 (bwin->activedev->dev, event);
417 return(0);
418 }
419
420 if (device == 0)
421 return(0);
422
423 ((brightonDevice *) device->dev)->configure(device->dev, event);
424 }
425
426 if (event->command == BRIGHTON_KEYPRESS)
427 {
428 /*
429 * Deliver the event.
430 */
431 event->x -= panel->sx;
432 event->y -= panel->sy;
433
434 if (bwin->activedev)
435 {
436 ((brightonDevice *) bwin->activedev->dev)->configure
437 (bwin->activedev->dev, event);
438 return(0);
439 }
440
441 if (device == 0)
442 return(0);
443
444 ((brightonDevice *) device->dev)->configure(device->dev, event);
445 }
446 return(0);
447 }
448
449 static int
brightonCreateDevices(brightonWindow * bwin,brightonResource * res,int index)450 brightonCreateDevices(brightonWindow *bwin, brightonResource *res, int index)
451 {
452 int i;
453 brightonLocations *dev = res->devlocn;
454
455 /*printf("brightonCreateDevices(%x, %x, %i)\n", bwin, res, index); */
456
457 bwin->app->resources[index].devlocn = (brightonILocations *)
458 brightonmalloc(res->ndevices * sizeof(brightonILocations));
459
460 for (i = 0; i < res->ndevices; i++)
461 {
462 /*printf(" %s %i (%f,%f)/(%f,%f)\n %s, %s\n", */
463 /* dev[i].name, dev[i].device, */
464 /* dev[i].x, dev[i].y, dev[i].width, dev[i].height, */
465 /* dev[i].image, dev[i].image2); */
466
467 bwin->app->resources[index].devlocn[i].type = dev[i].device;
468 bwin->app->resources[index].devlocn[i].index = i;
469 bwin->app->resources[index].devlocn[i].panel = index;
470 bwin->app->resources[index].devlocn[i].x = dev[i].x;
471 bwin->app->resources[index].devlocn[i].y = dev[i].y;
472 bwin->app->resources[index].devlocn[i].width = dev[i].width;
473 bwin->app->resources[index].devlocn[i].height = dev[i].height;
474
475 bwin->app->resources[index].devlocn[i].from = dev[i].from;
476 bwin->app->resources[index].devlocn[i].to = dev[i].to;
477
478 if (dev[i].device == -1)
479 continue;
480
481 bwin->app->resources[index].devlocn[i].callback = dev[i].callback;
482 bwin->app->resources[index].devlocn[i].flags = dev[i].flags;
483
484 bwin->app->resources[index].devlocn[i].image =
485 brightonReadImage(bwin, dev[i].image);
486
487 if (dev[i].image2 != 0)
488 {
489 bwin->app->resources[index].devlocn[i].image2 =
490 brightonReadImage(bwin, dev[i].image2);
491 }
492
493 bwin->app->resources[index].devlocn[i].dev =
494 (struct brightonDevice *)
495 brightonCreateDevice(bwin, dev[i].device, index, i, dev[i].image);
496 }
497 return(0);
498 }
499
500 int
brightonCreateInterface(brightonWindow * bwin,brightonApp * app)501 brightonCreateInterface(brightonWindow *bwin, brightonApp *app)
502 {
503 int i;
504 brightonResource *res;
505
506 if (app == 0)
507 return(0);
508
509 /*printf("brightonCreateInterface(%x, %x)\n", bwin, app); */
510
511 bwin->template = app;
512 bwin->app = (brightonIApp *) brightonmalloc(sizeof(brightonIApp));
513
514 bwin->app->nresources = app->nresources;
515 bwin->app->flags = app->flags;
516 bwin->app->init = app->init;
517
518 /* if (bwin->app->init) */
519 /* bwin->app->init(bwin); */
520 bwin->app->resources = (brightonIResource *)
521 brightonmalloc(bwin->app->nresources * sizeof(brightonIResource));
522
523 /*
524 * Go through each panel on the app panels list, generate them, then do the
525 * same for each device on each panel.
526 */
527 for (i = 0; i < app->nresources; i++)
528 {
529 res = &app->resources[i];
530
531 /*printf("%s (%i,%i)/(%i,%i)\n %s, %s\n", res->name, */
532 /* res->x, res->y, res->width, res->height, */
533 /* res->image, res->surface); */
534
535 bwin->app->resources[i].x = res->x;
536 bwin->app->resources[i].y = res->y;
537 bwin->app->resources[i].width = res->width;
538 bwin->app->resources[i].height = res->height;
539 bwin->app->resources[i].flags = res->flags | BRIGHTON_ACTIVE;
540
541 bwin->app->resources[i].image = brightonReadImage(bwin, res->image);
542 bwin->app->resources[i].surface = brightonReadImage(bwin, res->surface);
543
544 /*
545 * We need to calculate our size, and then create a backgorund canvas
546 * for panel rendering. This will only happen when the first configure
547 * notify arrives.
548 */
549 bwin->app->resources[i].init = res->init;
550 bwin->app->resources[i].configure = configurePanel;
551 bwin->app->resources[i].callback = res->callback;
552
553 bwin->app->resources[i].ndevices = res->ndevices;
554
555 brightonCreateDevices(bwin, res, i);
556 }
557 return(0);
558 }
559
560 static int
brightonDestroyDevices(brightonWindow * bwin,brightonIResource * res)561 brightonDestroyDevices(brightonWindow *bwin, brightonIResource *res)
562 {
563 int i;
564 brightonILocations *dev = res->devlocn;
565 brightonDevice *device = (brightonDevice *) dev->dev;
566
567 for (i = 0; i < res->ndevices; i++)
568 {
569 device = (brightonDevice *) dev[i].dev;
570
571 if ((device == 0) || (device->device == -1))
572 continue;
573
574 brightonFreeBitmap(bwin, device->image);
575 brightonFreeBitmap(bwin, device->image2);
576
577 brightonFreeBitmap(bwin,
578 bwin->app->resources[device->panel].devlocn[device->index].image);
579 brightonFreeBitmap(bwin,
580 bwin->app->resources[device->panel].devlocn[device->index].image2);
581
582 /* brightoneDestroyDevice(bwin, dev->device); */
583 }
584
585 brightonfree(res->devlocn);
586
587 return(0);
588 }
589
590 int
brightonDestroyInterface(brightonWindow * bwin)591 brightonDestroyInterface(brightonWindow *bwin)
592 {
593 int i;
594
595 printf("brightonDestroyInterface(%p): %i\n", bwin, bwin->app->nresources);
596
597 for (i = 0; i < bwin->app->nresources; i++)
598 {
599 /*
600 * Since we are going to wipe out this interface, prevent any further
601 * rendering.
602 */
603 bwin->app->resources[i].flags |= BRIGHTON_WITHDRAWN;
604
605 brightonDestroyDevices(bwin, &bwin->app->resources[i]);
606
607 brightonFreeBitmap(bwin, bwin->app->resources[i].image);
608 brightonFreeBitmap(bwin, bwin->app->resources[i].surface);
609 }
610
611 brightonfree(bwin->app->resources);
612 brightonfree(bwin->app);
613
614 return(0);
615 }
616
617