一、从左上角显示
1)先描画第一行
2)算出边框
下面在lcd左上角上显示两行字符
/* 清屏: 全部设为黑色 */
memset(fbmem, 0, screen_size);
/* 显示矢量字体 */
error = FT_Init_FreeType( &library );
error = FT_New_Face( library, argv[1], 0, &face );
slot = face->glyph;
FT_Set_Pixel_Sizes(face, 24, 0);
/* 确定座标:
* lcd_x = 0
* lcd_y = 24
* 笛卡尔座标系:
* x = lcd_x = 0
* y = var.yres - lcd_y = var.yres - 24
*/
pen.x = 0 * 64; //设置原点坐标,这个坐标是笛卡尔的坐标,
pen.y = (var.yres - 24) * 64;
for(i = 0; i < wcslen(wstr1); i++) //在for循环中一次取出要显示的字符的位图
{
/* set transformation */
FT_Set_Transform( face, 0, &pen); //设置转化参数
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, wstr1[i], FT_LOAD_RENDER ); //根据unicode码加载glpyh并转换为位图
if (error)
{
printf("FT_Load_Char error\n");
return -1;
}
error = FT_Get_Glyph( face->glyph, &glyph ); //获取得到的当前的glpyh位图
if (error)
{
printf("FT_Get_Glyph error!\n");
return -1;
}
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &bbox );//得到glpyh变量里的bbox参数,这个参数记录了位图的xmin,
//yMin等参数信息,获取它可以判定下一行的原点位置
if (line_box_ymin > bbox.yMin)
line_box_ymin = bbox.yMin;
if (line_box_ymax < bbox.yMax)
line_box_ymax = bbox.yMax;
draw_bitmap( &slot->bitmap,
slot->bitmap_left,
var.yres - slot->bitmap_top);
pen.x += slot->advance.x;
}
/* 确定座标: 下面显示的是第二行的数据,第二行的x坐标还是0,
* lcd_x = 0 y坐标是根据bbox确定的,这里假设加上24
* lcd_y = line_box_ymax - line_box_ymin + 24
* 笛卡尔座标系:
* x = lcd_x = 0
* y = var.yres - lcd_y = var.yres - (line_box_ymax - line_box_ymin + 24)
*/
pen.x = 0 * 64; //重新设置第二行的数据坐标
pen.y = (var.yres - (line_box_ymax - line_box_ymin + 24)) * 64;
for(i = 0; i < wcslen(wstr2); i++)
{
/* set transformation */
FT_Set_Transform( face, 0, &pen);
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, wstr2[i], FT_LOAD_RENDER );
if (error)
{
printf("FT_Load_Char error\n");
return -1;
}
error = FT_Get_Glyph( face->glyph, &glyph );
if (error)
{
printf("FT_Get_Glyph error!\n");
return -1;
}
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &bbox );
if (line_box_ymin > bbox.yMin)
line_box_ymin = bbox.yMin;
if (line_box_ymax < bbox.yMax)
line_box_ymax = bbox.yMax;
draw_bitmap( &slot->bitmap,
slot->bitmap_left,
var.yres - slot->bitmap_top);
pen.x += slot->advance.x;
}
return 0;
二、居中显示
1)先算出边框
2)再确定代码并描画
main.c
/* 清屏: 全部设为黑色 */
memset(fbmem, 0, screen_size);
/* 显示矢量字体 */
error = FT_Init_FreeType( &library );
error = FT_New_Face( library, argv[1], 0, &face );
slot = face->glyph;
FT_Set_Pixel_Sizes(face, 24, 0);
/* 显示第一行字符 */
//glyphs是一个TGlyph类型的数组,用来存放需要显示的字符的glyph
//Get_Glyphs_Frm_Wstr这个函数是自己实现的,从face文件中根据wstr1的unicode码找到glyph,
//并保存到glyphs数组中,此函数的返回值是数组中的glyph的个数,也就是要显示的字符的个数
num_glyphs = Get_Glyphs_Frm_Wstr(face, wstr1, glyphs);
//此函数自己实现,用来算出第一行显示的字符的边框,方便计算下一行的原点位置
compute_string_bbox(glyphs, num_glyphs, &bbox);
line_box_width = bbox.xMax - bbox.xMin;
line_box_height = bbox.yMax - bbox.yMin;
pen.x = (var.xres - line_box_width)/2 * 64; //设置要显示的位置,这里子显示到屏幕的中间
pen.y = (var.yres - line_box_height)/2 * 64;
//显示第一行字符,此函数自己实现
Draw_Glyphs(glyphs, num_glyphs, pen);
/* 显示第二行字符 */
num_glyphs = Get_Glyphs_Frm_Wstr(face, wstr2, glyphs);
compute_string_bbox(glyphs, num_glyphs, &bbox);
line_box_width = bbox.xMax - bbox.xMin;
line_box_height = bbox.yMax - bbox.yMin;
pen.x = (var.xres - line_box_width)/2 * 64;
pen.y = pen.y - 24 * 64;
Draw_Glyphs(glyphs, num_glyphs, pen);
return 0;
Get_Glyphs_Frm_Wstr函数实现
int Get_Glyphs_Frm_Wstr(FT_Face face, wchar_t * wstr, TGlyph glyphs[])
{
int n;
PGlyph glyph = glyphs;
int pen_x = 0;
int pen_y = 0;
int error;
FT_GlyphSlot slot = face->glyph;;
for(n = 0; n < wcslen(wstr); n++)
{
//使用此函数根据wstr[n]的unicode码在face中找到glyph的索引值
glyph->index = FT_Get_Char_Index( face, wstr[n]);
/* store current pen position */
glyph->pos.x = pen_x; //指定显示的坐标
glyph->pos.y = pen_y;
/* load时是根据索引值把glyph放入插槽face->glyph */
error = FT_Load_Glyph(face, glyph->index, FT_LOAD_DEFAULT);
if ( error )
continue;
//上面的函数是加载了glyph值到插槽slot中,单数函数执行过后这个插槽中的值就会更换新成下一个值
//因此FT_Get_Glyph函数能够保存并本次的glyph值,方便后面获取参数等操作
error = FT_Get_Glyph(face->glyph, &glyph->image );
if ( error )
continue;
/* 这使得glyph->image里含有位置信息 */
FT_Glyph_Transform(glyph->image, 0, &glyph->pos );
pen_x += slot->advance.x; /* 1/64 point */
/* increment number of glyphs */
glyph++;
}
}
compute_string_bbox函数实现计算出边框
void compute_string_bbox(TGlyph glyphs[], FT_UInt num_glyphs, FT_BBox *abbox )
{
FT_BBox bbox;
int n;
bbox.xMin = bbox.yMin = 32000; //先把xMin、yMin等设置为一个较大的值
bbox.xMax = bbox.yMax = -32000;
for(n = 0; n < num_glyphs; n++)
{
FT_BBox glyph_bbox;
//先得到CBOX,信息放入glyph_bbox变量中
FT_Glyph_Get_CBox(glyphs[n].image, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox );
if (glyph_bbox.xMin < bbox.xMin) //之后设置bbox.xMin等的值
bbox.xMin = glyph_bbox.xMin;
if (glyph_bbox.yMin < bbox.yMin)
bbox.yMin = glyph_bbox.yMin;
if (glyph_bbox.xMax > bbox.xMax)
bbox.xMax = glyph_bbox.xMax;
if (glyph_bbox.yMax > bbox.yMax)
bbox.yMax = glyph_bbox.yMax;
}
*abbox = bbox;
}
Draw_Glyphs函数实现
void Draw_Glyphs(TGlyph glyphs[], FT_UInt num_glyphs, FT_Vector pen)
{
int n;
int error;
for (n = 0; n < num_glyphs; n++)
{
//设置参数
FT_Glyph_Transform(glyphs[n].image, 0, &pen);
//将glyph转化为位图
error = FT_Glyph_To_Bitmap(&glyphs[n].image, FT_RENDER_MODE_NORMAL, 0, 1 );
if ( !error )
{
FT_BitmapGlyph bit = (FT_BitmapGlyph)glyphs[n].image;
draw_bitmap(&bit->bitmap, bit->left, var.yres - bit->top);
FT_Done_Glyph(glyphs[n].image ); //最后释放数组
}
}
}