• freeType2.9.1移植到A7(2)


    上一篇文章说了freeType移植并编译通过,但是还没有调试并显示字体,今天就讲讲freeType接口的调用。

    在调试过程中发现,freeType在解码时对RAM的大小是有要求的,否则会堆栈溢出,这里我们将MCIMX6Y2xxx05_ram.icf文件中的堆空间设置为0x60000,正好是384K,此条件下,调用freeType接口是没有问题的。

    创建一个字体的结构体,方便gui进行调用,因为是基于C语言的,为了方便gui后期能够打包为lib库,这里使用回调函数的方式来调用字体渲染函数。

    typedef struct {
    	U16 Flags;	//取值参考 GUI_TTF_MAP_FILE_MEMERY_MODE
    
    	GUI_DISPCHAR	 * pfDispChar; //绘制字形的函数
    	GUI_GETCHARDISTX * pfGetCharDistX; //获取字形所占的像素个数
    	GUI_GETFONTINFO  * pfGetFontInfo; //获取字号大小,及字体的显示方式
    	union{
    		const GUI_TTF_DATA *pTtfData;
    		const GUI_TTF_FONT_MAP *pMap;
    
    	}p;
    	U8 height;
    	U8 bold;//加粗,0-不加粗
    	U8 itailc;  //斜体
    	void *matrix;
    
    }GUI_FONT;

    上篇文章提到,因为要支持三种模式来显示字体,所以需要3个字体的结构体

    typedef struct
    {
    //   FONT_TYPE font_type;
       U8* ASCII_addr;
       U8* HZ_addr;
       U8 width;
       U8 height;
    }GUI_TTF_FONT_MAP;
    
    //ttf矢量字库文件
    typedef struct{
    	const void * pData;//ttf字体文件地址
    	U32 NumBytes;//大小
    
    }GUI_TTF_DATA;
    
    typedef struct{
    	GUI_TTF_DATA *pTTF;
    	int height;//字体像素高度
    	int faceIndex;//有些字体文件可能包含多种字体风格。对于多种风格,此索引指定使用基于零的风格索引来创建字体。通常为 0。
    }GUI_TTF_CS;

    第一种,预先在PC端,用软件转换ttf对应字号的字模数据文件,然后在单片机中使用,初始化函数如下:

    int GUI_MAP_CreateFont(GUI_FONT * pFont,GUI_TTF_FONT_MAP *pMap)
    {
    	pFont->Flags = GUI_TTF_MAP_FILE_MEMERY_MODE;
    	pFont->pfDispChar = (GUI_DISPCHAR*)GUI_X_DispCharMap;
    
    	pFont->pfGetCharDistX = (GUI_GETCHARDISTX*)GUI_GetCharDistX;
    	pFont->height = pMap->height;
    	pFont->p.pMap = pMap;
    	return 0;
    }

    显示字体函数:

    //先用工具生成字体位图文件,根据字符编码定位字库数据
    
    /*
    style  获取背景色颜色
    
    
    */
    I16 GUI_X_DispCharMap(int x,int y,const GUI_FONT* font,U16 c,U32 color,U32 bk_color,U8 type,U8 style)
    {
    	U32 addrsse = 0;
    	U8 msb,lsb;
    	U8 *pData;
    	U8 fontwidth;
    	const GUI_TTF_FONT_MAP* pMap =font->p.pMap;
    	int i,j;
    	U32 *pIndex;
    
    	  if(c&0x80){//汉字
    	  	 lsb = c&0xff;
    		 msb = (c>>8)&0xff;
    		 addrsse = ( ( lsb - 0xA0) * 94 + msb - 0xA1 )*pMap->width*font->height;
    		 pData = (U8*)(pMap->HZ_addr+addrsse);
     	     fontwidth = pMap->width;
    	  }else{//assic
    	     pIndex = (U32*)pMap->ASCII_addr;
    		 addrsse = pIndex[c];
    		 fontwidth = (addrsse>>24)&0xff;
    		 addrsse &= 0x00ffffff;
    		 pData = (U8*)(pMap->ASCII_addr+addrsse);
    	  }
    
    	  for(i=y;i<pMap->height +y;i++){
    		 for(j = x;j <fontwidth + x;j++){
    		 	if(style)
    		 		bk_color = INDEX2COLOR_FUNC(GUI_GetPixelIndex(j, i));
    
    			GUI_SET_PIXEL(type, i*GUI_Context.xSize+j, setcolor( pData[(i - y)*fontwidth + (j - x)] ,color,bk_color));
    //			GUI_SET_PIXEL(0, i*GUI_Context.xSize+j, setcolor( pData[(i - y)*fontwidth + (j - x)] ,color,bk_color));
    			}
    	  }
    	return fontwidth;
    
    }

    第二种,将ttf文件写入内存,然后调用freeType接口渲染字体。

    字体初始化函数:主要负责文件的加载,以及字库的生成。

    I16 GUI_loadFontData(GUI_TTF_DATA *ttfData,U8 *pData,U32 fileSize)
    {
    
    	FT_Error error = 0;
    	if(ttfData->pData==NULL)
    		return 1;
    	ttfData->pData = pData;
    	ttfData->NumBytes = fileSize;
    
    	error = FT_Init_FreeType(&pFTLib);
    	error = FT_New_Memory_Face(pFTLib,pData,fileSize,0,&pFTFace);
    	if(error)
    		return 1;
    	return 0;
    }

    创建字库函数,根据字号不同,创建不同字号的字体:

    int GUI_TTF_CreateFont(GUI_FONT * pFont, GUI_TTF_CS * pCS,GUI_TTF_DATA *ttfData,U8 fontsize)
    {
    	pCS->pTTF = ttfData;
    	pCS->height = fontsize;
    	FT_Set_Char_Size(pFTFace,  fontsize << 6 ,  fontsize << 6 ,  72 , 72 );
    
    	pFont->pfDispChar = (GUI_DISPCHAR *)GUI_X_DispCharTTF;
    	pFont->pfGetCharDistX = (GUI_GETCHARDISTX*)GUI_GetCharDistX;
    	pFont->Flags = GUI_TTF_FILE_MEMERY_MODE;
    	pFont->height = pCS->height;
    	pFont->itailc = 0;
    	pFont->matrix = NULL;
    	pFont->bold = 0;
    	return 0;
    }

    最后一种,是基于文件流方式读取ttf文件,也是我们工程推荐采用的方式,可以节省大量内存资源。

    加载文件函数

    int GUI_loadFontFile(const char* path)
    {
    	FT_Error error = 0;
    
    	error = FT_Init_FreeType(&pFTLib);
    
    
    	error = FT_New_Face(pFTLib,path,0,&pFTFace);
    
    	if(error)
    		return 1;
    
    	return 0;
    }

    创建字体函数

    int GUI_TTF_CreateFontStream(GUI_FONT * pFont,U8 fontSize)
    {
    
    	FT_Set_Char_Size(pFTFace,  fontSize << 6 ,  fontSize << 6 ,  72 , 72 );
    	pFont->Flags = GUI_TTF_FILE_STREAM_MODE;
    	pFont->pfDispChar = (GUI_DISPCHAR *)GUI_X_DispCharTTF;
    
    	pFont->pfGetCharDistX = (GUI_GETCHARDISTX*)GUI_GetCharDistX;
    	pFont->height = fontSize;
    	pFont->itailc = 0;
    	pFont->matrix = NULL;
    	pFont->bold = 0;
    	return 0;
    }

    除了第一种方式外,我们用到了freeType的以下接口:

    FT_Init_FreeType    //初始化freeType

    FT_New_Memory_Face //从内存中加载ttf文件数据生成pFTFace

    FT_New_Face//直接加载ttf文件生成pFTFace

    FT_Set_Char_Size//设置字体大小

    具体使用方式可以参考官方网站的api说明。

    渲染的时候,有一个注意的地方,对于汉字,字符编码参数传进来是gb2312码,需要转换成unicode码,需要用到db2312转unicode码的映射表。文章末尾会附上这个映射表。

    使用这个表的关键代码如下:

    	if(code&0x80){//判断是否为汉字编码
    
    		U8 msb = (code>>8)&0xff;
    		U8 lsb = (code)&0xff;
    		offset = (lsb-GB_MIN_ZONE)*GB_OFFSET_NUMBER+(msb-GB_MIN_OFFSET);
    		code = gb2312_to_ucs2_table[offset];
    	}else{
    		y+=2;//字符统一在垂直方向向下偏移2个像素
    	}

    而字符编码是ascii码是不需要转换的。

    经测试,gui对着三种方式都能很好的支持,同时添加了部分功能的api

    将字体加粗;

    void GUI_TTF_SetBold(GUI_FONT * pFont,U8 bold)//设置粗体
    {
    	pFont->bold = bold;
    }
    

    在渲染的函数中会判断pFont->bold的值,从而确定是否执行

            FT_Outline_Embolden(&pFTFace->glyph->outline,font->bold<<6);

    生成斜体:

            FT_Outline_Transform(&pFTFace->glyph->outline,(FT_Matrix *)(font->matrix));

    这里需要初始化一个FT_Matrix这样的结构体变量,FT_Matrix matrix ,并初始化

        matrix.xx = 0x10000;
        matrix.xy = 0x8000;
        matrix.yx = 0;
        matrix.yy = 0x10000;

    其中xx是xy的倍数关系,这个系数可以自己调节,到目前还是觉得2倍的关系,效果能够接受。

    在移植过程中,参考了不少csdn上各位大神的文章,在此表示感谢,就不在此贴博文链接了(找不着链接了o(╥﹏╥)o)。

    这个是unicode.h文件下载地址

  • 相关阅读:
    python计算机基础
    计算机基础知识
    ftok函数
    可重入函数与不可重入函数
    Redis学习资料整理
    小记6月18
    libxml2简单的生成、解析操作
    切换日志是否更新检查点?
    第五课 数据备份恢复实验
    第四课 Grid Control实验 GC Agent安装(第一台机器部署) 及卸载
  • 原文地址:https://www.cnblogs.com/10cm/p/12568952.html
Copyright © 2020-2023  润新知