freetype的介绍各种博客都有,可以搜索看看。
freetype2.8的源码及编译出的库及头文件链接:/download/weixin_40550094/12117925
我这边就直接写demo,本demo可以生成带颜色的bitmap;
使用freetype显示一个字符简单,网上示例也很多,但是将整屏的数据都一起传递给freetype,让其生成整屏完整的bitmap,网上几乎没有找到,再加上字体的渲染,就更少之有少,本问应用是24行40列的电视图文显示使用,也会提供本范例编译出来的freetype库文件及头文件的连接。
本范例实现整屏数据整体转换,整体渲染字色,大小和间距需要按需调整,可以NewFTString中调整;
FT_Set_Char_Size设置大小及分辨率;
#include "ftglyph.h"
#include "freetype.h"
#include <sys/stat.h>
static S32 indexLength = 0;
#define WIDTH_TTX 1280
#define HEIGHT_TTX 720
#define MAX_GLYPHS 1024
/* origin is the upper left corner */
#define dataLength (24 * 40)
static U32 dataIndexBuf[dataLength];
unsigned char* imageBuffer;
static FT_Face pFTFace;
static FT_Library library;
typedef struct FTCode_ {
FT_ULong code;
char utf8str[8];
}FTCode;
typedef struct FTStrImage {
unsigned int width;
unsigned int height;
unsigned char* imageBuffer;
}FTStrImage;
typedef struct TGlyph_
{
FT_UInt index;
FT_Vector pos;
FT_BBox drawBox;
FT_Glyph glyph;
} TGlyph, *PGlyph;
typedef struct {
unsigned char* image;
unsigned int width;
unsigned int height;
unsigned int strLen;
}FTString;
struct color_ttx
{
U8 blue;
U8 green;
U8 red;
};
color_ttx color_BITMAP[6]
{
{0x00,0x00,0xff},/**red*/
{0x00,0xFF,0x00},/**green**/
{0xFF,0x00,0x00},/**blue**/
{0x00,0x00,0x00},/**black**/
{0xFF,0xFF,0xFF},/**white**/
{0x00,0xFF,0xFF}/**yellow**/
};
static FTStrImage strim;
S32 initFontLib()
{
FT_Error error = FT_Init_FreeType(&library);
if (error)
{
LOGE("error = %d\n", error);
return 0;
}
error = FT_New_Face(library, "/factory/atv/font/文件名.ttf", 0, &pFTFace);
if (error == FT_Err_Unknown_File_Format )
{
LOGE(" ERROR: fonts not support format!\n");
return 0;
}
else if (error)
{
LOGE("ERROR: fonts file cannot open!\n");
return 0;
}
return 0;
}
S32 deInitFontLib()
{
//free face?
FT_Done_Face(pFTFace);
pFTFace = NULL;
free(pFTFace);
//free FreeType Lib
FT_Done_FreeType(library);
library = NULL;
return 0;
}
FTStrImage NewFTString()
{
FT_Error error;
FT_Set_Char_Size(pFTFace,16 << 6,16 << 6 ,120,120);
FT_GlyphSlot slot = pFTFace->glyph;
FT_UInt glyph_index = 0;
FT_Bool use_kerning = FT_HAS_KERNING(pFTFace);
FT_UInt previous = 0;
FTCode* codes = 0;
U32 spacing = 10;
int pen_x = 0;
int pen_y = 0;
TGlyph glyphs[MAX_GLYPHS];
FT_UInt num_glyphs = 0;
FT_BBox bbox;
U32 charSpace = 20;
bbox.xMin = bbox.yMin = 100000;
bbox.xMax = bbox.yMax = -100000;
PGlyph glyph = glyphs;
U32 line = 23;
LOGE("use_kerning = %d",use_kerning);
for( unsigned int n = 0; n < indexLength; n++)
{
FT_BBox glyph_bbox;
memset(&glyph_bbox,0x00,sizeof(glyph_bbox));
if((n%40 == 0) && (n != 0))
{
pen_y = spacing + pen_y + 10;
pen_x = 0;
line--;
}
glyph->index = FT_Get_Char_Index(pFTFace, dataIndexBuf[dataLength - (24 - line)*40 + n %40]);
if ( use_kerning && previous && glyph->index)
{
FT_Vector delta;
FT_Get_Kerning(pFTFace, previous, glyph->index,
FT_KERNING_DEFAULT, &delta );
pen_x += delta.x >> 6;
LOGE("pen_x = %d delta.x = %d\n",pen_x,delta.x);
}
glyph->pos.x = pen_x;
glyph->pos.y = pen_y;
error = FT_Load_Glyph(pFTFace, glyph->index, FT_LOAD_DEFAULT);
if ( error )
{
LOGE("ERROR: FT_Load_Glyph\n");
}
error = FT_Get_Glyph(pFTFace->glyph, &glyph->glyph);//装载一个新的字形图像到字形槽,前面装载的将会从字形槽中抹去
if ( error )
{
LOGE("ERROR: FT_Get_Glyph!\n");
}
pen_x += slot->advance.x >> 6;
previous = glyph->index;
FT_Glyph_Get_CBox(glyph->glyph, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);
//LOGE("pos.x = %d,pos.y = %d,,previous = %d",glyph->pos.x,glyph->pos.y,previous);
glyph_bbox.xMin += glyph->pos.x;
glyph_bbox.xMax += glyph->pos.x;
glyph_bbox.yMin += glyph->pos.y;
glyph_bbox.yMax += glyph->pos.y;
if(n == 0)
{
spacing = glyph_bbox.yMax;//用于保存字符的行高
}
if (glyph_bbox.xMin < bbox.xMin)
{
bbox.xMin = glyph_bbox.xMin;
}
if (glyph_bbox.yMin < bbox.yMin)
{
bbox.yMin = glyph_bbox.yMin;
}
if (glyph_bbox.xMax > bbox.xMax)
{
bbox.xMax = glyph_bbox.xMax;
}
if (glyph_bbox.yMax > bbox.yMax)
{
bbox.yMax = glyph_bbox.yMax;
}
//LOGE("[%d %d %d %d]\n", glyph_bbox.xMin, glyph_bbox.yMin, glyph_bbox.xMax, glyph_bbox.yMax);
glyph->drawBox = glyph_bbox;
glyph++;
}
num_glyphs = glyph - glyphs;
if ( bbox.xMin > bbox.xMax )
{
bbox.xMin = 0;
bbox.yMin = 0;
bbox.xMax = 0;
bbox.yMax = 0;
}
unsigned int width = bbox.xMax+1;
unsigned int height = bbox.yMax-bbox.yMin+1;
unsigned int start_x = 0;
unsigned int start_y = 0;
LOGE("width = %d height = %d \n", width, height);
for ( unsigned int n = 0; n < indexLength; n++)
{
PGlyph pplyph = glyphs+n;
FT_Vector pen = glyph->pos;
error = FT_Glyph_To_Bitmap(&pplyph->glyph, FT_RENDER_MODE_NORMAL, &pen, 0);
if ( !error )
{
FT_BitmapGlyph bit = (FT_BitmapGlyph)pplyph->glyph;
start_x = pplyph->drawBox.xMin;
start_y = height - (pplyph->drawBox.yMin-bbox.yMin+bit->bitmap.rows);
for (unsigned int y = 0; y < bit->bitmap.rows; y++)
{
for (unsigned int x = 0; x < bit->bitmap.width; x++)
{
unsigned int iy = start_y + y;
unsigned int ix = start_x + x;
unsigned int index = (iy*width + ix)*4;
imageBuffer[index] = color_BITMAP[4].blue;
imageBuffer[index+1] = color_BITMAP[4].green;
imageBuffer[index+2] = color_BITMAP[4].red;
imageBuffer[index+3] = bit->bitmap.buffer[y * bit->bitmap.width + x];
}
}
FT_Done_Glyph(pplyph->glyph);
}
}
//free codes
free(codes);
strim.width = width;
strim.height = height;
strim.imageBuffer = imageBuffer;//release after
return strim;
}
void test()
{
initFontLib();
memset(&strim,0x00,sizeof(strim));
imageBuffer = (unsigned char*)malloc(WIDTH_TTX*HEIGHT_TTX*4);
memset(imageBuffer,0x00,WIDTH_TTX*HEIGHT_TTX*4);
for(U32 loop = 0,value = 0;loop < dataLength;loop ++)
{
dataIndexBuf[indexLength] = value + 57360;
indexLength++;
if(loop%9 == 0 && loop != 0)
{
value = 0;
}
else
{
value++;
}
}
memset(imageBuffer,0x00,WIDTH_TTX*HEIGHT_TTX*4);
strim = NewFTString();
Draw_Bitmap_Argb8888(0, 0, strim.width, strim.height, strim.imageBuffer);
GFX_Flip_Window();
deInitFontLib();
free(strim.imageBuffer);
free(imageBuffer);
}