數碼相框(二)freetype庫實現向量顯示
一、向量字型原理
將漢字的筆劃邊緣用直線段描述成封閉的曲線,並將線段各端點的座標經壓縮儲存,如下圖所示:
由於每個漢字的比劃不一樣,從而每個漢字資料長度也不同,所以只能採用索引的方法。因而每種向量字型檔都是由兩部分組成,一部分是漢字的字形(glyph)資料。當顯示文字時,便提取出各端點,並通過貝塞爾曲線來連線各個座標,最後填充封閉空間。
接下來使用freetype庫製作向量字型
二、安裝freetype-2.4.10庫
freetype庫是一個開源的字型引擎,支援多種字符集編碼(utf-8等)
2.1 如何使用freetype
1)包含標頭檔案:
#include <ft2build.h> #include FT_FREETYPE_H
2)初始化庫:
使用FT_Init_FreeType()函式初始化一個FT_Library型別的變數,例如:
FT_LIBRARY library; //庫的控制代碼
error = FT_Init_FreeType( &library );
if ( error )
{
//初始化失敗
}
... ...
3)載入face物件:
通過FT_NEW_Face()開啟一個字型檔案,然後提取該檔案的一個FT_Face型別的face變數,例如:
FT_LIBRARY library; //庫的控制代碼 FT_Face face; /* face物件的控制代碼 */ error = FT_Init_FreeType ( &library ); if ( error ) {... ...} ... ... error = FT_New_Face( library, "/usr/share/fonts/truetype/arial.ttf", 0, &face ); //字形檔案
4)設定字型大小
方法1:
FT_Set_Char_Size(
FT_Face face,
FT_F26Dot6 char_width, //字元寬度,單位為1/64點
FT_F26Dot6 char_height, //字元高度,單位為1/64點
FT_UInt horz_resolution, //水平解析度
FT_UInt vert_resolution
); //垂直解析度
字元寬度和高度以1/64點為單位表示。點是物理上的距離,一個點代表1/72英寸(2.54cm),解析度以dpi(dots per inch)為單位表示,表示一個英寸有多少個畫素
例如:
error = FT_Set_Char_Size( face, 50 * 64, 0,100, 0 ); //0表示與另一個尺寸值相等。
得出:
字元物理大小為:50*64* (1/64) * (1/72)英寸
字元的畫素為:50*64* (1/64) * (1/72)*100
方法2:
FT_Set_Pixel_Sizes(
FT_Face face,
FT_UInt pixel_width, //畫素寬度
FT_UInt pixel_height
); //畫素高低
例如:
error = FT_Set_Pixel_Sizes( face, 0,16); //把字元畫素設定為16*16畫素, 0表示與另一個尺寸值相等。
5)設定字型位置,以及旋轉度數(不設定的話表示原點位於0,0):
error = FT_Set_Transform(
face, /* 目標face物件 */
&matrix, /* 指向2x2矩陣的指標,寫0表示不旋轉,使用正矩形 */
&delta
); /*字型座標位置(用的笛卡爾座標),以1/64畫素為單位表示,寫0表示原點是(0,0) */
由於我們LCD的座標原點是位於左上方
笛卡爾座標:表示座標原點位於左下方(與LCD的y軸相反)
所以轉換之前填寫座標時,需要轉換一下y軸值(總高度-y)
轉換成功後還需要轉換回來(總高度-y)
比如,旋轉25,並在(300,200)處顯示:
FT_Vector pen; /* */
FT_Matrix matrix; /* transformation matrix */
angle = ( 25.0 / 360 ) * 3.14159 * 2; /* use 25 degrees */
/*將該文字座標轉為笛卡爾座標*/
pen.x = 300 * 64;
pen.y = ( target_height - 200 ) * 64; // target_height: LCD總高度
//設定 矩形引數
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
FT_Set_Transform( face, &matrix, &pen );
6)載入字形影象
a)獲取編碼的索引
通過FT_Get_Char_Inde()函式將字元編碼轉換為一個字形(glyph)索引(Freetype預設是utf-16編碼型別),例如:
glyph_index = FT_Get_Char_Index( face, charcode );
若glyph_index為NULL,表示沒找到字形(glyph)索引,如果使用其他字元編碼,則通過FT_Select_Charmap()來獲取,例如獲取big5編碼:
error = FT_Select_Charmap(
face, /* 目標face物件 */
FT_ENCODING_BIG5
); /* big5編碼 */
//FT_ENCODING_BIG5列舉定義在FT_FREETYPE_H中
//FT_ENCODING_GB2312 :GB2312編碼
//該函式標頭檔案位於:FT_FREETYPE_H (freetype/freetype.h).
b)通過索引,從face中載入字形
獲得字形索引後,接下來便根據字形索引,來將字形影象儲存到字形槽(glyph slot)中.
字形槽:每次只能儲存一個字形影象,每個face物件都有一個字形槽,位於face->glyph
通過FT_Load_Glyph()來載入一個字形影象到字形槽:
error = FT_Load_Glyph
(
face, /* face物件的控制代碼 */
glyph_index, /* 字形索引 */
load_flags
); /* 裝載標誌,一般填FT_LOAD_DEFAULT*/
並更新face->glyph下的其它成員,比如:
FT_Int bitmap_left; //該字形影象的最左邊的X值
FT_Int bitmap_top; //該字形影象的最上邊的Y值
c)轉為點陣圖
通過FT_Render_Glyph()函式,將字形槽的字形影象轉為點陣圖,並存到 face->glyph->bitmap->buffer[]裡
error = FT_Render_Glyph( face->glyph, /* 字形槽 */
render_mode ); /* 渲染模式 */
render_mode標誌可以設為以下幾種:
FT_RENDER_MODE_NORMAL:表示生成點陣圖每個畫素是RGB888的
FT_RENDER_MODE_MONO:表示生成點陣圖每個畫素是1位的(黑白圖)
並更新face->glyph->bitmap下的其它成員,比如:
int rows; //該點陣圖總高度,有多少行
int width; //該點陣圖總寬度,有多少列畫素點
int pitch: //指一行的資料跨度(位元組數),比如對於24位(3位元組)的24*30漢字,則pitch=24*3
char pixel_mode //畫素模式,1 指單色的,8 表示反走樣灰度值
unsigned char* buffer //glyph 的點陣點陣圖記憶體綬衝區
d)也可以直接使用FT_Load_Char()來代替FT_Get_Char_Index()、FT_Get_Load_Glyph()和FT_Render_Glyph().
例如:
error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );
其中FT_LOAD_RENDER:表示直接將影象轉為點陣圖,所以不需要使用FT_Render_Glyph()函式
該函式預設生成的點陣圖是預設生成的FT_RENDER_MODE_NORMAL型別,RGB888的
若想生成FT_RENDER_MODE_MONO(黑白圖)型別,操作如下:
error = FT_Load_Char( face, charcode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME );
生成出來的點陣圖畫素,每8個畫素點便表示 face->glyph->bitmap->buffer[]裡的一個位元組。
三、PC虛擬機器裡程式設計例程:example1.c
/* example1.c */
/* */
/* This small program shows how to print a rotated string with the */
/* FreeType 2 library. */
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#define WIDTH 80
#define HEIGHT 80
/* origin is the upper left corner */
unsigned char image[HEIGHT][WIDTH];
/* Replace this function with something useful. */
void
draw_bitmap( FT_Bitmap* bitmap,
FT_Int x,
FT_Int y)
{
FT_Int i, j, p, q;
FT_Int x_max = x + bitmap->width;
FT_Int y_max = y + bitmap->rows;
for ( i = x, p = 0; i < x_max; i++, p++ )
{
for ( j = y, q = 0; j < y_max; j++, q++ )
{
if ( i < 0 || j < 0 ||
i >= WIDTH || j >= HEIGHT )
continue;
image[j][i] |= bitmap->buffer[q * bitmap->width + p];
}
}
}
void
show_image( void )
{
int i, j;
for ( i = 0; i < HEIGHT; i++ )
{
for ( j = 0; j < WIDTH; j++ )
putchar( image[i][j] == 0 ? ' '
: image[i][j] < 128 ? '+'
: '*' );
putchar( '\n' );
}
}
int
main( int argc,
char** argv )
{
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_Matrix matrix; /* transformation matrix */
FT_Vector pen; /* untransformed origin */
FT_Error error;
char* filename;
char* text;
double angle;
int target_height;
int n, num_chars;
if ( argc != 3 )
{
fprintf ( stderr, "usage: %s font sample-text\n", argv[0] );
exit( 1 );
}
filename = argv[1]; /* first argument */
text = argv[2]; /* second argument */
num_chars = strlen( text );
angle = ( 0.0 / 360 ) * 3.14159 * 2; /* use 25 degrees */
target_height = HEIGHT;
error = FT_Init_FreeType( &library ); /* initialize library */
/* error handling omitted */
error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
/* error handling omitted */
#if 0
/* use 50pt at 100dpi */
error = FT_Set_Char_Size( face, 50 * 64, 0,
100, 0 ); /* set character size */
/* pixels = 50 /72 * 100 = 69 */
#else
FT_Set_Pixel_Sizes(face, 24, 0);
#endif
/* error handling omitted */
slot = face->glyph;
/* set up matrix */
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
/* the pen position in 26.6 cartesian space coordinates; */
/* start at (0,40) relative to the upper left corner */
pen.x = 0 * 64;
pen.y = ( target_height - 40 ) * 64;
for ( n = 0; n < num_chars; n++ )
{
/* set transformation */
FT_Set_Transform( face, &matrix, &pen );
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
if ( error )
continue; /* ignore errors */
/* now, draw to our target surface (convert position) */
draw_bitmap( &slot->bitmap,
slot->bitmap_left,
target_height - slot->bitmap_top );
/* increment pen position */
pen.x += slot->advance.x;
pen.y += slot->advance.y;
}
show_image();
FT_Done_Face ( face );
FT_Done_FreeType( library );
return 0;
}
/* EOF */
3.1 安裝freetype到/usr/local/裡(給PC機用)
tar -xjf freetype-2.4.10.tar.bz2
mv freetype-2.4.10 freetype-2.4.10_pc
cd freetype-2.4.10_pc/
./configure --host=arm-linux --prefix=/root/code/Project/數碼相框/freetype-2.4.10/freetype(自定義目錄) //配置
make //編譯
make install //直接將庫安裝到根目錄/usr/local/裡,所以需要加
由於example1.c的列印範圍是640*480,而我們secureCRT沒有那麼大,所以修改example1.c
#define WIDTH 640
#define HEIGHT 480
改為:
#define WIDTH 80
#define HEIGHT 80
然後將119行處的文字顯示座標:
pen.x = 300 * 64;
pen.y = ( target_height - 200 ) * 64;
改為:
pen.x = 0 * 64;
pen.y = ( target_height - 40 ) * 64;
3.2 編譯執行
gcc -o example1 example1.c
所以通過-I,直接指定標頭檔案目錄:
gcc -o example1 example1.c -I /usr/local/include/freetype2/
發現這些出錯的都是函式,其中FT開頭的是freetype庫的函式,cos等都是數學庫的函式,
freetype庫的檔名是 libfreetype.so
數學庫的檔名是libm.so
所以編譯時,加上-l,指定庫檔案:
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype -lm
3.3 執行example1
將C:\Windows\Fonts下的simsun.ttc(宋體)字型檔案拷到虛擬機器裡,輸入./example1 simsun.ttc agf,發現是斜的:
這是因為example1.c裡通過FT_Set_Transform()設定了字型旋轉
3.4 修改example1.c
關閉字型旋轉,將
FT_Set_Transform( face, &matrix, &pen );
改為
FT_Set_Transform( face, 0, &pen );
修改字型大小,將
error = FT_Set_Char_Size( face, 50 * 64, 0, 100, 0 );
改為
error = FT_Set_Pixel_Sizes( face, 24, 0 ); //24*24畫素
編譯執行:
3.5 顯示漢字
如果用char儲存漢字英文等,則還需要判斷資料型別,而wchar_t剛好可以放一個unicode字元。
注意:wchar_t在windows佔2byte,在linux佔4bytes.
寬字元:wchar_t
標頭檔案: #include<wchar.h>
通過wcslen()判斷wchar_t陣列大小
修改example1.c
...
#include<wchar.h> //新增此行
...
int main( int argc,char** argv )
{
... ...
wchar_t *chinese_str=L"韋東山g"; //新增此行
... ...
for ( n = 0; n <wcslen(chinese_str); n++ ) //修改此行
{
FT_Set_Transform( face, 0, &pen ); //字型轉換
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER ); //修改此行
... ...
}
return 0;
}
通過另存為檔案,來看看檔案本身是什麼編碼格式
如下圖所示,看到是ANSI編碼, 對於中文PC,ANSI編碼對應的是GBK編碼:
linux預設是utf-8編碼,所以編譯時,需要指定字符集:
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype -lm -finput-charset=GBK -fexec-charset=utf-8
// -finput-charset:告訴編譯器,檔案裡的字元是GBK格式
//-fexec-charset:告訴編譯器,需要先將裡面的內容轉換為utf-8格式後,再來編譯
執行程式碼:
新增列印座標:
發現,我們列印座標是在(40,0),為什麼文字座標還會超過原點?,參考以下圖所示:
advance: 位於face->glyph-> advance,用來存放每個文字之間的間隔資訊,每當載入一個新的影象時,系統便會更新該資料。
3.6 獲取點陣圖文字的資訊
當我們每次將新的字形影象(face->glyph)轉為點陣圖後,而存放的前一個字形影象就會被刪除.
當有時候,有可能需要提取字形影象的座標,該怎麼做?
1)首先新增標頭檔案:
#include FT_GLYPH_H
2)通過FT_Get_Glyph()將一個字形影象(face->glyph)存到FT_Glyph型別的變數裡,例如
FT_Glyph glyph; /* a handle to the glyph image */
...
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NORMAL );
//通過字元編碼,獲取字形影象存到face->glyph裡,並轉為點陣圖存到face->glyph->bitmap->buffer[]裡
if ( error ) { ... }
error = FT_Get_Glyph( face->glyph, &glyph ); //將字形影象(face->glyph)存到glyph裡
if ( error ) { ... }
3) 通過FT_Glyph_Get_CBox()獲取文字的xMin, xMax, yMin, yMax座標資訊
參考: /freetype-2.4.10/docs/reference/ft2-index.html
FT_Glyph_Get_CBox(
FT_Glyph glyph, //該值通過FT_Get_Glyph()來獲取
FT_UInt bbox_mode, //模式,填入FT_GLYPH_BBOX_TRUNCATE即可
FT_BBox *acbox
); //用來存放獲取到的xMin, xMax, yMin, yMax資訊
其中FT_GLYPH_BBOX_TRUNCATE表示:獲取的座標資訊是畫素座標,而不是點座標
修改example1.c,使它能列印每個漢字的座標資訊:
#include FT_GLYPH_H //新增此行
... ...
int main( int argc, char** argv )
{
FT_Glyph glyph;
FT_BBox acbox;
... ...
for ( n = 0; n < wcslen(chinese_str); n++ )
{
... ...
error = FT_Load_Char( face,chinese_str[n], FT_LOAD_RENDER );
if ( error )
continue; /* ignore errors */
error = FT_Get_Glyph( face->glyph, &glyph ); //新增此行
FT_Glyph_Get_CBox( glyph,FT_GLYPH_BBOX_TRUNCATE,&acbox ); //新增此行
printf("0x%x:xMin=%ld,xMax=%ld,yMin=%ld,yMax=%ld\n",chinese_str[n],acbox.xMin,acbox.xMax,acbox.yMin,acbox.yMax); //新增此行
... ...
編譯執行:
表示韋字(97e6)的笛卡爾座標 : X座標在0~23,y座標在37~60,是個24*24字型.
由於笛卡爾座標的原點座標位於左下方.
所以對應韋字(97e6)的LCD座標: X座標在0~23 ,y座標為20~43
四、在LCD上顯示向量文字
安裝freetype到交叉編譯目錄裡(供arm-linux-gcc編譯)
4.1首先檢視,需要安裝到哪個lib和include目錄
1)通過$PATH找到arm-linu-gcc交叉編譯位於:/work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/bin然後進入.../arm/4.3.2/目錄,通過find查詢stdio.h檔案,找到:
所以編譯出來的標頭檔案應該放入:/work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include
2)通過find查詢lib,找到:
由於ARM9屬於ARMv4T架構,所以編譯出來的庫檔案應該放入:/work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib
4.2 安裝
參考:freetype-2.4.10/docs/INSTALL.CROSS
tar -xjf freetype-2.4.10.tar.bz2
mv freetype-2.4.10 freetype-2.4.10_arm
cd freetype-2.4.10_arm
mkdir tmp //建立安裝的臨時目錄,後面會拷貝到交叉編譯目錄裡
./configure --host=arm-linux --prefix=$PWD/tmp //配置交叉編譯,安裝字首
make
make install
cd tmp/
cp ./include/* /work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include/ -rfd
//將include下的標頭檔案拷貝到交叉編譯裡去
cp lib/* /work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/ -rfd
//將lib下的庫檔案拷貝到交叉編譯裡去
cp lib/ * /work/nfs_root/3.4_fs_mini_mdev/lib/ -rfd
//將lib下的庫檔案拷貝到nfs檔案系統去
4.3 寫程式碼(參考上章程式碼和example1.c)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/fb.h>
#include <math.h>
#include<wchar.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
unsigned char *fbmem;
unsigned char *hzkmem;
struct fb_var_screeninfo fb_var;
struct fb_fix_screeninfo fb_fix;
unsigned int screensize;
#define FONTDATAMAX 4096
static const unsigned char fontdata_8x16[FONTDATAMAX] = {
//ASCII碼點陣太長,省略...
};
/*rgb565*/
void pixel_show(int x,int y, unsigned int color)
{
unsigned int red,green,blue;
switch(fb_var.bits_per_pixel) //rgb 畫素
{
case 32:
{
unsigned int *addr=(unsigned int *)fbmem+(fb_var.xres*y+x);
*addr=color;
break;
}
case 24:
{
unsigned int *addr=(unsigned int *)fbmem+(fb_var.xres*y+x);
*addr=color;
break;
}
case 16: //將RGB888 轉為RGB565
{
unsigned short *addr=(unsigned short *)fbmem+(fb_var.xres*y+x);
red = (color >> 16) & 0xff;
green = (color >> 8) & 0xff;
blue = (color >> 0) & 0xff;
color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
*addr = color;
break;
}
case 8:
{
unsigned char *addr=(unsigned char *)fbmem+(fb_var.xres*y+x);
*addr = (unsigned char)color;
break;
}
default:
{
printf("can't surport %dbpp \n",fb_var.bits_per_pixel);
break;
}
}
}
/*顯示ascii碼*/
void lcd_put_char(int x,int y, unsigned char s)
{
unsigned char *index=(unsigned char *)&fontdata_8x16[s*16];
unsigned char i,j;
for(i=0;i<16;i++) //8*16
for(j=0;j<8;j++)
{
//從高位到低
if(index[i]&(1<<(7-j))) //亮
pixel_show(x+j,y+i, 0xffffff); //白色
else //滅
pixel_show(x+j,y+i, 0x0); //黑色
}
}
/*顯示GBK碼*/
void lcd_put_chinese(int x,int y, unsigned char *s)
{
unsigned char i,j,k;
//將編碼轉為區碼
unsigned int index=(s[0]-0xA1)*94+(s[1]-0xA1);
//轉為點陣碼(每個漢字32位元組)
unsigned char *dots=hzkmem+index*32;
for(i=0;i<16;i++) //16*16
for(k=0;k<2;k++)
for(j=0;j<8;j++)
{
if((dots[i*2+k]>>(7-j))&0X01) //亮
pixel_show(x+8*k+j,y+i, 0xffffff); //白色
else //滅
pixel_show(x+8*k+j,y+i, 0x0); //黑色
}
}
void lcd_put(int x,int y, unsigned char *s)
{
while(*s)
{
if(*s<0xA1) //ASCII碼8*16
{
printf("ASCII %x \r\n",*s );
lcd_put_char(x,y,*s);
s+=1;
x+=8;
}
else //GB2313 16*16
{
printf("GBK %x %x\r\n",*s, *(s+1));
lcd_put_chinese(x,y,s);
s+=2;
x+=16;
}
}
}
void draw_bitmap( FT_Bitmap* bitmap,
FT_Int x,
FT_Int y)
{
FT_Int i, j, p, q;
FT_Int x_max = x + bitmap->width; //x:當前X位置, bitmap->width:該字寬度
FT_Int y_max = y + bitmap->rows;
for ( i = x, p = 0; i < x_max; i++, p++ ) //i:lcd的x軸
{
for ( j = y, q = 0; j < y_max; j++, q++ ) //j:lcd的y軸
{
if ( i < 0 || j < 0 ||
i >= fb_var.xres || j >= fb_var.yres )
continue;
pixel_show( i, j, bitmap->buffer[q * bitmap->width + p]);
}
}
}
void lcd_vector_show(char *argv,wchar_t *str)
{
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_Vector pen; /* untransformed origin */
unsigned char error;
unsigned char n,font_size;
error = FT_Init_FreeType( &library ); /* initialize library */
if(error)
{
printf("FT_Init_FreeType ERROR\n");
return ;
}
error = FT_New_Face( library, argv, 0, &face ); /* create face object */
if(error)
{
printf("FT_New_Face ERROR\n");
return ;
}
slot = face->glyph;
/*顯示座標(從LCD中間顯示)
*x=fb_var.xres /2
*y=fb_var.yres-fb_var.yres/2-16 (減16,是因為笛卡爾座標以左下方開始計算座標值的)
*/
pen.x = fb_var.xres /2* 64;
pen.y = ( fb_var.yres/2-16) * 64;
for ( n = 0; n < wcslen(str); n++ )
{
font_size=(n%6)*4+20; // 20*20 24*24 28*28 32*32 36*36 40*40
error = FT_Set_Pixel_Sizes( face, 0,font_size); /* set character size */
FT_Set_Transform( face, 0, &pen );
error = FT_Load_Char( face,str[n], FT_LOAD_RENDER );
if ( error )
{
printf("FT_Load_Char ERROR\n");
continue;
}
draw_bitmap( &slot->bitmap,
slot->bitmap_left,
fb_var.yres- slot->bitmap_top );
pen.x += slot->advance.x;
pen.y += slot->advance.y;
}
FT_Done_Face( face );
FT_Done_FreeType( library );
}
int main(int argc,char **argv)
{
int fd_fb,fd_hzk;
struct stat hzk_start; //HZK16檔案資訊
unsigned char s[]="abc 中國chinese";
wchar_t *chinese_str=L"韋東山g h ";
if ( argc != 2 )
{
printf ("usage: %s font_file \n", argv[0] );
return 0;
}
fd_hzk=open("HZK16",O_RDONLY);
if(fd_hzk<0)
{
printf("can't open HZK16 \n");
return 0;
}
if(fstat(fd_hzk,&hzk_start)<0) //獲取HZK16檔案資訊
{
printf("can't get fstart \n");
return 0;
}
hzkmem =(unsigned char *)mmap(NULL,hzk_start.st_size, PROT_READ,MAP_SHARED,
fd_hzk, 0); //對映HZK16檔案
if(!hzkmem)
{
printf("can't map HZK16 \n");
return 0;
}
fd_fb=open("/dev/fb0", O_RDWR);
if(fd_fb<0)
{
printf("can't open /dev/fb0 \n");
return 0;
}
if(ioctl(fd_fb,FBIOGET_VSCREENINFO,&fb_var)<0)
{
printf("can't get var \n");
return 0;
}
if(ioctl(fd_fb,FBIOGET_FSCREENINFO,&fb_fix)<0)
{
printf("can't get fix \n");
return 0;
}
screensize=fb_var.xres*fb_var.yres*(fb_var.bits_per_pixel/8); //視訊記憶體大小
fbmem =(unsigned char *)mmap(NULL,screensize, PROT_READ|PROT_WRITE,MAP_SHARED,
fd_fb, 0); //對映fb0
if(!fbmem)
{
printf("can't map /dev/fb0 \n");
return 0;
}
memset(fbmem, 0, screensize); //清屏黑色
/*顯示資料*/
lcd_put(0,fb_var.yres/2,s);
/*顯示向量文字*/
lcd_vector_show(argv[1], chinese_str);
munmap(hzkmem,hzk_start.st_size);
munmap(fbmem,screensize);
return 0;
}
4.4 編譯程式
編譯報錯: 56:38: error: freetype/config/ftheader.h: No such file or directory
通過find找到ftheader.h的位置是位於:../include/freetype2/freetype/config/ftheader.h
輸入:
cd ./arm-none-linux-gnueabi/libc/usr/include/freetype2
mv freetype/ ../freetype //將freetype2下的freetype移到include目錄下
編譯:
arm-linux-gcc -o show_font show_font.c -lfreetype -lm -finput-charset=GBK -fexec-charset=GBK
執行:
(發現,顯示16*16字型時,會亂碼, 新宋字型simsun不支援16點陣大小的字型)