source: branches/release-1_0/core/gui_draw.c @ 1795

Revision 1795, 16.5 KB checked in by philmoz, 14 months ago (diff)

Merged revision(s) 1762 from trunk:

  • Property svn:eol-style set to native
Line 
1#include "stdlib.h"
2#include "platform.h"
3#include "core.h"
4#include "keyboard.h"
5#include "conf.h"
6#include "font.h"
7#include "gui_draw.h"
8
9//-------------------------------------------------------------------
10static char*    frame_buffer[2];
11unsigned int    screen_width=0, screen_height=0, screen_size=0;
12unsigned int    screen_buffer_width=0, screen_buffer_height=0, screen_buffer_size=0;
13void            (*draw_pixel_proc)(unsigned int offset, color cl);
14
15//-------------------------------------------------------------------
16static void draw_pixel_std(unsigned int offset, color cl) {
17#ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY       
18        extern int active_bitmap_buffer;
19        frame_buffer[active_bitmap_buffer][offset] = cl & 0xff;
20#else
21        frame_buffer[0][offset] = frame_buffer[1][offset] = cl & 0xff;
22#endif
23}
24
25//-------------------------------------------------------------------
26void draw_set_draw_proc(void (*pixel_proc)(unsigned int offset, color cl)) {
27    draw_pixel_proc = (pixel_proc)?pixel_proc:draw_pixel_std;
28}
29
30//-------------------------------------------------------------------
31#ifdef CAM_DETECT_SCREEN_ERASE
32
33#define GUARD_VAL   SCREEN_COLOR
34
35void draw_set_guard()
36{
37    *((unsigned char*)(frame_buffer[0])) = GUARD_VAL;
38    *((unsigned char*)(frame_buffer[1])) = GUARD_VAL;
39}
40
41int draw_test_guard()
42{
43    if (*((unsigned char*)(frame_buffer[0])) != GUARD_VAL) return 0;
44    if (*((unsigned char*)(frame_buffer[1])) != GUARD_VAL) return 0;
45    return 1;
46}
47
48// Test a pixel value in both frame buffers, returns 0 if either doesn't match or co-ords out of range
49int draw_test_pixel(coord x, coord y, color c)
50{
51    if (x >= screen_width || y >= screen_height) return 0;
52    return (frame_buffer[0][y * screen_buffer_width + ASPECT_XCORRECTION(x)] == c) &&
53           (frame_buffer[1][y * screen_buffer_width + ASPECT_XCORRECTION(x)] == c);
54}
55
56#endif
57
58//-------------------------------------------------------------------
59void draw_init() {
60    register int i;
61
62    screen_width = vid_get_bitmap_screen_width();
63    screen_height  = vid_get_bitmap_screen_height();
64    screen_size = screen_width * screen_height;
65    screen_buffer_width = vid_get_bitmap_buffer_width();
66    screen_buffer_height = vid_get_bitmap_buffer_height();
67    screen_buffer_size = screen_buffer_width * screen_buffer_height;
68    frame_buffer[0] = vid_get_bitmap_fb();
69    frame_buffer[1] = frame_buffer[0] + screen_buffer_size;
70    draw_set_draw_proc(NULL);
71
72#ifdef CAM_DETECT_SCREEN_ERASE
73    draw_set_guard();
74#endif
75}
76
77//-------------------------------------------------------------------
78void draw_pixel(coord x, coord y, color cl) {
79    if (x >= screen_width || y >= screen_height) return;
80    else {
81        register unsigned int offset = y * screen_buffer_width + ASPECT_XCORRECTION(x);
82        draw_pixel_proc(offset,   cl);
83#if CAM_USES_ASPECT_CORRECTION
84        draw_pixel_proc(offset+1, cl);  // Draw second pixel if screen scaling is needed
85#endif
86   }
87}
88
89//-------------------------------------------------------------------
90color draw_get_pixel(coord x, coord y) {
91    if (x >= screen_width || y >= screen_height) return 0;
92    return frame_buffer[0][y * screen_buffer_width + ASPECT_XCORRECTION(x) ];
93}
94
95//-------------------------------------------------------------------
96#define swap(v1, v2)   {v1^=v2; v2^=v1; v1^=v2;}
97//-------------------------------------------------------------------
98void draw_line(coord x1, coord y1, coord x2, coord y2, color cl) {
99     unsigned char steep = abs(y2 - y1) > abs(x2 - x1);
100     if (steep) {
101         swap(x1, y1);
102         swap(x2, y2);
103     }
104     if (x1 > x2) {
105         swap(x1, x2);
106         swap(y1, y2);
107     }
108     int deltax = x2 - x1;
109     int deltay = abs(y2 - y1);
110     int error = 0;
111     int y = y1;
112     int ystep = (y1 < y2)?1:-1;
113     int x;
114     for (x=x1; x<=x2; ++x) {
115         if (steep) draw_pixel(y, x, cl);
116         else draw_pixel(x, y, cl);
117         error += deltay;
118         if ((error<<1) >= deltax) {
119             y += ystep;
120             error -= deltax;
121         }
122     }
123}
124//-------------------------------------------------------------------
125void draw_hline(coord x, coord y, int len, color cl)
126{
127    if (x >= screen_width || y >= screen_height) return;
128    if (x < 0) { len += x; x = 0; }
129    if ((x + len) > screen_width) len = screen_width - x;
130    register unsigned int offset = y * screen_buffer_width + ASPECT_XCORRECTION(x);
131    len = ASPECT_XCORRECTION(len);      // Scale the line length if needed
132    for (; len>0; len--, offset++)
133        draw_pixel_proc(offset, cl);
134}
135
136void draw_vline(coord x, coord y, int len, color cl)
137{
138    if ((x < 0) || (x >= screen_width) || (y >= screen_height)) return;
139    if (y < 0) { len += y; y = 0; }
140    if ((y + len) > screen_height) len = screen_height - y;
141    for (; len>0; len--, y++)
142      draw_pixel(x, y, cl);
143}
144//-------------------------------------------------------------------
145
146// Local variables set up by draw_rectangle, and used in fill_rect
147static unsigned int xMin, yMin, xMax, yMax;
148
149static void draw_rectangle(coord x1, coord y1, coord x2, coord y2, color cl, int round)
150{
151    register unsigned int x, y;
152
153    if (x1>x2) {
154        xMax=x1; xMin=x2;
155    } else {
156        xMin=x1; xMax=x2;
157    }
158    if (y1>y2) {
159        yMax=y1; yMin=y2;
160    } else {
161        yMin=y1; yMax=y2;
162    }
163    if (xMax>=screen_width) xMax=screen_width-1;
164    if (xMin>=screen_width) xMin=screen_width-1;
165    if (yMax>=screen_height) yMax=screen_height-1;
166    if (yMin>=screen_height) yMin=screen_height-1;
167
168    for (y=yMin+(round<<1); y<=yMax-(round<<1); ++y)
169    {
170      draw_pixel(xMin, y, cl);
171      draw_pixel(xMax, y, cl);
172    }
173
174    draw_hline(xMin+1+round, yMin, (xMax-1-round) - (xMin+1+round) + 1, cl);
175    draw_hline(xMin+1+round, yMax, (xMax-1-round) - (xMin+1+round) + 1, cl);
176}
177
178//-------------------------------------------------------------------
179void draw_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
180    draw_rectangle(x1,y1,x2,y2,cl&0xff,0);
181}
182
183void draw_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
184    int i;
185    cl = cl & 0xff;
186    for (i=0; i<thickness; i++)
187    {
188        draw_rectangle(x1+i,y1+i,x2-i,y2-i,cl,0);
189    }
190}
191
192void draw_rect_shadow(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
193    int i;
194    cl = cl & 0xff;
195    for (i=0; i<thickness; i++)
196    {
197        draw_rectangle(x1+i,y1+i,x2+i,y2+i,cl,0);
198    }
199}
200//-------------------------------------------------------------------
201void draw_round_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
202    draw_rectangle(x1,y1,x2,y2,cl&0xff,1);
203}
204
205void draw_round_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
206    int i;
207    cl = cl & 0xff;
208    draw_rectangle(x1,y1,x2,y2,cl,1);
209    for (i=1; i<thickness; i++)
210    {
211        draw_rectangle(x1+i,y1+i,x2-i,y2-i,cl,0);
212    }
213}
214//-------------------------------------------------------------------
215static void fill_rect(color cl) {
216    register unsigned int x, y;
217
218    cl = cl >> 8;
219    for (y=yMin+1; y<=yMax-1; ++y)
220    {
221        draw_hline(xMin+1, y, (xMax-1) - (xMin+1) + 1, cl);
222    }
223}
224//-------------------------------------------------------------------
225void draw_filled_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
226    draw_rect(x1, y1, x2, y2, cl);
227    fill_rect(cl);
228}
229
230void draw_filled_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
231    draw_rect_thick(x1, y1, x2, y2, cl, thickness);
232    fill_rect(cl);
233}
234//-------------------------------------------------------------------
235void draw_filled_round_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
236    draw_round_rect(x1, y1, x2, y2, cl);
237    fill_rect(cl);
238}
239
240void draw_filled_round_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
241    draw_round_rect_thick(x1, y1, x2, y2, cl, thickness);
242    fill_rect(cl);
243}
244//-------------------------------------------------------------------
245void draw_char(coord x, coord y, const char ch, color cl) {
246    const unsigned char *sym = (unsigned char*)current_font + ((const unsigned char)ch)*FONT_HEIGHT;
247    int i, ii;
248
249    // XXX optimize. probably use 4bit -> 32bit lookup table
250    // so 4(8) pixels were drawn at a time
251    for (i=0; i<FONT_HEIGHT; i++)
252    {
253            for (ii=0; ii<FONT_WIDTH; ii++)
254        {
255            draw_pixel(x+ii ,y+i, (sym[i] & (0x80>>ii))? cl&0xff : cl>>8);
256            }
257    }
258}
259
260//-------------------------------------------------------------------
261void draw_string(coord x, coord y, const char *s, color cl) {
262    while(*s)
263    {
264            draw_char(x, y, *s, cl);
265            s++;
266            x+=FONT_WIDTH;
267            if ((x>=screen_width) && (*s))
268        {
269                draw_char(x-FONT_WIDTH,y, '>', cl);
270                break;
271            }
272    }
273}
274
275//-------------------------------------------------------------------
276void draw_txt_rect(coord col, coord row, unsigned int length, unsigned int height, color cl) {
277    draw_rect(col*FONT_WIDTH, row*FONT_HEIGHT, (col+length)*FONT_WIDTH-1, (row+height)*FONT_HEIGHT-1, cl);
278}
279
280//-------------------------------------------------------------------
281void draw_txt_rect_exp(coord col, coord row, unsigned int length, unsigned int height, unsigned int exp, color cl) {
282    draw_rect(col*FONT_WIDTH-exp, row*FONT_HEIGHT-exp, (col+length)*FONT_WIDTH-1+exp, (row+height)*FONT_HEIGHT-1+exp, cl);
283}
284
285//-------------------------------------------------------------------
286void draw_txt_filled_rect(coord col, coord row, unsigned int length, unsigned int height, color cl) {
287    draw_filled_rect(col*FONT_WIDTH, row*FONT_HEIGHT, (col+length)*FONT_WIDTH-1, (row+height)*FONT_HEIGHT-1, cl);
288}
289
290//-------------------------------------------------------------------
291void draw_txt_filled_rect_exp(coord col, coord row, unsigned int length, unsigned int height, unsigned int exp, color cl) {
292    draw_filled_rect(col*FONT_WIDTH-exp, row*FONT_HEIGHT-exp, (col+length)*FONT_WIDTH-1+exp, (row+height)*FONT_HEIGHT-1+exp, cl);
293}
294
295//-------------------------------------------------------------------
296void draw_txt_string(coord col, coord row, const char *str, color cl) {
297    draw_string(col*FONT_WIDTH, row*FONT_HEIGHT, str, cl);
298}
299
300//-------------------------------------------------------------------
301void draw_txt_char(coord col, coord row, const char ch, color cl) {
302    draw_char(col*FONT_WIDTH, row*FONT_HEIGHT, ch, cl);
303}
304
305//-------------------------------------------------------------------
306void draw_clear() {
307    memset(frame_buffer[0], COLOR_TRANSPARENT, screen_buffer_size*2);
308}
309
310//-------------------------------------------------------------------
311void draw_restore() {
312    vid_bitmap_refresh();
313
314#ifdef CAM_DETECT_SCREEN_ERASE
315    draw_set_guard();
316#ifdef CAM_TOUCHSCREEN_UI
317    extern int redraw_buttons;
318    redraw_buttons = 1;
319#endif
320#endif
321}
322
323//-------------------------------------------------------------------
324//void draw_fill(coord x, coord y, color cl_fill, color cl_bound) {
325//   if (draw_get_pixel(x, y) != cl_bound && draw_get_pixel(x, y) != cl_fill) {
326//       draw_pixel(x, y, cl_fill);
327//
328//       draw_fill((x+1), y, cl_fill,cl_bound);
329//       draw_fill((x-1), y, cl_fill,cl_bound);
330//       draw_fill(x, (y+1), cl_fill,cl_bound);
331//       draw_fill(x, (y-1), cl_fill,cl_bound);
332//   }
333//}
334
335//-------------------------------------------------------------------
336void draw_circle(coord x, coord y, const unsigned int r, color cl) {
337    int dx = 0;
338    int dy = r;
339    int p=(3-(r<<1));
340
341    do {
342        draw_pixel((x+dx),(y+dy),cl);
343        draw_pixel((x+dy),(y+dx),cl);
344        draw_pixel((x+dy),(y-dx),cl);
345        draw_pixel((x+dx),(y-dy),cl);
346        draw_pixel((x-dx),(y-dy),cl);
347        draw_pixel((x-dy),(y-dx),cl);
348        draw_pixel((x-dy),(y+dx),cl);
349        draw_pixel((x-dx),(y+dy),cl);
350
351        ++dx;
352
353        if (p<0)
354            p += ((dx<<2)+6);
355        else {
356            --dy;
357            p += (((dx-dy)<<2)+10);
358        }
359    } while (dx<=dy);
360}
361
362//-------------------------------------------------------------------
363void draw_ellipse(coord xc, coord yc, unsigned int a, unsigned int b, color cl) {
364    int x = 0, y = b;
365    long a2 = (long)a*a, b2 = (long)b*b;
366    long crit1 = -((a2>>2) + (a&1) + b2);
367    long crit2 = -((b2>>2) + (b&1) + a2);
368    long crit3 = -((b2>>2) + (b&1));
369    long t = -a2*y;
370    long dxt = b2*x*2, dyt = -2*a2*y;
371    long d2xt = b2*2, d2yt = a2*2;
372
373    while (y>=0 && x<=a) {
374        draw_pixel(xc+x, yc+y, cl);
375        if (x!=0 || y!=0)
376            draw_pixel(xc-x, yc-y, cl);
377        if (x!=0 && y!=0) {
378            draw_pixel(xc+x, yc-y, cl);
379            draw_pixel(xc-x, yc+y, cl);
380        }
381        if (t + b2*x <= crit1 || t + a2*y <= crit3)
382            ++x, dxt += d2xt, t += dxt;
383        else if (t - a2*y > crit2)
384            --y, dyt += d2yt, t += dyt;
385        else {
386            ++x, dxt += d2xt, t += dxt;
387            --y, dyt += d2yt, t += dyt;
388        }
389   }
390}
391
392//-------------------------------------------------------------------
393void draw_filled_ellipse(coord xc, coord yc, unsigned int a, unsigned int b, color cl) {
394    int x = 0, y = b;
395    int rx = x, ry = y;
396    unsigned int width = 1;
397    unsigned int height = 1;
398    long a2 = (long)a*a, b2 = (long)b*b;
399    long crit1 = -((a2>>2) + (a&1) + b2);
400    long crit2 = -((b2>>2) + (b&1) + a2);
401    long crit3 = -((b2>>2) + (b&1));
402    long t = -a2*y;
403    long dxt = 2*b2*x, dyt = -2*a2*y;
404    long d2xt = 2*b2, d2yt = 2*a2;
405   
406    color cl_fill = ((cl >> 8) & 0xff) | (cl & 0xff00);
407
408    if (b == 0) {
409        draw_filled_rect(xc-a, yc, (a<<1)+1, 1, cl_fill);
410    } else {
411        while (y>=0 && x<=a) {
412            if (t + b2*x <= crit1 || t + a2*y <= crit3) {
413                if (height == 1)
414                    ; /* draw nothing */
415                else if (ry*2+1 > (height-1)*2) {
416                    draw_filled_rect(xc-rx, yc-ry, xc-rx+width-1, yc-ry+(height-1)-1, cl_fill);
417                    draw_filled_rect(xc-rx, yc+ry+1, xc-rx+width-1, yc+ry+1+(1-height)-1, cl_fill);
418                    ry -= height-1;
419                    height = 1;
420                }
421                else {
422                    draw_filled_rect(xc-rx, yc-ry, xc-rx+width-1, yc-ry+(ry*2+1)-1, cl_fill);
423                    ry -= ry;
424                    height = 1;
425                }
426                ++x, dxt += d2xt, t += dxt;
427                rx++;
428                width += 2;
429            }
430            else if (t - a2*y > crit2) {
431                --y, dyt += d2yt, t += dyt;
432                height++;
433            }
434            else {
435                if (ry*2+1 > height*2) {
436                    draw_filled_rect(xc-rx, yc-ry, xc-rx+width-1, yc-ry+height-1, cl_fill);
437                    draw_filled_rect(xc-rx, yc+ry+1, xc-rx+width-1, yc+ry+1-height-1, cl_fill);
438                }
439                else {
440                    draw_filled_rect(xc-rx, yc-ry, xc-rx+width-1, yc-ry+(ry*2+1)-1, cl_fill);
441                }
442                ++x, dxt += d2xt, t += dxt;
443                --y, dyt += d2yt, t += dyt;
444                rx++;
445                width += 2;
446                ry -= height;
447                height = 1;
448            }
449        }
450
451        if (ry > height) {
452            draw_filled_rect(xc-rx, yc-ry, xc-rx+width-1, yc-ry+height-1, cl_fill);
453            draw_filled_rect(xc-rx, yc+ry+1, xc-rx+width-1, yc+ry+1-height-1, cl_fill);
454        }
455        else {
456            draw_filled_rect(xc-rx, yc-ry, xc-rx+width-1, yc-ry+(ry*2+1)-1, cl_fill);
457        }
458    }
459}
460//-------------------------------------------------------------------
461
462// Colors for icons
463// 3 shades for each color
464//  icon_xxx[0] = dark, icon_xxx[1] = medium, icon_xxx[2] = light
465color icon_green[3], icon_red[3], icon_yellow[3], icon_grey[3];
466
467void draw_get_icon_colors()
468{
469    if((mode_get()&MODE_MASK) == MODE_REC)
470    {
471        icon_green[0]  = COLOR_ICON_REC_GREEN_DK;  icon_green[1]  = COLOR_ICON_REC_GREEN;  icon_green[2]  = COLOR_ICON_REC_GREEN_LT;
472        icon_yellow[0] = COLOR_ICON_REC_YELLOW_DK; icon_yellow[1] = COLOR_ICON_REC_YELLOW; icon_yellow[2] = COLOR_ICON_REC_YELLOW_LT;
473        icon_red[0]    = COLOR_ICON_REC_RED_DK;    icon_red[1]    = COLOR_ICON_REC_RED;    icon_red[2]    = COLOR_ICON_REC_RED_LT;
474        icon_grey[0]   = COLOR_ICON_REC_GREY_DK;   icon_grey[1]   = COLOR_ICON_REC_GREY;   icon_grey[2]   = COLOR_ICON_REC_GREY_LT;
475    }
476    else
477    {
478        icon_green[0]  = COLOR_ICON_PLY_GREEN_DK;  icon_green[1]  = COLOR_ICON_PLY_GREEN;  icon_green[2]  = COLOR_ICON_PLY_GREEN_LT;
479        icon_yellow[0] = COLOR_ICON_PLY_YELLOW_DK; icon_yellow[1] = COLOR_ICON_PLY_YELLOW; icon_yellow[2] = COLOR_ICON_PLY_YELLOW_LT;
480        icon_red[0]    = COLOR_ICON_PLY_RED_DK;    icon_red[1]    = COLOR_ICON_PLY_RED;    icon_red[2]    = COLOR_ICON_PLY_RED_LT;
481        icon_grey[0]   = COLOR_ICON_PLY_GREY_DK;   icon_grey[1]   = COLOR_ICON_PLY_GREY;   icon_grey[2]   = COLOR_ICON_PLY_GREY_LT;
482    }
483}
Note: See TracBrowser for help on using the repository browser.