[Deven] Use fontgen to implement ultra-small font

Source: Internet
Author: User

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]

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.