#include
#include
#include "gb2312.h"
#include "freetype2.h"
static struct{
char szFontName[64];
char szFontFile[128];
}FontInfo[] = {
{ "楷体", "./simkai.ttf" },
{ "黑体", "./simhei.ttf" },
{ "宋体", "./simsun.ttc" },
{ "Uming", "./uming.ttf" }
};
static char* GetFontFile(char *pszFontName)
{
int i;
int nSize;
if((NULL == pszFontName) || ('\0' == *pszFontName))
goto err;
nSize = sizeof(FontInfo) / sizeof(FontInfo[0]);
for(i=0; i {
if(!strcmp(pszFontName, FontInfo[i].szFontName))
return FontInfo[i].szFontFile;
}
err:
return FontInfo[2].szFontFile;
}
BOOL FreeType2_InitFont(PFREETYPE2FONT pFont, char *pszName)
{
char *pszFontFile;
FT_Error err;
if((NULL == pFont) || (NULL == pszName) || ('\0' == *pszName))
return FALSE;
pszFontFile = GetFontFile(pszName);
if(NULL == pszFontFile)
return FALSE;
err = FT_Init_FreeType(&pFont->library);
if(err != FT_Err_Ok)
{
printf("InitFont->FT_InitFreeType error: %d\n", err);
pFont->library = NULL;
return FALSE;
}
err = FT_New_Face(pFont->library, pszFontFile, 0, &pFont->face);
if(err != FT_Err_Ok)
{
printf("InitFont->FT_New_Face error: %d\n", err);
FT_Done_FreeType(pFont->library);
pFont->library = NULL;
pFont->face = NULL;
return FALSE;
}
err = FT_Set_Char_Size(pFont->face, 0, 64 << 4, 300, 300);
if(err != FT_Err_Ok)
{
printf("InitFont->FT_Set_Char_Size error: %d\n", err);
FT_Done_Face(pFont->face);
FT_Done_FreeType(pFont->library);
pFont->library = NULL;
pFont->face = NULL;
return FALSE;
}
pFont->pucData = NULL;
return TRUE;
}
BOOL FreeType2_DestroyFont(PFREETYPE2FONT pFont)
{
if(NULL == pFont)
return FALSE;
if(pFont->face != NULL)
FT_Done_Face(pFont->face);
if(pFont->library != NULL)
FT_Done_FreeType(pFont->library);
pFont->face = NULL;
pFont->library = NULL;
if(pFont->pucData != NULL)
free(pFont->pucData);
pFont->pucData = NULL;
return TRUE;
}
BOOL FreeType2_SetFontSize(PFREETYPE2FONT pFont, int nWid, int nHei)
{
FT_Error err;
if((NULL == pFont) || (NULL == pFont->face))
return FALSE;
err = FT_Set_Pixel_Sizes(pFont->face, nWid, nHei);
if(err != FT_Err_Ok)
{
printf("SetFontSize->FT_Set_Pixel_Sizes error: %d\n", err);
return FALSE;
}
return TRUE;
}
static unsigned short s_font_utf8_to_unicode (const unsigned char *utf8)
{
unsigned short unicode;
unicode = utf8[0];
if (unicode >= 0xF0) {
unicode = (unsigned short) (utf8[0] & 0x07) << 18;
unicode |= (unsigned short) (utf8[1] & 0x3F) << 12;
unicode |= (unsigned short) (utf8[2] & 0x3F) << 6;
unicode |= (unsigned short) (utf8[3] & 0x3F);
} else if (unicode >= 0xE0) {
unicode = (unsigned short) (utf8[0] & 0x0F) << 12;
unicode |= (unsigned short) (utf8[1] & 0x3F) << 6;
unicode |= (unsigned short) (utf8[2] & 0x3F);
} else if (unicode >= 0xC0) {
unicode = (unsigned short) (utf8[0] & 0x1F) << 6;
unicode |= (unsigned short) (utf8[1] & 0x3F);
}
return unicode;
}
BOOL FreeType2_GetFontChar(FT_Face face, char *pszText, PXGlyph pXGlyph, BOOL bFlag)
{
unsigned short unicode;
FT_UInt index;
FT_BBox bbox;
FT_Error err;
FT_Vector origin;
FT_Glyph glyph;
if((NULL == face) || (NULL == pszText) || ('\0' == *pszText) || (NULL == pXGlyph))
return FALSE;
memset((void*)pXGlyph, 0, sizeof(XGlyph));
if(*pszText & 0x80)
unicode = gb2312_0_conv_to_uc32(pszText);
else
unicode = s_font_utf8_to_unicode(pszText);
index = FT_Get_Char_Index(face, unicode);
if(!index)
{
printf("FreeType2_GetFontChar->FT_Get_Char_Index fail: index=0 !\n");
return FALSE;
}
err = FT_Load_Glyph(face, index, FT_LOAD_DEFAULT);
if(err)
{
printf("FreeType2_GetFontChar->FT_Load_Glyph fail !\n");
return FALSE;
}
err = FT_Get_Glyph(face->glyph, &glyph);
if(err)
{
printf("FreeType2_GetFontChar->FT_Get_Glyph fail !\n");
return FALSE;
}
FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_gridfit, &bbox);
origin.x = -bbox.xMin;
origin.y = -bbox.yMin;
if(FT_IS_SCALABLE(face))
{
err = FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, &origin, 1);
if(err)
{
FT_Done_Glyph(glyph);
printf("FreeType2_GetFontChar->FT_Glyph_To_Bitmap fail !\n");
return FALSE;
}
else
{
int nSize;
FT_Bitmap bm = ((FT_BitmapGlyph)glyph)->bitmap;
nSize = bm.pitch * bm.rows;
if(nSize > 0)
{
if(bFlag)
{
pXGlyph->pucData = (unsigned char*)calloc(nSize, sizeof(unsigned char));
if(NULL == pXGlyph->pucData)
{
FT_Done_Glyph(glyph);
printf("FreeType2_GetFontChar->calloc unsigned char fail !\n");
return FALSE;
}
memcpy((void*)pXGlyph->pucData, (void*)bm.buffer, nSize);
}
pXGlyph->nWid = bm.width;
pXGlyph->nHei = bm.rows;
pXGlyph->nLineStep = bm.pitch;
pXGlyph->nBearingx = face->glyph->metrics.horiBearingX / 64;
pXGlyph->nBearingy = face->glyph->metrics.horiBearingY / 64;
pXGlyph->nAdvance = face->glyph->metrics.horiAdvance / 64;
}
}
}
FT_Done_Glyph(glyph);
return TRUE;
}
BOOL FreeType2_GetFontData(PFREETYPE2FONT pFont, char *pText)
{
int i;
int j;
int n;
int x;
int y;
int pen_x;
int pen_y;
int num_chars;
int xmin;
int xmax;
int glyph_min_x = 0;
FT_UInt previous;
FT_UInt glyph_index;
FT_UInt num_glyphs;
FT_UInt glyph_advance_x;
FT_BBox bbox;
FT_Error Error;
FT_Glyph glyph;
FT_Bool use_kerning;
FT_BBox glyph_bbox;
FT_BitmapGlyph bit;
unsigned short *unicode;
char *pszTemp = NULL;
FT_Vector *pos;
FT_Vector *pens;
PIMAGE pImage;
if((NULL == pFont) || (NULL == pFont->face) || (NULL == pText) || '\0' == *pText)
return FALSE;
for(num_chars=0,pszTemp=pText; *pszTemp!='\0'; )
{
if(*pszTemp & 0x80)
pszTemp += 2;
else
pszTemp++;
num_chars++;
}
pos = (FT_Vector*)calloc(num_chars, sizeof(FT_Vector));
if(NULL == pos)
{
printf("FreeType2_GetFontData->calloc FT_Vector pos fail !\n");
return FALSE;
}
pens = (FT_Vector*)calloc(num_chars, sizeof(FT_Vector));
if(NULL == pens)
{
free(pos);
printf("FreeType2_GetFontData->calloc FT_Vector pens fail !\n");
return FALSE;
}
pImage = (PIMAGE)calloc(num_chars, sizeof(IMAGE));
if(NULL == pImage)
{
free(pos);
free(pens);
printf("FreeType2_GetFontData->calloc IMAGE fail !\n");
return FALSE;
}
unicode = (unsigned short*)calloc(num_chars, sizeof(unsigned short));
if(NULL == unicode)
{
free(pos);
free(pens);
free(pImage);
printf("FreeType2_GetFontData->calloc unsigned short fail !\n");
return FALSE;
}
for(i=0,pszTemp=pText; *pszTemp!='\0'; i++)
{
if(*pszTemp & 0x80)
{
unicode[i] = gb2312_0_conv_to_uc32(pszTemp);
pszTemp += 2;
}
else
{
unicode[i] = s_font_utf8_to_unicode(pszTemp);
pszTemp++;
}
}
pen_x = 0;
pen_y = 0;
previous = 0;
num_glyphs = 0;
use_kerning = FT_HAS_KERNING(pFont->face);
bbox.xMin = 32000;
bbox.yMin = 32000;
bbox.xMax = -32000;
bbox.yMax = -32000;
xmin = 3200;
xmax = -3200;
x = 0;
y = 0;
for(i=0; i {
glyph_index = FT_Get_Char_Index(pFont->face, unicode[i]);
if(!glyph_index)
continue;
if(use_kerning && previous && glyph_index)
{
FT_Vector delta;
Error = FT_Get_Kerning(pFont->face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
if(Error)
continue;
pen_x += delta.x >> 6;
}
Error = FT_Load_Glyph(pFont->face, glyph_index, FT_LOAD_DEFAULT);
if(Error)
continue;
Error = FT_Get_Glyph(pFont->face->glyph, &glyph);
if(Error)
continue;
Error = FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1);
if(Error)
continue;
FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox);
glyph_min_x = FT_FLOOR(pFont->face->glyph->metrics.horiBearingX);
glyph_advance_x = FT_CEIL(pFont->face->glyph->metrics.horiAdvance);
pos[num_glyphs].x = pen_x;
pos[num_glyphs].y = pen_y;
pen_x += glyph_advance_x;
glyph_bbox.xMin += pen_x;
glyph_bbox.xMax += pen_x;
glyph_bbox.yMin += pen_y;
glyph_bbox.yMax += pen_y;
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;
bit = (FT_BitmapGlyph)glyph;
pens[num_glyphs].x = pos[num_glyphs].x;
pens[num_glyphs].y = pos[num_glyphs].y;
x = pens[num_glyphs].x;
xmin = MIN(xmin, x);
xmax = MAX(xmax, x + bit->bitmap.width + glyph_min_x);
pImage[num_glyphs].image = glyph;
pImage[num_glyphs].min_x = glyph_min_x;
pImage[num_glyphs].advance_x = glyph_advance_x;
previous = glyph_index;
num_glyphs++;
}
if(xmin > xmax)
{
xmin = 0;
xmax = 0;
}
if(bbox.xMin > bbox.xMax)
{
bbox.xMin = 0;
bbox.yMin = 0;
bbox.xMax = 0;
bbox.yMax = 0;
}
pFont->nWid = xmax - xmin;
pFont->nHei = bbox.yMax - bbox.yMin;
pFont->pucData = (unsigned char*)calloc(pFont->nWid*pFont->nHei, sizeof(unsigned char));
if(NULL == pFont->pucData)
{
free(pos);
free(pens);
free(unicode);
free(pImage);
printf("FreeType2_GetFontData->calloc unsigned char fail !\n");
return FALSE;
}
for(n=0; n {
unsigned char *start;
unsigned char *end;
unsigned char *pucBmp;
unsigned char *pucBuf;
bit = (FT_BitmapGlyph)pImage[n].image;
x = pens[n].x + pImage[n].min_x;
y = pens[n].y - bit->top + bbox.yMax;
pucBuf = bit->bitmap.buffer;
start = pFont->pucData;
pucBmp = start + (x + y*pFont->nWid);
end = start + pFont->nWid*pFont->nHei;
for(i=0; ibitmap.rows; i++)
{
for(j=0; jbitmap.width; j++)
{
if(*pucBuf && (pucBmp >= start) && (pucBmp < end))
*pucBmp = 1;
pucBuf++;
pucBmp++;
}
pucBuf += (bit->bitmap.pitch - bit->bitmap.width);
pucBmp += (pFont->nWid - bit->bitmap.width);
}
FT_Done_Glyph(pImage[n].image);
}
free(pos);
free(pens);
free(unicode);
free(pImage);
return TRUE;
}
int FreeType2_GetHeigh(PFREETYPE2FONT pFont)
{
if(NULL == pFont)
return 0;
return pFont->nHei;
}