freeType2.9.1移植到A7(2)

寫在前面:

freeType2.9.1移植到A7(1)

上一篇文章說了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文件下載地址

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章