网上的FreeType2例子太少,能显示汉字的比较难找,C语言代码写的更难找,能找到的,基本上是被转载了N遍的同一个示例代码,基本上解决不了我的问题。
于是乎,花费了不少时间才完成了这些代码;
主要功能是:
将传入的GB2312编码的char型字符串转换成图片数组并输出。
主要原理是:
将GB2312编码的char型字符串,转换成unicode编码的wchar_t型字符串;
之后,利用FreeType2的API获取汉字的字体位图。
代码看似不怎么复杂,之前找char转wchar_t的代码,没找到一个合适的,最后呢,东拼西凑,就得到了想要的代码;
还有,输出的是记录每个像素点的256级灰度的数组,也就是和png图片中alpha通道一样,0- 255表示透明度, 0为完全透明,255为不透明;
想要将这些文字贴到图片上,有个公式:
r2 = (r1 * alpha + r2 * (255 - alpha)) /255;
g2 = (g1 * alpha + g2 * (255 - alpha)) /255;
b2 = (b1 * alpha + b2 * (255 - alpha))/255;
r、g、b表示图片的red、green、blue三种颜色,这三种颜色通过组合可以变成不同的颜色;
alpha是文字位图的alpha通道;
r2、b2、g2是图片重叠后该像素点显示的颜色;
r1、b1、g1是文字位图的每个像素点显示的颜色。
相关信息请参考这篇文章:http://www.linuxidc.com/Linux/2012-01/52144.htm
有需要这些代码的人的话,请把代码改一下,因为这是从我的LCUI图形库的代码中复制过来的,不能直接使用。
[cpp]
#include"LCUI_Build.h"
#includeLCUI_MAIN_H
#includeLCUI_FONTS_H
#include"all.h"
intcode_convert(char *from_charset,char *to_charset,const char*inbuf,unsigned int inlen,
unsignedchar *outbuf,unsigned int outlen)
{
iconv_t cd;
const char **pin = &inbuf;
unsigned char **pout = &outbuf;
cd = iconv_open(to_charset,from_charset);
if (cd==0) return -1;
memset(outbuf,0,outlen);
if(iconv(cd,(char**)pin,&inlen,(char**)pout,&outlen)==-1)return -1;
iconv_close(cd);
return 0;
}
intGB2312_To_UTF8(const char *inbuf,unsigned int inlen,unsigned char*outbuf,unsigned int outlen)
{
return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}
unsignedshort Get_Unicode(char *in_gb2312)
{
unsigned char out[256];
int rc;
unsigned int length_gb2312;
length_gb2312 = strlen(in_gb2312);
rc = GB2312_To_UTF8(in_gb2312,length_gb2312,out,256);
unsigned short unicode;
unicode = out[0];
if (unicode >= 0xF0) {
unicode = (unsigned short) (out[0] & 0x07)<< 18;
unicode |= (unsigned short) (out[1] & 0x3F)<< 12;
unicode |= (unsigned short) (out[2] & 0x3F)<< 6;
unicode |= (unsigned short) (out[3] & 0x3F);
} else if (unicode >= 0xE0) {
unicode = (unsigned short) (out[0] & 0x0F)<< 12;
unicode |= (unsigned short) (out[1] & 0x3F)<< 6;
unicode |= (unsigned short) (out[2] & 0x3F);
} else if (unicode >= 0xC0) {
unicode = (unsigned short) (out[0] & 0x1F)<< 6;
unicode |= (unsigned short) (out[1] & 0x3F);
}
return unicode;
}
intShow_Font_Bitmap(Font_Bitmap_Data *in_fonts)
{
int x,y;
for(y=0;y<in_fonts->height;++y){
for(x=0;x<in_fonts->width;++x){
if(in_fonts->text_alpha[y*in_fonts->width+x]>0)
printf("1");
else printf("0");
}
printf("\n");
}
printf("\n");
return 0;
}
intGet_Fonts_Bitmap(
char*font_file,
char*in_text,
intfonts_pixel_size,
intspace,
Font_Bitmap_Data *out_fonts
)
{
FT_Library p_FT_Lib =NULL;
FT_Face p_FT_Face =NULL;
FT_Error error = 0;
FT_Bitmap bitmap;
FT_BitmapGlyph bitmap_glyph;
FT_Glyph glyph;
FT_GlyphSlot slot;
int i , j ,temp,num,bg_height;
char error_str[200];
error = FT_Init_FreeType( &p_FT_Lib);
if (error)
{
p_FT_Lib = 0 ;
printf(FT_INIT_ERROR);
return - 1 ;
}
error = FT_New_Face(p_FT_Lib, font_file , 0 , &p_FT_Face);
if ( error == FT_Err_Unknown_File_Format )
{
printf(FT_UNKNOWN_FILE_FORMAT);
return - 1 ;
}
else if (error)
{
printf(FT_OPEN_FILE_ERROR);
perror("FreeeType2");
return - 1 ;
}
j = 0;
wchar_t *unicode_text;
char ch[256];
unicode_text =(wchar_t*)calloc(1,sizeof(wchar_t)*(strlen(in_text)*2));
for(i=0;i<strlen(in_text);++i){
memset(ch,0,sizeof(ch));
ch[0] = in_text[i];
if(ch[0] < 0) {
if(i < strlen(in_text)-1){
ch[1] = in_text[i+1];
++i;
}
else break;
}
unicode_text[j] = Get_Unicode(ch);
++j;
}
num = j;
int start_x = 0,start_y = 0;
int ch_height = 0,ch_width = 0;
int k,text_width = 0;
size_t size = 0;
unsigned char **text_alpha;
bg_height = fonts_pixel_size+5;
text_alpha = (unsigned char**)malloc(sizeof(unsignedchar*)*bg_height);
for(i=0;i<bg_height;++i){
text_alpha[i] = (unsigned char*)malloc(sizeof(unsignedchar)*1);
}
FT_Select_Charmap(p_FT_Face,FT_ENCODING_UNICODE);
FT_Set_Pixel_Sizes(p_FT_Face,0,fonts_pixel_size);
slot = p_FT_Face->glyph;
for(temp=0;temp<num;++temp){
error = FT_Load_Char( p_FT_Face,unicode_text[temp], FT_LOAD_RENDER |FT_LOAD_NO_AUTOHINT);
if(!error){
error = FT_Get_Glyph(p_FT_Face -> glyph,&glyph);
if (!error)
{
if(unicode_text[temp] == ' ') {
k = 0;
ch_width = (fonts_pixel_size-2)/2;
ch_height = fonts_pixel_size;
text_width = start_x + ch_width;
start_y = 0;
for(i=0;i<bg_height;++i){
text_alpha[i] = (unsignedchar*)realloc(text_alpha[i],sizeof(unsigned char)*text_width);
for(j=start_x-space;j<text_width;++j)text_alpha[i][j] = 0;
}
for ( i = 0 ; i < ch_height; ++i)
{
for ( j = 0 ; j < ch_width; ++j)
{
text_alpha[start_y + i][start_x + j] = 0;
++k;
}
}
start_x += (ch_width+space);
}
else{
FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0,1);
bitmap_glyph = (FT_BitmapGlyph)glyph;
bitmap = bitmap_glyph -> bitmap;
k = 0;
start_y = fonts_pixel_size - slot->bitmap_top + 2;
if(start_y < 0) start_y = 0;
if(bitmap.rows > bg_height) ch_height =fonts_pixel_size;
else ch_height = bitmap.rows;
if(ch_height+start_y > bg_height) ch_height =bg_height - start_y;
ch_width = bitmap.width;
text_width = start_x + bitmap.width;
for(i=0;i<bg_height;++i){
text_alpha[i] = (unsignedchar*)realloc(text_alpha[i],sizeof(unsigned char)*text_width);
for(j=start_x-space;j<text_width;++j)text_alpha[i][j] = 0;
}
for(i = 0; i < bg_height; ++i){
for(j = 0;j < ch_width; ++j){
if(i >= start_y && i< start_y + ch_height){
text_alpha[i][start_x + j] = bitmap.buffer[k];
++k;
}
else text_alpha[i][start_x + j] = 0;
}
}
start_x += (ch_width+space);
FT_Done_Glyph(glyph);
glyph = NULL;
}
}
else{
sprintf(error_str,"FreeType2 错误[%d]",error);
perror(error_str);
}
}
else{
sprintf(error_str,"FreeType2 错误[%d]",error);
perror(error_str);
}
}
FT_Done_Face(p_FT_Face);
p_FT_Face = NULL;
FT_Done_FreeType(p_FT_Lib);
p_FT_Lib = NULL;
temp = 0;
out_fonts->width =text_width;
out_fonts->height =bg_height;
if(out_fonts->malloc == IS_TRUE)free(out_fonts->text_alpha);
size = sizeof(unsigned char) * text_width * bg_height;
out_fonts->text_alpha = (unsignedchar*)calloc(1,size);
k = 0;
for ( i = 0 ; i < bg_height; ++i)
{
for ( j = 0 ; j < text_width; ++j)
{
out_fonts->text_alpha[k] = text_alpha[i][j];
++k;
}
}
out_fonts->malloc = IS_TRUE;
for(i=0;i<bg_height;++i){
free(text_alpha[i]);
}
free(text_alpha);
free(unicode_text);
return 0;
}
这些代码在我的工程里的运行效果: