@@ -238,6 +238,10 @@ wrap_paragraph(char *text)
238238 return text ;
239239}
240240
241+
242+ static unsigned char font_data [(FONT_W * FONT_COUNT + 7 ) / 8 * FONT_H ];
243+ static bool font_data_initialized = false;
244+
241245// since the data are already in memory, it would be also possible to use
242246// pointer directly to font array (skipping or deleting PBM header)
243247static bool draw_line_init (unsigned char * out ) {
@@ -263,41 +267,51 @@ static bool draw_line_init(unsigned char *out) {
263267
264268 memcpy (out , font_data , (info .width + 7 ) / 8 * info .height );
265269 free (font_data );
270+ font_data_initialized = true;
266271 return true;
267272}
268273
274+ /// draw the letter as RGBA pixmap
269275static void
270- draw_letter (char c , uint32_t color , char * buf , const unsigned char * font_data ,
271- int pitch , bool solid )
276+ draw_letter (char c , uint32_t fg , uint32_t bg , unsigned char * buf ,
277+ const unsigned char * font_data , int pitch )
272278{
273279 if (c < ' ' || c > '~' ) {
274280 c = '?' ;
275281 }
276282 c -= ' ' ;
283+ const unsigned char fg0 = fg & 0xFFU ;
284+ const unsigned char fg1 = (fg >> 8U ) & 0xFFU ;
285+ const unsigned char fg2 = (fg >> 16U ) & 0xFFU ;
286+ const unsigned char fg3 = (fg >> 24U ) & 0xFFU ;
287+ const unsigned char bg0 = bg & 0xFFU ;
288+ const unsigned char bg1 = (bg >> 8U ) & 0xFFU ;
289+ const unsigned char bg2 = (bg >> 16U ) & 0xFFU ;
290+ const unsigned char bg3 = (bg >> 24U ) & 0xFFU ;
277291 for (int j = 0 ; j < FONT_H ; ++ j ) {
278292 for (int i = 0 ; i < FONT_W ; ++ i ) {
279293 int pos_x = (FONT_W * c + i ) / 8 ;
280294 int mask = 1 << (FONT_W - ((FONT_W * c + i ) % 8 ));
281295 int offset = (FONT_W * FONT_COUNT + 7 ) / 8 * j ;
282296 if (font_data [offset + pos_x ] & mask ) {
283297 // clang-format off
284- buf [(j * pitch ) + (4 * i )] = color & 0xFFU ;
285- buf [(j * pitch ) + (4 * i ) + 1 ] = ( color >> 8U ) & 0xFFU ;
286- buf [(j * pitch ) + (4 * i ) + 2 ] = ( color >> 16U ) & 0xFFU ;
287- buf [(j * pitch ) + (4 * i ) + 3 ] = ( color >> 24U ) & 0xFFU ;
298+ buf [(j * pitch ) + (4 * i )] = fg0 ;
299+ buf [(j * pitch ) + (4 * i ) + 1 ] = fg1 ;
300+ buf [(j * pitch ) + (4 * i ) + 2 ] = fg2 ;
301+ buf [(j * pitch ) + (4 * i ) + 3 ] = fg3 ;
288302 // clang-format on
289- } else if (solid ) {
290- buf [(j * pitch ) + (4 * i )] = 0 ;
291- buf [(j * pitch ) + (4 * i ) + 1 ] = 0 ;
292- buf [(j * pitch ) + (4 * i ) + 2 ] = 0 ;
293- buf [(j * pitch ) + (4 * i ) + 3 ] = 0xFFU ; // alpha
303+ } else if (bg != 0 ) {
304+ buf [(j * pitch ) + (4 * i )] = bg0 ;
305+ buf [(j * pitch ) + (4 * i ) + 1 ] = bg1 ;
306+ buf [(j * pitch ) + (4 * i ) + 2 ] = bg2 ;
307+ buf [(j * pitch ) + (4 * i ) + 3 ] = bg3 ;
294308 }
295309 }
296- if (solid ) { // fill space between characters
297- buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 ))] = 0 ;
298- buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 )) + 1 ] = 0 ;
299- buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 )) + 2 ] = 0 ;
300- buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 )) + 3 ] = 0xFFU ;
310+ if (bg ) { // fill space between characters
311+ buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 ))] = bg0 ;
312+ buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 )) + 1 ] = bg1 ;
313+ buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 )) + 2 ] = bg2 ;
314+ buf [(j * pitch ) + (4 * (FONT_W_SPACE - 1 )) + 3 ] = bg3 ;
301315 }
302316 }
303317}
@@ -306,19 +320,17 @@ draw_letter(char c, uint32_t color, char *buf, const unsigned char *font_data,
306320 * draws a line with built-in bitmap 12x7 bitmap font separated by 1 px space, RGBA
307321 */
308322bool draw_line (char * buf , int pitch , const char * text , uint32_t color , bool solid ) {
309- static unsigned char font_data [(FONT_W * FONT_COUNT + 7 ) / 8 * FONT_H ];
310- static bool font_data_initialized = false;
311- if (!font_data_initialized ) {
312- if (!draw_line_init (font_data )) {
313- return false;
314- }
315- font_data_initialized = true;
323+ if (!font_data_initialized && !draw_line_init (font_data )) {
324+ return false;
316325 }
317326 int idx = 0 ;
327+ const uint32_t bg = solid ? 0xFF000000U : 0 ;
318328 while (* text ) {
319329 char c = * text ++ ;
320- draw_letter (c , color , buf + (size_t ) (4 * idx * FONT_W_SPACE ),
321- font_data , pitch , solid );
330+ draw_letter (c , color , bg ,
331+ (unsigned char * ) buf +
332+ (size_t ) (4 * idx * FONT_W_SPACE ),
333+ font_data , pitch );
322334 if ((++ idx + 1 ) * FONT_W_SPACE * 4 > pitch ) {
323335 return true;
324336 }
@@ -327,6 +339,48 @@ bool draw_line(char *buf, int pitch, const char *text, uint32_t color, bool soli
327339 return true;
328340}
329341
342+ /**
343+ * similar to draw_line() but integer upscaling can be applied
344+ *
345+ * transparency not supported/implemented
346+ *
347+ * @param bg must not be 0, use 0xFF<<24 (alpha set to 0xFF)
348+ */
349+ bool
350+ draw_line_scaled (char * buf , int pitch , const char * text , uint32_t fg ,
351+ uint32_t bg , unsigned scale )
352+ {
353+ (void ) buf ;
354+ assert (scale > 0 );
355+ assert (bg != 0 ); // draw letter would than assume transparency which
356+ // doesn't work with the _scaled version
357+ if (!font_data_initialized && !draw_line_init (font_data )) {
358+ return false;
359+ }
360+ int idx = 0 ;
361+ while (* text ) {
362+ char c = * text ++ ;
363+ unsigned char letter [4 * FONT_W_SPACE * FONT_H ];
364+ draw_letter (c , fg , bg , letter , font_data , 4 * FONT_W_SPACE );
365+ // resize
366+ for (unsigned y = 0 ; y < FONT_H ; ++ y ) {
367+ for (unsigned x = 0 ; x < FONT_W_SPACE ; ++ x ) {
368+ for (unsigned sv = 0 ; sv < scale ; ++ sv ) {
369+ for (unsigned sh = 0 ; sh < scale ; ++ sh ) {
370+ memcpy (buf + ((scale * y + sv ) * pitch + (((idx * scale * FONT_W_SPACE )
371+ + (x * scale + sh )) * 4 )), letter + (4 * (y * FONT_W_SPACE + x )), 4 );
372+ }
373+ }
374+ }
375+ }
376+ if ((++ idx + 1 ) * FONT_W_SPACE * 4 * scale > (unsigned ) pitch ) {
377+ return true;
378+ }
379+ }
380+
381+ return true;
382+ }
383+
330384/// @returns null-terminated list of TTF font candidates
331385const char * const *
332386get_font_candidates ()
0 commit comments