Linux下,利用FreeType2的API实现字符的显示
2011-11-04 18:37
453 查看
网上的FreeType2例子太少,能显示汉字的比较难找,C语言代码写的更难找,能找到的,基本上是被转载了N遍的同一个示例代码,基本上解决不了我的问题。
于是乎,花费了不少时间才完成了这些代码。
主要是先解决编码问题,需要用wchar_t类型保存unicode编码的字符,字符串常量倒好弄,例如:wchar_t str[]=L"一段文本"; 编译时编译器就自动帮你转换好,但前提是源码文件的编码要为UTF-8,其它编码,例如ASCII,编译时会报错。
而字符串变量的话,需要程序自己转换,UTF-8转Unicode,代码在这里:
https://github.com/lc-soft/LCUI/blob/master/src/font/charset.c
看utf8_to_unicode函数的代码。
其次是要知道如何获取一个字的位图的相关度量,例如:字形的宽、高、左边界距、上边界距、水平跨距等等。
以前看中译版本的FreeType文档,没看明白,最近看了后,终于知道了如何获取字形的这些度量。
我目前使用的代码在这里:
https://github.com/lc-soft/LCUI/blob/master/src/font/bitmapfont.c
主要看Convert_FTGlyph函数和Get_FontBMP函数的代码。
Get_FontBMP函数只获取单个字的位图信息,要获取字符串的话,连续调用Get_FontBMP函数并保存得到的字体数据,之后根据字体数据中的信息绘制到目标面上即可。
除了看代码外,建议看FreeType2的文档,网上有中译版本。
文字绘制的效果截图:
主要演示彩色文本的渲染,不同大小字体的绘制,字体使用的是 微软雅黑。
以下代码中用到的结构体:
以下是部分代码,Convert_FTGlyph函数中主要获取字体位图的相关度量信息。
Open_Fontfile函数是打开指定路径的字体文件,并将FT库的句柄及face对象指针保存至结构体中。
于是乎,花费了不少时间才完成了这些代码。
主要是先解决编码问题,需要用wchar_t类型保存unicode编码的字符,字符串常量倒好弄,例如:wchar_t str[]=L"一段文本"; 编译时编译器就自动帮你转换好,但前提是源码文件的编码要为UTF-8,其它编码,例如ASCII,编译时会报错。
而字符串变量的话,需要程序自己转换,UTF-8转Unicode,代码在这里:
https://github.com/lc-soft/LCUI/blob/master/src/font/charset.c
看utf8_to_unicode函数的代码。
其次是要知道如何获取一个字的位图的相关度量,例如:字形的宽、高、左边界距、上边界距、水平跨距等等。
以前看中译版本的FreeType文档,没看明白,最近看了后,终于知道了如何获取字形的这些度量。
我目前使用的代码在这里:
https://github.com/lc-soft/LCUI/blob/master/src/font/bitmapfont.c
主要看Convert_FTGlyph函数和Get_FontBMP函数的代码。
Get_FontBMP函数只获取单个字的位图信息,要获取字符串的话,连续调用Get_FontBMP函数并保存得到的字体数据,之后根据字体数据中的信息绘制到目标面上即可。
除了看代码外,建议看FreeType2的文档,网上有中译版本。
文字绘制的效果截图:
主要演示彩色文本的渲染,不同大小字体的绘制,字体使用的是 微软雅黑。
以下代码中用到的结构体:
/******************************保存字体信息********************************/ struct _LCUI_Font/* 字体信息数据 */ { int type; /* 类型(DEFAULT / CUSTOM) */ LCUI_String font_file; /* 字体文件的路径 */ LCUI_String family_name; /* 字体名称 */ LCUI_String style_name; /* 字体风格名称 */ void* ft_lib; /* FreeType2库的句柄 */ void* ft_face; /* FreeType2的face对象的句柄 */ int load_flags; /* 字形载入标志 */ int render_mode; /* 字形转换模式标志 */ int status; /* 状态,是否打开了字体库 */ }; /************************************************************************/ /********** 保存字体位图数据 ***************/ struct _LCUI_FontBMP { int top; /* 与顶边框的距离 */ int left; /* 与左边框的距离 */ int width; /* 位图宽度 */ int rows; /* 位图行数 */ int pitch; uchar_t *buffer; /* 字体位图数据 */ short num_grays; char pixel_mode; LCUI_Pos advance; /* XY轴的跨距 */ }; /*****************************************/
以下是部分代码,Convert_FTGlyph函数中主要获取字体位图的相关度量信息。
Open_Fontfile函数是打开指定路径的字体文件,并将FT库的句柄及face对象指针保存至结构体中。
int Open_Fontfile(LCUI_Font *font_data, char *fontfile)/* 打开指定路径中的字体文件,并保存数据至LCUI_Font结构体中 */{#ifdef USE_FREETYPE int type; FT_Library library; FT_Face face; FT_Error face_error = 0, lib_error = 0; type = font_data->type; if(font_data->status == ACTIVE) { /* 如果字体文件路径无效,或该路径和默认的字体文件路径一样,则退出函数 */ if( !fontfile || !Strcmp(&font_data->font_file, fontfile) ) { return 0; } else if( Strcmp(&font_data->font_file, LCUI_Sys.default_font.font_file.string)) { /* 否则,如果不一样,就将type赋值为CUSTOM,表示自定义 */ type = CUSTOM; } } else if( !fontfile ) { return -1; } /* 初始化FreeType库 */ lib_error = FT_Init_FreeType( & library); /* 当初始化库时发生了一个错误 */ if (lib_error) { printf("open fontfile: "FT_INIT_ERROR); return - 1 ; } face_error = FT_New_Face( library, fontfile , 0 , &face ); if(face_error) { FT_Done_FreeType(library); if ( face_error == FT_Err_Unknown_File_Format ) { /* 未知文件格式 */ printf("open fontfile: "FT_UNKNOWN_FILE_FORMAT); } else { /* 打开错误 */ printf("open fontfile: "FT_OPEN_FILE_ERROR); } /* 打印错误信息 */ perror(fontfile); return -1; } /* 打印字体信息 */ printf( "=============== font info ==============\n" "family name: %s\n" "style name : %s\n" "========================================\n" , face->family_name, face->style_name ); /* 先处理掉之前保存的字体信息 */ Font_Free( font_data ); /* 保存新的字体信息 */ Strcpy(&font_data->family_name, face->family_name); Strcpy(&font_data->style_name, face->style_name); Strcpy(&font_data->font_file, fontfile); font_data->type = type; font_data->status = ACTIVE; font_data->ft_lib = library; font_data->ft_face = face; return 0;#else printf("warning: not font engine support!\n"); return -1;#endif} /* 如果定义了USE_FREETYPE宏定义,则使用FreeType字体引擎处理字体数据 */#ifdef USE_FREETYPE static int Convert_FTGlyph( LCUI_FontBMP *des, FT_GlyphSlot slot, int render_mode )/* 转换FT_GlyphSlot类型数据为LCUI_FontBMP */{ static FT_Error error; static size_t size; static FT_BitmapGlyph bitmap_glyph; static FT_Glyph glyph; /* 从字形槽中提取一个字形图像 * 请注意,创建的FT_Glyph对象必须与FT_Done_Glyph成对使用 */ error = FT_Get_Glyph( slot, &glyph ); if(error) { return -1; } /*---------------------- 打印字体信息 -------------------------- printf(" width= %ld, met->height= %ld\n" "horiBearingX = %ld, horiBearingY = %ld, horiAdvance = %ld\n" "vertBearingX = %ld, vertBearingY = %ld, vertAdvance = %ld\n", slot->metrics.width>>6, slot->metrics.height>>6, slot->metrics.horiBearingX>>6, slot->metrics.horiBearingY>>6, slot->metrics.horiAdvance>>6, slot->metrics.vertBearingX>>6, slot->metrics.vertBearingY>>6, slot->metrics.vertAdvance>>6 ); ------------------------------------------------------------*/ if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) { error = FT_Glyph_To_Bitmap(&glyph, render_mode, 0 ,1); if(error) { return -1; } } bitmap_glyph = (FT_BitmapGlyph)glyph; /* * FT_Glyph_Metrics结构体中保存字形度量,通过face->glyph->metrics结 * 构访问,可得到字形的宽、高、左边界距、上边界距、水平跨距等等。 * 注意:因为不是所有的字体都包含垂直度量,当FT_HAS_VERTICAL为假时, * vertBearingX,vertBearingY和vertAdvance的值是不可靠的,目前暂不考虑 * 此情况的处理。 * */ des->top = bitmap_glyph->top; des->left = slot->metrics.horiBearingX>>6; des->rows = bitmap_glyph->bitmap.rows; des->width = bitmap_glyph->bitmap.width; des->pixel_mode = bitmap_glyph->bitmap.pixel_mode; des->num_grays = bitmap_glyph->bitmap.num_grays; des->advance.x = slot->metrics.horiAdvance>>6; /* 水平跨距 */ des->advance.y = slot->metrics.vertAdvance>>6; /* 垂直跨距 */ /* 分配内存,用于保存字体位图 */ size = des->rows * des->width * sizeof(uchar_t); des->buffer = malloc( size ); if( !des->buffer ) { FT_Done_Glyph(glyph); return -1; } /* 拷贝至该内存空间内 */ memcpy( des->buffer, bitmap_glyph->bitmap.buffer, size ); FT_Done_Glyph(glyph); return size;} #endif int Get_FontBMP( LCUI_Font *font_data, wchar_t ch, int pixel_size, LCUI_FontBMP *out_bitmap)/* * 功能:获取单个wchar_t型字符的字体位图数据 * 说明:LCUI_Font结构体中储存着已被打开的字体文件句柄和face对象的句柄,如果字体文件 * 已经被成功打开一次,此函数不会再次打开字体文件。 */{#ifdef USE_FREETYPE size_t size; BOOL have_space = FALSE; FT_Face p_FT_Face = NULL; /* face对象的句柄 */ FT_Error error; if( font_data ) { /* 如果font_data有效,则打开font_data中的指定的字体文件,并将字体文件 * 和face对象的句柄保存至结构体中。 * 当然,如果LCUI_Font结构体有有效的字体文件和face对象的句柄,就不会再重新 * 打开字体文件。 */ if( !font_data->ft_face || !font_data->ft_lib ) { error = Open_Fontfile( font_data, font_data->font_file.string); if( error ) { Get_Default_FontBMP( ch, out_bitmap ); return 1; } } /* 引用face对象句柄 */ p_FT_Face = font_data->ft_face; } else { /* 使用内置的字体位图 */ Get_Default_FontBMP( ch, out_bitmap ); return -1; } /* 设定为UNICODE,默认的也是 */ FT_Select_Charmap( p_FT_Face, FT_ENCODING_UNICODE ); /* 设定字体尺寸 */ FT_Set_Pixel_Sizes( p_FT_Face, 0, pixel_size ); /* 如果是空格 */ if( ch == ' ' ) { ch = 'a'; have_space = TRUE; } /* 这个函数只是简单地调用FT_Get_Char_Index和FT_Load_Glyph */ error = FT_Load_Char( p_FT_Face, ch, font_data->load_flags); if(error) { return error; } size = Convert_FTGlyph( out_bitmap, p_FT_Face->glyph, font_data->render_mode ); /* 如果是空格则将位图内容清空 */ if( have_space ) { memset( out_bitmap->buffer, 0, size ); } return 0;#else Get_Default_FontBMP( ch, out_bitmap ); return -1;#endif}
相关文章推荐
- 嵌入式 Linux下利用FreeType2的API实现字符的显示
- 嵌入式 Linux下利用FreeType2的API实现字符的显示
- java的api操作HDFS实现递归打印目录并实现在Linux下的显示效果
- 利用汇编语言编程实现,输入显示字符
- 在linux中用C程序实现读取一个文件中的字符,计算它的个数,并把个数显示在另外一个文件夹内
- linux Fedora core 6 字符界面修改分辨率实现宽屏显示
- Linux-(C)利用Mysql相关API实现类似mysql的操作
- 利用腾讯位置服务API实现简单的网页地图显示
- linux 下利用ls grep 和正则表达式实现目录和文件的分开显示
- 两个C/C++的小程序,实现不显示字符的键盘输入和实现动态显示的百分数
- 怎样向一个c++函数传数组、Linux下怎么显示unicode字符、Linux的地址空间
- 非MFC,利用window api OPENFILENAME实现文件夹选择
- 利用51单片机,HC-SR04超声波模块实现测距,LCD显示
- 《新闻发布系统》利用第三方控件FreeTextBox实现在ASP.NET下插入和显示新闻
- linux 下基于特定通信协议利用多线程同步通信机制实现的串口通信
- 非MFC,利用window api OPENFILENAME实现定制打开文件对话框
- 利用iStylePDF的API实现在PDF文档中动态插入一幅图片
- 利用HTML5+的API实现基于MUI的文件上传
- 利用层实现具体新闻分页显示
- dp与px间相互转换:利用Android原生API实现px转换dp,dp转换px