3.數位相框-通過freetype庫實現矢量顯示

来源:https://www.cnblogs.com/lifexy/archive/2018/03/03/8503070.html
-Advertisement-
Play Games

本章主要內容如下: 1)矢量字體原理 2)使用freetype庫實現矢量字體顯示 1. 矢量字體原理 將漢字的筆劃邊緣用直線段描述成封閉的曲線,並將線段各端點的坐標經壓縮存儲,如下圖所示: 由於每個漢字的筆劃不一樣,從而每個漢字數據長度也不同,所以只能採用索引的方法。因而每種矢量字型檔都是由兩部分組成 ...


本章主要內容如下:

  • 1)矢量字體原理
  • 2)使用freetype庫實現矢量字體顯示

 


 

1. 矢量字體原理

   將漢字的筆劃邊緣用直線段描述成封閉的曲線,並將線段各端點的坐標經壓縮存儲,如下圖所示:

       

 

                                       

由於每個漢字的筆劃不一樣,從而每個漢字數據長度也不同,所以只能採用索引的方法。因而每種矢量字型檔都是由兩部分組成,一部分是漢字的索引信息,一部分是漢字的字形(glyph)數據.

當顯示文字時,便提取出各端點,並通過貝塞爾曲線來連接各個坐標,最後填充封閉空間.

接下來便使用freetype庫製作矢量字體

2. freetype-2.4.10庫

freetype庫是一個開源的字體引擎,支持多種字元集編碼(utf-8等).

freetype庫下載: https://sourceforge.net/projects/freetype/files/freetype2/2.4.10/

freetyoe英文參考文檔下載:https://sourceforge.net/projects/freetype/files/freetype-docs/2.4.10/

 FreeType 中文使用參考:

http://wenku.baidu.com/view/2d24be10cc7931b765ce155b.html

https://wenku.baidu.com/view/e7149f6748d7c1c708a14574.html

 

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)設置字體大小(參考freetype-2.4.10/docs/reference/ft2-base_interface.html):

方法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中

 

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[]里的一個位元組.

 

2.2參考example1.c常式

example1.c位於freetype-doc-2.4.10.tar.bz2\freetype-2.4.10\docs\tutorial下

 

3.在PC虛擬機里編譯常式:example1.c

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                                 //配置

make                                        //編譯

sudo make install                           //直接將庫安裝到根目錄/usr/local/里,所以需要加sudo

由於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;                                //在坐標(0,40)處顯示
  pen.y = ( target_height - 40 ) * 64;

 

3.2 編譯運行

gcc -o example1 example1.c

編譯出錯:

 

通過ls,發現又有這個文件:

 

 

所以通過-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,在linux4bytes.

寬字元: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

 

4.在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文件系統去

為什麼不拷貝頭文件? 因為編譯好了freetype程式後,頭文件會被gcc展開存到可執行文件里,所以運行時,只會用到庫文件.

 

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點陣大小的字體)

 

下章學習:

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 經常用到的一個知識點,每次用到就去百度一下,今天又用到了(又跑去擺渡了),為了防止用完就忘,用到就搜,今天自己記錄一下。 如何根據分隔符(比如逗號),將List<string>泛型集合合併成一個string字元串?以往的開發中,都是使用迴圈的方式來拼接成字元串,不僅要寫更多的代碼不說,還會消耗更多的 ...
  • 首先聲明,本文寫的有點粗糙,只讓你瞭解什麼是協變和逆變,沒有深入研究,根據這些年的工作經驗,發現我們在開發過程中,很少會自己去寫逆變和協變,因為自從net 4.0 (Framework 3.0) 以後,.net 就為我們提供了 定義好的逆變與協變。我們只要會使用就可以。協變和逆變都是在泛型中使用的。 ...
  • 一,什麼是NPOI 該項目是位於http://poi.apache.org/的POI Java項目的.NET版本。POI是一個開源項目,可以幫助您讀取/寫入xls,doc,ppt文件。它有著廣泛的應用。 二,NPOI的優勢 一個。它完全免費使用 灣 涵蓋Excel的大部分功能(單元格樣式,數據格式, ...
  • 從2012年4月份工作至今,做過大小各種項目差不多有20來個,最近有認識的好友, 轉行學軟體開發,我向他推薦了C#. 藉此機會, 我也好好從頭整理一下C#. 工欲善其事,必先利其器. VS IDE 宇宙第一, 這個毫無疑問. 然後VS裡面可以附帶一些小插件, 我覺得這樣能更好的輔助我們開發. 下麵是 ...
  • 如果你用MVC寫過程式,那麼你應該知道ViewBag這個用於前後臺的數據傳遞工具,那麼你是否對ViewBag的用法感到過疑惑呢? 我們知道,在使用對象屬性的時候要先申明(即這個對象的類中已經定義了這個屬性)才能使用(此時VS的自動提示能彈出此類的所有屬性),然而使用ViewBag時你會發現 View ...
  • #region CheckBox與TextBox綁定 Dictionary<CheckBox, TextBox> CheckTextBoxDic = new Dictionary<CheckBox, TextBox>(); //找到控制項下所有勾選框並與其相對應的文本框綁定 private void ...
  • #region 通過當前代碼執行路徑向上找到相關exe,並根據processes.Length判斷是否已啟動 private bool CheckAndOpenExe(string exeName) { Process[] processes = Process.GetProcessesByName ...
  • 在Asp.net MVC 3 web應用程式中,我們會用到ViewData與ViewBag,對比一下: 在Controller中使用ViewData: 對應UsingViewData View的cshtml: 然後是ViewBag: 對應View UsingViewBag 的cshtml的ViewB ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...