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

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