root/core/gui_draw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. draw_pixel_std
  2. set_transparent
  3. color_to_rawpx
  4. draw_dblpixel_raw
  5. color_to_rawpx
  6. draw_dblpixel_raw
  7. set_transparent
  8. draw_pixel_proc_rotated
  9. draw_set_draw_proc
  10. update_draw_proc
  11. draw_pixel_simple_start
  12. draw_1pixel_simple
  13. draw_2pixels_simple
  14. draw_hline_simple
  15. draw_set_guard
  16. draw_test_guard
  17. draw_set_guard
  18. draw_test_guard
  19. draw_init
  20. draw_restore
  21. draw_pixel
  22. draw_pixel_unrotated
  23. draw_get_pixel
  24. draw_get_pixel_unrotated
  25. draw_line
  26. draw_hline
  27. draw_vline
  28. draw_rectangle
  29. get_cdata
  30. draw_char
  31. draw_char
  32. draw_char_unscaled
  33. draw_char_scaled
  34. draw_char_scaled
  35. draw_string_clipped
  36. draw_string
  37. draw_string_justified
  38. text_dimensions
  39. draw_text_justified
  40. draw_string_scaled
  41. draw_string_scaled
  42. draw_osd_string
  43. draw_osd_string
  44. draw_txt_string
  45. draw_ellipse
  46. draw_button
  47. draw_icon_cmds
  48. set_palette
  49. get_script_color
  50. chdkColorToCanonColor
  51. user_color

   1 #include "platform.h"
   2 #include "stdlib.h"
   3 #include "touchscreen.h"
   4 #include "conf.h"
   5 #include "font.h"
   6 #include "lang.h"
   7 #include "gui_draw.h"
   8 
   9 #define GET_FONT_COMPRESSION_MODE 1
  10 #include "../lib/font/font_8x16_uni_packed.h"
  11 #undef  GET_FONT_COMPRESSION_MODE
  12 
  13 #ifdef THUMB_FW
  14 // macros for computing palette from a single byte color value
  15 #define CALC_YUV_LUMA_OPACITY_FOR_COLOR(color,luma,opacity) \
  16     { \
  17         luma = ((color-1)^0xffffffff)&0xf0; \
  18         opacity = (color&0xf)?255:color; \
  19     }
  20 
  21 #define CALC_YUV_CHROMA_FOR_COLOR(color,u,v) \
  22     { \
  23         v = color; \
  24         u = (v+1); \
  25         if (!(u&2)) \
  26         { \
  27             u = 128; \
  28             v = 128; \
  29         } \
  30         else \
  31         { \
  32             u *= 3; \
  33             v <<= 3; \
  34         } \
  35     }
  36 
  37 extern volatile char *opacity_buffer[];
  38 
  39 #endif
  40 //-------------------------------------------------------------------
  41 void            (*draw_pixel_proc)(unsigned int offset, color cl);
  42 void            (*draw_pixel_proc_norm)(unsigned int offset, color cl);
  43 
  44 #ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
  45 extern char* bitmap_buffer[];
  46 extern int active_bitmap_buffer;
  47 #else
  48 static char* frame_buffer[2];
  49 #endif
  50 //-------------------------------------------------------------------
  51 
  52 static void draw_pixel_std(unsigned int offset, color cl)
  53 {
  54 #ifndef THUMB_FW
  55     // drawing on 8bpp paletted overlay
  56 #ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
  57         bitmap_buffer[active_bitmap_buffer][offset] = cl;
  58 #else
  59         frame_buffer[0][offset] = frame_buffer[1][offset] = cl;
  60 #endif
  61 #else
  62     // DIGIC 6, drawing on 16bpp YUV overlay
  63 
  64 #ifndef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
  65 #error DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY is required for DIGIC 6 ports
  66 #endif
  67 
  68     int active_buffer_index =  active_bitmap_buffer & 1;
  69     unsigned char *obu = (unsigned char *)(&opacity_buffer[active_buffer_index][0]);
  70     unsigned char *bbu = (unsigned char *)(&bitmap_buffer[active_buffer_index][0]);
  71     unsigned int y;
  72     unsigned int o;
  73     CALC_YUV_LUMA_OPACITY_FOR_COLOR(cl,y,o);
  74     obu[offset] = o;
  75     register unsigned int offs2 = (offset>>1)<<2;
  76     if (offset&1) // x is odd
  77     {
  78         bbu[offs2+3] = y; // Y
  79     }
  80     else // x is even
  81     {
  82         unsigned int u;
  83         unsigned int v;
  84         CALC_YUV_CHROMA_FOR_COLOR(cl,u,v);
  85         bbu[offs2+1] = y; // Y
  86         bbu[offs2+0] = u; // U?
  87         bbu[offs2+2] = v; // V?
  88 
  89     }
  90 #endif
  91 }
  92 //-------------------------------------------------------------------
  93 #ifdef THUMB_FW
  94 // direct drawing functions for YUV overlay, currently used by the zebra module
  95 // ATTENTION: these functions do not support guard pixels or rotation
  96 
  97 // function for setting part of the overlay transparent (DIGIC 6 only), used in zebra module
  98 // n_pixel is the number of pixels to set
  99 // offst is the byte offset in bitmap_buffer, 2 bytes per pixel
 100 void set_transparent(unsigned int offst, int n_pixel)
 101 {
 102     extern void _bzero(char *s, int n);
 103     extern void _memset32(char *s, int n, unsigned int pattern);
 104     //offset is the byte (same as pixel) offset in the opacity buffer
 105     unsigned int offset = offst>>2;
 106     unsigned int w_pattern = 0x00800080;
 107 
 108     int active_buffer_index = active_bitmap_buffer & 1;
 109 
 110     _memset32(&bitmap_buffer[active_buffer_index][offst], n_pixel<<1, w_pattern);
 111     _bzero((char*)&opacity_buffer[active_buffer_index][offset], n_pixel);
 112 
 113 }
 114 
 115 // translate single byte CHDK color to a whole yuv unit (2 pixels)
 116 // opacity is returned via the second argument
 117 unsigned int color_to_rawpx(color cl, unsigned int *op)
 118 {
 119     unsigned int y,u,v,o;
 120     CALC_YUV_CHROMA_FOR_COLOR(cl,u,v);
 121     CALC_YUV_LUMA_OPACITY_FOR_COLOR(cl,y,o);
 122     if (op) *op = o;
 123     return (u&255)+((y&255)<<8)+((v&255)<<16)+(y<<24);
 124 }
 125 
 126 // function for drawing a whole yuv unit (2 pixels, aligned)
 127 // opacity is a single byte, used for both pixels
 128 // drawing offset is pixel offset, calculated by caller
 129 void draw_dblpixel_raw(unsigned int offset, unsigned int px, unsigned int op)
 130 {
 131     int active_buffer_index =  active_bitmap_buffer & 1;
 132     offset >>= 2;
 133     unsigned short * opbuf = (unsigned short*)(opacity_buffer[active_buffer_index]);
 134     unsigned int * bmbuf = (unsigned int*)(bitmap_buffer[active_buffer_index]);
 135     bmbuf[offset] = px;
 136     opbuf[offset] = op | (op<<8);
 137 }
 138 
 139 #else // !THUMB_FW
 140 // not implemented for earlier DIGICs
 141 unsigned int color_to_rawpx(color cl, unsigned int *op)
 142 {
 143     return 0;
 144 }
 145 void draw_dblpixel_raw(unsigned int offset, unsigned int px, unsigned int op)
 146 {
 147 }
 148 void set_transparent(unsigned int offst, int n_pixel)
 149 {
 150 }
 151 #endif // THUMB_FW
 152 
 153 //-------------------------------------------------------------------
 154 unsigned int rotate_base;
 155 
 156 void draw_pixel_proc_rotated(unsigned int offset, color cl)
 157 {
 158     draw_pixel_proc_norm(rotate_base - offset, cl);
 159 }
 160 
 161 void draw_set_draw_proc(void (*pixel_proc)(unsigned int offset, color cl))
 162 {
 163     draw_pixel_proc_norm = (pixel_proc)?pixel_proc:draw_pixel_std;
 164     if (conf.rotate_osd)
 165     {
 166         rotate_base = (camera_screen.height - 1) * camera_screen.buffer_width + ASPECT_XCORRECTION(camera_screen.width) - 1;
 167         draw_pixel_proc = draw_pixel_proc_rotated;
 168     }
 169     else
 170     {
 171         draw_pixel_proc = draw_pixel_proc_norm;
 172     }
 173 }
 174 
 175 void update_draw_proc()
 176 {
 177     draw_set_draw_proc(draw_pixel_proc_norm);
 178 }
 179 
 180 //-------------------------------------------------------------------
 181 #ifdef THUMB_FW
 182 // pixel drawing functions for YUV, meant to be optimized for greater speed
 183 // drawing is done directly, drawing function replacement is not supported
 184 // OSD rotation is respected
 185 
 186 static unsigned char *current_opacity_buf;
 187 static unsigned char *current_bitmap_buf;
 188 static unsigned char yuvclr[8]; // order of bytes: background u,y,v,opacity; foreground u,y,v,opacity
 189 
 190 // sets up decoded colors and buffer addresses for the following drawing operation
 191 static void draw_pixel_simple_start(twoColors tc)
 192 {
 193     color cl;
 194     int active_buffer_index =  active_bitmap_buffer & 1;
 195     current_opacity_buf = (unsigned char *)(&opacity_buffer[active_buffer_index][0]);
 196     current_bitmap_buf = (unsigned char *)(&bitmap_buffer[active_buffer_index][0]);
 197     cl = BG_COLOR(tc);
 198     CALC_YUV_LUMA_OPACITY_FOR_COLOR(cl,yuvclr[1],yuvclr[3]);
 199     CALC_YUV_CHROMA_FOR_COLOR(cl,yuvclr[0],yuvclr[2]);
 200     cl = FG_COLOR(tc);
 201     CALC_YUV_LUMA_OPACITY_FOR_COLOR(cl,yuvclr[5],yuvclr[7]);
 202     CALC_YUV_CHROMA_FOR_COLOR(cl,yuvclr[4],yuvclr[6]);
 203 }
 204 
 205 // px: bit0 unset for background, set for foreground
 206 static void draw_1pixel_simple(coord x, coord y, int px, int vrepeat)
 207 {
 208     if ((x < 0) || (y < 0) || (x >= camera_screen.width) || (y+vrepeat >= camera_screen.height)/* || ((x == 0) && (y == 0))*/) return;
 209     unsigned char *obu = current_opacity_buf;
 210     unsigned char *bbu = current_bitmap_buf;
 211     unsigned int offset = y * camera_screen.buffer_width + x;
 212     int plus = camera_screen.buffer_width;
 213     if (conf.rotate_osd)
 214     {
 215         offset = rotate_base - offset;
 216         plus = -plus;
 217     }
 218 
 219     if (!offset) return; // skip guard pixel
 220 
 221     int fg = px<<2;
 222     register unsigned int offs2 = (offset>>1)<<2;
 223     
 224     if (offset&1) // x is odd
 225     {
 226         while (1)
 227         {
 228             obu[offset] = yuvclr[fg+3];
 229             bbu[offs2+3] = yuvclr[fg+1]; // Y
 230             if (!vrepeat) return;
 231             vrepeat--;
 232             offset += plus;
 233             offs2 += (plus<<1);
 234         }
 235     }
 236     else // x is even
 237     {
 238         while (1)
 239         {
 240             obu[offset] = yuvclr[fg+3];
 241             bbu[offs2+1] = yuvclr[fg+1]; // Y
 242             bbu[offs2+0] = yuvclr[fg]; // U
 243             bbu[offs2+2] = yuvclr[fg+2]; // V
 244             if (!vrepeat) return;
 245             vrepeat--;
 246             offset += plus;
 247             offs2 += (plus<<1);
 248         }
 249     }
 250 
 251 }
 252 
 253 // px: 2 bits, describing 2 pixels (foreground when set, background when not), LSB is the second pixel
 254 // first pixel specifies chroma
 255 static void draw_2pixels_simple(coord x, coord y, int px, int vrepeat)
 256 {
 257     if ((x < 0) || (y < 0) || (x+1 >= camera_screen.width) || (y+vrepeat >= camera_screen.height)/* || ((x == 0) && (y == 0))*/) return;
 258     unsigned int y1, y2;
 259     unsigned int offset = (y * camera_screen.buffer_width + x)>>1;
 260     int plus;
 261     unsigned short co;
 262     unsigned int yuv;
 263     if (conf.rotate_osd)
 264     {
 265         offset = (rotate_base>>1) - offset;
 266         plus = -(camera_screen.buffer_width>>1);
 267         y1 = px&1?4:0;
 268         y2 = px&2?4+1:0+1;
 269     }
 270     else
 271     {
 272         plus = camera_screen.buffer_width>>1;
 273         y1 = px&2?4:0;
 274         y2 = px&1?4+1:0+1;
 275     }
 276 
 277     if (!offset) return; // skip guard pixel
 278 
 279     co = yuvclr[y1+3]+(yuvclr[y1+3]<<8);
 280     yuv = (*(unsigned int*)(&yuvclr[y1]) & 0xffffff) + (yuvclr[y2]<<24);
 281     unsigned short *obu = (unsigned short *)current_opacity_buf;
 282     unsigned int *bbu = (unsigned int *)current_bitmap_buf;
 283     while (1)
 284     {
 285         obu[offset] = co;
 286         bbu[offset] = yuv;
 287         if (!vrepeat) return;
 288         vrepeat--;
 289         offset += plus;
 290     }
 291 
 292 }
 293 
 294 void draw_hline_simple(coord x, coord y, int len, int px)
 295 {
 296     if ((y < 0) || (x >= camera_screen.width) || (y >= camera_screen.height)) return;
 297     if (x < 0) { len += x; x = 0; }
 298     if ((x + len) > camera_screen.width) len = camera_screen.width - x;
 299     /*if ((x == 0) && (y == 0)) { x++; len--; }   // Skip guard pixel*/
 300 
 301     register unsigned int offset = y * camera_screen.buffer_width + (x);
 302     if (conf.rotate_osd)
 303     {
 304         offset = rotate_base - offset - len;
 305     }
 306 
 307     // Skip guard pixel
 308     if (!offset)
 309     {
 310         offset++;
 311         len--;
 312     }
 313 
 314     int fg = px<<2;
 315     if (offset & 1)
 316     {
 317         unsigned char *obu = current_opacity_buf;
 318         unsigned char *bbu = current_bitmap_buf;
 319         register unsigned int offs2 = (offset>>1)<<2;
 320         obu[offset] = yuvclr[fg+3];
 321         bbu[offs2+3] = yuvclr[fg+1]; // Y
 322         offset++;
 323         len--;
 324     }
 325     unsigned short co = yuvclr[fg+3]+(yuvclr[fg+3]<<8);
 326     unsigned int yuv = (*(unsigned int*)(&yuvclr[fg]) & 0xffffff) + (yuvclr[fg+1]<<24);
 327     unsigned short *obud = (unsigned short *)current_opacity_buf;
 328     unsigned int *bbud = (unsigned int *)current_bitmap_buf;
 329     for (; len>0; len-=2, offset+=2)
 330     {
 331         obud[offset>>1] = co;
 332         bbud[offset>>1] = yuv;
 333     }
 334     if (len == -1)
 335     {
 336         offset--;
 337         unsigned char *obu = current_opacity_buf;
 338         unsigned char *bbu = current_bitmap_buf;
 339         register unsigned int offs2 = (offset>>1)<<2;
 340         obu[offset] = yuvclr[fg+3];
 341         bbu[offs2+3] = yuvclr[fg+1]; // Y
 342     }
 343 }
 344 
 345 
 346 #endif // THUMB_FW
 347 //-------------------------------------------------------------------
 348 #ifndef THUMB_FW
 349 
 350 #define GUARD_VAL   COLOR_GREY_DK
 351 
 352 void draw_set_guard()
 353 {
 354 #ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
 355     *((unsigned char*)(bitmap_buffer[0])) = GUARD_VAL;
 356     *((unsigned char*)(bitmap_buffer[1])) = GUARD_VAL;
 357 #else
 358     *((unsigned char*)(frame_buffer[0])) = GUARD_VAL;
 359     *((unsigned char*)(frame_buffer[1])) = GUARD_VAL;
 360 #endif
 361 }
 362 
 363 int draw_test_guard()
 364 {
 365 #ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
 366     if (*((unsigned char*)(bitmap_buffer[active_bitmap_buffer])) != GUARD_VAL) return 0;
 367 #else
 368     if (*((unsigned char*)(frame_buffer[0])) != GUARD_VAL) return 0;
 369     if (*((unsigned char*)(frame_buffer[1])) != GUARD_VAL) return 0;
 370 #endif
 371     return 1;
 372 }
 373 
 374 #else // DIGIC 6
 375 
 376 void draw_set_guard()
 377 {
 378     opacity_buffer[active_bitmap_buffer][0] = 0x42;
 379 }
 380 
 381 int draw_test_guard()
 382 {
 383     if (opacity_buffer[active_bitmap_buffer][0] != 0x42) return 0;
 384     return 1;
 385 }
 386 
 387 #endif
 388 //-------------------------------------------------------------------
 389 void draw_init()
 390 {
 391 #ifndef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
 392     frame_buffer[0] = vid_get_bitmap_fb();
 393     frame_buffer[1] = frame_buffer[0] + camera_screen.buffer_size;
 394 #endif
 395     draw_set_draw_proc(NULL);
 396 
 397     draw_set_guard();
 398 }
 399 
 400 // Restore CANON_OSD
 401 //-------------------------------------------------------------------
 402 void draw_restore()
 403 {
 404     vid_bitmap_refresh();
 405 
 406     draw_set_guard();
 407 #ifdef CAM_TOUCHSCREEN_UI
 408     redraw_buttons = 1;
 409 #endif
 410 }
 411 
 412 //-------------------------------------------------------------------
 413 void draw_pixel(coord x, coord y, color cl)
 414 {
 415     // Make sure pixel is on screen. Skip top left pixel if screen erase detection is on to avoid triggering the detector.
 416     if ((x < 0) || (y < 0) || (x >= camera_screen.width) || (y >= camera_screen.height) || ((x == 0) && (y == 0))) return;
 417     else
 418     {
 419         register unsigned int offset = y * camera_screen.buffer_width + ASPECT_XCORRECTION(x);
 420         draw_pixel_proc(offset,   cl);
 421 #if CAM_USES_ASPECT_CORRECTION
 422         draw_pixel_proc(offset+1, cl);  // Draw second pixel if screen scaling is needed
 423 #endif
 424    }
 425 }
 426 
 427 void draw_pixel_unrotated(coord x, coord y, color cl)
 428 {
 429     // Make sure pixel is on screen. Skip top left pixel if screen erase detection is on to avoid triggering the detector.
 430     if ((x < 0) || (y < 0) || (x >= camera_screen.width) || (y >= camera_screen.height) || ((x == 0) && (y == 0))) return;
 431     else
 432     {
 433         register unsigned int offset = y * camera_screen.buffer_width + ASPECT_XCORRECTION(x);
 434         draw_pixel_proc_norm(offset,   cl);
 435 #if CAM_USES_ASPECT_CORRECTION
 436         draw_pixel_proc_norm(offset+1, cl);  // Draw second pixel if screen scaling is needed
 437 #endif
 438    }
 439 }
 440 
 441 //-------------------------------------------------------------------
 442 color draw_get_pixel(coord x, coord y)
 443 {
 444 #ifndef THUMB_FW
 445     if ((x < 0) || (y < 0) || (x >= camera_screen.width) || (y >= camera_screen.height)) return 0;
 446     if (conf.rotate_osd)
 447     {
 448 #ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
 449         return bitmap_buffer[0][rotate_base - (y * camera_screen.buffer_width + ASPECT_XCORRECTION(x))];
 450 #else
 451         return frame_buffer[0][rotate_base - (y * camera_screen.buffer_width + ASPECT_XCORRECTION(x))];
 452 #endif
 453     }
 454     else
 455     {
 456 #ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
 457         return bitmap_buffer[0][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x)];
 458 #else
 459         return frame_buffer[0][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x)];
 460 #endif
 461     }
 462 #else
 463     // DIGIC 6 not supported
 464     return 0;
 465 #endif
 466 }
 467 
 468 color draw_get_pixel_unrotated(coord x, coord y)
 469 {
 470 #ifndef THUMB_FW
 471     if ((x < 0) || (y < 0) || (x >= camera_screen.width) || (y >= camera_screen.height)) return 0;
 472 #ifdef DRAW_ON_ACTIVE_BITMAP_BUFFER_ONLY
 473     return bitmap_buffer[0][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x)];
 474 #else
 475     return frame_buffer[0][y * camera_screen.buffer_width + ASPECT_XCORRECTION(x)];
 476 #endif
 477 #else
 478     // DIGIC 6 not supported
 479     return 0;
 480 #endif
 481 }
 482 
 483 //-------------------------------------------------------------------
 484 #define swap(v1, v2)   {v1^=v2; v2^=v1; v1^=v2;}
 485 //-------------------------------------------------------------------
 486 void draw_line(coord x1, coord y1, coord x2, coord y2, color cl)
 487 {
 488      unsigned char steep = abs(y2 - y1) > abs(x2 - x1);
 489      if (steep)
 490      {
 491          swap(x1, y1);
 492          swap(x2, y2);
 493      }
 494      if (x1 > x2)
 495      {
 496          swap(x1, x2);
 497          swap(y1, y2);
 498      }
 499      int deltax = x2 - x1;
 500      int deltay = abs(y2 - y1);
 501      int error = 0;
 502      int y = y1;
 503      int ystep = (y1 < y2)?1:-1;
 504      int x;
 505      for (x=x1; x<=x2; ++x)
 506      {
 507          if (steep) draw_pixel(y, x, cl);
 508          else draw_pixel(x, y, cl);
 509          error += deltay;
 510          if ((error<<1) >= deltax)
 511          {
 512              y += ystep;
 513              error -= deltax;
 514          }
 515      }
 516 }
 517 
 518 //-------------------------------------------------------------------
 519 void draw_hline(coord x, coord y, int len, color cl)
 520 {
 521     if ((y < 0) || (x >= camera_screen.width) || (y >= camera_screen.height)) return;
 522     if (x < 0) { len += x; x = 0; }
 523     if ((x + len) > camera_screen.width) len = camera_screen.width - x;
 524     if (conf.rotate_osd)
 525     {
 526         if ((y == camera_screen.height-1) && ((x+len) >= camera_screen.width-1)) { x--; len--; }   // Skip guard pixel
 527     }
 528     else
 529     {
 530         if ((y == 0) && (x == 0)) { x++; len--; }   // Skip guard pixel
 531     }
 532     register unsigned int offset = y * camera_screen.buffer_width + ASPECT_XCORRECTION(x);
 533     len = ASPECT_XCORRECTION(len);      // Scale the line length if needed
 534     for (; len>0; len--, offset++)
 535         draw_pixel_proc(offset, cl);
 536 }
 537 
 538 void draw_vline(coord x, coord y, int len, color cl)
 539 {
 540     if ((x < 0) || (x >= camera_screen.width) || (y >= camera_screen.height)) return;
 541     if (y < 0) { len += y; y = 0; }
 542     if ((y + len) > camera_screen.height) len = camera_screen.height - y;
 543     for (; len>0; len--, y++)
 544         draw_pixel(x, y, cl);
 545 }
 546 
 547 //-------------------------------------------------------------------
 548 // Generic rectangle
 549 // 'flags' defines type - filled, round corners, shadow and border thickness
 550 void draw_rectangle(coord x1, coord y1, coord x2, coord y2, twoColors cl, int flags)
 551 {
 552     // Normalise values
 553     if (x1 > x2)
 554         swap(x1, x2);
 555     if (y1 > y2)
 556         swap(y1, y2);
 557 
 558     // Check if completely off screen
 559     if ((x2 < 0) || (y2 < 0) || (x1 >= camera_screen.width) || (y1 >= camera_screen.height))
 560         return;
 561 
 562     int round = (flags & RECT_ROUND_CORNERS) ? 1 : 0;
 563     int thickness;
 564     int i;
 565 
 566     // Shadow (do this first, as edge draw shrinks rectangle for fill)
 567     if (flags & RECT_SHADOW_MASK)
 568     {
 569         thickness = ((flags & RECT_SHADOW_MASK) >> 4);
 570         for (i=1; i<=thickness; i++)
 571         {
 572             draw_vline(x2+i, y1+1, y2 - y1, COLOR_BLACK);
 573             draw_hline(x1+1, y2+i, x2 - x1 + thickness, COLOR_BLACK);
 574         }
 575     }
 576 
 577     // Edge
 578     thickness = flags & RECT_BORDER_MASK;
 579     for (i=0; i<thickness; i++)
 580     {
 581         // Clipping done in draw_hline and draw_vline
 582         draw_vline(x1, y1 + round * 2, y2 - y1 - round * 4 + 1, FG_COLOR(cl));
 583         draw_vline(x2, y1 + round * 2, y2 - y1 - round * 4 + 1, FG_COLOR(cl));
 584         draw_hline(x1 + 1 + round, y1, x2 - x1 - round * 2 - 1, FG_COLOR(cl));
 585         draw_hline(x1 + 1 + round, y2, x2 - x1 - round * 2 - 1, FG_COLOR(cl));
 586 
 587         x1++; x2--;
 588         y1++; y2--;
 589 
 590         round = 0;
 591     }
 592 
 593     // Fill
 594     if (flags & DRAW_FILLED)
 595     {
 596         // Clip values
 597         if (x1 < 0) x1 = 0;
 598         if (y1 < 0) y1 = 0;
 599         if (x2 >= camera_screen.width)  x2 = camera_screen.width - 1;
 600         if (y2 >= camera_screen.height) y2 = camera_screen.height - 1;
 601 
 602         coord y;
 603         for (y = y1; y <= y2; ++y)
 604             draw_hline(x1, y, x2 - x1 + 1, BG_COLOR(cl));
 605     }
 606 }
 607 
 608 //-------------------------------------------------------------------
 609 #pragma pack(1)
 610 // Format of header block for each character in the 'font_data' array
 611 // This is immediately followed by '16 - top - bottom' bytes of character data.
 612 typedef struct {
 613     unsigned char skips;    // Top and Bottom skip counts for blank rows (4 bits each - ((top << 4) | bottom))
 614 } FontData;
 615 #pragma pack()
 616 
 617 static unsigned char* get_cdata(unsigned int *offset, unsigned int *size, const char ch)
 618 {
 619     FontData *f = (FontData*)get_current_font_data(ch);
 620 
 621     *offset = f->skips >> 4;            // # of blank lines at top
 622     *size = 16 - (f->skips & 0xF);      // last line of non-blank data
 623     if (*size == *offset)               // special case for blank char (top == 15 && bottom == 1)
 624         *offset++;
 625 
 626     return (unsigned char*)f + sizeof(FontData) - *offset;
 627 }
 628 
 629 #ifndef THUMB_FW
 630 // DIGIC II...5
 631 void draw_char(coord x, coord y, const char ch, twoColors cl)
 632 {
 633     int i, ii;
 634 
 635     unsigned int offset, size;
 636     unsigned char *sym = get_cdata(&offset, &size, ch);
 637 
 638     // First draw blank lines at top
 639     for (i=0; i<offset; i++)
 640         draw_hline(x, y+i, FONT_WIDTH, BG_COLOR(cl));
 641 
 642     // Now draw character data
 643 
 644     int j;
 645     for (j=i; i<size;)
 646     {
 647         unsigned int dsym;
 648         int rep;
 649 #ifdef BUILTIN_FONT_RLE_COMPRESSED
 650         dsym = fontdata_lookup[sym[j] & 0x7f];
 651         rep = sym[j] & 0x80;
 652 #else
 653         dsym = sym[j];
 654         rep = 0;
 655 #endif
 656         for (ii=0; ii<FONT_WIDTH; ii++)
 657         {
 658             draw_pixel(x+ii, y+i, (dsym & (0x80>>ii))? FG_COLOR(cl) : BG_COLOR(cl));
 659         }
 660         if (rep)
 661         {
 662             i++;
 663             for (ii=0; ii<FONT_WIDTH; ii++)
 664             {
 665                 draw_pixel(x+ii, y+i, (dsym & (0x80>>ii))? FG_COLOR(cl) : BG_COLOR(cl));
 666             }
 667         }
 668         i++;
 669         j++;
 670     }
 671 
 672     // Last draw blank lines at bottom
 673     for (; i<FONT_HEIGHT; i++)
 674         draw_hline(x, y+i, FONT_WIDTH, BG_COLOR(cl));
 675 }
 676 #endif
 677 
 678 #ifdef THUMB_FW
 679 // DIGIC 6: "optimizations" to improve speed
 680 void draw_char(coord x, coord y, const char ch, twoColors cl)
 681 {
 682     int i, ii;
 683 
 684     unsigned int offset, size;
 685     unsigned char *sym = get_cdata(&offset, &size, ch);
 686     color fg = FG_COLOR(cl);
 687     color bg = BG_COLOR(cl);
 688     unsigned int fw = FONT_WIDTH;
 689 
 690     draw_pixel_simple_start(cl);
 691 
 692     // First draw blank lines at top
 693     for (i=0; i<offset; i++)
 694     {
 695         int j;
 696         j = i<<1;
 697         draw_hline_simple(x, y+j, fw, 0);
 698         draw_hline_simple(x, y+j+1, fw, 0);
 699     }
 700 
 701     // Now draw character data
 702 
 703     int j;
 704     for (j=i; i<size;)
 705     {
 706         unsigned int dsym;
 707         int rep;
 708 #ifdef BUILTIN_FONT_RLE_COMPRESSED
 709         dsym = fontdata_lookup[sym[j] & 0x7f];
 710         rep = sym[j] & 0x80;
 711 #else
 712         dsym = sym[j];
 713         rep = 0;
 714 #endif
 715         {
 716             // upscaling 8 pixels to 14
 717             ii = 0;
 718             ii += (dsym&1)?3:0;
 719             ii += (dsym&2)?4:0;
 720             ii += (dsym&4)?0x18:0;
 721             ii += (dsym&8)?0x60:0;
 722             ii += (dsym&16)?0x180:0;
 723             ii += (dsym&32)?0x600:0;
 724             ii += (dsym&64)?0x1800:0;
 725             ii += (dsym&128)?0x2000:0;
 726             dsym = ii;
 727         }
 728 
 729         while (rep >= 0)
 730         {
 731             unsigned int px;
 732             unsigned int yt = y+(i<<1);
 733             ii = 0;
 734             if (x&1)
 735             {
 736                 draw_1pixel_simple(x+ii, yt, dsym>>(fw-1), 1);
 737                 ii++;
 738             }
 739             for (; ii<fw; ii+=2)
 740             {
 741                 px = (dsym & ((3<<(fw-2))>>ii))>>(fw-2-ii);
 742                 draw_2pixels_simple(x+ii, yt, px, 1);
 743             }
 744             if (x&1)
 745             {
 746                 draw_1pixel_simple(x+ii-1, yt, dsym&1, 1);
 747             }
 748             rep -= 0x80;
 749             i++;
 750         }
 751 
 752         j++;
 753     }
 754 
 755     // Last draw blank lines at bottom
 756     for (; i<FONT_REAL_HEIGHT; i++)
 757     {
 758         int j;
 759         j = i<<1;
 760         draw_hline_simple(x, y+j, fw, 0);
 761         draw_hline_simple(x, y+j+1, fw, 0);
 762     }
 763 }
 764 
 765 void draw_char_unscaled(coord x, coord y, const char ch, twoColors cl)
 766 {
 767     int i, ii;
 768 
 769     unsigned int offset, size;
 770     unsigned char *sym = get_cdata(&offset, &size, ch);
 771     color fg = FG_COLOR(cl);
 772     color bg = BG_COLOR(cl);
 773     unsigned int fw = FONT_REAL_WIDTH;
 774 
 775     draw_pixel_simple_start(cl);
 776 
 777     // First draw blank lines at top
 778     for (i=0; i<offset; i++)
 779     {
 780         draw_hline_simple(x, y+i, fw, 0);
 781     }
 782 
 783     // Now draw character data
 784 
 785     int j;
 786     for (j=i; i<size;)
 787     {
 788         unsigned int dsym;
 789         int rep;
 790 #ifdef BUILTIN_FONT_RLE_COMPRESSED
 791         dsym = fontdata_lookup[sym[j] & 0x7f];
 792         rep = sym[j] & 0x80;
 793 #else
 794         dsym = sym[j];
 795         rep = 0;
 796 #endif
 797 
 798         while (rep >= 0)
 799         {
 800             unsigned int px;
 801             unsigned int yt = y+(i);
 802             ii = 0;
 803             if (x&1)
 804             {
 805                 draw_1pixel_simple(x+ii, yt, dsym>>(fw-1), 0);
 806                 ii++;
 807             }
 808             for (; ii<fw; ii+=2)
 809             {
 810                 px = (dsym & ((3<<(fw-2))>>ii))>>(fw-2-ii);
 811                 draw_2pixels_simple(x+ii, yt, px, 0);
 812             }
 813             if (x&1)
 814             {
 815                 draw_1pixel_simple(x+ii-1, yt, dsym&1, 0);
 816             }
 817             rep -= 0x80;
 818             i++;
 819         }
 820 
 821         j++;
 822     }
 823 
 824     // Last draw blank lines at bottom
 825     for (; i<FONT_REAL_HEIGHT; i++)
 826     {
 827         draw_hline_simple(x, y+i, fw, 0);
 828     }
 829 }
 830 
 831 #endif // THUMB_FW
 832 
 833 #ifndef THUMB_FW
 834 void draw_char_scaled(coord x, coord y, const char ch, twoColors cl, int xsize, int ysize)
 835 {
 836     int i, ii;
 837 
 838     twoColors clf = MAKE_COLOR(FG_COLOR(cl),FG_COLOR(cl));
 839     twoColors clb = MAKE_COLOR(BG_COLOR(cl),BG_COLOR(cl));
 840 
 841     unsigned int offset, size;
 842     unsigned char *sym = get_cdata(&offset, &size, ch);
 843 
 844     // First draw blank lines at top
 845     if (offset > 0)
 846         draw_rectangle(x,y,x+FONT_WIDTH*xsize-1,y+offset*ysize+ysize-1,clb,RECT_BORDER0|DRAW_FILLED);
 847 
 848     // Now draw character data
 849     int j;
 850     for (j=i=offset; i<size;)
 851     {
 852         unsigned int dsym;
 853         int rep;
 854         unsigned int last;
 855         int len;
 856 #ifdef BUILTIN_FONT_RLE_COMPRESSED
 857         dsym = fontdata_lookup[sym[j] & 0x7f];
 858         rep = sym[j] & 0x80;
 859 #else
 860         dsym = sym[j];
 861         rep = 0;
 862 #endif
 863         while (rep >= 0)
 864         {
 865             last = dsym & 0x80;
 866             len = 1;
 867             for (ii=1; ii<FONT_WIDTH; ii++)
 868             {
 869                 if (((dsym << ii) & 0x80) != last)
 870                 {
 871                     draw_rectangle(x+(ii-len)*xsize,y+i*ysize,x+ii*xsize-1,y+i*ysize+ysize-1,(last)?clf:clb,RECT_BORDER0|DRAW_FILLED);
 872                     last = (dsym << ii) & 0x80;
 873                     len = 1;
 874                 }
 875                 else
 876                 {
 877                     len++;
 878                 }
 879             }
 880             draw_rectangle(x+(ii-len)*xsize,y+i*ysize,x+ii*xsize-1,y+i*ysize+ysize-1,(last)?clf:clb,RECT_BORDER0|DRAW_FILLED);
 881             i++;
 882             rep -= 0x80;
 883         }
 884         j++;
 885     }
 886 
 887     // Last draw blank lines at bottom
 888     if (i < FONT_HEIGHT)
 889         draw_rectangle(x,y+i*ysize,x+FONT_WIDTH*xsize-1,y+FONT_HEIGHT*ysize+ysize-1,clb,RECT_BORDER0|DRAW_FILLED);
 890 }
 891 #endif // !THUMB_FW
 892 
 893 #ifdef THUMB_FW
 894 void draw_char_scaled(coord x, coord y, const char ch, twoColors cl, int xsize, int ysize)
 895 {
 896     int i, ii;
 897 
 898     twoColors clf = MAKE_COLOR(FG_COLOR(cl),FG_COLOR(cl));
 899     twoColors clb = MAKE_COLOR(BG_COLOR(cl),BG_COLOR(cl));
 900 
 901     unsigned int offset, size;
 902     unsigned char *sym = get_cdata(&offset, &size, ch);
 903 
 904     ysize <<= 1;
 905 
 906     // First draw blank lines at top
 907     if (offset > 0)
 908         draw_rectangle(x,y,x+FONT_WIDTH*xsize-1,y+offset*ysize+ysize-1,clb,RECT_BORDER0|DRAW_FILLED);
 909 
 910     // Now draw character data
 911     int j;
 912     for (j=i=offset; i<size;)
 913     {
 914         unsigned int dsym;
 915         int rep;
 916         unsigned int last;
 917         int len;
 918         unsigned int lastmask = 1 << (FONT_WIDTH-1);
 919 #ifdef BUILTIN_FONT_RLE_COMPRESSED
 920         dsym = fontdata_lookup[sym[j] & 0x7f];
 921         rep = sym[j] & 0x80;
 922 #else
 923         dsym = sym[j];
 924         rep = 0;
 925 #endif
 926         {
 927             // upscaling 8 pixels to 14
 928             ii = 0;
 929             ii += (dsym&1)?3:0;
 930             ii += (dsym&2)?4:0;
 931             ii += (dsym&4)?0x18:0;
 932             ii += (dsym&8)?0x60:0;
 933             ii += (dsym&16)?0x180:0;
 934             ii += (dsym&32)?0x600:0;
 935             ii += (dsym&64)?0x1800:0;
 936             ii += (dsym&128)?0x2000:0;
 937             dsym = ii;
 938         }
 939         while (rep >= 0)
 940         {
 941             last = dsym & lastmask;
 942             len = 1;
 943             for (ii=1; ii<FONT_WIDTH; ii++)
 944             {
 945                 if (((dsym << ii) & lastmask) != last)
 946                 {
 947                     draw_rectangle(x+(ii-len)*xsize,y+i*ysize,x+ii*xsize-1,y+i*ysize+ysize-1,(last)?clf:clb,RECT_BORDER0|DRAW_FILLED);
 948                     last = (dsym << ii) & lastmask;
 949                     len = 1;
 950                 }
 951                 else
 952                 {
 953                     len++;
 954                 }
 955             }
 956             draw_rectangle(x+(ii-len)*xsize,y+i*ysize,x+ii*xsize-1,y+i*ysize+ysize-1,(last)?clf:clb,RECT_BORDER0|DRAW_FILLED);
 957             i++;
 958             rep -= 0x80;
 959         }
 960         j++;
 961     }
 962 
 963     // Last draw blank lines at bottom
 964     if (i < FONT_REAL_HEIGHT)
 965         draw_rectangle(x,y+i*ysize,x+FONT_WIDTH*xsize-1,y+FONT_REAL_HEIGHT*ysize+ysize-1,clb,RECT_BORDER0|DRAW_FILLED);
 966 }
 967 #endif // THUMB_FW
 968 //-------------------------------------------------------------------
 969 // String & text functions
 970 
 971 // Draw a single line string up to a maximum pixel width
 972 int draw_string_clipped(coord x, coord y, const char *s, twoColors cl, int max_width)
 973 {
 974     while (*s && (*s != '\n') && (max_width >= FONT_WIDTH))
 975     {
 976             draw_char(x, y, *s, cl);
 977             s++;
 978         max_width -= FONT_WIDTH;
 979             x += FONT_WIDTH;
 980             if ((x>=camera_screen.width) && (*s))
 981         {
 982                 draw_char(x-FONT_WIDTH,y, '>', cl);
 983                 break;
 984             }
 985     }
 986     return x;
 987 }
 988 
 989 // Draw a single line string
 990 int draw_string(coord x, coord y, const char *s, twoColors cl)
 991 {
 992     return draw_string_clipped(x, y, s, cl, camera_screen.width);
 993 }
 994 
 995 // Draw a single line string:
 996 //      - xo = left offset to start text (only applies to left justified text)
 997 //      - max_width = maximum pixel width to use (staring from x)
 998 //      - justification = left, center or right justified, also controls if unused area to be filled with background color
 999 // Returns x position of first character drawn
1000 int draw_string_justified(coord x, coord y, const char *s, twoColors cl, int xo, int max_width, int justification)
1001 {
1002     // Get length in pixels
1003     const char *e = strchr(s, '\n');
1004     int l;
1005     if (e)
1006         l = (e - s) * FONT_WIDTH;
1007     else
1008         l = strlen(s) * FONT_WIDTH;
1009     if (l > max_width) l = max_width;
1010 
1011     // Calculate justification offset
1012     switch (justification & 0xF)
1013     {
1014     case TEXT_RIGHT:
1015         xo = (max_width - l);
1016         break;
1017     case TEXT_CENTER:
1018         xo = ((max_width - l) >> 1);
1019         break;
1020     }
1021 
1022     // Fill left side
1023     if ((justification & TEXT_FILL) && (xo > 0))
1024         draw_rectangle(x, y, x+xo-1, y+FONT_HEIGHT-1, cl, RECT_BORDER0|DRAW_FILLED);
1025 
1026     // Draw string (get length drawn in pixels)
1027     l = draw_string_clipped(x+xo, y, s, cl, max_width - xo) - x;
1028 
1029     // Fill right side
1030     if ((justification & TEXT_FILL) && (l < max_width))
1031         draw_rectangle(x+l, y, x+max_width-1, y+FONT_HEIGHT-1, cl, RECT_BORDER0|DRAW_FILLED);
1032 
1033     // Return start of first character
1034     return x+xo;
1035 }
1036 
1037 // Calculate the max line length and number of lines of a multi line string
1038 // Lines are separated by newline '\n' characters
1039 // Returns:
1040 //      - max line length (return value)
1041 //      - number of lines (in *max_lines)
1042 int text_dimensions(const char *s, int width, int max_chars, int *max_lines)
1043 {
1044     int l = 0, n;
1045     while (s && *s && (l < *max_lines))
1046     {
1047         const char *e = strchr(s, '\n');
1048         if (e)
1049         {
1050             n = e - s;
1051             e++;
1052         }
1053         else
1054         {
1055             n = strlen(s);
1056         }
1057 
1058         if (n > width) width = n;
1059 
1060         s = e;
1061         l++;
1062     }
1063     *max_lines = l;
1064     if (width > max_chars) width = max_chars;
1065     return width;
1066 }
1067 
1068 // Draw multi-line text string:
1069 //      - max_chars = max # of chars to draw
1070 //      - max_lines = max # of lines to draw
1071 //      - justification = left, center or right justified, with optional fill of unused space
1072 // Returns x position of first character on last line
1073 int draw_text_justified(coord x, coord y, const char *s, twoColors cl, int max_chars, int max_lines, int justification)
1074 {
1075     int rx = 0;
1076     while (s && *s && (max_lines > 0))
1077     {
1078         const char *e = strchr(s, '\n');
1079         if (e) e++;
1080 
1081         rx = draw_string_justified(x, y, s, cl, 0, max_chars*FONT_WIDTH, justification);
1082 
1083         s = e;
1084         y += FONT_HEIGHT;
1085         max_lines--;
1086     }
1087     return rx;
1088 }
1089 
1090 // Draw single line string, with optiona X and Y scaling
1091 #ifndef THUMB_FW
1092 void draw_string_scaled(coord x, coord y, const char *s, twoColors cl, int xsize, int ysize)
1093 {
1094     while (*s && (*s != '\n'))
1095     {
1096         draw_char_scaled(x, y, *s, cl, xsize, ysize);
1097         s++;
1098         x+=FONT_WIDTH*xsize;
1099         if ((x>=camera_screen.width) && (*s))
1100         {
1101             draw_char_scaled(x-FONT_WIDTH*xsize,y, '>', cl, xsize, ysize);
1102             break;
1103         }
1104     }
1105 }
1106 #endif
1107 
1108 #ifdef THUMB_FW
1109 void draw_string_scaled(coord x, coord y, const char *s, twoColors cl, int xsize, int ysize)
1110 {
1111     if ((xsize==0) || (ysize==0))
1112     {
1113         while (*s && (*s != '\n'))
1114         {
1115             draw_char_unscaled(x, y, *s, cl);
1116             s++;
1117             x+=FONT_REAL_WIDTH;
1118             if ((x>=camera_screen.width) && (*s))
1119             {
1120                 draw_char_unscaled(x-FONT_REAL_WIDTH,y, '>', cl);
1121                 break;
1122             }
1123         }
1124     }
1125     else
1126     {
1127         while (*s && (*s != '\n'))
1128         {
1129             draw_char_scaled(x, y, *s, cl, xsize, ysize);
1130             s++;
1131             x+=FONT_WIDTH*xsize;
1132             if ((x>=camera_screen.width) && (*s))
1133             {
1134                 draw_char_scaled(x-FONT_WIDTH*xsize,y, '>', cl, xsize, ysize);
1135                 break;
1136             }
1137         }
1138     }
1139 }
1140 #endif
1141 
1142 // Draw CHDK OSD string at user defined position and scale
1143 #ifndef THUMB_FW
1144 void draw_osd_string(OSD_pos pos, int xo, int yo, char *s, twoColors c, OSD_scale scale)
1145 {
1146     if ((scale.x == 0) || (scale.y == 0) || ((scale.x == 1) && (scale.y == 1)))
1147         draw_string(pos.x+xo, pos.y+yo, s, c);
1148     else
1149         draw_string_scaled(pos.x+(xo*scale.x), pos.y+(yo*scale.y), s, c, scale.x, scale.y);
1150 }
1151 #endif
1152 
1153 #ifdef THUMB_FW
1154 void draw_osd_string(OSD_pos pos, int xo, int yo, char *s, twoColors c, OSD_scale scale)
1155 {
1156     if ((scale.x == 1) && (scale.y == 1))
1157     {
1158         draw_string(pos.x+xo, pos.y+yo, s, c);
1159     }
1160     else if ((scale.x == 0) || (scale.y == 0))
1161     {
1162         draw_string_scaled(pos.x+(xo>>1), pos.y+(yo>>1), s, c, scale.x, scale.y);
1163     }
1164     else
1165     {
1166         draw_string_scaled(pos.x+(xo*scale.x), pos.y+(yo*scale.y), s, c, scale.x, scale.y);
1167     }
1168 }
1169 #endif
1170 
1171 //-------------------------------------------------------------------
1172 // Draw single line string at 'character' screen position (row, col)
1173 // Pixel co-ordinate conversion --> x = col * FONT_WIDTH, y = row * FONT_HEIGHT
1174 void draw_txt_string(coord col, coord row, const char *str, twoColors cl)
1175 {
1176     draw_string(col*FONT_WIDTH, row*FONT_HEIGHT, str, cl);
1177 }
1178 
1179 //-------------------------------------------------------------------
1180 // *** Not used ***
1181 //void draw_circle(coord x, coord y, const unsigned int r, color cl)
1182 //{
1183 //    int dx = 0;
1184 //    int dy = r;
1185 //    int p=(3-(r<<1));
1186 //
1187 //    do {
1188 //        draw_pixel((x+dx),(y+dy),cl);
1189 //        draw_pixel((x+dy),(y+dx),cl);
1190 //        draw_pixel((x+dy),(y-dx),cl);
1191 //        draw_pixel((x+dx),(y-dy),cl);
1192 //        draw_pixel((x-dx),(y-dy),cl);
1193 //        draw_pixel((x-dy),(y-dx),cl);
1194 //        draw_pixel((x-dy),(y+dx),cl);
1195 //        draw_pixel((x-dx),(y+dy),cl);
1196 //
1197 //        ++dx;
1198 //
1199 //        if (p<0)
1200 //            p += ((dx<<2)+6);
1201 //        else {
1202 //            --dy;
1203 //            p += (((dx-dy)<<2)+10);
1204 //        }
1205 //    } while (dx<=dy);
1206 //}
1207 
1208 //-------------------------------------------------------------------
1209 void draw_ellipse(coord CX, coord CY, unsigned int XRadius, unsigned int YRadius, color cl, int flags)
1210 {
1211     // Bresenham fast ellipse algorithm - http://homepage.smc.edu/kennedy_john/BELIPSE.PDF
1212     int X, Y;
1213     int XChange, YChange;
1214     int EllipseError;
1215     int TwoASquare, TwoBSquare;
1216     int StoppingX, StoppingY;
1217     TwoASquare = 2*XRadius*XRadius;
1218     TwoBSquare = 2*YRadius*YRadius;
1219     X = XRadius;
1220     Y = 0;
1221     XChange = YRadius*YRadius*(1-2*XRadius);
1222     YChange = XRadius*XRadius;
1223     EllipseError = 0;
1224     StoppingX = TwoBSquare*XRadius;
1225     StoppingY = 0;
1226     while ( StoppingX >= StoppingY ) 
1227     {
1228         if (flags & DRAW_FILLED)
1229         {
1230             draw_hline(CX-X,CY-Y,X*2+1,cl);
1231             draw_hline(CX-X,CY+Y,X*2+1,cl);
1232         }
1233         else
1234         {
1235             draw_pixel(CX-X,CY-Y,cl);
1236             draw_pixel(CX-X,CY+Y,cl);
1237             draw_pixel(CX+X,CY-Y,cl);
1238             draw_pixel(CX+X,CY+Y,cl);
1239         }
1240         Y++;
1241         StoppingY += TwoASquare;
1242         EllipseError += YChange;
1243         YChange += TwoASquare;
1244         if ((2*EllipseError + XChange) > 0 )
1245         {
1246             X--;
1247             StoppingX -= TwoBSquare;
1248             EllipseError += XChange;
1249             XChange += TwoBSquare;
1250         }
1251     }
1252     X = 0;
1253     Y = YRadius;
1254     XChange = YRadius*YRadius;
1255     YChange = XRadius*XRadius*(1-2*YRadius);
1256     EllipseError = 0;
1257     StoppingX = 0;
1258     StoppingY = TwoASquare*YRadius;
1259     int lastY = Y + 1;
1260     while ( StoppingX <= StoppingY )
1261     {
1262         if (flags & DRAW_FILLED)
1263         {
1264             // Only draw lines if Y has changed
1265             if (lastY != Y)
1266             {
1267                 draw_hline(CX-X,CY-Y,X*2+1,cl);
1268                 draw_hline(CX-X,CY+Y,X*2+1,cl);
1269                 lastY = Y;
1270             }
1271         }
1272         else
1273         {
1274             draw_pixel(CX-X,CY-Y,cl);
1275             draw_pixel(CX-X,CY+Y,cl);
1276             draw_pixel(CX+X,CY-Y,cl);
1277             draw_pixel(CX+X,CY+Y,cl);
1278         }
1279         X++;
1280         StoppingX += TwoBSquare;
1281         EllipseError += XChange;
1282         XChange += TwoBSquare;
1283         if ((2*EllipseError + YChange) > 0 )
1284         {
1285             Y--;
1286             StoppingY -= TwoASquare;
1287             EllipseError += YChange;
1288             YChange += TwoASquare;
1289         }
1290     }
1291 }
1292 
1293 //-------------------------------------------------------------------
1294 // Draw a button
1295 void draw_button(int x, int y, int w, int str_id, int active)
1296 {
1297     twoColors cl = MAKE_COLOR((active) ? COLOR_RED : COLOR_BLACK, COLOR_WHITE);
1298     w = w * FONT_WIDTH;
1299 
1300     draw_rectangle(x-2, y-2, x+w+2, y+FONT_HEIGHT+2, cl, RECT_BORDER1|DRAW_FILLED|RECT_SHADOW1);     // main box
1301     draw_string(x+((w-(strlen(lang_str(str_id))*FONT_WIDTH))>>1), y, lang_str(str_id), cl);
1302 }
1303 
1304 //-------------------------------------------------------------------
1305 // Draw an OSD icon from an array of actions
1306 void draw_icon_cmds(coord x, coord y, icon_cmd *cmds)
1307 {
1308     int x1, y1, x2, y2;
1309     while (1)
1310     {
1311         if (FONT_HEIGHT > 16)
1312         {
1313             x1 = cmds->x1<<1;
1314             y1 = cmds->y1<<1;
1315             x2 = cmds->x2<<1;
1316             y2 = cmds->y2<<1;
1317         }
1318         else
1319         {
1320             x1 = cmds->x1;
1321             y1 = cmds->y1;
1322             x2 = cmds->x2;
1323             y2 = cmds->y2;
1324         }
1325         color cf = chdk_colors[cmds->cf];       // Convert color indexes to actual colors
1326         color cb = chdk_colors[cmds->cb];
1327         switch (cmds->action)
1328         {
1329         default:
1330         case IA_END:
1331             return;
1332         case IA_HLINE:
1333             draw_hline(x+x1, y+y1, x2, cb);
1334             break;
1335         case IA_VLINE:
1336             draw_vline(x+x1, y+y1, y2, cb);
1337             break;
1338         case IA_LINE:
1339             draw_line(x+x1, y+y1, x+x2, y+y2, cb);
1340             break;
1341         case IA_RECT:
1342             draw_rectangle(x+x1, y+y1, x+x2, y+y2, MAKE_COLOR(cb,cf), RECT_BORDER1);
1343             break;
1344         case IA_FILLED_RECT:
1345             draw_rectangle(x+x1, y+y1, x+x2, y+y2, MAKE_COLOR(cb,cf), RECT_BORDER1|DRAW_FILLED);
1346             break;
1347         case IA_ROUND_RECT:
1348             draw_rectangle(x+x1, y+y1, x+x2, y+y2, MAKE_COLOR(cb,cf), RECT_BORDER1|RECT_ROUND_CORNERS);
1349             break;
1350         case IA_FILLED_ROUND_RECT:
1351             draw_rectangle(x+x1, y+y1, x+x2, y+y2, MAKE_COLOR(cb,cf), RECT_BORDER1|DRAW_FILLED|RECT_ROUND_CORNERS);
1352             break;
1353         }
1354         cmds++;
1355     }
1356 }
1357 
1358 //-------------------------------------------------------------------
1359 
1360 extern unsigned char ply_colors[];
1361 extern unsigned char rec_colors[];
1362 
1363 unsigned char *chdk_colors = ply_colors;
1364 
1365 void set_palette()
1366 {
1367 #ifndef THUMB_FW
1368     if (camera_info.state.mode_rec)
1369         chdk_colors = rec_colors;
1370     else
1371         chdk_colors = ply_colors;
1372 #endif
1373 }
1374 
1375 color get_script_color(int cl)
1376 {
1377     if (cl < 256)
1378         return cl;
1379     else
1380         return chdk_colors[cl-256];
1381 }
1382 
1383 // Convert user adjustable color (from conf struct) to Canon colors
1384 color chdkColorToCanonColor(chdkColor col)
1385 {
1386     if (col.type)
1387         return chdk_colors[col.col];
1388     return col.col;
1389 }
1390 
1391 twoColors user_color(confColor cc)
1392 {
1393     color fg = chdkColorToCanonColor(cc.fg);
1394     color bg = chdkColorToCanonColor(cc.bg);
1395 
1396     return MAKE_COLOR(bg,fg);
1397 }
1398 
1399 //-------------------------------------------------------------------

/* [<][>][^][v][top][bottom][index][help] */