I have used fontgen before. I have been using a relatively good screen, so the size does not matter. The font is 16x16, and no problem is found, when I used the 12x12 font, I found that the program still had some defects-displaying garbled characters.
The problem lies in the function exfont_draw_one_char. I used this method when I made a printer. Later, I found that it was not feasible, and implementation was complicated and prone to problems. In the end, this is actually a bitblt function of a monochrome bitmap, and I changed it with a piece of code in the printer.
A total of three files, one of which is a small font file.
/*
* Exfont. c
*/
# Include <stdlib. h>
# Include <string. h>
# Include "exfont. H"
Int exfont_init (pexfont font, char * Name, int foreground_color, int background_color,
Unsigned char bk_mode, draw_pixel_func draw_pixel)
{
If (font! = NULL)
{
Memset (font, 0x00, sizeof (* font ));
Font-> name = Name;
Font-> draw_pixel = draw_pixel;
Font-> foreground_color = foreground_color;
Font-> background_color = background_color;
Font-> bk_mode = bk_mode;
If (draw_pixel! = NULL)
{
Return 0;
}
}
Return-1;
}
Int exfont_set_thin_font_data (pexfont font, pexfont_data thin_font_data)
{
If (font! = NULL)
{
Font-> thin_font_data = thin_font_data;
Return 0;
}
Else
{
Return-1;
}
}
Int exfont_set_wide_font_data (pexfont font, pexfont_data wide_font_data)
{
If (font! = NULL)
{
Font-> wide_font_data = wide_font_data;
Return 0;
}
Else
{
Return-1;
}
}
Int exfont_font_index (const pexfont_data font_data, unsigned short cchar)
{
Int low = 0;
Int hign = font_data-> NR;
Int mid = (low + hign)/2;
If (font_data = NULL) Return-1;
If (font_data! = NULL)
{
While (low <= hign)
{
If (font_data-> items [Mid]. value = cchar)
{
Return mid;
}
If (font_data-> items [Mid]. value> cchar)
{
Hign = mid-1;
}
Else
{
Low = Mid + 1;
}
Mid = (low + hign)/2;
}
}
Return-1;
}
# Define big_endian 1
# If big_endian
_ Inline unsigned char graphicgetpixel (char * pbuffer, int linewidth, int X, int y)
{
Int Index = (y * linewidth + x );
Return (pbuffer [index> 3] & (0x1 <(7-(index & 0x07)> (7-(index & 0x07 ));
}
_ Inline void graphicputpixel (char * pbuffer, int linewidth, int X, int y, unsigned char pixel)
{
Int Index = (y * linewidth + x );
Pbuffer [index> 3] | = (unsigned char) pixel & 0x01) <(7-(index & 0x07 ));
}
# Else
_ Inline unsigned char graphicgetpixel (char * pbuffer, int linewidth, int X, int y)
{
Int Index = (y * linewidth + x );
Return (pbuffer [index> 3] & (0x1 <(index & 0x07)> (index & 0x07 );
}
_ Inline void graphicputpixel (char * pbuffer, int linewidth, int X, int y, unsigned char pixel)
{
Int Index = (y * linewidth + x );
Pbuffer [index> 3] | = (unsigned char) pixel & 0x01) <(index & 0x07 );
}
# Endif
Void exfont_draw_one_char_new (const pexfont font, int X, int y, int index, unsigned char is_thin_char)
{
Int I, J;
Int isrcheight, isrcwidth, ilinewidth;
Int color;
Pexfont_data thin_wide_font_data;
Char * psrcbuff;
Thin_wide_font_data = is_thin_char? Font-> thin_font_data: font-> wide_font_data;
Psrcbuff = (char *) thin_wide_font_data-> items [Index]. Data;
Isrcheight = thin_wide_font_data-> height;
Isrcwidth = thin_wide_font_data-> width;
Ilinewidth = (isrcwidth & 0xf8) + (isrcwidth & 07 = 0 )? 0: 8 );
For (I = 0; I <isrcheight; I ++)
{
For (j = 0; j <isrcwidth; j ++)
{
Color = graphicgetpixel (psrcbuff, ilinewidth, J, I );
// Graphicputpixel (pdstbuff, printwidth, x + J, x + I, color );
If (color = 1)
{
Font-> draw_pixel (x + J, Y + I, font-> foreground_color );
}
Else if (font-> bk_mode = bkmode_opaque)
{
Font-> draw_pixel (x + J, Y + I, font-> background_color );
}
}
}
}
# Define is_thin_char (C) (C <128)
Void exfont_draw_one_char (const pexfont font, int X, int y, int index, unsigned char is_thin_char)
{
Pexfont_data thin_wide_font_data = is_thin_char? Font-> thin_font_data: font-> wide_font_data;
Int W;
Int h;
Int max_w = x + thin_wide_font_data-> width;
Int max_h = Y + thin_wide_font_data-> height;
Unsigned char * font_data = thin_wide_font_data-> items [Index]. Data;
Unsigned short I = 0;
Unsigned char byte = 0;
Unsigned char bit = 0;
For (H = y; H <max_h; H ++)
{
For (W = x; W <max_w; W ++)
{
Bit = 7-(W-x) % 8;
If (byte & (1 <bit ))
{
Font-> draw_pixel (W, H, font-> foreground_color );
}
Else if (font-> bk_mode = bkmode_opaque)
{
Font-> draw_pixel (W, H, font-> background_color );
}
If (bit = 0)
{
I ++;
Byte = font_data [I];
}
}
}
Return;
}
Int exfont_draw_w (const pexfont font, int X, int y, const wchar_t * text)
{
If (font! = NULL & text! = NULL)
{
Unsigned short I = 0;
Int Index = 0;
Unsigned char thin_char = 0;
Int left = X;
Int Top = y;
While (Text [I])
{
Thin_char = is_thin_char (Text [I]);
If (thin_char)
{
Index = exfont_font_index (font-> thin_font_data, text [I]);
If (index> font-> thin_font_data-> nr)
{
Return-1;
}
}
Else
{
Index = exfont_font_index (font-> wide_font_data, text [I]);
If (index> font-> wide_font_data-> nr)
{
Return-1;
}
}
Exfont_draw_one_char_new (font, left, top, index, thin_char );
// Exfont_draw_one_char (font, left, top, index, thin_char );
Left + = thin_char? Font-> thin_font_data-> width: font-> wide_font_data-> width;
I ++;
}
Return 0;
}
Else
{
Return-1;
}
}
Int exfont_draw_a (const pexfont font, int X, int y, const char * text)
{
If (font! = NULL & text! = NULL)
{
Unsigned short I = 0;
Unsigned short charcontent = 0;
Unsigned short Index = 0;
Unsigned char thin_char = 0;
Int left = X;
Int Top = y;
While (Text [I])
{
Thin_char = is_thin_char (unsigned char) Text [I]);
If (thin_char)
{
Index = exfont_font_index (font-> thin_font_data, text [I]);
If (index> font-> thin_font_data-> nr)
{
Return-1;
}
I ++;
}
Else
{
* (Char *) & charcontent = text [I];
* (Char *) & charcontent + 1) = text [I + 1];
Index = exfont_font_index (font-> wide_font_data, charcontent );
If (index> font-> wide_font_data-> nr)
{
Return-1;
}
I + = 2;
}
Exfont_draw_one_char_new (font, left, top, index, thin_char );
// Exfont_draw_one_char (font, left, top, index, thin_char );
Left + = thin_char? Font-> thin_font_data-> width: font-> wide_font_data-> width;
}
Return 0;
}
Else
{
Return-1;
}
}
Pexfont gpcurrfont = NULL;
Pexfont gui_setfont (pexfont pfont)
{
Gpcurrfont = pfont;
}
Int gui_drawstring (int x, int y, const char * text)
{
If (gpcurrfont = NULL)
Return-1;
If (gpcurrfont-> encode = encode_ansi)
Exfont_draw_a (gpcurrfont, X, Y, text );
Else
Exfont_draw_w (gpcurrfont, X, Y, (wchar_t *) text );
Return 0;
}
/*
* Demofont. c
*/
# Include "zgr. H"
Void installfont (draw_pixel_func my_draw_pixel)
{
// Install_ansi_16x16_font (my_draw_pixel );
// Install_unicode_32x32_font (my_draw_pixel );
Install_unicode_16x16_font (my_draw_pixel );
Install_ansi_12x12_font (my_draw_pixel );
Install_ansi_16x16_font (my_draw_pixel );
}
// I am a Chinese transparent background with a narrow character 16x32widechar: thinabc2354465478568dfgs
# Define str_ansi_transparent "16x16: Wide-character transparent background I am a Chinese thin char 123abc"
# Define str_unicode_transparent l "32x32: Wide-character transparent background I am a Chinese thin char 123abc"
# Define str_ansi_opaque "16x16: Wide-character opaque background I am a Chinese thin char 123abc"
# Define str_unicode_opaque l "32x32: Wide-character opaque background I am a Chinese thin char 123abc"
Void testdrawtext (void)
{
Exfont_bkmode (& g_unicode_font16) = bkmode_transparent;
Exfont_draw_a (& g_unicode_font16, 10, 10, str_ansi_transparent );
Exfont_bkmode (& g_unicode_font16) = bkmode_opaque;
Exfont_draw_a (& g_unicode_font16, 10, 40, str_ansi_opaque );
# If defined (win32) | defined (Linux)
Exfont_bkmode (& g_unicode_font16) = bkmode_transparent;
Exfont_draw_w (& g_unicode_font16, 10, 80, str_unicode_transparent );
Exfont_bkmode (& g_unicode_font16) = bkmode_opaque;
Exfont_draw_w (& g_unicode_font16, 10,120, str_unicode_opaque );
# Endif
Return;
}
Modify the font file
Void install_ansi_16x16_font (draw_pixel_func my_draw_pixel)
{
Size_t I = 0;
For (I = 0; I <thin_char_nr; I ++)
{
Thin_font16_items [I]. value = thin_ansi_font8x16 [I]. value;
Thin_font16_items [I]. Data = (unsigned char *) thin_ansi_font8x16 [I]. Data;
}
For (I = 0; I <wide_char_nr; I ++)
{
Wide_font16_items [I]. value = wide_ansi_font16x16 [I]. value;
Wide_font16_items [I]. Data = (unsigned char *) wide_ansi_font16x16 [I]. Data;
}
Exfont_data_init (& thin_font16, 8, 16, thin_char_nr, thin_font16_items );
Exfont_data_init (& wide_font16, 16, 16, wide_char_nr, wide_font16_items );
Exfont_init (& g_ansi_font16, "g_ansi_font16 ",
1, // RGB (255, 0, 0 ),//
0, // RGB (0,255, 0), // I have a monochrome screen, so I have to modify it like this.
Bkmode_transparent,
My_draw_pixel );
Exfont_set_thin_font_data (& g_ansi_font16, & thin_font16 );
Exfont_set_wide_font_data (& g_ansi_font16, & wide_font16 );
G_ansi_font16.encode = encode_ansi; // This is newly added, indicating that this font is an ANSI-encoded small font.
Return;
}
To identify whether the font is ANSI or Unicode, an encode is added to the exfont struct representing the font to indicate the encoding type. In the exfont. h file, modify the following:
# Define encode_ansi 0x00
# Define encode_unicode 0x01
Typedef struct _ exfont {
/*
* Name of the font, used for retrieving purpose.
*/
Char * Name;
/*
* Background mode: bkmode_opaque or bkmode_transparent
*/
Unsigned char bk_mode;
/*
* Encode mode: bkmode_opaque or bkmode_transparent
*/
Unsigned char encode;
/*
* Color of the char.
*/
Int foreground_color;
Int background_color;
/*
* Font data:
* Thin_font_data: font data of ASCII chars.
* Wide_font_data: font data of multibytes chars.
*/
Pexfont_data thin_font_data;
Pexfont_data wide_font_data;
/*
* Output function.
*/
Draw_pixel_func draw_pixel;
} Exfont, * pexfont;
In this way, the 12x12 font can be displayed smoothly. The result also encountered a special problem: the Chinese character is followed by a number, and then followed by a Chinese character. If the number is an even number, the subsequent Chinese characters cannot be displayed.
After tracking, it is found that Chinese characters are not aligned by 2 bytes. Finally, the solution is to read data in bytes one by one.
* (Char *) & charcontent = text [I];
* (Char *) & charcontent + 1) = text [I + 1];
But let me think: why is there an error in reading two bytes from an odd address? Is it my hardware? So far.
[07.05.22]