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

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