歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux下利用FreeType2的API實現字符的顯示

網上的FreeType2例子太少,能顯示漢字的比較難找,C語言代碼寫的更難找,能找到的,基本上是被轉載了N遍的同一個示例代碼,基本上解決不了我的問題。

於是乎,花費了不少時間才完成了這些代碼;

主要功能是:

將傳入的GB2312編碼的char型字符串轉換成圖片數組並輸出。

主要原理是:

將GB2312編碼的char型字符串,轉換成unicode編碼的wchar_t型字符串;

之後,利用FreeType2的API獲取漢字的字體位圖。

代碼看似不怎麼復雜,之前找char轉wchar_t的代碼,沒找到一個合適的,最後呢,東拼西湊,就得到了想要的代碼;

還有,輸出的是記錄每個像素點的256級灰度的數組,也就是和png圖片中alpha通道一樣,0 - 255表示透明度, 0為完全透明,255為不透明;

想要將這些文字貼到圖片上,有個公式:

r2 = (r1 * alpha + r2 * (255 - alpha)) /255;
g2 = (g1 * alpha + g2 * (255 - alpha)) /255;
b2 = (b1 * alpha + b2 * (255 - alpha)) /255;

r、g、b表示圖片的red、green、blue三種顏色,這三種顏色通過組合可以變成不同的顏色;

alpha是文字位圖的alpha通道; 

r2、b2、g2是圖片重疊後該像素點顯示的顏色;
r1、b1、g1是文字位圖的每個像素點顯示的顏色。

相關信息請參考這篇文章:http://www.linuxidc.com/Linux/2012-01/52144.htm

有需要這些代碼的人的話,請把代碼改一下,因為這是從我的LCUI圖形庫的代碼中復制過來的,不能直接使用。

[cpp]
  1. #include "LCUI_Build.h"   
  2. #include LCUI_MAIN_H   
  3. #include LCUI_FONTS_H    
  4. #include "all.h"   
  5.   
  6. /*代碼轉換:從一種編碼轉為另一種編碼*/  
  7. int code_convert(char *from_charset,char *to_charset,const char *inbuf,unsigned int inlen,  
  8. unsigned char *outbuf,unsigned int outlen)  
  9. {  
  10.     iconv_t cd;  
  11.     const char **pin = &inbuf;  
  12.     unsigned char **pout = &outbuf;  
  13.     cd = iconv_open(to_charset,from_charset);  
  14.     if (cd==0) return -1;  
  15.     memset(outbuf,0,outlen);  
  16.     if (iconv(cd,(char**)pin,&inlen,(char**)pout,&outlen)==-1) return -1;  
  17.     iconv_close(cd);  
  18.     return 0;  
  19. }  
  20.   
  21. /*GB2312碼轉為utf-8碼*/  
  22. int GB2312_To_UTF8(const char *inbuf,unsigned int inlen,unsigned char *outbuf,unsigned int outlen)  
  23. {  
  24.     return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);  
  25. }  
  26.   
  27. unsigned short Get_Unicode(char *in_gb2312)  
  28. {  
  29.     unsigned char out[256];  
  30.     int rc;  
  31.     unsigned int length_gb2312;  
  32.   
  33.     /* gb2312碼轉為utf8碼 */  
  34.     length_gb2312 = strlen(in_gb2312);  
  35.     rc = GB2312_To_UTF8(in_gb2312,length_gb2312,out,256);  
  36.   
  37.     /* utf8轉unicode碼 */  
  38.     unsigned short unicode;  
  39.     unicode = out[0];  
  40.     if (unicode >= 0xF0) {  
  41.         unicode = (unsigned short) (out[0] & 0x07) << 18;  
  42.         unicode |= (unsigned short) (out[1] & 0x3F) << 12;  
  43.         unicode |= (unsigned short) (out[2] & 0x3F) << 6;  
  44.         unicode |= (unsigned short) (out[3] & 0x3F);  
  45.     } else if (unicode >= 0xE0) {  
  46.         unicode = (unsigned short) (out[0] & 0x0F) << 12;  
  47.         unicode |= (unsigned short) (out[1] & 0x3F) << 6;  
  48.         unicode |= (unsigned short) (out[2] & 0x3F);  
  49.     } else if (unicode >= 0xC0) {  
  50.         unicode = (unsigned short) (out[0] & 0x1F) << 6;  
  51.         unicode |= (unsigned short) (out[1] & 0x3F);  
  52.     }  
  53.     return unicode;  
  54. }  
  55.   
  56.   
  57.   
  58.   
  59. int Show_Font_Bitmap(Font_Bitmap_Data *in_fonts)  
  60. /* 功能:在屏幕上以0和1表示字體位圖 */  
  61. {  
  62.     int x,y;  
  63.     for(y=0;y<in_fonts->height;++y){  
  64.         for(x=0;x<in_fonts->width;++x){  
  65.             if(in_fonts->text_alpha[y*in_fonts->width+x]>0)  
  66.             printf("1");  
  67.             else printf("0");  
  68.         }  
  69.         printf("\n");  
  70.     }  
  71.     printf("\n");  
  72.     return 0;  
  73. }  
  74.   
  75.   
  76.   
  77.   
  78. int Get_Fonts_Bitmap(  
  79. char *font_file,             /* 字體文件路徑 */  
  80. char *in_text,               /* 輸入的字符串 */  
  81. int fonts_pixel_size,        /* 字體大小 */  
  82. int space,                   /* 間距 */  
  83. Font_Bitmap_Data *out_fonts  /* 輸出的位圖數據,Pic_Data是結構體 */  
  84. )  
  85. /* ****************************************** */  
  86. /* 根據傳入的字體庫路徑、字符串、字體尺寸,輸 */  
  87. /* 出該字符串的位圖數組                       */  
  88. /* 本函數使用了freetype2的API                 */  
  89. /* ****************************************** */  
  90. {  
  91.     FT_Library         p_FT_Lib = NULL;    /* 庫的句柄  */  
  92.     FT_Face            p_FT_Face = NULL;      /* face對象的句柄 */  
  93.     FT_Error           error = 0;  
  94.     FT_Bitmap          bitmap;  
  95.     FT_BitmapGlyph     bitmap_glyph;  
  96.     FT_Glyph           glyph;  
  97.     FT_GlyphSlot       slot;  
  98.     int i , j ,temp,num,bg_height;  
  99.     char error_str[200];  
  100.     error = FT_Init_FreeType( & p_FT_Lib);  /* 初始化FreeType庫 */  
  101.     if (error)   /* 當初始化庫時發生了一個錯誤 */  
  102.     {  
  103.         p_FT_Lib = 0 ;  
  104.         printf(FT_INIT_ERROR);  
  105.         return - 1 ;  
  106.     }  
  107.     /* 從字體庫文件中獲取字體 */  
  108.     error = FT_New_Face(p_FT_Lib, font_file , 0 , & p_FT_Face);  
  109.     if ( error == FT_Err_Unknown_File_Format )   
  110.     {   
  111.         printf(FT_UNKNOWN_FILE_FORMAT); /* 未知文件格式 */  
  112.         return - 1 ;  
  113.     }   
  114.     else if (error)  
  115.     {  
  116.         printf(FT_OPEN_FILE_ERROR);/* 打開錯誤 */  
  117.         perror("FreeeType2");  
  118.         return - 1 ;  
  119.     }  
  120.     j = 0;  
  121.     wchar_t *unicode_text;/* 用於存儲unicode字符 */  
  122.     char ch[256];  
  123.     unicode_text = (wchar_t*)calloc(1,sizeof(wchar_t)*(strlen(in_text)*2));/* 申請內存 */  
  124.     for(i=0;i<strlen(in_text);++i){  
  125.         memset(ch,0,sizeof(ch));  /* 所有元素置零 */  
  126.         ch[0] = in_text[i];  /* 獲取in_text中的第i個元素 */  
  127.         if(ch[0] < 0) {   
  128.             /* GB2312編碼的漢字,每byte是負數,因此,可以用來判斷是否有漢字 */  
  129.             if(i < strlen(in_text)-1){/* 如果沒有到字符串末尾 */  
  130.                 ch[1] = in_text[i+1];  
  131.                 ++i;  
  132.             }  
  133.             else break;  
  134.         }  
  135.         unicode_text[j] = Get_Unicode(ch);  /* 開始轉換編碼 */  
  136.         ++j;  
  137.     }  
  138.     num = j; /* 記錄字符的數量 */  
  139.       
  140.     int start_x = 0,start_y = 0;  
  141.     int ch_height = 0,ch_width = 0;  
  142.     int k,text_width = 0;  
  143.     size_t size = 0;  
  144.     unsigned char **text_alpha;   
  145.     bg_height = fonts_pixel_size+5; /* 背景圖形的高度,這個高度要大於字體的高度,所以是+5 */  
  146.     /* 分配內存,用於存儲字體背景圖的數據 */  
  147.     text_alpha = (unsigned char**)malloc(sizeof(unsigned char*)*bg_height);   
  148.     for(i=0;i<bg_height;++i){  
  149.     /* 預先為背景圖的每一行分配內存 */  
  150.         text_alpha[i] = (unsigned char*)malloc(sizeof(unsigned char)*1);   
  151.     }  
  152.     FT_Select_Charmap(p_FT_Face,FT_ENCODING_UNICODE);   /* 設定為UNICODE,默認的也是 */  
  153.     FT_Set_Pixel_Sizes(p_FT_Face,0,fonts_pixel_size);   /* 設定字體大小 */  
  154.   
  155.     slot = p_FT_Face->glyph;  
  156.     for(temp=0;temp<num;++temp){  
  157.         /* 開始遍歷unicode編碼的字符串中的每個元素  */  
  158.         /* 這個函數只是簡單地調用FT_Get_Char_Index和FT_Load_Glyph */  
  159.         error = FT_Load_Char( p_FT_Face, unicode_text[temp],  FT_LOAD_RENDER | FT_LOAD_NO_AUTOHINT);   
  160.         if(!error){  
  161.             /* 從插槽中提取一個字形圖像 */  
  162.             /* 請注意,創建的FT_Glyph對象必須與FT_Done_Glyph成對使用 */  
  163.             error = FT_Get_Glyph(p_FT_Face -> glyph, &glyph);  
  164.             if (!error)  
  165.             {  
  166.                 if(unicode_text[temp] == ' ') {  
  167.                     /* 如果有空格 */  
  168.                     k = 0;  
  169.                     ch_width   = (fonts_pixel_size -2)/2;  
  170.                     ch_height  = fonts_pixel_size;  
  171.                     text_width = start_x + ch_width;  
  172.                     start_y = 0;  
  173.                     for(i=0;i<bg_height;++i){  
  174.                         text_alpha[i] = (unsigned char*)realloc(text_alpha[i],sizeof(unsigned char)*text_width);  
  175.                         for(j=start_x-space;j<text_width;++j) text_alpha[i][j] = 0;  
  176.                     }  
  177.                     for ( i = 0 ; i < ch_height; ++i)  
  178.                     {  
  179.                         for ( j = 0 ; j < ch_width; ++j)  
  180.                         {  
  181.                             text_alpha[start_y + i][start_x + j] = 0;  
  182.                             ++k;  
  183.                         }  
  184.                     }  
  185.                     start_x += (ch_width+space); /* 畫筆向右邊移動 */  
  186.                 }  
  187.                 else{  
  188.                     /* 256級灰度字形轉換成位圖 */  
  189.                     FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0 ,1);  
  190.                     /* FT_RENDER_MODE_NORMAL       這是默認渲染模式,它對應於8位抗鋸齒位圖。 */  
  191.                     bitmap_glyph = (FT_BitmapGlyph)glyph;  
  192.                     bitmap       = bitmap_glyph -> bitmap;  
  193.                     k = 0;  
  194.                       
  195.                     start_y = fonts_pixel_size - slot->bitmap_top + 2; /* 獲取起點的y軸坐標 */  
  196.                     if(start_y < 0) start_y = 0;  
  197.                     if(bitmap.rows > bg_height) ch_height = fonts_pixel_size;  
  198.                     else ch_height = bitmap.rows;  
  199.                     if(ch_height+start_y > bg_height) ch_height = bg_height - start_y;  
  200.                     ch_width = bitmap.width;  
  201.                       
  202.                     text_width = start_x + bitmap.width;  
  203.                     for(i=0;i<bg_height;++i){  
  204.                     /* 動態擴增存儲字體位圖的背景圖形占用的空間 */  
  205.                         text_alpha[i] = (unsigned char*)realloc(text_alpha[i],sizeof(unsigned char)*text_width);  
  206.                         for(j=start_x-space;j<text_width;++j) text_alpha[i][j] = 0;/* 多出來的空間全部置零 */  
  207.                     }  
  208.                     /* 開始將字體位圖貼到背景圖形中 */  
  209.                     for(i = 0; i < bg_height; ++i){   
  210.                         for(j = 0;j < ch_width; ++j){  
  211.                             if(i >= start_y && i < start_y + ch_height){  
  212.                             /* 如果在字體位圖的范圍內 */  
  213.                                 text_alpha[i][start_x + j] = bitmap.buffer[k];  
  214.                                 ++k;  
  215.                             }  
  216.                             else text_alpha[i][start_x + j] = 0;/* 否則就置零 */  
  217.                         }  
  218.                     }  
  219.                     start_x += (ch_width+space); /* 畫筆向右邊移動 */  
  220.                     /* 釋放字形占用的內存 */  
  221.                     FT_Done_Glyph(glyph);  
  222.                     glyph = NULL;  
  223.                 }  
  224.             }  
  225.             else{  
  226.                 sprintf(error_str,"FreeType2 錯誤[%d]",error);  
  227.                 perror(error_str);  
  228.             }  
  229.         }  
  230.         else{  
  231.             sprintf(error_str,"FreeType2 錯誤[%d]",error);  
  232.             perror(error_str);  
  233.         }  
  234.     }  
  235.     /* 釋放face占用的內存 */  
  236.     FT_Done_Face(p_FT_Face);  
  237.     p_FT_Face = NULL;  
  238.     /* 釋放FreeType Lib占用的內存 */  
  239.     FT_Done_FreeType(p_FT_Lib);  
  240.     p_FT_Lib = NULL;    
  241.     temp = 0;  
  242.     out_fonts->width    = text_width;          /* 要輸出的位圖的寬度 */  
  243.     out_fonts->height   = bg_height;           /* 要輸出的位圖的高度 */  
  244.     if(out_fonts->malloc == IS_TRUE) free(out_fonts->text_alpha);  
  245.     size = sizeof(unsigned char) * text_width * bg_height;  
  246.     out_fonts->text_alpha = (unsigned char*)calloc(1,size);   /* 申請內存用來存儲 */  
  247.     k = 0;  
  248.     for ( i = 0 ; i < bg_height; ++i)  
  249.     {  
  250.         for ( j = 0 ; j < text_width; ++j)  
  251.         {  
  252.             out_fonts->text_alpha[k] = text_alpha[i][j];  
  253.             ++k;  
  254.         }  
  255.     }  
  256.     out_fonts->malloc = IS_TRUE;  
  257.     /* 釋放內存 */  
  258.     for(i=0;i<bg_height;++i){  
  259.         free(text_alpha[i]);  
  260.     }  
  261.     free(text_alpha);  
  262.     free(unicode_text);  
  263.     return 0;  
  264. }  

這些代碼在我的工程裡的運行效果:

Copyright © Linux教程網 All Rights Reserved