root/lib/font/rbf_font.c

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

DEFINITIONS

This source file includes following definitions.
  1. new_font
  2. init_fonts
  3. alloc_cTable
  4. code_page_char
  5. rbf_font_char
  6. font_read
  7. rbf_font_load
  8. rbf_load_symbol
  9. rbf_load_from_file
  10. rbf_set_codepage
  11. rbf_font_height
  12. rbf_symbol_height
  13. rbf_char_width
  14. rbf_symbol_width
  15. rbf_str_width
  16. rbf_str_clipped_width
  17. font_draw_char
  18. rbf_draw_char
  19. rbf_draw_symbol
  20. rbf_draw_string_c
  21. rbf_draw_string
  22. rbf_enable_cursor
  23. rbf_disable_cursor
  24. rbf_draw_clipped_string
  25. rbf_draw_string_len
  26. rbf_draw_string_right_len
  27. rbf_draw_menu_header

   1 #include "camera_info.h"
   2 #include "stdlib.h"
   3 #include "conf.h"
   4 #include "gui.h"
   5 #include "gui_draw.h"
   6 #include "font.h"
   7 
   8 //-------------------------------------------------------------------
   9 #define RBF_MAX_NAME        64
  10 #define UBUFFER_SIZE        256 // Amount of uncached memory to allocate for file reading
  11 //-------------------------------------------------------------------
  12 static int RBF_HDR_MAGIC1 = 0x0DF00EE0;
  13 static int RBF_HDR_MAGIC2 = 0x00000003;
  14 
  15 // Header as seperate structure so it can be directly loaded from the font file easily
  16 // structure layout maps to file layout - do not change !
  17 typedef struct {
  18     int magic1, magic2;         // header magic numbers to identify correct font file
  19     char name[RBF_MAX_NAME];    // name of font (max 64 characters)
  20     int charSize;               // # of bytes used to store each character
  21     int points;                 // font size in points
  22     int height;                 // font height in pixels
  23     int maxWidth;               // width of widest character
  24     int charFirst;              // first character #
  25     int charLast;               // last character #
  26     int _unknown4;              // ?
  27     int _wmapAddr;              // offset in font file of wTable array
  28     int _cmapAddr;              // offset in font file of cTable array
  29     int descent;                // font descent (not used)
  30     int intline;                // interline spacing (not used)
  31 } font_hdr;
  32 
  33 typedef struct _font {
  34     font_hdr hdr;
  35 
  36     // calculated values (after font is loaded)
  37     int charCount;              // count of chars containing in font
  38     int width;                  // font element width in pixels
  39 
  40     // Width table
  41     // List of character widths. Elements of list is width of char 
  42     char wTable[256];
  43 
  44     // Character data
  45     // List of chars. Element of list is a bytecode string, contains pixels representation of char
  46     char *cTable;
  47 
  48     // Flag to indicate we are actually using the built in 8x16 font rather than a loaded font
  49     int usingFont8x16;
  50 
  51     // Current size of the cTable data
  52     int cTableSize;
  53     int cTableSizeMax;                // max size of cTable (max size currently allocated)
  54 } font;
  55 
  56 static unsigned char *ubuffer = 0;                  // uncached memory buffer for reading font data from SD card
  57 static font *rbf_symbol_font = 0, *rbf_font = 0;
  58 static int rbf_codepage = FONT_CP_WIN; 
  59 
  60 //-------------------------------------------------------------------
  61 
  62 font *new_font() {
  63     // allocate font from cached memory
  64     font *f = malloc(sizeof(font));
  65     if (f) {
  66         memset(f,0,sizeof(font));      // wipe memory
  67         // return address in cached memory
  68         return f;
  69     }
  70 
  71     // memory not allocated ! should probably do something else in this case ?
  72     return 0;
  73 }
  74 
  75 void init_fonts()
  76 {
  77     // Allocate base font memory if needed
  78     if (rbf_font == 0) rbf_font = new_font();
  79     if (rbf_symbol_font == 0) rbf_symbol_font = new_font();
  80 
  81     // allocate uncached memory buffer for reading
  82     ubuffer = umalloc(UBUFFER_SIZE);
  83 }
  84 
  85 void alloc_cTable(font *f) {
  86 
  87     // Calculate additional values for font
  88     if (f->usingFont8x16) {
  89         f->width = FONT_WIDTH;
  90     }
  91     else {
  92         f->width = 8 * f->hdr.charSize / f->hdr.height;
  93     }
  94     f->charCount = f->hdr.charLast - f->hdr.charFirst + 1;
  95 
  96     // set width table to default value
  97     memset(f->wTable, f->width, 256);
  98     
  99     // allocate cTable memory
 100 
 101     // If existing data has been allocated then we are re-using the font data
 102     // See if it the existing cTable data is large enough to hold the new font data
 103     // If not free it so new memory will be allocated
 104     if ((f->cTable != 0) && (f->cTableSizeMax < (f->charCount*f->hdr.charSize))) {
 105         free(f->cTable);              // free the memory
 106         f->cTable = 0;                // clear pointer so new memory is allocated
 107         f->cTableSizeMax = 0;
 108     }
 109 
 110     // Allocated memory if needed
 111     if (f->cTable == 0 && !f->usingFont8x16) {
 112         // Allocate memory from cached pool
 113         f->cTable = malloc(f->charCount*f->hdr.charSize);
 114 
 115         // save size
 116         f->cTableSize = f->charCount*f->hdr.charSize;
 117         if (f->cTableSizeMax == 0) f->cTableSizeMax = f->cTableSize;    // Save actual size allocated
 118     }
 119 }
 120 
 121 //-------------------------------------------------------------------
 122 static const char tbl_dos2win[] = {
 123     0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
 124     0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
 125     0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
 126     0x2D, 0x2D, 0x2D, 0xA6, 0x2B, 0xA6, 0xA6, 0xAC, 0xAC, 0xA6, 0xA6, 0xAC, 0x2D, 0x2D, 0x2D, 0xAC,
 127     0x4C, 0x2B, 0x54, 0x2B, 0x2D, 0x2B, 0xA6, 0xA6, 0x4C, 0xE3, 0xA6, 0x54, 0xA6, 0x3D, 0x2B, 0xA6,
 128     0xA6, 0x54, 0x54, 0x4C, 0x4C, 0x2D, 0xE3, 0x2B, 0x2B, 0x2D, 0x2D, 0x2D, 0x2D, 0xA6, 0xA6, 0x2D,
 129     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
 130     0xA8, 0xB8, 0xAA, 0xBA, 0xAF, 0xBF, 0xA1, 0xA2, 0xB0, 0x95, 0xB7, 0x76, 0xB9, 0xA4, 0xA6, 0xA0
 131 };
 132 
 133 int code_page_char(int ch)
 134 {
 135     // convert character value based on selected code page
 136     if ((rbf_codepage == FONT_CP_DOS) && (ch >= 128) && (ch < 256)) {
 137         // Convert DOS to WIN char
 138         ch = tbl_dos2win[ch-128];
 139     }
 140     return ch;
 141 }
 142 
 143 //-------------------------------------------------------------------
 144 // Return address of 'character' data for specified font & char
 145 char* rbf_font_char(font* f, int ch)
 146 {
 147     if (f && (ch >= f->hdr.charFirst) && (ch <= f->hdr.charLast))
 148     {
 149         return &f->cTable[(ch-f->hdr.charFirst)*f->hdr.charSize];
 150     }
 151 
 152     return 0;
 153 }
 154 //-------------------------------------------------------------------
 155 // Read data from SD file using uncached buffer and copy to cached
 156 // font memory
 157 int font_read(int fd, unsigned char *dest, int len)
 158 {
 159     // Return actual bytes read
 160     int bytes_read = 0;
 161 
 162     if (ubuffer)
 163     {
 164         // Read file in UBUFFER_SIZE blocks
 165         while (len)
 166         {
 167             // Calc size of next block to read = min(UBUFFER_SIZE, len)
 168             int to_read = UBUFFER_SIZE;
 169             if (to_read > len) to_read = len;
 170 
 171             // Read block and copy to dest
 172             bytes_read += read(fd, ubuffer, to_read);
 173             memcpy(dest, ubuffer, to_read);
 174 
 175             // Increment dest pointer, decrement len left to read
 176             dest += to_read;
 177             len -= to_read;
 178         }
 179     }
 180 
 181     return bytes_read;
 182 }
 183 //-------------------------------------------------------------------
 184 // Load from from file. If maxchar != 0 limit charLast (for symbols)
 185 int rbf_font_load(char *file, font* f, int maxchar)
 186 {
 187     int i;
 188     int rv = 0; // return value
 189 
 190     // make sure the font has been allocated, and a valid filename is given
 191     if ((f == 0) || (*file == 0)) return 0;
 192 
 193     // turn of default font if it was being used
 194     f->usingFont8x16 = 0;
 195 
 196     // open file (can't use fopen here due to potential conflict FsIoNotify crash)
 197     int fd = open(file, O_RDONLY, 0777);
 198     if (fd >= 0) {
 199         // read header
 200         i = font_read(fd, (unsigned char*)&f->hdr, sizeof(font_hdr));
 201 
 202         // check size read is correct and magic numbers are valid
 203         if ((i == sizeof(font_hdr)) && (f->hdr.magic1 == RBF_HDR_MAGIC1) && (f->hdr.magic2 == RBF_HDR_MAGIC2)) {
 204 
 205             if (maxchar != 0) {
 206                 f->hdr.charLast = maxchar;
 207             }
 208 
 209             alloc_cTable(f);
 210 
 211             // read width table (using uncached buffer)
 212             lseek(fd, f->hdr._wmapAddr, SEEK_SET);
 213             font_read(fd, (unsigned char*)&f->wTable[f->hdr.charFirst], f->charCount);
 214 
 215             // read cTable data (using uncached buffer)
 216             lseek(fd, f->hdr._cmapAddr, SEEK_SET);
 217             font_read(fd, (unsigned char*)f->cTable, f->charCount*f->hdr.charSize);
 218 
 219             // Reset symbol display if symbol font too tall
 220             if (conf.menu_symbol_enable && rbf_font && rbf_symbol_font)
 221                 conf.menu_symbol_enable=(rbf_font->hdr.height>=rbf_symbol_font->hdr.height);
 222 
 223             rv = 1;
 224         }
 225 
 226         close(fd);
 227     }
 228 
 229     return rv;
 230 }
 231 
 232 //-------------------------------------------------------------------
 233 #define maxSymbols 128
 234 int rbf_load_symbol(char *file) {
 235     // Allocate font if needed
 236     init_fonts();
 237     // Load font
 238     return rbf_font_load(file, rbf_symbol_font, maxSymbols+32);
 239 }
 240 
 241 //-------------------------------------------------------------------
 242 // Attempt to load font from file and set codepage
 243 void rbf_load_from_file(char *file, int codepage)
 244 {
 245     // Allocate font if needed
 246     init_fonts();
 247     // Load font, load default on failure
 248     if (!rbf_font_load(file, rbf_font, 0))
 249     {
 250         // Reset back to built in font, file load failed
 251         rbf_font->hdr.charSize  = FONT_HEIGHT;
 252         rbf_font->hdr.height    = FONT_HEIGHT;
 253         rbf_font->hdr.maxWidth  = FONT_WIDTH;
 254         rbf_font->hdr.charFirst = 0;
 255         rbf_font->hdr.charLast  = 255;
 256 
 257         // This is only ever called to copy the 'current_font' data into the rbf_font
 258         // Instead of doing this set the rbf_font flag so we call 'draw_char' directly (which uses current_font)
 259         // This avoids allocating memory for a copy of something we already have
 260         rbf_font->usingFont8x16 = 1;
 261 
 262         alloc_cTable(rbf_font);
 263     }
 264     // Set codepage
 265     rbf_set_codepage(codepage);
 266 }
 267 
 268 //-------------------------------------------------------------------
 269 void rbf_set_codepage(int codepage) {
 270     rbf_codepage = codepage;
 271 }
 272 
 273 //-------------------------------------------------------------------
 274 int rbf_font_height() {
 275     return rbf_font->hdr.height;
 276 }
 277 //-------------------------------------------------------------------
 278 int rbf_symbol_height() {
 279     return rbf_symbol_font->hdr.height;
 280 }
 281 
 282 //-------------------------------------------------------------------
 283 int rbf_char_width(int ch) {
 284     return rbf_font->wTable[code_page_char(ch)];
 285 }
 286 
 287 //-------------------------------------------------------------------
 288 int rbf_symbol_width(int ch) {
 289     return rbf_symbol_font->wTable[ch];
 290 }
 291 
 292 //-------------------------------------------------------------------
 293 int rbf_str_width(const char *str) {
 294     int l=0;
 295 
 296     // Calculate how long the string is in pixels
 297     while (*str)
 298         l+=rbf_char_width(*str++);
 299 
 300     return l;
 301 }
 302 
 303 int rbf_str_clipped_width(const char *str, int l, int maxlen) {
 304     // Calculate how long the string is in pixels (possibly clipped to 'maxlen')
 305     while (*str && l+rbf_char_width(*str)<=maxlen)
 306         l+=rbf_char_width(*str++);
 307 
 308     return l;
 309 }
 310 
 311 //-------------------------------------------------------------------
 312 void font_draw_char(int x, int y, char *cdata, int width, int height, int pixel_width, twoColors cl) {
 313     int xx, yy;
 314 
 315     // draw pixels for font character
 316     if (cdata)
 317         for (yy=0; yy<height; ++yy)
 318             for (xx=0; xx<pixel_width; ++xx)
 319                 draw_pixel(x+xx ,y+yy, (cdata[yy*width/8+xx/8] & (1<<(xx%8))) ? FG_COLOR(cl) : BG_COLOR(cl));
 320 }
 321 
 322 //-------------------------------------------------------------------
 323 int rbf_draw_char(int x, int y, int ch, twoColors cl) {
 324     // Convert char for code page
 325     ch = code_page_char(ch);
 326 
 327     // Get char data pointer
 328     char* cdata = rbf_font_char(rbf_font, ch);
 329 
 330     // Draw font character (either loaded font, or from default font)
 331     if (rbf_font->usingFont8x16 || !cdata)
 332         draw_char(x,y,ch,cl);
 333     else
 334         font_draw_char(x, y, cdata, rbf_font->width, rbf_font->hdr.height, rbf_font->wTable[ch], cl);
 335 
 336     return rbf_font->wTable[ch];
 337 }
 338 
 339 //-------------------------------------------------------------------
 340 int rbf_draw_symbol(int x, int y, int ch, twoColors cl) {
 341     int space=0, pixel_width, sym_height, txt_height;
 342 
 343     // Skip if symbol font height taller than text font height (or invalid char value)
 344     if (rbf_font->hdr.height<rbf_symbol_font->hdr.height || ch==0x0) return 0;
 345 
 346     // get width of symbol in pixels
 347     pixel_width = rbf_symbol_width(ch);
 348     // get height of symbol font
 349     sym_height = rbf_symbol_font->hdr.height;
 350     // get height of text font
 351     txt_height = rbf_font->hdr.height;
 352 
 353     // Get char data pointer
 354     char* cdata = rbf_font_char(rbf_symbol_font, ch);
 355 
 356     if (cdata) {
 357       // if symbol font shorter than text font center symbol vertically and fill empty space above
 358       if (txt_height > sym_height) {
 359         space = (txt_height - sym_height)/2;
 360         draw_rectangle(x, y, x+pixel_width, y+space, MAKE_COLOR(BG_COLOR(cl), BG_COLOR(cl)), RECT_BORDER0|DRAW_FILLED);
 361         y+=space;
 362       }
 363 
 364       // Draw font character
 365       font_draw_char(x, y, cdata, rbf_symbol_font->width, sym_height, pixel_width, cl);
 366 
 367       // Fill space below symbol if shorter than text font
 368       if (txt_height > sym_height)
 369           draw_rectangle(x, y+sym_height, x+pixel_width, y-space+txt_height-1, MAKE_COLOR(BG_COLOR(cl), BG_COLOR(cl)), RECT_BORDER0|DRAW_FILLED);
 370     }
 371 
 372     return pixel_width;
 373 }
 374 
 375 //-------------------------------------------------------------------
 376 // Draw a string colored 'c1' with the character at string-position 'c' colored 'c2'.
 377 int rbf_draw_string_c(int x, int y, const char *str, twoColors c1, int c, twoColors c2) {
 378      int l=0, i=0;
 379 
 380      while (*str) {
 381           l+=rbf_draw_char(x+l, y, *str++, (i==c)?c2:c1);
 382           ++i;
 383      }
 384      return l;
 385 }
 386 
 387 //-------------------------------------------------------------------
 388 int rbf_draw_string(int x, int y, const char *str, twoColors cl) {
 389     return rbf_draw_string_c(x, y, str, cl, -1, MAKE_COLOR(0,0));
 390 }
 391 
 392 //-------------------------------------------------------------------
 393 static int cursor_on = 0;
 394 static int cursor_start = 0;
 395 static int cursor_end = 0;
 396 
 397 void rbf_enable_cursor(int s, int e)
 398 {
 399     cursor_on = 1;
 400     cursor_start = s;
 401     cursor_end = e;
 402 }
 403 
 404 void rbf_disable_cursor()
 405 {
 406     cursor_on = 0;
 407 }
 408 
 409 int rbf_draw_clipped_string(int x, int y, const char *str, twoColors cl, int l, int maxlen)
 410 {
 411     int i = 0;
 412     twoColors inv_cl = MAKE_COLOR(FG_COLOR(cl), BG_COLOR(cl));
 413 
 414     // Draw chars from string up to max pixel length
 415     while (*str && l+rbf_char_width(*str)<=maxlen)
 416     {
 417         if (cursor_on && (cursor_start <= i) && (i <= cursor_end))
 418             l+=rbf_draw_char(x+l, y, *str++, inv_cl);
 419         else
 420             l+=rbf_draw_char(x+l, y, *str++, cl);
 421         i++;
 422     }
 423 
 424     return l;
 425 }
 426 
 427 //-------------------------------------------------------------------
 428 int rbf_draw_string_len(int x, int y, int len, const char *str, twoColors cl) {
 429     // Draw string characters
 430     int l = rbf_draw_clipped_string(x, y, str, cl, 0, len);
 431 
 432     // Fill any remaining space on right with background color
 433     if (l < len)
 434         draw_rectangle(x+l, y, x+len-1, y+rbf_font->hdr.height-1, MAKE_COLOR(BG_COLOR(cl), BG_COLOR(cl)), RECT_BORDER0|DRAW_FILLED);
 435 
 436     return len;
 437 }
 438 
 439 //-------------------------------------------------------------------
 440 int rbf_draw_string_right_len(int x, int y, int len, const char *str, twoColors cl) {
 441     // Calulate amount of padding needed on the left
 442     int l = len - rbf_str_clipped_width(str, 0, len);
 443 
 444     // Fill padding with background color
 445     if (l > 0)
 446         draw_rectangle(x, y, x+l-1, y+rbf_font->hdr.height-1, MAKE_COLOR(BG_COLOR(cl), BG_COLOR(cl)), RECT_BORDER0|DRAW_FILLED);
 447 
 448     // Draw chars
 449     l = rbf_draw_clipped_string(x, y, str, cl, l, len);
 450 
 451     return l;
 452 }
 453 
 454 //-------------------------------------------------------------------
 455 int rbf_draw_menu_header(int x, int y, int len, char symbol, const char *str, twoColors cl) { 
 456     int l=0, i, ll, lr;
 457 
 458     // If symbol to be added to string determing the width of the symbol + space
 459     if (symbol!=0x0 && conf.menu_symbol_enable && rbf_font_height()>=rbf_symbol_height()) {
 460         l += rbf_symbol_width(symbol);
 461         l += rbf_char_width(' ');
 462     }
 463 
 464     // Add the length of the string (possibly clipped to fit)
 465     l = rbf_str_clipped_width(str, l, len);
 466 
 467     // Calculate padding required on left and right side
 468     ll = 8;
 469     lr = len-l-ll; 
 470 
 471     int right = x+len-1, bottom = y+rbf_font_height()-1;
 472 
 473     // Fill left & right sides of string area with a rectangle that has rounded top corners
 474     for (i=0; i<=l && i<3; i++) {
 475         if (i < 2) {
 476             // First and second columns make rounded top corners
 477             draw_line(x+i,     y+2-i, x+i,     bottom, BG_COLOR(cl));        // left side
 478             draw_line(right-i, y+2-i, right-i, bottom, BG_COLOR(cl));        // right side
 479         }
 480         else {
 481             // Rest of empty space is just filled with rectangles
 482             draw_rectangle(x+i,      y, x+ll-1,   bottom, MAKE_COLOR(BG_COLOR(cl), BG_COLOR(cl)), RECT_BORDER0|DRAW_FILLED);    // left side
 483             draw_rectangle(right-lr, y, right-i,  bottom, MAKE_COLOR(BG_COLOR(cl), BG_COLOR(cl)), RECT_BORDER0|DRAW_FILLED);    // right side
 484         }
 485     }
 486 
 487     // Draw symbol and space if required
 488     if (symbol!=0x0 && conf.menu_symbol_enable && rbf_font_height()>=rbf_symbol_height()) {
 489       ll += rbf_draw_symbol(x+ll, y, symbol, cl);
 490       ll += rbf_draw_char(x+ll, y, ' ', cl);
 491     }
 492 
 493     // Draw chars
 494     ll = rbf_draw_clipped_string(x, y, str, cl, ll, len);
 495 
 496     return ll;
 497 } 
 498 
 499 //-------------------------------------------------------------------

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