C语言使用stb_truetype显示utf8编码的中文
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h" //http://nothings.org/stb/stb_image_write.h
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h" //http://nothings.org/stb/stb_truetype.h
int main(int argc, char** argv)
{
static int g_argc = argc;
//加载字体(.ttf)文件
long int size = 0;
unsigned char* fontBuffer = NULL;
std::string fontName = UtilTool().app_dir + "/res/fonts/msyh.ttf";
FILE* fontFile = fopen(fontName.c_str(), "rb");
if (fontFile == NULL)
{
printf("Can not open font file!\n");
return 0;
}
fseek(fontFile, 0, SEEK_END); //设置文件指针到文件尾,基于文件尾偏移0字节
size = ftell(fontFile); //获取文件大小(文件尾 - 文件头 单位:字节)
fseek(fontFile, 0, SEEK_SET); //重新设置文件指针到文件头
fontBuffer = (unsigned char*)calloc(size, sizeof(unsigned char));
fread(fontBuffer, size, 1, fontFile);
fclose(fontFile);
//初始化字体
stbtt_fontinfo info;
if (!stbtt_InitFont(&info, fontBuffer, 0))
{
printf("stb init font failed\n");
return (-1);
}
//创建位图
int bitmap_w = 1912; //位图的宽
int bitmap_h = 128; //位图的高
unsigned char* bitmap = (unsigned char*)calloc(bitmap_w * bitmap_h, sizeof(unsigned char));
//"STB"的 unicode 编码
//char* text = { 0x53, 0x54, 0x42 };
char* text = u8"天下ABCDBV明日复明日asdfasfd";
//计算字体缩放
float pixels = 94.0; //字体大小(字号)
float scale = stbtt_ScaleForPixelHeight(&info, pixels); //scale = pixels / (ascent - descent)
//////////////////////////////////////////
// 获取垂直方向上的度量
// ascent:字体从基线到顶部的高度;
// descent:基线到底部的高度,通常为负值;
// lineGap:两个字体之间的间距;
// 行间距为:ascent - descent + lineGap。
int ascent = 0;
int descent = 0;
int lineGap = 0;
stbtt_GetFontVMetrics(&info, &ascent, &descent, &lineGap);
//根据缩放调整字高
ascent = roundf(ascent * scale);
descent = roundf(descent * scale);
//位图的x
int x = 0;
//循环加载text中每个字符
int text_len = strlen(text);
int curr_len = 0;
int next_len = 0;
uint32_t word = 0;
uint32_t next_word = 0;
////////////////////////////////////////
// 获取水平方向上的度量
// advanceWidth:字宽;
// leftSideBearing:左侧位置;
int advanceWidth = 0;
int leftSideBearing = 0;
int c_x1 = 0;
int c_y1 = 0;
int c_x2 = 0;
int c_y2 = 0;
//计算位图的y (不同字符的高度不同)
int y = 0;
//渲染字符
int byteOffset = 0;
//调整字距
int kern = 0;
next_len = my_utf8_decode(text + curr_len, &word, text_len - curr_len);
while (next_len)
{
curr_len += next_len;
// 获取水平方向上的度量
advanceWidth = leftSideBearing = 0;
stbtt_GetCodepointHMetrics(&info, word, &advanceWidth, &leftSideBearing);
//获取字符的边框(边界)
c_x1 = c_y1 = c_x2 = c_y2 = 0;
stbtt_GetCodepointBitmapBox(&info, word, scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);
//计算位图的y (不同字符的高度不同)
y = ascent + c_y1;
//渲染字符
byteOffset = x + roundf(leftSideBearing * scale) + (y * bitmap_w);
stbtt_MakeCodepointBitmap(&info, bitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, bitmap_w, scale, scale, word);
//调整x
x += roundf(advanceWidth * scale);
next_len = my_utf8_decode(text + curr_len, &next_word, text_len - curr_len);
if (next_len > 0)
{
//调整字距
kern = stbtt_GetCodepointKernAdvance(&info, word, next_word);
x += roundf(kern * scale);
word = next_word;
}
}
// 将位图数据保存到1通道的png图像中
stbi_write_png("STB.png", bitmap_w, bitmap_h, 1, bitmap, bitmap_w);
free(fontBuffer);
free(bitmap);
return 0;
}