文字系统
1.数据结构抽象#
描述字符:位置、大小、点阵
文字的点阵可以从固定大小的点阵字库得到,也可以从freetype这类矢量字库得到。
所以后一个字符的位置会受到前一个字符的影响。
为给定字符,得到和操作FontBitMap,还需要构造一个结构体:
2.freetype#
Freetype 是开源的字体引擎库,它提供统一的接口来访问多种字体格式文件,从而实现矢量字体显示。
我们编写freetype.c调用freetype库。
编程:
先修改一下FontBitMap
结构体:实用与显示系统一样的Region结构体,且将Region结构体放入common.h
,避免disp_manager.h
与font_manager.h
的相互包含错误。
然后实现三个函数,定义g_tFreetypeOpr
结构体:
FreetypeFontInit
: 初始化freetype,加载字体文件,保存在&g_tFace中,设置一个默认的字体大小FreetypeSetFontSize
:设置字体大小FT_Set_Pixel_SizesFreetypeGetFontBitMap
:先确定坐标原点为当前原点,FT_Set_Transform。根据编码值得到位图,使用 FT_Load_Char 函数
ptFontBitMap->iLeftUpY
需要将位图坐标(笛卡尔坐标)转换到LCD坐标:
3.文字管理#
4.测试#
编译#
(1)修改makefile
在font子目录下
(2)相互包含问题:将Region结构体放入common.h中,disp和font都可以使用
(3)freetype库
(4)交叉编译freetype方法
一定要先设置交叉编译工具链!!!不然编译出来的默认是X86架构的程序
参考《嵌入式Linux应用开发完全手册》6.4.4给IMX6ULL交叉编译freetype
确定库的位置:
编译libpng:
编译freetype
上机测试#
font_test.c
:
初始化显示系统,获取显存buffer
DisplayInit();SelectDefaultDisplay("fb");InitDefaultDisplay();ptBuffer = GetDisplayBuffer(); //获得显存buffer注册所有Fonts,选择freetype字体库,字体文件通过argv[1]传入
FontsRegister();err = SelectAndInitFont("freetype", argv[1]);if (err){printf("SelectAndInitFont err\n");return -1;}设置字体大小
SetFontSize(font_size);循环遍历字符串,获取位图,绘制位图
while (str[i]){tFontBitMap.iCurOriginX = lcd_x;tFontBitMap.iCurOriginY = lcd_y;err = GetFontBitMap(str[i], &tFontBitMap);if (err){printf("%c GetFontBitMap err\n", str[i]);return -1;}/* 绘制位图 */DrawFontBitMap(&tFontBitMap, 0xff0000);FlushDispalyRegion(&tFontBitMap.tRegion, ptBuffer);/* 更新 */lcd_x = tFontBitMap.iNextOriginX;lcd_y = tFontBitMap.iNextOriginY;i++;}DrawFontBitMap函数在
disp_manager.c
中实现:基本方法就是遍历位图buffer中的每一个像素点,如果不等于0就绘制一个像素点,等于0就跳过不绘制。
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor){int i, j, p, q;int x = ptFontBitMap->tRegion.iLeftUpX;int y = ptFontBitMap->tRegion.iLeftUpY;int x_max = x + ptFontBitMap->tRegion.iWidth;int y_max = y + ptFontBitMap->tRegion.iHight;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_tDisplay.iXres || j >= g_tDisplay.iYres)continue;if (buffer[q * width + p] != 0)PutPixel(i, j, dwColor);}}}
主函数完整代码
错误:if (buffer[q * width + p] == 1)
不一定是等于1,正确的逻辑应该是不等于零的点就绘制像素,等于0的点跳过
请点击左侧菜单(移动端为右下角)选择要查看的所有笔记吧。