source: trunk/core/gui_draw.c @ 1790

Revision 1790, 16.4 KB checked in by philmoz, 14 months ago (diff)

Fix for SX220 movie record crash from funnel.
http://chdk.setepontos.com/index.php?topic=650.msg83729#msg83729

  • 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];
11void            (*draw_pixel_proc)(unsigned int offset, color cl);
12
13//-------------------------------------------------------------------
14static void draw_pixel_std(unsigned int offset, color cl) {
15#ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY       
16        extern int active_bitmap_buffer;
17        frame_buffer[active_bitmap_buffer][offset] = cl & 0xff;
18#else
19        frame_buffer[0][offset] = frame_buffer[1][offset] = cl & 0xff;
20#endif
21}
22
23//-------------------------------------------------------------------
24void draw_set_draw_proc(void (*pixel_proc)(unsigned int offset, color cl)) {
25    draw_pixel_proc = (pixel_proc)?pixel_proc:draw_pixel_std;
26}
27
28//-------------------------------------------------------------------
29#ifdef CAM_DETECT_SCREEN_ERASE
30
31#define GUARD_VAL   SCREEN_COLOR
32
33void draw_set_guard()
34{
35    *((unsigned char*)(frame_buffer[0])) = GUARD_VAL;
36    *((unsigned char*)(frame_buffer[1])) = GUARD_VAL;
37}
38
39int draw_test_guard()
40{
41    if (*((unsigned char*)(frame_buffer[0])) != GUARD_VAL) return 0;
42    if (*((unsigned char*)(frame_buffer[1])) != GUARD_VAL) return 0;
43    return 1;
44}
45
46// Test a pixel value in both frame buffers, returns 0 if either doesn't match or co-ords out of range
47int draw_test_pixel(coord x, coord y, color c)
48{
49    if (x >= camera_screen.width || y >= camera_screen.height) return 0;
50    return (frame_buffer[0][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x)] == c) &&
51           (frame_buffer[1][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x)] == c);
52}
53
54#endif
55
56//-------------------------------------------------------------------
57void draw_init() {
58    register int i;
59
60    frame_buffer[0] = vid_get_bitmap_fb();
61    frame_buffer[1] = frame_buffer[0] + camera_screen.buffer_size;
62    draw_set_draw_proc(NULL);
63
64#ifdef CAM_DETECT_SCREEN_ERASE
65    draw_set_guard();
66#endif
67}
68
69//-------------------------------------------------------------------
70void draw_pixel(coord x, coord y, color cl) {
71    if (x >= camera_screen.width || y >= camera_screen.height) return;
72    else {
73        register unsigned int offset = y * camera_screen.buffer_width + ASPECT_XCORRECTION(x);
74        draw_pixel_proc(offset,   cl);
75#if CAM_USES_ASPECT_CORRECTION
76        draw_pixel_proc(offset+1, cl);  // Draw second pixel if screen scaling is needed
77#endif
78   }
79}
80
81//-------------------------------------------------------------------
82color draw_get_pixel(coord x, coord y) {
83    if (x >= camera_screen.width || y >= camera_screen.height) return 0;
84    return frame_buffer[0][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x) ];
85}
86
87//-------------------------------------------------------------------
88#define swap(v1, v2)   {v1^=v2; v2^=v1; v1^=v2;}
89//-------------------------------------------------------------------
90void draw_line(coord x1, coord y1, coord x2, coord y2, color cl) {
91     unsigned char steep = abs(y2 - y1) > abs(x2 - x1);
92     if (steep) {
93         swap(x1, y1);
94         swap(x2, y2);
95     }
96     if (x1 > x2) {
97         swap(x1, x2);
98         swap(y1, y2);
99     }
100     int deltax = x2 - x1;
101     int deltay = abs(y2 - y1);
102     int error = 0;
103     int y = y1;
104     int ystep = (y1 < y2)?1:-1;
105     int x;
106     for (x=x1; x<=x2; ++x) {
107         if (steep) draw_pixel(y, x, cl);
108         else draw_pixel(x, y, cl);
109         error += deltay;
110         if ((error<<1) >= deltax) {
111             y += ystep;
112             error -= deltax;
113         }
114     }
115}
116//-------------------------------------------------------------------
117void draw_hline(coord x, coord y, int len, color cl)
118{
119    if (x >= camera_screen.width || y >= camera_screen.height) return;
120    if (x < 0) { len += x; x = 0; }
121    if ((x + len) > camera_screen.width) len = camera_screen.width - x;
122    register unsigned int offset = y * camera_screen.buffer_width + ASPECT_XCORRECTION(x);
123    len = ASPECT_XCORRECTION(len);      // Scale the line length if needed
124    for (; len>0; len--, offset++)
125        draw_pixel_proc(offset, cl);
126}
127
128void draw_vline(coord x, coord y, int len, color cl)
129{
130    if ((x < 0) || (x >= camera_screen.width) || (y >= camera_screen.height)) return;
131    if (y < 0) { len += y; y = 0; }
132    if ((y + len) > camera_screen.height) len = camera_screen.height - y;
133    for (; len>0; len--, y++)
134      draw_pixel(x, y, cl);
135}
136//-------------------------------------------------------------------
137
138// Local variables set up by draw_rectangle, and used in fill_rect
139static unsigned int xMin, yMin, xMax, yMax;
140
141static void draw_rectangle(coord x1, coord y1, coord x2, coord y2, color cl, int round)
142{
143    register unsigned int x, y;
144
145    if (x1>x2) {
146        xMax=x1; xMin=x2;
147    } else {
148        xMin=x1; xMax=x2;
149    }
150    if (y1>y2) {
151        yMax=y1; yMin=y2;
152    } else {
153        yMin=y1; yMax=y2;
154    }
155    if (xMax>=camera_screen.width) xMax=camera_screen.width-1;
156    if (xMin>=camera_screen.width) xMin=camera_screen.width-1;
157    if (yMax>=camera_screen.height) yMax=camera_screen.height-1;
158    if (yMin>=camera_screen.height) yMin=camera_screen.height-1;
159
160    for (y=yMin+(round<<1); y<=yMax-(round<<1); ++y)
161    {
162      draw_pixel(xMin, y, cl);
163      draw_pixel(xMax, y, cl);
164    }
165
166    draw_hline(xMin+1+round, yMin, (xMax-1-round) - (xMin+1+round) + 1, cl);
167    draw_hline(xMin+1+round, yMax, (xMax-1-round) - (xMin+1+round) + 1, cl);
168}
169
170//-------------------------------------------------------------------
171void draw_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
172    draw_rectangle(x1,y1,x2,y2,cl&0xff,0);
173}
174
175void draw_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
176    int i;
177    cl = cl & 0xff;
178    for (i=0; i<thickness; i++)
179    {
180        draw_rectangle(x1+i,y1+i,x2-i,y2-i,cl,0);
181    }
182}
183
184void draw_rect_shadow(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
185    int i;
186    cl = cl & 0xff;
187    for (i=0; i<thickness; i++)
188    {
189        draw_rectangle(x1+i,y1+i,x2+i,y2+i,cl,0);
190    }
191}
192//-------------------------------------------------------------------
193void draw_round_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
194    draw_rectangle(x1,y1,x2,y2,cl&0xff,1);
195}
196
197void draw_round_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
198    int i;
199    cl = cl & 0xff;
200    draw_rectangle(x1,y1,x2,y2,cl,1);
201    for (i=1; i<thickness; i++)
202    {
203        draw_rectangle(x1+i,y1+i,x2-i,y2-i,cl,0);
204    }
205}
206//-------------------------------------------------------------------
207static void fill_rect(color cl) {
208    register unsigned int x, y;
209
210    cl = BG_COLOR(cl);
211    for (y=yMin+1; y<=yMax-1; ++y)
212    {
213        draw_hline(xMin+1, y, (xMax-1) - (xMin+1) + 1, cl);
214    }
215}
216//-------------------------------------------------------------------
217void draw_filled_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
218    draw_rect(x1, y1, x2, y2, cl);
219    fill_rect(cl);
220}
221
222void draw_filled_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
223    draw_rect_thick(x1, y1, x2, y2, cl, thickness);
224    fill_rect(cl);
225}
226//-------------------------------------------------------------------
227void draw_filled_round_rect(coord x1, coord y1, coord x2, coord y2, color cl) {
228    draw_round_rect(x1, y1, x2, y2, cl);
229    fill_rect(cl);
230}
231
232void draw_filled_round_rect_thick(coord x1, coord y1, coord x2, coord y2, color cl, int thickness) {
233    draw_round_rect_thick(x1, y1, x2, y2, cl, thickness);
234    fill_rect(cl);
235}
236//-------------------------------------------------------------------
237void draw_char(coord x, coord y, const char ch, color cl)
238{
239    FontData *f = (FontData*)get_current_font_data(ch);
240    const unsigned char *sym = (unsigned char*)f + sizeof(FontData) - f->offset;
241    int i, ii;
242
243    // First draw blank lines at top
244    for (i=0; i<f->offset; i++)
245        draw_hline(x, y+i, FONT_WIDTH, BG_COLOR(cl));
246    // Now draw character data
247    for (; i<f->offset+f->size; i++)
248    {
249            for (ii=0; ii<FONT_WIDTH; ii++)
250        {
251            draw_pixel(x+ii ,y+i, (sym[i] & (0x80>>ii))? FG_COLOR(cl) : BG_COLOR(cl));
252            }
253    }
254    // Last draw blank lines at bottom
255    for (; i<FONT_HEIGHT; i++)
256        draw_hline(x, y+i, FONT_WIDTH, BG_COLOR(cl));
257}
258
259//-------------------------------------------------------------------
260void draw_string(coord x, coord y, const char *s, color cl) {
261    while(*s)
262    {
263            draw_char(x, y, *s, cl);
264            s++;
265            x+=FONT_WIDTH;
266            if ((x>=camera_screen.width) && (*s))
267        {
268                draw_char(x-FONT_WIDTH,y, '>', cl);
269                break;
270            }
271    }
272}
273
274//-------------------------------------------------------------------
275void draw_txt_rect(coord col, coord row, unsigned int length, unsigned int height, color cl) {
276    draw_rect(col*FONT_WIDTH, row*FONT_HEIGHT, (col+length)*FONT_WIDTH-1, (row+height)*FONT_HEIGHT-1, cl);
277}
278
279//-------------------------------------------------------------------
280void draw_txt_rect_exp(coord col, coord row, unsigned int length, unsigned int height, unsigned int exp, color cl) {
281    draw_rect(col*FONT_WIDTH-exp, row*FONT_HEIGHT-exp, (col+length)*FONT_WIDTH-1+exp, (row+height)*FONT_HEIGHT-1+exp, cl);
282}
283
284//-------------------------------------------------------------------
285void draw_txt_filled_rect(coord col, coord row, unsigned int length, unsigned int height, color cl) {
286    draw_filled_rect(col*FONT_WIDTH, row*FONT_HEIGHT, (col+length)*FONT_WIDTH-1, (row+height)*FONT_HEIGHT-1, cl);
287}
288
289//-------------------------------------------------------------------
290void draw_txt_filled_rect_exp(coord col, coord row, unsigned int length, unsigned int height, unsigned int exp, color cl) {
291    draw_filled_rect(col*FONT_WIDTH-exp, row*FONT_HEIGHT-exp, (col+length)*FONT_WIDTH-1+exp, (row+height)*FONT_HEIGHT-1+exp, cl);
292}
293
294//-------------------------------------------------------------------
295void draw_txt_string(coord col, coord row, const char *str, color cl) {
296    draw_string(col*FONT_WIDTH, row*FONT_HEIGHT, str, cl);
297}
298
299//-------------------------------------------------------------------
300void draw_txt_char(coord col, coord row, const char ch, color cl) {
301    draw_char(col*FONT_WIDTH, row*FONT_HEIGHT, ch, cl);
302}
303
304//-------------------------------------------------------------------
305void draw_clear() {
306    memset(frame_buffer[0], COLOR_TRANSPARENT, camera_screen.buffer_size*2);
307}
308
309// Restore CANON_OSD
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 = MAKE_COLOR(BG_COLOR(cl), BG_COLOR(cl));
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.