做天然文化石的网站,一个空间2个网站代码,公司经营范围网站开发及运营,晚上必看的正能量网站app前言#xff1a; 前面我们已经把显示系统#xff0c;输入系统的框架搭建好了#xff0c;那么有了输入和显示#xff0c;显示的内容应该是什么呢#xff1f;这节就要让我们一起对显示的内容#xff0c;文字系统进行搭建。 目录
一、数据结构抽象
1.描述一个文字的位图 前面我们已经把显示系统输入系统的框架搭建好了那么有了输入和显示显示的内容应该是什么呢这节就要让我们一起对显示的内容文字系统进行搭建。 目录
一、数据结构抽象
1.描述一个文字的位图
2.描述一个字库操作
3.font_manager.h
二、实现Freetype代码
freetype.c 三、文字管理
font_manager.c
四、单元测试
1.font_test.c
2.disp_manager.c
3.disp_manager.h
4. common.h
5.unittest下的Makefile
6.font下的Makefile
7.顶层的Makefile
五、上板测试 一、数据结构抽象 描述字符的方式1.位置、大小 2.点阵 点阵可以从固定大小的点阵字体文件中获得也可以从Freetype的矢量字体文件中获得所以我们需要抽象出一个结构体用来描述这些字符一个结构体描述一个文字的位图一个结构体描述一个字库操作。
1.描述一个文字的位图 2.描述一个字库操作 使用点阵绘制文字时每个文字的大小一样前后文件互不影响 ,使用Freetype绘制文字时大小可能不同前面文字会影响后面文字 对于单个Freetype字符格式如下 我们要抽象出一个结构体FontBitMap能描述一个“字符”位置、大小、位图,我们还要抽象出一个结构体FontOpr能描述字体的操作比如Freetype的操作、固定点阵字体的操作
3.font_manager.h
#ifndef _FONT_MANAGER_H
#define _FONT_MANAGER_H#include common.htypedef struct FontBitMap {int iLeftUpX;int iLeftUpY;int iWidth;int iRows;int iCurOriginX;int iCurOriginY;int iNextOriginX;int iNextOriginY;unsigned char *pucBuffer;
}FontBitMap, *PFontBitMap;typedef struct FontOpr {char *name;int (*FontInit)(char *aFineName);int (*SetFontSize)(int iFontSize);int (*GetFontBitMap)(unsigned int dwCode, PFontBitMap ptFontBitMap);struct FontOpr *ptNext;
}FontOpr, *PFontOpr;void RegisterFont(PFontOpr ptFontOpr);void FontsRegister(void);int SelectAndInitFont(char *aFontOprName, char *aFontFileName);
int SetFontSize(int iFontSize);
int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap);#endif 第28行链表 第30行注册单个字符库 从链表里挑出想要的字库 第32行在g_ptFonts链表里面挑出来你想要的字体文件 第33行将找到的字体设置字体大小 第34行将找到的字体设置位图 为了方便后续使用区域我们进行如下操作将区域定义到一个结构体上Region tRegion;
typedef struct FontBitMap {Region tRegion;int iCurOriginX;int iCurOriginY;int iNextOriginX;int iNextOriginY;unsigned char *pucBuffer;
}FontBitMap, *PFontBitMap;
这个 tRegion在disp manager.h中有声明
typedef struct Region {int iLeftUpX;int iLeftUpY;int iWidth;int iHeigh;
}Region, *PRegion;
二、实现Freetype代码
freetype.c
#include sys/mman.h
#include sys/types.h
#include sys/stat.h
#include unistd.h
#include linux/fb.h
#include fcntl.h
#include stdio.h
#include string.h
#include math.h
#include wchar.h
#include sys/ioctl.h
#include font_manager.h#include ft2build.h
#include FT_FREETYPE_H
#include FT_GLYPH_Hstatic FT_Face g_tFace;
static int g_iDefaultFontSize 12;static int FreeTypeFontInit(char *aFineName)
{FT_Library library;int error;error FT_Init_FreeType( library ); /* initialize library */ if (error){printf(FT_Init_FreeType err\n);return -1;}error FT_New_Face(library, aFineName, 0, g_tFace ); /* create face object */if (error){printf(FT_New_Face err\n);return -1;}FT_Set_Pixel_Sizes(g_tFace, g_iDefaultFontSize, 0);return 0;
}static int FreeTypeSetFontSize(int iFontSize)
{FT_Set_Pixel_Sizes(g_tFace, iFontSize, 0);return 0;
}static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{int error;FT_Vector pen;FT_Glyph glyph;pen.x ptFontBitMap-iCurOriginX * 64; /* 单位: 1/64像素 */pen.y ptFontBitMap-iCurOriginY * 64; /* 单位: 1/64像素 *//* 转换transformation */FT_Set_Transform(g_tFace, 0, pen);/* 加载位图: load glyph image into the slot (erase previous one) */error FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER);if (error){printf(FT_Load_Char error\n);return -1;}ptFontBitMap-pucBuffer slot-bitmap.buffer;ptFontBitMap-tRegion.iLeftUpX slot-bitmap_left;ptFontBitMap-tRegion.iLeftUpY ptFontBitMap-iCurOriginY*2 - slot-bitmap_top;ptFontBitMap-tRegion.iWidth slot-bitmap.width;ptFontBitMap-tRegion.iHeigh slot-bitmap.rows;ptFontBitMap-iNextOriginX ptFontBitMap-iCurOriginX slot-advance.x / 64;ptFontBitMap-iNextOriginY ptFontBitMap-iCurOriginY;return 0;
}static FontOpr g_tFreetypeOpr {.name freetype,.FontInit FreeTypeFontInit,.SetFontSize FreeTypeSetFontSize,.GetFontBitMap FreeTypeGetFontBitMap,
};void FreetypeRegister(void)
{RegisterFont(g_tFreetypeOpr);
} static FontOpr g_tFreetypeOpr 第86~91行实现FontOpr这个结构体里面的函数 第87行之后可以通过freetype这个名字找到FontOpr这个结构体 第88行初始化函数 第89行自定义设置字符大小 第90行得到位图并且设置坐标值 第19行对应字体文件 第20行对应字体大小 static int FreeTypeFontInit(char *aFineName) 第22~44行进行初始化 第27行初始化freetype库 第34行加载字体文件 第41行设置默认的字体大小 static int FreeTypeSetFontSize(int iFontSize) 第 46~50行自定义设置字符大小 给一个字符的编码值如何得到它的位图呢 static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap) 第52~83行得到位图并且设置坐标值 第55行pen用来反推原点 第57行记录点阵 第59、60行根据位图原点的X和Y坐标反推原点 第63行转换 第66行加载位图 第73行存放点阵 第75~80行描述一个文字的位图 void FreetypeRegister(void) 第93~96行 进行注册上层font_manager.c提供 三、文字管理 我们可能要用到的字体有多种那么怎么选择用哪个字符呢所以我们要编写一个程序管理多种字符。 font_manager.c #include font_manager.h
#include string.hstatic PFontOpr g_ptFonts NULL;
static PFontOpr g_ptDefaulFontOpr NULL;void RegisterFont(PFontOpr ptFontOpr)
{ptFontOpr-ptNext g_ptFonts;g_ptFonts ptFontOpr;
}void FontsRegister(void)
{extern void FreetypeRegister(void);FreetypeRegister();
}int SelectAndInitFont(char *aFontOprName, char *aFontFileName)
{PFontOpr ptTmp g_ptFonts;while (ptTmp){if (strcmp(ptTmp-name, aFontOprName) 0)break;ptTmp ptTmp-ptNext;}if (!ptTmp)return -1;g_ptDefaulFontOpr ptTmp;return ptTmp-FontInit(aFontFileName);
}int SetFontSize(int iFontSize)
{return g_ptDefaulFontOpr-SetFontSize(iFontSize);
}int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{return g_ptDefaulFontOpr-GetFontBitMap(dwCode, ptFontBitMap);
}
实现这四个函数 第6行 注册的单个字库链表头放到g_ptFonts中 第7行将22~37行找到的字库名字保存在g_ptDefaulFontOpr中 void RegisterFont(PFontOpr ptFontOpr) 第10~14行实现与freetype.c链接的链表 void FontsRegister(void) 第16~20行实现多个字体的注册 第18行调用底层代码提供一个注册函数注册单个字库从链表里挑出想要的字库 假设你有多个字库你要选择某一个要提供一个SelectAndInitFont字体文件 int SelectAndInitFont(char *aFontOprName, char *aFontFileName) 第22~37行首先在g_ptFonts链表里面挑出来你想要的字体文件 aFontOprName表示字库操作的名字aFontFileName表示字体文件的名字 第24行在链表里面挑出来 第27行表示已经找到了 第29行没有找到继续在链表里的下一个位置找 第32行表示不存在 第35行如果存在则调用初始化函数 int SetFontSize(int iFontSize) 第39~42行将找到的字体设置字体大小 int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap) 第44~47行将找到的字体设置位图 四、单元测试 1.font_test.c
#include sys/mman.h
#include sys/types.h
#include sys/stat.h
#include unistd.h
#include linux/fb.h
#include fcntl.h
#include stdio.h
#include string.h
#include sys/ioctl.h
#include stdlib.h
#include font_manager.h
#include disp_manager.h#define FONTDATAMAX 4096static const unsigned char fontdata_8x16[FONTDATAMAX] {//此处点阵省略.........};/*********************************************************************** 函数名称 lcd_put_ascii* 功能描述 在LCD指定位置上显示一个8*16的字符* 输入参数 x坐标y坐标ascii码* 输出参数 无* 返 回 值 无***********************************************************************/
void lcd_put_ascii(int x, int y, unsigned char c)
{unsigned char *dots (unsigned char *)fontdata_8x16[c*16];int i, b;unsigned char byte;for (i 0; i 16; i){byte dots[i];for (b 7; b 0; b--){if (byte (1b)){/* show */PutPixel(x7-b, yi, 0xffffff); /* 白 */}else{/* hide */PutPixel(x7-b, yi, 0); /* 黑 */}}}
}int main(int argc, char **argv)
{PDispBuff ptBuffer;int error;FontBitMap tFontBitMap;char *str Hello Linux;int i 0;int lcd_x;int lcd_y;int font_size;if (argc ! 5){printf(Usage: %s font_file lcd_x lcd_y font_size\n, argv[0]);return -1;}lcd_x strtol(argv[2], NULL, 0);lcd_y strtol(argv[3], NULL, 0);font_size strtol(argv[4], NULL, 0);DisplayInit();SelectDefaultDisplay(fb);InitDefaultDisplay();ptBuffer GetDisplayBuffer();FontsRegister();error SelectAndInitFont(freetype, argv[1]);if (error){printf(SelectAndInitFont err\n);return -1;}SetFontSize(font_size);while (str[i]){/* get bitmap */tFontBitMap.iCurOriginX lcd_x;tFontBitMap.iCurOriginY lcd_y;error GetFontBitMap(str[i], tFontBitMap);if (error){printf(SelectAndInitFont err\n);return -1;}/* draw on buffer */ DrawFontBitMap(tFontBitMap,0xff0000);//0xff0000为红色/* flush to lcd/web */ FlushDisplayRegion(tFontBitMap.tRegion, ptBuffer);lcd_x tFontBitMap.iNextOriginX;lcd_y tFontBitMap.iNextOriginY; i;}return 0;
} 第60行保存字符位图 第61行想要显示的字符串 第68~72行打印出具体用法 font_file 字体文件 lcd_x lcd_y 显示的位置 font_size 字体的大小 第74、75行将字符串转化成整数传入到lcd_x和lcd_y 第77行将字符串转化成整数传入到 font_size 第86行获得显示的设备 第88行FontsRegister()注册单个字符库 从链表里挑出想要的字库 第90行SelectAndInitFont(freetype, argv[1])去选择freetype字库操作传入argv[1]字体文件 第97行SetFontSize设置字体大小 第102、103行绘制图像的原点 第104行GetFontBitMap得到字符位图 第112行把位图绘制出来绘制到默认设备中 第115行绘制的内容刷到LCD或者web上 第118、119行绘制完后取下一个位图的坐标 2.disp_manager.c
在disp_manager.c中实现位图绘制
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor) 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.iHeigh;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;//image[j][i] | bitmap-buffer[q * bitmap-width p];if (buffer[q * width p])PutPixel(i, j, dwColor);}}}
3.disp_manager.h
声明函数DrawFontBitMap
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);
头文件包含#include font_manager.h
#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H#include common.h
#include font_manager.htypedef struct DispBuff {int iXres;int iYres;int iBpp;char *buff;
}DispBuff, *PDispBuff;typedef struct DispOpr {char *name;int (*DeviceInit)(void);int (*DeviceExit)(void);int (*GetBuffer)(PDispBuff ptDispBuff);int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff);struct DispOpr *ptNext;
}DispOpr, *PDispOpr;void RegisterDisplay(PDispOpr ptDispOpr);void DisplayInit(void);
int SelectDefaultDisplay(char *name);
int InitDefaultDisplay(void);
int PutPixel(int x, int y, unsigned int dwColor);
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff);
PDispBuff GetDisplayBuffer(void);
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor);#endif
4. common.h 因为显示系统和文字系统都需要用到这个区域结构体所以我们直接把它拿出来定义成一个公共的头文件
#ifndef _COMMON_H
#define _COMMON_H#ifndef NULL
#define NULL (void *)0
#endiftypedef struct Region {int iLeftUpX;int iLeftUpY;int iWidth;int iHeigh;
}Region, *PRegion;#endif
5.unittest下的Makefile
EXTRA_CFLAGS :
CFLAGS_file.o : #obj-y disp_test.o
#obj-y input_test.o
obj-y font_test.o
6.font下的Makefile
EXTRA_CFLAGS :
CFLAGS_file.o : obj-y font_manager.o
obj-y freetype.o7.顶层的Makefile CROSS_COMPILE ?
AS $(CROSS_COMPILE)as
LD $(CROSS_COMPILE)ld
CC $(CROSS_COMPILE)gcc
CPP $(CC) -E
AR $(CROSS_COMPILE)ar
NM $(CROSS_COMPILE)nmSTRIP $(CROSS_COMPILE)strip
OBJCOPY $(CROSS_COMPILE)objcopy
OBJDUMP $(CROSS_COMPILE)objdumpexport AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMPCFLAGS : -Wall -O2 -g
CFLAGS -I $(shell pwd)/includeLDFLAGS : -lts -lpthread -lfreetypeexport CFLAGS LDFLAGSTOPDIR : $(shell pwd)
export TOPDIRTARGET : testobj-y display/
obj-y input/
obj-y font/
obj-y unittest/all : start_recursive_build $(TARGET)echo $(TARGET) has been built!start_recursive_build:make -C ./ -f $(TOPDIR)/Makefile.build$(TARGET) : built-in.o$(CC) -o $(TARGET) built-in.o $(LDFLAGS)clean:rm -f $(shell find -name *.o)rm -f $(TARGET)distclean:rm -f $(shell find -name *.o)rm -f $(shell find -name *.d)rm -f $(TARGET) 第20行链接库
LDFLAGS : -lts -lpthread -lfreetype 第30~33行打开这四个文件夹进行make
obj-y display/
obj-y input/
obj-y font/
obj-y unittest/
五、上板测试
book100ask:17_font_unittest_ok$ make
book100ask:17_font_unittest_ok$ cp -r 17_font_unittest_ok/ ~/nfs_rootfs/[root100ask:~]# mount -t nfs -o nolock,vers3 192.168.5.11:/home/book/nfs_rootfs /mnt
[root100ask:~]# cd /mnt/
[root100ask:/mnt/17_font_unittest_ok]# ./test ./simsun.ttc 100 400 100
注意编译时候要将字库文件一起上传上去
运行效果