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