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 );
53 retroflat_blit_t* target,
const char* str,
size_t str_sz,
54 MAUG_MHANDLE font_h,
size_t max_w,
size_t max_h,
55 size_t* p_out_w,
size_t* p_out_h, 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 ) {
96 if(
'-' == *p_c ||
'_' == *p_c ) {
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 );
114 RETROFONT_TRACE_LVL,
"detected glyph height: " SIZE_T_FMT, glyph_h );
120 const char* font_name, MAUG_MHANDLE* p_font_h,
121 uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count
125 char line[RETROFONT_LINE_SZ];
127 char* line_bytes = NULL;
128 uint16_t glyph_idx = 0;
129 uint8_t* p_glyph = NULL;
131 uint8_t glyph_w_bytes = 0;
141 glyph_h = retrofont_sz_from_filename( font_name );
144 error_printf(
"unable to determine font height!" );
150 #define retrofont_split_glyph_line( line, line_bytes ) \
151 line_bytes = maug_strchr( line, ':' ); \
152 if( NULL == line_bytes ) { \
153 error_printf( "invalid line: %s", line ); \
154 retval = MERROR_PARSE; \
156 line_bytes[0] = '\0'; \
160 maug_cleanup_if_not_ok();
162 debug_printf( RETROFONT_TRACE_LVL,
"font file opened, reading..." );
165 retval = font_file.read_line( &font_file, line, RETROFONT_LINE_SZ, 0 );
166 maug_cleanup_if_not_ok();
167 retrofont_split_glyph_line( line, line_bytes );
168 maug_cleanup_if_not_ok();
169 glyph_w_bytes = (maug_strlen( line_bytes ) / glyph_h) >> 1;
170 debug_printf( RETROFONT_TRACE_LVL,
"glyph_w_bytes: %u", glyph_w_bytes );
171 glyph_w = glyph_w_bytes * 8;
173#if 0 < RETROFONT_TRACE_LVL
174 debug_printf( RETROFONT_TRACE_LVL,
"glyph_w: %u, glyph_sz: %u",
175 glyph_w, glyph_h * glyph_w_bytes );
179 *p_font_h = maug_malloc( 1,
181 (glyph_h * glyph_w_bytes * (1 + glyphs_count)) );
182 maug_cleanup_if_null_alloc( MAUG_MHANDLE, *p_font_h );
184#if 0 < RETROFONT_TRACE_LVL
185 debug_printf( RETROFONT_TRACE_LVL,
"allocated font %s: " SIZE_T_FMT
" bytes",
186 font_name, (glyph_h * glyph_w_bytes * (1 + glyphs_count)) +
190 maug_mlock( *p_font_h, font );
191 maug_cleanup_if_null_alloc(
struct RETROFONT*, font );
195 font->first_glyph = first_glyph;
196 font->glyph_w = glyph_w;
197 font->glyph_h = glyph_h;
198 font->glyph_sz = glyph_h * glyph_w_bytes;
200 while( font_file.has_bytes( &font_file ) ) {
201 retval = font_file.read_line( &font_file, line, RETROFONT_LINE_SZ, 0 );
203 retrofont_split_glyph_line( line, line_bytes );
204 if( MERROR_PARSE == retval ) {
213 glyph_idx = maug_atou32( line, 0, 16 );
214 if( glyph_idx < first_glyph || glyph_idx > first_glyph + glyphs_count ) {
219 debug_printf( RETROFONT_TRACE_LVL,
"found glyph: %u", glyph_idx );
224 for( i = 0 ; font->glyph_h > i ; i++ ) {
225 switch( font->glyph_w ) {
228 p_glyph[i] |= maug_hctoi( line_bytes[i << 1] ) << 4;
229 p_glyph[i] |= maug_hctoi( line_bytes[(i << 1) + 1] );
241 error_printf(
"invalid font width: %u", font->glyph_w );
242 retval = MERROR_PARSE;
247#if 0 < RETROFONT_TRACE_LVL
249 if( glyph_idx ==
'0' ) {
250 retrofont_dump_glyph( p_glyph, glyph_w, glyph_h );
254 font->glyphs_count++;
256 debug_printf( RETROFONT_TRACE_LVL,
257 "parsed %u glyphs...", font->glyphs_count );
260#if 0 < RETROFONT_TRACE_LVL
261 debug_printf( RETROFONT_TRACE_LVL,
262 "%u %s (" SIZE_T_FMT
" hbytes)", glyph_idx - first_glyph, line_bytes,
263 maug_strlen( line_bytes ) );
270 maug_munlock( *p_font_h, font );
278void retrofont_blit_glyph(
280 char c,
struct RETROFONT* font,
size_t x,
size_t y, uint8_t flags
283 int16_t x_iter, y_iter, y_start, y_end, x_end, x_pen_down = -1;
284 uint8_t prev_px_was_clear = 0;
286 debug_printf( RETROFONT_TRACE_LVL,
"blit glyph: %c", c );
291 font->glyph_h + 1 : font->glyph_h;
293 font->glyph_w + 1 : font->glyph_w;
295 #define _retrofont_px_is_clear( x_iter, y_iter ) \
296 (0 > (x_iter) || font->glyph_w <= (x_iter) || \
297 0 > (y_iter) || font->glyph_h <= (y_iter) || \
298 (1 << (font->glyph_w - (x_iter)) != \
299 (glyph[(y_iter)] & (1 << (font->glyph_w - (x_iter))))))
301 for( y_iter = y_start ; y_end > y_iter ; y_iter++ ) {
303 prev_px_was_clear = 1;
309 for( x_iter = 0 ; x_end >= x_iter ; x_iter++ ) {
310 if( _retrofont_px_is_clear( x_iter, y_iter ) ) {
312 if( 0 <= x_pen_down ) {
316 x + x_pen_down, y + y_iter, x + x_iter, y + y_iter, 0 );
322 (!prev_px_was_clear ||
323 !_retrofont_px_is_clear( x_iter + 1, y_iter ) ||
324 !_retrofont_px_is_clear( x_iter, y_iter + 1 ) ||
325 !_retrofont_px_is_clear( x_iter, y_iter - 1 ))
329 target, RETROFLAT_COLOR_DARKBLUE,
330 x + x_iter, y + y_iter, 0 );
334 prev_px_was_clear = 1;
339 if( 0 > x_pen_down ) {
344 prev_px_was_clear = 0;
350void retrofont_string(
352 const char* str,
size_t str_sz,
353 MAUG_MHANDLE font_h,
size_t x,
size_t y,
354 size_t max_w,
size_t max_h, uint8_t flags
361 if( (MAUG_MHANDLE)NULL == font_h ) {
362 error_printf(
"NULL font specified!" );
367 str_sz = maug_strlen( str );
370 maug_mlock( font_h, font );
372 error_printf(
"could not lock font!" );
378 for( i = 0 ; str_sz > i ; i++ ) {
380 if(
'\0' == str[i] ) {
385 if(
'\r' == str[i] ||
'\n' == str[i] ) {
387 y_iter += font->glyph_h;
390 "newline: " SIZE_T_FMT
", " SIZE_T_FMT, x_iter, y_iter );
397 str[i] < font->first_glyph ||
398 str[i] >= font->first_glyph + font->glyphs_count
401 error_printf(
"invalid character: 0x%02x", str[i] );
406 if(
' ' != str[i] ) {
407 retrofont_blit_glyph(
408 target, color, str[i], font, x_iter, y_iter, flags );
411 x_iter += font->glyph_w;
412 if( 0 < max_w && (x + max_w) <= x_iter + font->glyph_w ) {
414 y_iter += font->glyph_h;
421 maug_munlock( font_h, font );
426 retroflat_blit_t* target,
const char* str,
size_t str_sz,
427 MAUG_MHANDLE font_h,
size_t max_w,
size_t max_h,
428 size_t* p_out_w,
size_t* p_out_h, uint8_t flags
436 if( (MAUG_MHANDLE)NULL == font_h ) {
437 error_printf(
"NULL font specified!" );
442 if( NULL == p_out_h ) {
447 str_sz = maug_strlen( str );
450 maug_mlock( font_h, font );
451 maug_cleanup_if_null_alloc(
struct RETROFONT*, font );
453 for( i = 0 ; str_sz > i ; i++ ) {
455 if(
'\0' == str[i] ) {
460 if(
'\r' == str[i] ||
'\n' == str[i] ) {
462 *p_out_h += font->glyph_h;
466 x_iter += font->glyph_w;
468 if( NULL != p_out_w && *p_out_w <= x_iter ) {
471 if( 0 < max_w && max_w < x_iter + font->glyph_w ) {
473 *p_out_h += font->glyph_h;
474 if( 0 < max_h && *p_out_h + font->glyph_h >= max_h && i < str_sz ) {
475 error_printf(
"string will not fit!" );
484 *p_out_h += font->glyph_h;
485 if( NULL != p_out_w ) {
492 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:65
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:325
#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