源碼: https://sourceforge.net/projects/freetype/files/freetype2
- 下載解壓后,進(jìn)入源碼目錄執(zhí)行cmake-gui,界面中配置源碼目錄與編譯目錄,然后點(diǎn)擊左下角Configure。
- 界面中FT_DISABLE_BROTLI、FT_DISABLE_BZIP2、FT_DISABLE_HARFBUZZ、FT_DISABLE_PNG、FT_DISABLE_ZLIB全部選中。
- 再次點(diǎn)擊Configure,點(diǎn)擊Generate。
- 進(jìn)入配置的編譯目錄,執(zhí)行make命令即可編譯出靜態(tài)庫。
- 編輯CMakeLists.txt,找到"add_library(freetype"這一行,改為 "add_library(freetype SHARED",保存后重新執(zhí)行cmake-gui,Configure、Gernerate,進(jìn)入編譯目錄執(zhí)行make命令后即可編譯出動(dòng)態(tài)庫。
以下為測(cè)試代碼。
#include <stdio.h>
#include <string.h>
#include <freetype/freetype.h>
#include <freetype/ftoutln.h>
#include <freetype/ftglyph.h>
int main(int argc, char* argv[])
{
FT_Library library;
FT_Face face;
FT_Vector pen;
FT_Error error;
FT_UInt charIdx;
wchar_t wch_data[] = L"pp happy, new year!!!\n天地轉(zhuǎn),光陰迫,一萬年太久,只爭(zhēng)朝夕!";//u'Z', U'Z'
char* char_buffer; // 用戶申請(qǐng)的顯示區(qū)域空間
int startX, startY; // 字符圖像開始裝入的位置
char *font_file = "simfang.ttf";
int font_width = 32;//
int font_height = 32;//!!!
printf("sizeof(wchar_t) = %ld\n", sizeof(wchar_t));
/*
1.在windows平臺(tái)下sizeof(wchar_t)為2,而在linux平臺(tái)下sizeof(wchar_t)為4。
2.在windows平臺(tái)下寬字符(或字符串)字面量使用UTF-16編碼,linux平臺(tái)下使用UTF-32編碼。
*/
if(argc <= 1){
}else if(argc <= 2){
font_file = argv[1];
}else if(argc <= 3){
font_file = argv[1];
font_width = atoi(argv[2]);
font_height = atoi(argv[2]);
}else if(argc <= 4){
font_file = argv[1];
font_width = atoi(argv[2]);
font_height = atoi(argv[3]);
}
// 1. 初始化freetype2庫
error = FT_Init_FreeType(&library);
// 2. 創(chuàng)建一個(gè)face
error = FT_New_Face(library, font_file, 0, &face);
// 3. 設(shè)置字體尺寸
#if 0
/*
字符寬度和高度以1/64點(diǎn)為單位表示。點(diǎn)是物理上的距離,一個(gè)點(diǎn)代表1/72英寸(2.54cm)
分辨率以dpi(dots per inch)為單位表示,表示一個(gè)英寸有多少個(gè)像素
字符物理大小為: char_width*64* (1/64) * (1/72)英寸
字符的像素為: char_width*64* (1/64) * (1/72)*horz_resolution
FT_Set_Char_Size( FT_Face face,
FT_F26Dot6 char_width, //字符寬度,單位為1/64點(diǎn)
FT_F26Dot6 char_height, //字符高度,單位為1/64點(diǎn)
FT_UInt horz_resolution, //水平分辨率
FT_UInt vert_resolution ); //垂直分辨率
*/
error = FT_Set_Char_Size(face, 0, font_height*64, 72, 72);
#else
error = FT_Set_Pixel_Sizes(face, font_width, font_height);
#endif
//斜體在FreeType中可以通過矩陣變換來實(shí)現(xiàn),只要把矩陣設(shè)置成一個(gè)切邊矩陣就可以了
// 傾斜度,越大就越斜
float lean = 0.6f;
FT_Matrix matrix;
matrix.xx = 0x10000L;
matrix.xy = lean * 0x10000L;
matrix.yx = 0;
matrix.yy = 0x10000L;
//FT_Set_Transform(face, &matrix, 0);
//pen.x = img_x*64;
//pen.y = (img_y)*64;//
pen.x = 0;
pen.y = 0;
FT_Set_Transform(face, &matrix, &pen);
//error = FT_Select_Charmap(fontFace, FT_ENCODING_UNICODE);
//error = FT_Select_Charmap(face, FT_ENCODING_BIG5 ); /* big5編碼 , 默認(rèn)為UNICODE */
//error = FT_Set_Transform( face, &matrix, &pen );//旋轉(zhuǎn)
char bitmap_file[256];
int img_width = 320;
int img_height = 240;
int img_x = 0;
int img_y = 0;
char *bitmap_buffer = malloc(img_width*img_height);
memset(bitmap_file, 0, sizeof(bitmap_file));
sprintf(bitmap_file, "bitmap_%d_%d_gray.yuv", img_width, img_height);
FILE *pBitMapFd = fopen(bitmap_file, "wb");
for(int index = 0; index < sizeof(wch_data)/sizeof(wch_data[0]); index++){
wchar_t wch = wch_data[index];
if(wch == 0){
break;
}else if(wch == U'\r'){
img_x = 0;
continue;
}else if(wch == U'\n'){
img_x = 0;
img_y += font_height;
continue;
}
#if 0
// 4. 獲取字符圖像索引
charIdx = FT_Get_Char_Index(face, wch);
// 5. 加載字符圖像
FT_Load_Glyph(face, charIdx, FT_LOAD_DEFAULT);
if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
{
FT_Outline_Embolden(&(face->glyph->outline), 16); // 加粗輪廓線
}
// 6. 獲取字符位圖
if (face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
{
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
}
#else
error = FT_Load_Char(face, wch, FT_LOAD_RENDER);//FT_LOAD_MONOCHROME 8pixel per byte
#endif
/*
FT_Bitmap(字形位圖對(duì)象):
rows: 位圖行數(shù)(高度)
width: 位圖寬度
buffer: 位圖數(shù)據(jù)(默認(rèn)8位灰度值)
*/
FT_Glyph glyph;
FT_BBox acbox;
FT_GlyphSlot slot = face->glyph;
error = FT_Get_Glyph(face->glyph, &glyph);
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &acbox);
int lcd_x_min = acbox.xMin;
int lcd_x_max = acbox.xMax;
int lcd_y_min = font_height - acbox.yMax;
int lcd_y_max = font_height - acbox.yMin;
lcd_y_min -= (font_height/8);
lcd_y_max -= (font_height/8);
printf("0x%x: xMin=%ld, xMax=%ld, yMin=%ld, yMax=%ld, V-yMin = %ld, v-yMax = %ld, advance x = %ld, advance y = %ld, w = %d, h = %d, left = %d, top = %d\n", \
wch, acbox.xMin, acbox.xMax, acbox.yMin, acbox.yMax, font_height - acbox.yMax, font_height - acbox.yMin, slot->advance.x, slot->advance.y, \
slot->bitmap.width, slot->bitmap.rows, slot->bitmap_left, slot->bitmap_top);
int wch_h_size = (slot->advance.x/64)>=slot->bitmap.width ? (slot->advance.x/64) : slot->bitmap.width;
if(img_x + wch_h_size >= img_width){
img_x = 0;
img_y += font_height;
}
if(img_y + font_height >= img_height){
img_y = 0;
break;//
}
for(int j = 0; j < slot->bitmap.rows; j++){
for(int i = 0; i < slot->bitmap.width; i++){
if(slot->bitmap.buffer[j*slot->bitmap.width + i]){
#if 1//
//if(lcd_x_min < 0){
if(img_x + lcd_x_min + i < 0){
bitmap_buffer[img_width*img_y + img_x + (j+lcd_y_min)*img_width + i] = slot->bitmap.buffer[j*slot->bitmap.width + i];
}else
#endif
{
bitmap_buffer[img_width*img_y + img_x + (j+lcd_y_min)*img_width + i + lcd_x_min] = slot->bitmap.buffer[j*slot->bitmap.width + i];
}
}
}
}
img_x += slot->advance.x/64;
//img_x += wch_h_size;
}
fwrite(bitmap_buffer, 1, img_width*img_height, pBitMapFd);
fclose(pBitMapFd);
FT_Done_Face(face);
FT_Done_FreeType(library);
printf("-------------- end ----------------\n");
}
預(yù)覽生成的yuv數(shù)據(jù)
ffplay -i bitmap_320_240_gray.yuv -pixel_format gray -video_size 320*240

ffplay顯示結(jié)果.png