11#define RETROFONT_PRESENT 1 
   13#ifndef RETROFONT_LINE_SZ 
   14#  define RETROFONT_LINE_SZ 80 
   17#ifndef RETROFONT_TRACE_LVL 
   18#  define RETROFONT_TRACE_LVL 0 
   27#define RETROFONT_FLAG_OUTLINE  0x04 
   32   uint16_t glyphs_count;
 
 
   39   const char* font_name, MAUG_MHANDLE* p_font_h,
 
   40   uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count );
 
   42void retrofont_blit_glyph(
 
   44   char c, 
struct RETROFONT* font, 
size_t x, 
size_t y, uint8_t flags );
 
   48   const char* str, 
size_t str_sz,
 
   49   MAUG_MHANDLE font_h, 
size_t x, 
size_t y,
 
   50   size_t max_w, 
size_t max_h, uint8_t flags );
 
   54   MAUG_MHANDLE font_h, 
size_t max_w, 
size_t max_h,
 
   55   size_t* out_w_p, 
size_t* out_h_p, uint8_t flags );
 
   60#define retrofont_glyph_at( p_font, idx ) \ 
   61   &(((uint8_t*)(p_font))[(p_font)->sz + \ 
   62      ((p_font)->glyph_sz * (idx - (p_font)->first_glyph))]) 
 
   66void retrofont_dump_glyph( uint8_t* glyph, uint8_t w, uint8_t h ) {
 
   70   for( y = 0 ; h > y ; y++ ) {
 
   71      memset( glyph_bin, 
'\0', 65 );
 
   73      for( x = 0 ; w > x ; x++ ) {
 
   74         glyph_bin[x] = 1 << (w - x) == (glyph[y] & (1 << (w - x))) ? 
'x' : 
'.';
 
   77      debug_printf( RETROFONT_TRACE_LVL, 
"%s", glyph_bin );
 
   81static size_t retrofont_sz_from_filename( 
const char* font_name ) {
 
   82   const char* p_c = NULL;
 
   89   assert( NULL != font_name );
 
   90   assert( 
' ' <= font_name[0] );
 
   92   p_c = maug_strrchr( font_name, 
'.' );
 
   93   while( p_c - 1 > font_name ) {
 
  103      for( i = 9 ; 0 < i ; i-- ) {
 
  104         glyph_h_buf[i] = glyph_h_buf[i - 1];
 
  108      glyph_h_buf[0] = *p_c;
 
  111   glyph_h = atoi( glyph_h_buf );
 
  113   debug_printf( 1, 
"detected glyph height: " SIZE_T_FMT, glyph_h );
 
  119   const char* font_name, MAUG_MHANDLE* p_font_h,
 
  120   uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count
 
  124   char line[RETROFONT_LINE_SZ];
 
  126   char* line_bytes = NULL;
 
  127   uint16_t glyph_idx = 0;
 
  128   uint8_t* p_glyph = NULL;
 
  130   uint8_t glyph_w_bytes = 0;
 
  140      glyph_h = retrofont_sz_from_filename( font_name );
 
  143      error_printf( 
"unable to determine font height!" );
 
  149   #define retrofont_split_glyph_line( line, line_bytes ) \ 
  150      line_bytes = maug_strchr( line, ':' ); \ 
  151      if( NULL == line_bytes ) { \ 
  152         error_printf( "invalid line: %s", line ); \ 
  153         retval = MERROR_PARSE; \ 
  155      line_bytes[0] = '\0'; \ 
  159   maug_cleanup_if_not_ok();
 
  162   retval = font_file.read_line( &font_file, line, RETROFONT_LINE_SZ, 0 );
 
  163   maug_cleanup_if_not_ok();
 
  164   retrofont_split_glyph_line( line, line_bytes );
 
  165   maug_cleanup_if_not_ok();
 
  166   glyph_w_bytes = (maug_strlen( line_bytes ) / glyph_h) >> 1; 
 
  167   debug_printf( RETROFONT_TRACE_LVL, 
"glyph_w_bytes: %u", glyph_w_bytes );
 
  168   glyph_w = glyph_w_bytes * 8;
 
  170#if 0 < RETROFONT_TRACE_LVL 
  171   debug_printf( RETROFONT_TRACE_LVL, 
"glyph_w: %u, glyph_sz: %u",
 
  172      glyph_w, glyph_h * glyph_w_bytes );
 
  176   *p_font_h = maug_malloc( 1,
 
  178      (glyph_h * glyph_w_bytes * (1 + glyphs_count)) );
 
  179   maug_cleanup_if_null_alloc( MAUG_MHANDLE, *p_font_h );
 
  181#if 0 < RETROFONT_TRACE_LVL 
  182   debug_printf( RETROFONT_TRACE_LVL, 
"allocated font %s: " SIZE_T_FMT 
" bytes",
 
  183      font_name, (glyph_h * glyph_w_bytes * (1 + glyphs_count)) + 
 
  187   maug_mlock( *p_font_h, font );
 
  188   maug_cleanup_if_null_alloc( 
struct RETROFONT*, font );
 
  192   font->first_glyph = first_glyph;
 
  193   font->glyph_w = glyph_w;
 
  194   font->glyph_h = glyph_h;
 
  195   font->glyph_sz = glyph_h * glyph_w_bytes;
 
  197   while( mfile_has_bytes( &font_file ) ) {
 
  198      retval = font_file.read_line( &font_file, line, RETROFONT_LINE_SZ, 0 );
 
  200      retrofont_split_glyph_line( line, line_bytes );
 
  201      if( MERROR_PARSE == retval ) {
 
  210      glyph_idx = maug_atou32( line, 0, 16 );
 
  211      if( glyph_idx < first_glyph || glyph_idx > first_glyph + glyphs_count ) {
 
  216      debug_printf( RETROFONT_TRACE_LVL, 
"found glyph: %u", glyph_idx );
 
  221      for( i = 0 ; font->glyph_h > i ; i++ ) {
 
  222         switch( font->glyph_w ) {
 
  225            p_glyph[i] |= 
maug_hctoi( line_bytes[i << 1] ) << 4;
 
  226            p_glyph[i] |= 
maug_hctoi( line_bytes[(i << 1) + 1] );
 
  238            error_printf( 
"invalid font width: %u", font->glyph_w );
 
  239            retval = MERROR_PARSE;
 
  244#if 0 < RETROFONT_TRACE_LVL 
  246      if( glyph_idx == 
'0' ) {
 
  247         retrofont_dump_glyph( p_glyph, glyph_w, glyph_h );
 
  251      font->glyphs_count++;
 
  253      debug_printf( RETROFONT_TRACE_LVL,
 
  254         "parsed %u glyphs...", font->glyphs_count );
 
  257#if 0 < RETROFONT_TRACE_LVL 
  258      debug_printf( RETROFONT_TRACE_LVL,
 
  259         "%u %s (" SIZE_T_FMT 
" hbytes)", glyph_idx - first_glyph, line_bytes,
 
  260         maug_strlen( line_bytes ) );
 
  267      maug_munlock( *p_font_h, font );
 
  275void retrofont_blit_glyph(
 
  277   char c, 
struct RETROFONT* font, 
size_t x, 
size_t y, uint8_t flags
 
  280   int16_t x_iter, y_iter, y_start, y_end, x_end;
 
  281   uint8_t prev_px_was_clear = 0;
 
  283   debug_printf( RETROFONT_TRACE_LVL, 
"blit glyph: %c", c );
 
  288      font->glyph_h + 1 : font->glyph_h;
 
  290      font->glyph_w + 1 : font->glyph_w;
 
  292   #define _retrofont_px_is_clear( x_iter, y_iter ) \ 
  293      (0 > (x_iter) || font->glyph_w <= (x_iter) || \ 
  294      0 > (y_iter) || font->glyph_h <= (y_iter) || \ 
  295         (1 << (font->glyph_w - (x_iter)) != \ 
  296            (glyph[(y_iter)] & (1 << (font->glyph_w - (x_iter)))))) 
  298   for( y_iter = y_start ; y_end > y_iter ; y_iter++ ) {
 
  299      prev_px_was_clear = 1;
 
  300      for( x_iter = 0 ; x_end > x_iter ; x_iter++ ) {
 
  301         if( _retrofont_px_is_clear( x_iter, y_iter ) ) {
 
  304               (!prev_px_was_clear ||
 
  305               !_retrofont_px_is_clear( x_iter + 1, y_iter ) ||
 
  306               !_retrofont_px_is_clear( x_iter, y_iter + 1 ) ||
 
  307               !_retrofont_px_is_clear( x_iter, y_iter - 1 ))
 
  311                  target, RETROFLAT_COLOR_DARKBLUE,
 
  312                  x + x_iter, y + y_iter, 0 );
 
  316            prev_px_was_clear = 1;
 
  320            retroflat_px( target, color, x + x_iter, y + y_iter, 0 );
 
  322            prev_px_was_clear = 0;
 
  328void retrofont_string(
 
  330   const char* str, 
size_t str_sz,
 
  331   MAUG_MHANDLE font_h, 
size_t x, 
size_t y,
 
  332   size_t max_w, 
size_t max_h, uint8_t flags
 
  339   if( (MAUG_MHANDLE)NULL == font_h ) {
 
  340      error_printf( 
"NULL font specified!" );
 
  345      str_sz = maug_strlen( str );
 
  348   maug_mlock( font_h, font );
 
  350      error_printf( 
"could not lock font!" );
 
  356   for( i = 0 ; str_sz > i ; i++ ) {
 
  358      if( 
'\0' == str[i] ) {
 
  363      if( 
'\r' == str[i] || 
'\n' == str[i] ) {
 
  365         y_iter += font->glyph_h;
 
  368            "newline: " SIZE_T_FMT 
", " SIZE_T_FMT, x_iter, y_iter );
 
  375            str[i] < font->first_glyph ||
 
  376            str[i] >= font->first_glyph + font->glyphs_count
 
  379         error_printf( 
"invalid character: 0x%02x", str[i] );
 
  384      if( 
' ' != str[i] ) {
 
  385         retrofont_blit_glyph(
 
  386            target, color, str[i], font, x_iter, y_iter, flags );
 
  389      x_iter += font->glyph_w;
 
  390      if( 0 < max_w && (x + max_w) <= x_iter + font->glyph_w ) {
 
  392         y_iter += font->glyph_h;
 
  399      maug_munlock( font_h, font );
 
  405   MAUG_MHANDLE font_h, 
size_t max_w, 
size_t max_h,
 
  406   size_t* out_w_p, 
size_t* out_h_p, uint8_t flags
 
  413   if( (MAUG_MHANDLE)NULL == font_h ) {
 
  414      error_printf( 
"NULL font specified!" );
 
  420      str_sz = maug_strlen( str );
 
  423   maug_mlock( font_h, font );
 
  424   maug_cleanup_if_null_alloc( 
struct RETROFONT*, font );
 
  426   for( i = 0 ; str_sz > i ; i++ ) {
 
  428      if( 
'\0' == str[i] ) {
 
  433      if( 
'\r' == str[i] || 
'\n' == str[i] ) {
 
  435         *out_h_p += font->glyph_h;
 
  439      x_iter += font->glyph_w;
 
  441      if( *out_w_p <= x_iter ) {
 
  444      if( 0 < max_w && max_w < x_iter + font->glyph_w ) {
 
  446         *out_h_p += font->glyph_h;
 
  447         if( 0 < max_h && *out_h_p + font->glyph_h >= max_h && i < str_sz ) {
 
  448            error_printf( 
"string will not fit!" );
 
  457   *out_h_p += font->glyph_h;
 
  463      maug_munlock( font_h, font );
 
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
 
#define maug_mzero(ptr, sz)
Zero the block of memory pointed to by ptr.
Definition mmem.h:62
 
MERROR_RETVAL mfile_open_read(const char *filename, mfile_t *p_file)
Open a file and read it into memory or memory-map it.
 
void mfile_close(mfile_t *p_file)
Close a file opened with mfile_open_read().
 
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition retroflt.h:307
 
#define maug_hctoi(c)
Convert a single char hex digit to the int it represents.
Definition uprintf.h:317
 
#define retrofont_glyph_at(p_font, idx)
Get a pointer to the glyph with the given index in the given font.
Definition retrofnt.h:60
 
#define RETROFONT_FLAG_OUTLINE
Flag for retroflat_string() and retroflat_string_sz() to print text as outline-only.
Definition retrofnt.h:27
 
Platform-specific bitmap structure. retroflat_bitmap_ok() can be used on a pointer to it to determine...
Definition retpltd.h:21