root/core/gui_draw.c

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

DEFINITIONS

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

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