嵌入式应用开发之文字系统
目标
封装字体管理模块,通过freetype字体引擎得到字体信息,并显示到显示器。
代码及说明
font_manager.h
typedef struct FontInfo{
Region tRegion; //当前字符的region,LCD坐标系
int iCurOriginX;
int iCurOriginY;
int iNextOriginX;
int iNextOriginY;
unsigned char *pucBuffer;
}FontInfo,*PFontInfo;
typedef struct FontOpr{
char *name;
int (*FontFileInit)(char * aFileName);
int (*SetFontSize)(int iFontSize);
int (*GetFontBitMap)(unsigned int dwCode, PFontInfo ptFontInfo);
struct FontOpr *ptNext;
}FontOpr,*PFontOpr;
在头文件中定义两个结构体,FontInfo是字体信息,包括位图的位置、大小,当前字符origin位置,下个字符的origin,存有字符的位图数据;FontOpr是指通过字体引擎库可对字符执行的操作;
freetype.c
存放用freetype字体引擎实现字符操作的函数实现
//初始化freetype库,加载字体文件,设置默认字体大小
static int FreeTypeFontFileInit(char * aFileName)
//设置字体大小
static int FreeTypeSetFontSize(int iFontSize)
//得到位图
static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontInfo ptFontInfo)
//将字符操作结构体注册到环形链表
void FreeTypeRegister(void)
font_manager.c
定义在可在主函数中调用的函数,完成结构体的注册及调用
//环形链表实现
void FontFilesRegister(PFontOpr ptFontOpr)
//如果有多个字体引擎库,依次注册多个字符操作结构体
void FontFilesInit(void)
//选择并初始化字体引擎库与字体文件,如freetype
int SelectAndInitFont(char *aFontOprName, char * aFontFileName)
//设置字体大小,自动调用已选择的字体引擎库中的函数实现
int SetFontSize(int iFontSize)
//获得位图
int GetFontBitMap(unsigned int dwCode, PFontInfo ptFontInfo)
测试
将显示系统与字体系统结合起来,需要再定义一个 DrawFontBitMap(&tFontInfo, color)函数,将得到的位图显示到显示器上;主函数只需要在循环中调用GetBitMap()->DrawBitMap()直到字符串写完即可
void DrawFontBitMap(PFontInfo ptFontBitMap, unsigned int dwcolor)
{
int i, j, p, q;
int x = ptFontBitMap->tRegion.iLeftUpX;
int y = ptFontBitMap->tRegion.iRightUpy;
int x_max = x + ptFontBitMap->tRegion.iWidth;
int y_max = y + ptFontBitMap->tRegion.iHeight;
int width = ptFontBitMap->tRegion.iWidth;
unsigned char *buffer = ptFontBitMap->pucBuffer;
//printf("x = %d, y = %d\n", x, y);
for ( j = y, q = 0; j < y_max; j++, q++ )
{
for ( i = x, p = 0; i < x_max; i++, p++ )
{
if ( i < 0 || j < 0 ||
i >= g_tDispBuff.iXres || j >= g_tDispBuff.iYres)
continue;
if (buffer[q * width + p])
PutPixel(i, j, dwcolor);
}
}
}
存在问题及解决
- 显示汉字乱码问题->使用宽字符
wchar_t *str = L"再不学就找不到工作";
- 坐标转换问题
- 按照韦东山老师之前讲解的课程,freetype使用的不是LCD坐标系,而是笛卡尔坐标系,应存在如下坐标转换代码,但是并没有发现,且显示正常
/* 把LCD坐标转换为笛卡尔坐标 */
int x = lcd_x;
int y = var.yres - lcd_y;
- 在GetBitMap函数中,每次会把获得的位图信息保存在 ptFontInfo->tRegion结构体中,Y坐标在里面的转换没有搞明白
ptFontInfo->tRegion.iLeftUpX = slot->bitmap_left;
ptFontInfo->tRegion.iRightUpy = ptFontInfo->iCurOriginY * 2 - slot->bitmap_top;/*????*/
ptFontInfo->tRegion.iHeight = slot->bitmap.rows;
ptFontInfo->tRegion.iWidth = slot->bitmap.width;
ptFontInfo->iNextOriginX = ptFontInfo->iCurOriginX + slot->advance.x / 64;
ptFontInfo->iNextOriginY = ptFontInfo->iCurOriginY; //同一水平线绘制,y值保持不变
用同样的环境跑了之前应用开发基础的代码,输入的坐标及字体大小都一样,显示结果如下:
可以看出,虽然同样是输入坐标是(100,100),但是应用基础的代码是做了坐标转换以后求出来origin的值,再输入freetype,文字系统是把(100,100)直接作为origin输入了,所以会有以上差别,但是为什么其中的坐标转换不一样还没想清楚,也许是这样根本不需要坐标转换,在GetBitMap函数中y坐标的计算绕开了屏幕的iresY,也许这就是区别,没想明白,但是降低了代码耦合性。