色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux應(yīng)用開(kāi)發(fā)【第一章】Framebuffer應(yīng)用開(kāi)發(fā)

weidongshan ? 來(lái)源:weidongshan ? 作者:weidongshan ? 2021-12-10 17:34 ? 次閱讀

文章目錄

1 Framebuffer應(yīng)用開(kāi)發(fā)

1.1 LCD Framebuffer操作原理

1.2 Framebuffer API接口

1.2.1 open系統(tǒng)調(diào)用

1.2.2 ioctl系統(tǒng)調(diào)用

1.2.3 mmap系統(tǒng)調(diào)用

1.3 在LCD上描點(diǎn)操作

1.3.1 在LCD上顯示點(diǎn)陣?yán)碚摶A(chǔ)

1.3.2 獲取fb_var_screeninfo結(jié)構(gòu)體

1.3.3 根據(jù)fb_var_screeninfo計(jì)算變量

1.3.4 使用mmap系統(tǒng)調(diào)用,映射內(nèi)存

1.3.5 描點(diǎn)函數(shù)編寫(xiě)

1.4 在LCD上使用點(diǎn)陣寫(xiě)字

1.4.1 在LCD上顯示英文字母

1.4.2 在LCD上顯示漢字

1.5 搭建freetype相關(guān)環(huán)境

1.5.1 交叉編譯freetype,并安裝

1.5.2 freetype庫(kù),頭文件移植至開(kāi)發(fā)板

1.6 使用freetype

1.5.1 矢量字體引入

1.5.2 Freetype理論介紹

1.5.2 在LCD上顯示一個(gè)矢量字體

1.5.3 在LCD上令矢量字體旋轉(zhuǎn)某個(gè)角度

1 Framebuffer應(yīng)用開(kāi)發(fā)

1.1 LCD Framebuffer操作原理

? LCD Framebuffer 就是一塊顯存,在嵌入式系統(tǒng)中,顯存是被包含在內(nèi)存中。LCD Framebuffer里的若干字節(jié)(根據(jù)驅(qū)動(dòng)程序?qū)CD控制器的配置而定)表示LCD屏幕中的一個(gè)像素點(diǎn),一一對(duì)應(yīng)整個(gè)LCD屏幕。舉個(gè)例子,LCD屏幕是800*600的分辨率,即LCD屏幕存在480000個(gè)像素點(diǎn),若每個(gè)像素點(diǎn)4個(gè)字節(jié)表示,那么LCD Framebuffer顯存大小為480000 *4=960000字節(jié),即1.92MB。因此我們的內(nèi)存將會(huì)分割至少1.92MB的空間用作顯存。具體地址在哪里,這個(gè)就是又驅(qū)動(dòng)程序去定,應(yīng)用程序只需直接使用即可,硬件相關(guān)操作已由驅(qū)動(dòng)程序封裝好。

poYBAGGzH9yAHqVBAAEtJ5ByOcg426.png

? 如上圖,我們只需要往Framebuffer中填入不同的值,驅(qū)動(dòng)程序和硬件控制器就會(huì)把這些數(shù)據(jù)傳輸?shù)綄?duì)應(yīng)LCD屏幕上的像素點(diǎn),從而顯示不同的顏色。由此可知,我們應(yīng)用程序只需要針對(duì)Framebuffer操作即可,其他交給驅(qū)動(dòng)程序和硬件。

1.2 Framebuffer API接口

1.2.1 open系統(tǒng)調(diào)用

pYYBAGGzH-GAcFaTAAD5ZsUkqlc738.png

頭文件:#include ,#include ,#include

函數(shù)原型:

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

函數(shù)說(shuō)明:

pathname 表示打開(kāi)文件的路徑;

Flags表示打開(kāi)文件的方式,常用的有以下6種,

①:O_RDWR表示可讀可寫(xiě)方式打開(kāi);

②:O_RDONLY表示只讀方式打開(kāi);

③:O_WRONLY表示只寫(xiě)方式打開(kāi);

④:O_APPEND 表示如果這個(gè)文件中本來(lái)是有內(nèi)容的,則新寫(xiě)入的內(nèi)容會(huì)接續(xù)到原來(lái)內(nèi)容的后面;

⑤:O_TRUNC表示如果這個(gè)文件中本來(lái)是有內(nèi)容的,則原來(lái)的內(nèi)容會(huì)被丟棄,截?cái)啵?/p>

⑥:O_CREAT表示當(dāng)前打開(kāi)文件不存在,我們創(chuàng)建它并打開(kāi)它,通常與O_EXCL結(jié)合使用,當(dāng)沒(méi)有文件時(shí)創(chuàng)建文件,有這個(gè)文件時(shí)會(huì)報(bào)錯(cuò)提醒我們;

Mode表示創(chuàng)建文件的權(quán)限,只有在flags中使用了O_CREAT時(shí)才有效,否則忽略。

返回值:打開(kāi)成功返回文件描述符,失敗將返回-1。

1.2.2 ioctl系統(tǒng)調(diào)用

poYBAGGzH-eAATmQAAE6IPC6S4w084.png

頭文件:#include

函數(shù)原型:

int ioctl(int fd, unsigned long request, …);

函數(shù)說(shuō)明:

fd 表示文件描述符;

request表示與驅(qū)動(dòng)程序交互的命令,用不同的命令控制驅(qū)動(dòng)程序輸出我們需要的數(shù)據(jù);

… 表示可變參數(shù)arg,根據(jù)request命令,設(shè)備驅(qū)動(dòng)程序返回輸出的數(shù)據(jù)。

返回值:打開(kāi)成功返回文件描述符,失敗將返回-1。

1.2.3 mmap系統(tǒng)調(diào)用

pYYBAGGzH-2AVN04AAEJkssKjnM704.png

頭文件:#include

函數(shù)原型:

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

函數(shù)說(shuō)明:

addr表示指定映射的內(nèi)存起始地址,通常設(shè)為 NULL表示讓系統(tǒng)自動(dòng)選定地址,并在成功映射后返回該地址;

length表示將文件中多大的內(nèi)容映射到內(nèi)存中;

prot 表示映射區(qū)域的保護(hù)方式,可以為以下4種方式的組合

①PROT_EXEC 映射區(qū)域可被執(zhí)行

②PROT_READ 映射區(qū)域可被讀寫(xiě)

③PROT_WRITE 映射區(qū)域可被寫(xiě)入

④PROT_NONE 映射區(qū)域不能存取

Flags 表示影響映射區(qū)域的不同特性,常用的有以下兩種

①M(fèi)AP_SHARED 表示對(duì)映射區(qū)域?qū)懭氲臄?shù)據(jù)會(huì)復(fù)制回文件內(nèi),原來(lái)的文件會(huì)改變。

②MAP_PRIVATE 表示對(duì)映射區(qū)域的操作會(huì)產(chǎn)生一個(gè)映射文件的復(fù)制,對(duì)此區(qū)域的任何修改都不會(huì)寫(xiě)回原來(lái)的文件內(nèi)容中。

返回值:若成功映射,將返回指向映射的區(qū)域的指針,失敗將返回-1。

1.3 在LCD上描點(diǎn)操作

1.3.1 在LCD上顯示點(diǎn)陣?yán)碚摶A(chǔ)

poYBAGGzH-6AOb1lAAGGfHZ10G4753.png

? 如上圖,當(dāng)我們需要顯示一個(gè)字母‘A’時(shí),是通過(guò)判斷點(diǎn)陣的每一個(gè)位數(shù)值狀態(tài),來(lái)填充顏色,達(dá)到顯示字符效果。其中‘1’表示一種顏色,‘0’表示填充另一種顏色。上圖的是8*16的點(diǎn)陣,我們也可以用其他不同大小點(diǎn)陣,只要有這個(gè)點(diǎn)陣,我們就可以在LCD上面描點(diǎn),達(dá)到顯示字符的效果。

1.3.2 獲取fb_var_screeninfo結(jié)構(gòu)體

? 在用點(diǎn)陣顯示字符之前,我們需要先從設(shè)備fb0中獲取相關(guān)的LCD信息,下圖截取我們將用到的fb_info結(jié)構(gòu)體部分內(nèi)容。

pYYBAGGzH--ALM2DAAMtAloXbvA917.png

? 通過(guò)系統(tǒng)調(diào)用ioctl,獲取xres(x方向總像素點(diǎn)),yres(y方向總像素點(diǎn)),bits_per_pixel(每個(gè)像素點(diǎn)占據(jù)的位數(shù)),根據(jù)獲取的三個(gè)資源,外加點(diǎn)陣,根據(jù)這四個(gè)資源,我們就可以顯示一個(gè)字符。

程序文件:show_ascii.c

4718        fd_fb = open("/dev/fb0", O_RDWR);
4719        if (fd_fb < 0)
4720        {
4721            printf("can't open /dev/fb0n");
4722            return -1;
4723        }
4724        if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
4725        {
4726			printf("can't get varn");
4727			return -1;
4728		}	

? 先打開(kāi)LCD設(shè)備(fb0),獲得文件描述符,再通過(guò)ioctl獲取fb_var_screeninfo信息并保存在var變量,后續(xù)只需訪問(wèn)var這個(gè)結(jié)構(gòu)體,就可以獲得xres(x方向總像素點(diǎn)),yres(y方向總像素點(diǎn)),bits_per_pixel(每個(gè)像素點(diǎn)占據(jù)的位數(shù))這三個(gè)關(guān)于fb0的資源。

1.3.3 根據(jù)fb_var_screeninfo計(jì)算變量

fb_var_screeninfo已保存在var結(jié)構(gòu)體變量中,接著來(lái)訪問(wèn)var結(jié)構(gòu)體變量即可

根據(jù)xres與bits_per_pixel算出每行像素點(diǎn)所占據(jù)的字節(jié)數(shù)

程序文件:show_ascii.c

4730	line_width  = var.xres * var.bits_per_pixel / 8;

根據(jù)bits_per_pixel算出每個(gè)像素點(diǎn)所占據(jù)的字節(jié)數(shù)

程序文件:show_ascii.c

4731    pixel_width = var.bits_per_pixel / 8;

根據(jù)xres,yres,bits_per_pixel算出全部像素點(diǎn)所占據(jù)的字節(jié)總和

程序文件:show_ascii.c

4732    screen_size = var.xres * var.yres * var.bits_per_pixel / 8;

1.3.4 使用mmap系統(tǒng)調(diào)用,映射內(nèi)存

程序文件:show_ascii.c

4733	fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | 			PROT_WRITE, MAP_SHARED, fd_fb, 0);
4734	if (fbmem == (unsigned char *)-1)
4735	{
4736		printf("can't mmapn");
4737		return -1;
4738	}
4739
4740	/* 清屏: 全部設(shè)為黑色 */
4741	memset(fbmem, 0, screen_size);

? 調(diào)用mmap將顯存映射在內(nèi)存中,以可讀可寫(xiě)(PROT_READ | PROT_WRITE)及內(nèi)存回寫(xiě)(MAP_SHARED)的方式映射,從而獲得一個(gè)指向映射在內(nèi)存空間的首地址fbmem,后續(xù)操作就是在這個(gè)首地址的基礎(chǔ)上計(jì)算各種不同的偏移量,填充顏色值。

1.3.5 描點(diǎn)函數(shù)編寫(xiě)

程序文件:show_ascii.c

4641	void lcd_put_pixel(int x, int y, unsigned int color)

描點(diǎn)函數(shù)有3個(gè)參數(shù),x坐標(biāo),y坐標(biāo),像素點(diǎn)顏色值。

程序文件:show_ascii.c

4643		unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;
4644		unsigned short *pen_16;	
4645		unsigned int *pen_32;	
4646
4647		unsigned int red, green, blue;	
4648
4649		pen_16 = (unsigned short *)pen_8;
4650		pen_32 = (unsigned int *)pen_8;

? 在此處函數(shù)參數(shù)x與y表示的是像素點(diǎn)的坐標(biāo),而單個(gè)像素點(diǎn)所占據(jù)的顯存大小可能會(huì)有不同的情況出現(xiàn),如1字節(jié)表示一個(gè)像素點(diǎn),2字節(jié)表示一個(gè)像素點(diǎn),4字節(jié)表示一個(gè)像素點(diǎn)等,為了更多的兼容不同的情況,因此申請(qǐng)3個(gè)指針,pen_8指向的是占據(jù)1個(gè)字節(jié)的像素點(diǎn)空間, pen_16指向的是占據(jù)2個(gè)字節(jié)的像素點(diǎn)空間,pen_32指向的是占據(jù)4個(gè)字節(jié)的像素點(diǎn)空間。

fbmem是系統(tǒng)調(diào)用mmap返回的顯存首地址,根據(jù)fbmem計(jì)算填充顏色的內(nèi)存空間。

當(dāng)像素點(diǎn)占據(jù)1個(gè)字節(jié)空間時(shí)

對(duì)應(yīng)描點(diǎn)地址= fbmem+Y * 一行所占據(jù)的字節(jié)數(shù) + x * 每個(gè)像素點(diǎn)所占據(jù)的字節(jié)數(shù)

程序文件:show_ascii.c

4652		switch (var.bits_per_pixel)
4653		{
4654			case 8:
4655			{
4656				*pen_8 = color;
4657				break;
4658			}
4659			case 16:
4660			{
4661				/* 565 */
4662				red   = (color >> 16) & 0xff;
4663				green = (color >> 8) & 0xff;
4664				blue  = (color >> 0) & 0xff;
4665				color = ((red >> 3) << 11) | ((green >> 2) << 5) | 						(blue >> 3);
4666				*pen_16 = color;
4667				break;
4668			}
4669			case 32:
4670			{
4671				*pen_32 = color;
4672				break;
4673			}
4674			default:
4675			{
4676				printf("can't surport %dbppn", var.bits_per_pixel);
4677				break;
4678			}
4679		}
4680	}

? 根據(jù)設(shè)備fb0實(shí)際的bits_per_pixel值,選擇對(duì)應(yīng)的pen(pen_8,pen_16,pen_32其中一個(gè)),最后把color顏色變量傳入選擇的pen中。

1.4 在LCD上使用點(diǎn)陣寫(xiě)字

1.4.1 在LCD上顯示英文字母

①找出英文字母在點(diǎn)陣數(shù)組中的地址,c所代表的是一個(gè)英文字母(ASCII值)。

程序文件:show_ascii.c

4693		unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];

②根據(jù)獲得的英文字母點(diǎn)陣,每一位依次判斷,描點(diǎn),‘1’表示白色,‘0’表示黑色。

poYBAGGzH_CAbvmzAAJUVPbsYPE456.png

? 根據(jù)上圖,我們分析下如何利用點(diǎn)陣在LCD上顯示一個(gè)英文字母,因?yàn)橛惺校允紫纫幸粋€(gè)循環(huán)16次的大循環(huán),然后每一行里有8位,那么在每一個(gè)大循環(huán)里也需要一個(gè)循環(huán)8次的小循環(huán),小循環(huán)里的判斷單行的描點(diǎn)情況,如果是1,就填充白色,如果是0就填充黑色,如此一來(lái),就可以顯示出黑色底,白色輪廓的英文字母。

程序文件:show_ascii.c

4697		for (i = 0; i < 16; i++)
4698		{
4699			byte = dots[i];
4700			for (b = 7; b >= 0; b--)
4701			{
4702				if (byte & (1<

③調(diào)用我們編寫(xiě)的lcd_put_ascii函數(shù)

程序文件:show_ascii.c

4743 lcd_put_ascii(var.xres/2, var.yres/2, 'A'); /*在屏幕中間顯示8*16的字母A*/

④編譯c文件show_ascii.c

編譯命令:arm-linux-gnueabihf-gcc -o show_ascii show_ascii.c

⑤將編譯出來(lái)的show_ascii傳輸?shù)介_(kāi)發(fā)板,并進(jìn)入show_ascii的目錄下

執(zhí)行命令:./show_ascii

如果實(shí)驗(yàn)成功,我們將看到屏幕中間會(huì)顯示出一個(gè)白色的字母‘A’。

1.4.2 在LCD上顯示漢字

pYYBAGGzH_CAU3iwAAAeGLDLNoE906.png

? 與顯示英文字母有點(diǎn)不同,因?yàn)闈h字的點(diǎn)陣我們是需要通過(guò)漢字庫(kù)提取出來(lái),并沒(méi)有直接提供點(diǎn)陣數(shù)組,因此我們程序開(kāi)頭需要打開(kāi)漢字庫(kù)文件(HZK16),然后再找到相應(yīng)的位置,提取出漢字的點(diǎn)陣,最后再按顯示英文字母一樣顯示它,不過(guò)這個(gè)漢字是16*16的。

① 打開(kāi)漢字庫(kù)文件

程序文件:show_font.c

4760	fd_hzk16 = open("HZK16", O_RDONLY); 

② 獲取漢字庫(kù)文件的屬性,存在hzk_stat結(jié)構(gòu)體變量中

程序文件:show_font.c

4793	if(fstat(fd_hzk16, &hzk_stat))

此處主要是用知道該文件的大小,因?yàn)楹竺鎚map時(shí)需要知道映射的文件大小。

③使用mmap系統(tǒng)調(diào)用

程序文件:show_font.c

4798	hzkmem = (unsigned char *)mmap(NULL , hzk_stat.st_size, 				PROT_READ, MAP_SHARED, fd_hzk16, 0);

hzkmem與fbmem類似,也是一個(gè)指向映射內(nèi)存的指針,但是它是指向漢字庫(kù),方便

后續(xù)計(jì)算漢字點(diǎn)陣偏移位置用。

④使用漢字庫(kù),調(diào)出點(diǎn)陣顯示漢字

? HZK16 字庫(kù)是符合GB2312標(biāo)準(zhǔn)的16×16點(diǎn)陣字庫(kù)HZK16的編碼,每個(gè)字需要32個(gè)字節(jié)的點(diǎn)陣來(lái)表示,例如我們將要顯示的‘中’字,編碼是D6D0,難道就是2個(gè)字節(jié)表示嗎?不是說(shuō)32字節(jié)嗎?D6D0編碼是一個(gè)類似于索引碼,D6是區(qū)碼,D0是位碼,先要找到D6-A1才是真正區(qū),在D6-A1區(qū)里找到D0-A1的真正位置,這才是‘中’字點(diǎn)陣的起始位置(減去A1是為了兼容ascii),每一個(gè)區(qū)有94個(gè)漢字。

程序文件:show_font.c

4734		unsigned int area  = str[0] - 0xA1;
4735		unsigned int where = str[1] - 0xA1;
4736		unsigned char *dots = hzkmem + (area * 94 + where)*32;
poYBAGGzH_GAHIvAAABp7Un6kZI896.png

? 上圖是漢字點(diǎn)陣排布的示意圖,總共有十六行,因此需要一個(gè)循環(huán)16次的大循環(huán),考慮到一行有兩個(gè)字節(jié),我們大循環(huán)中加入一個(gè)循環(huán)2次的循環(huán)用于區(qū)分是哪個(gè)字節(jié),最后判斷當(dāng)前字節(jié)的每一位,如果為 ‘1’描白色,如果為‘0’描黑色

程序文件:show_font.c

4740	for (i = 0; i < 16; i++)
4741			for (j = 0; j < 2; j++)
4742			{
4743				byte = dots[i*2 + j];
4744				for (b = 7; b >=0; b--)
4745				{
4746					if (byte & (1<

⑤調(diào)用我們編寫(xiě)的lcd_put_chinese函數(shù)

程序文件:show_font.c

4810	printf("chinese code: %02x %02xn", str[0], str[1]);
4811	lcd_put_chinese(var.xres/2 + 8,  var.yres/2, str);

⑥編譯c文件show_font.c

編譯命令:arm-linux-gnueabihf-gcc -o show_font show_font.c

注:使用此命令HZK16文件必須與show_font.C在同一目錄下。

⑦將編譯出來(lái)的show_font傳輸?shù)介_(kāi)發(fā)板,并進(jìn)入show_font的目錄下

執(zhí)行命令:./show_font

如果實(shí)驗(yàn)成功,我們將看到屏幕中間會(huì)顯示出一個(gè)白色的字母‘A’與漢字‘中’,同時(shí)在串口打印信息中看到‘中’對(duì)應(yīng)的編碼。

chinese code: d6 d0

1.5 搭建freetype相關(guān)環(huán)境

1.5.1 交叉編譯freetype,并安裝

①解壓freetype源文件

tar xjf freetype-2.4.10.tar.bz2 

②進(jìn)入解壓后的freetype-2.4.10目錄

cd freetype-2.4.10

③配置freetype-2.4.10

./configure --host=arm-linux-gnueabihf --prefix=/home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/

④建個(gè)目錄,避免后面安裝出錯(cuò)提示缺少這個(gè)internal目錄

mkdir /home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/freetype2/freetype/internal -p

④編譯

make

⑤安裝

make install

⑥移動(dòng)freetype頭文件,避免以后編譯總是需要指定頭文件路徑

mv /home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/freetype2/freetype /home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/

1.5.2 freetype庫(kù),頭文件移植至開(kāi)發(fā)板

? 由于100ask開(kāi)發(fā)板已經(jīng)有freetype相關(guān)的庫(kù)和頭文件,因此不需要移植,如果開(kāi)發(fā)板沒(méi)有freetype庫(kù)和頭文件就需要按以下方法移植

/home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/* 復(fù)制到開(kāi)發(fā)板的頭文件目錄中

/home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib/so 復(fù)制到開(kāi)發(fā)板的庫(kù)文件目錄中

注:鏈接文件需要保持它的鏈接屬性(即加-d選項(xiàng))。

1.6 使用freetype

1.5.1 矢量字體引入

? 點(diǎn)陣顯示英文字母,漢字時(shí),大小固定,如果放大會(huì)有鋸齒出現(xiàn),為了解決這個(gè)問(wèn)題,引用矢量字體。

矢量字體形成分三步,若干的關(guān)鍵點(diǎn),數(shù)學(xué)曲線(貝塞爾曲線),填充顏色組合而成。

①假設(shè)A字母的關(guān)鍵點(diǎn)如圖中的黃色圈圈,確定關(guān)鍵點(diǎn)。

pYYBAGGzH_GAT4ybAACJ6O3iEEc758.png

②用數(shù)學(xué)曲線將關(guān)鍵點(diǎn)都連接起來(lái),成為封閉的曲線。

poYBAGGzH_GAJbTEAABxkKnpFWE764.png

③最后把封閉空間填滿顏色,就顯示出一個(gè)A字母。

pYYBAGGzH_KAERlyAAB1L_teWgs078.png

? 如果需要放大或者縮小字體,關(guān)鍵點(diǎn)的相對(duì)位置是不變的,跟進(jìn)放大比例放大或縮小,但是相對(duì)位置不變,好像分?jǐn)?shù)中的1/2 和 2/4,比例是不變的,但是值卻大了,類似這個(gè)味道。

1.5.2 Freetype理論介紹

? 開(kāi)源的Freetype字體引擎庫(kù)它提供統(tǒng)一的接口來(lái)訪問(wèn)多種字體格式文件,從而實(shí)現(xiàn)矢量字體顯示。我們只需要移植這個(gè)字體引擎,調(diào)用對(duì)應(yīng)的API接口,提供字體關(guān)鍵點(diǎn),就可以讓freetype庫(kù)幫我們實(shí)現(xiàn)閉合曲線,填充顏色,達(dá)到顯示矢量字體的目的。

關(guān)鍵點(diǎn)(glyph)存在字體文件中,Windows使用的字體文件在FONTS目錄下,擴(kuò)展名為T(mén)TF的都是矢量字庫(kù),本次使用實(shí)驗(yàn)使用的是新宋字體simsun.ttc。

poYBAGGzH_KAYR2sAABAET51uMY263.png

字體文件結(jié)構(gòu)如上圖

? Charmaps表示字符映射表,字體文件可能支持哪一些編碼,GBK,UNICODE,BIG5還是別的編碼,如果字體文件支持該編碼,跟進(jìn)編碼,通過(guò)charmap,找到對(duì)應(yīng)的glyph,一般而言都支持UNICODE碼。

有了以上基礎(chǔ),我們想象一個(gè)文字的顯示過(guò)程

①給定一個(gè)文字嗎‘A’(0x41),‘中’(GBK,UNICODE ,BIG5)可以確定它的編碼值;

②跟進(jìn)編碼值,從枝頭文件中通過(guò)charmap找到對(duì)應(yīng)的關(guān)鍵點(diǎn)(glyph);

③設(shè)置字體大;

④用某些函數(shù)把關(guān)鍵點(diǎn)(glyph)縮放為我們?cè)O(shè)置的字體大小;

⑤轉(zhuǎn)換為位圖點(diǎn)陣

⑥在LCD上顯示出來(lái)

pYYBAGGzH_KAUHfBAACBU-2MSEg132.png

? 如上圖,參照step1,step2,step3里的內(nèi)容,可以學(xué)習(xí)如何使用freetype庫(kù),大致總結(jié)下,為如下步驟。

①初始化:FT_InitFreetype

②加載(打開(kāi))字體Face:FT_New_Face

③設(shè)置字體大小:FT_Set_Char_Sizes 或 FT_Set_Pixel_Sizes

④選擇charmap:FT_Select_Charmap

⑤根據(jù)編碼值charcode找到glyph : glyph_index = FT_Get_Char_Index(face,charcode)

⑥根據(jù)glyph_index取出glyph:FT_Load_Glyph(face,glyph_index)

⑦轉(zhuǎn)為位圖:FT_Render_Glyph

⑧移動(dòng)或旋轉(zhuǎn):FT_Set_Transform

1.5.2 在LCD上顯示一個(gè)矢量字體

poYBAGGzH_OAOEUkAACiakJkpto189.png

我們可以參考上圖位置的c程序,編寫(xiě)程序。

①初始化freetype庫(kù)

程序文件:freetype_show_font.c

4872	error = FT_Init_FreeType( &library );			   /* initialize library */

②用freetype庫(kù)中的FT_New_Face函數(shù)創(chuàng)建一個(gè)face字體文件對(duì)象,保存在&face中

程序文件:freetype_show_font.c

4875    error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */

③提取face對(duì)象中的glyph,即關(guān)鍵點(diǎn)集

程序文件:freetype_show_font.c

4877    slot = face->glyph;

④設(shè)置像素點(diǎn)大小,24*24

程序文件:freetype_show_font.c

4879    FT_Set_Pixel_Sizes(face, 24, 0);

⑤確定坐標(biāo)

? 目前我們前面所用的都是LCD的坐標(biāo)系對(duì)應(yīng)的x與y坐標(biāo),然后在freetype上卻是使用的笛卡爾坐標(biāo)系,因此我們還需要轉(zhuǎn)換x與y坐標(biāo)。

pYYBAGGzH_SACqrUAABGniipdVc829.png

我們將要顯示的是‘繁’字,根據(jù)上圖可知,先計(jì)算在lcd坐標(biāo)系的情況下‘繁’字

的左下角的x坐標(biāo)與y坐標(biāo),因?yàn)樵诘芽栕鴺?biāo)中左下角為字符的原點(diǎn),‘A’是的左上角為整個(gè)屏幕的中心點(diǎn),即(xres/2,yres/2)。

lcd_x = var.xres/2 + 8 + 16;lcd_y = var.yres/2 + 16

則笛卡爾座標(biāo)系:x = lcd_x = var.xres/2 + 8 + 16 ; y = var.yres - lcd_y = var.yres/2 – 16

單位是1/64像素,所以需要乘以64

程序文件:freetype_show_font.c

4888	pen.x = (var.xres/2 + 8 + 16) * 64;
4889	pen.y = (var.yres/2 - 16) * 64;
4890
4891	/* set transformation */
4892    FT_Set_Transform( face, 0, &pen);

⑥找到glyph的位置,然后取出,并轉(zhuǎn)換為位圖

4895    error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );
4896	if (error)
4897	{
4898		printf("FT_Load_Char errorn");
4899		return -1;
4900	}
poYBAGGzH_WAWmD5AABVKdSyrFI276.png

FT_Load_Char函數(shù)調(diào)用替代了上圖這3步。

最后把轉(zhuǎn)換出來(lái)的位圖打印出來(lái),也是參考example1.c編寫(xiě)

程序文件:freetype_show_font.c

4902 	  draw_bitmap( &slot->bitmap,
4903         	        slot->bitmap_left,
4904             	    var.yres - slot->bitmap_top);

程序文件:example1.c

pYYBAGGzH_WAA34ZAAA0gCuxXTA893.png

修改上圖3處位置

Width寬度:因?yàn)樵贚CD上顯示,寬度自然就是x方向的像素點(diǎn)數(shù),var.xres;

Height高度:因?yàn)樵贚CD上顯示,高度自然就是y方向的像素點(diǎn)數(shù),var.yres;

用點(diǎn)陣實(shí)驗(yàn)中的的描點(diǎn)函數(shù)lcd_put_pixel替代image數(shù)組

lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]);

⑥編譯C程序文件freetype_show_font.c

編譯命令:arm-linux-gnueabihf-gcc -finput-charset=GBK -fexec-charset=GBK -o freetype_show_font freetype_show_font.c -lfreetype -lm

⑦將編譯好的freetype_show_font的文件與simsun.ttc字體文件拷貝至開(kāi)發(fā)板,simsun.ttc字體文件放在freetype_show_font執(zhí)行文件的上一層目錄下,執(zhí)行以下命令。

執(zhí)行命令:./freetype_show_font …/simsun.ttc

如果實(shí)驗(yàn)成功,我們將看到屏幕中間會(huì)比之前實(shí)驗(yàn)多出一個(gè)藍(lán)色的‘繁’字。

1.5.3 在LCD上令矢量字體旋轉(zhuǎn)某個(gè)角度

在實(shí)現(xiàn)顯示一個(gè)矢量字體后,我們可以添加讓該字旋轉(zhuǎn)某個(gè)角度的功能。

我們根據(jù)輸入的第二個(gè)參數(shù),判斷其旋轉(zhuǎn)角度,主要代碼還是參照example1.c

poYBAGGzH_WAcxSnAACipLfUeRU735.png

根據(jù)上圖,增加旋轉(zhuǎn)角度功能,旋轉(zhuǎn)的角度由執(zhí)行命令的第二個(gè)參數(shù)指定。

程序文件:freetype_show_font_angle.c

		/* use 25 degrees */
4894	angle = ( 1.0 * strtoul(argv[2], NULL, 0) / 360 ) * 3.14159 * 2;

4895	/* set up matrix */
4896	matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
4897	matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
4898	matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
4899	matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
4900
4901    /* set transformation */
4902    FT_Set_Transform( face, &matrix, &pen);

最后編譯,在開(kāi)發(fā)板上運(yùn)行

編譯命令如下:

編譯命令:arm-linux-gnueabihf-gcc -finput-charset=GBK -fexec-charset=GBK -o freetype_show_font_angle freetype_show_font_angle.c -lfreetype -lm

編譯出的文件名為freetype_show_font_angle,將文件拷貝至開(kāi)發(fā)板

在含有該文件的目錄下執(zhí)行以下命令,以下命令正確執(zhí)行前提是執(zhí)行文件freetype_show_font在此目錄,而且字體文件simsun.ttc,在上一級(jí)目錄:

執(zhí)行命令:./freetype_show_font_angle …/simsun.ttc 90

如果實(shí)驗(yàn)成功,我們將看到屏幕中間的藍(lán)色‘繁’字,旋轉(zhuǎn)了90度。

審核編輯黃昊宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • lcd
    lcd
    +關(guān)注

    關(guān)注

    34

    文章

    4425

    瀏覽量

    167425
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11296

    瀏覽量

    209361
  • Display
    +關(guān)注

    關(guān)注

    1

    文章

    53

    瀏覽量

    24722
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    數(shù)據(jù)采集光盤(pán)實(shí)例第一章至第六

    數(shù)據(jù)采集光盤(pán)實(shí)例第一章至第六
    發(fā)表于 06-28 21:02

    labview寶典第一章.doc

    本帖最后由 502243 于 2012-10-19 13:07 編輯 目前只有第一章節(jié)...不是課件板labview寶典第一章.doc我覺(jué)得內(nèi)容寫(xiě)得很不錯(cuò)~大家可以看看..
    發(fā)表于 10-19 13:02

    第一章 數(shù)制與編碼

    第一章 數(shù)制與編
    發(fā)表于 04-16 23:35 ?838次閱讀
    <b class='flag-5'>第一章</b> 數(shù)制與編碼

    第一章 數(shù)制與編碼(Number System and Co

    第一章 數(shù)制與編碼(Number System and Codes) 四 數(shù)的原碼、反碼及補(bǔ)碼 1、數(shù)的表示形式 在生活中表示數(shù)的時(shí)候般都是把正
    發(fā)表于 01-26 10:59 ?1262次閱讀

    javascript語(yǔ)言精髓與編程實(shí)踐(第一章)介紹

    javascript語(yǔ)言精髓與編程實(shí)踐(第一章)
    發(fā)表于 10-30 10:07 ?0次下載

    第一章_遙感概述

    遙感概論課程的第一章含說(shuō)課內(nèi)容。包括說(shuō)課。
    發(fā)表于 03-15 09:54 ?0次下載

    第一章 質(zhì)點(diǎn)運(yùn)動(dòng)學(xué)

    大學(xué)物理上冊(cè)ppt第一章,質(zhì)點(diǎn)運(yùn)動(dòng)學(xué)共有63張頁(yè)面。
    發(fā)表于 05-11 14:33 ?0次下載

    HCIE復(fù)習(xí)資料第一章 二層技術(shù)

    HCIE復(fù)習(xí)資料第一章 二層技術(shù),HCIE全套復(fù)習(xí)資料
    發(fā)表于 05-10 17:22 ?0次下載

    《測(cè)控電路》習(xí)題完整參考答案(第一章

    《測(cè)控電路》習(xí)題完整參考答案(第一章
    發(fā)表于 02-07 15:17 ?0次下載

    電力系統(tǒng)繼電保護(hù)第一章-緒論(課件).PPT

    繼電保護(hù)第一章-緒論(課件)
    發(fā)表于 04-28 09:23 ?0次下載

    計(jì)算機(jī)網(wǎng)絡(luò)第一章概述課件下載

    計(jì)算機(jī)網(wǎng)絡(luò)第一章概述課件下載
    發(fā)表于 05-17 10:50 ?0次下載

    同濟(jì)大學(xué)高等數(shù)學(xué)第一章函數(shù)與極限PPT

    同濟(jì)大學(xué)高等數(shù)學(xué)第一章函數(shù)與極限PPT
    發(fā)表于 08-13 10:17 ?0次下載

    慕課嵌入式開(kāi)發(fā)及應(yīng)用(第一章.單元測(cè)試)

    慕課蘇州大學(xué).嵌入式開(kāi)發(fā)及應(yīng)用.第一章.基礎(chǔ)與硬件.單元測(cè)試0 目錄1 基礎(chǔ)與硬件1.1 單元測(cè)試1.1.1課堂重點(diǎn)1.1.2測(cè)試與作業(yè)2 下一章0 目錄1 基礎(chǔ)與硬件1.1 單元測(cè)試1.1.1課堂
    發(fā)表于 11-02 21:06 ?17次下載
    慕課嵌入式<b class='flag-5'>開(kāi)發(fā)</b>及應(yīng)用(<b class='flag-5'>第一章</b>.單元測(cè)試)

    第一章 嵌入式介紹

    第一章 嵌入式介紹. 嵌入式系統(tǒng)定義二 . SOC定義三 . ARM處理器系列四 . 交叉開(kāi)發(fā)模式1. 交叉開(kāi)發(fā)定義2. arm-linux
    發(fā)表于 11-03 19:36 ?10次下載
    <b class='flag-5'>第一章</b> 嵌入式介紹

    【TOLIN】第一章|開(kāi)發(fā)板硬件資源介紹

    【TOLIN】第一章|開(kāi)發(fā)板硬件資源介紹 作者:Tkwer公眾號(hào):Tkwer望遠(yuǎn)鏡TOLIN,是塊STM32核心板至于為什么叫Tolin,最可
    發(fā)表于 12-08 15:06 ?8次下載
    【TOLIN】<b class='flag-5'>第一章</b>|<b class='flag-5'>開(kāi)發(fā)</b>板硬件資源介紹
    主站蜘蛛池模板: 石原莉奈rbd806中文字幕| 成人免费在线观看| 精品在线观看一区| 国产AV精品久久久毛片| 女人被躁到高潮嗷嗷叫69| 中文字幕免费视频精品一| 久久re视频这里精品09免费| 亚洲精品123区在线观看| 国产精品爽爽久久久久久蜜桃网站| 日本阿v在线资源无码免费| AV天堂午夜精品一区| 免费无码又爽又黄又刺激网站| 2021自产拍在线观看视频| 久久亚洲精品成人综合| 精品国产国产综合精品| 亚洲黄色三级视频| 国内精品伊人久久久影院| 亚洲AV色香蕉一区二区三区| 国产人妻人伦精品98| 無码一区中文字幕少妇熟女网站| 国产成人综合视频| 四虎永久在线精品国产| 国产精品xxxav免费视频| 婷婷综合亚洲爱久久| 国产精品18久久久久久欧美| 天天操天天干天天透| 国产精品久久久久久久AV下载| 王雨纯羞羞| 国产亚洲精品久久久久久无码网站| 亚洲 天堂 欧美 日韩 国产| 国产亚洲精品久久77777| 亚洲国产五月综合网| 精品无码国产污污污免费网站2| 樱花草动漫www| 毛茸茸womansex| 99视频在线看观免费| 日本xxxx裸体xxxx| 国产精彩视频在线| 亚洲a视频在线| 久久国产乱子伦精品免费不卡| 中字幕视频在线永久在线观看免费 |