C语言使用stb_truetype显示utf8编码的中文

xingyun86 2021-12-21 1762

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;
}


×
打赏作者
最新回复 (0)
查看全部
全部楼主
返回