1、前言
这段时间的工做须要研究stb_truetype库,所以本篇文章记录一下该库的基本用法。stb_truetype是一个常见字体加载库, 只有一个头文件, 功能虽没有freetype库强大,但代码量小不少,在Flash很是小的开发板上也能够用,以为freetype库太大的,建议使用stb_truetype库。git
stb库的GitHub仓库:https://github.com/nothings/stb。github
2、stb_truetype解析ttf字体
使用stb_truetype库解析ttf字体的步骤一般以下:ide
一、加载并初始化ttf字体文件;函数
二、设置字体大小(字号)并计算缩放比例;字体
三、获取垂直方向上的度量并根据缩放比例调整,好比字高、行间距等;编码
四、获取水平方向上的度量,好比字宽、字间距等;url
五、获取字符图片的边框(每一个字符转化为图像的边界);.net
六、调整每一个字体图像的宽高(代码中的x、y),并渲染字体;指针
至此,解析ttf字体已完成,附加步骤为使用stb_image_write库将渲染出来的图像保存为本地图片,下面直接上代码:code
注意:在包含stb_truetype.h头文件的时候须要定义STB_TRUETYPE_IMPLEMENTATION,不然将会没法使用。
#include <stdio.h> #include <stdlib.h> #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, const char *argv[]) { /* 加载字体(.ttf)文件 */ long int size = 0; unsigned char *fontBuffer = NULL; FILE *fontFile = fopen("font/default.ttf", "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 = 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"); } /* 建立位图 */ int bitmap_w = 512; /* 位图的宽 */ int bitmap_h = 128; /* 位图的高 */ unsigned char *bitmap = calloc(bitmap_w * bitmap_h, sizeof(unsigned char)); /* "STB"的 unicode 编码 */ char word[20] = {0x53, 0x54, 0x42}; /* 计算字体缩放 */ float pixels = 64.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); int x = 0; /*位图的x*/ /* 循环加载word中每一个字符 */ for (int i = 0; i < strlen(word); ++i) { /** * 获取水平方向上的度量 * advanceWidth:字宽; * leftSideBearing:左侧位置; */ int advanceWidth = 0; int leftSideBearing = 0; stbtt_GetCodepointHMetrics(&info, word[i], &advanceWidth, &leftSideBearing); /* 获取字符的边框(边界) */ int c_x1, c_y1, c_x2, c_y2; stbtt_GetCodepointBitmapBox(&info, word[i], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2); /* 计算位图的y (不一样字符的高度不一样) */ int y = ascent + c_y1; /* 渲染字符 */ int 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[i]); /* 调整x */ x += roundf(advanceWidth * scale); /* 调整字距 */ int kern; kern = stbtt_GetCodepointKernAdvance(&info, word[i], word[i + 1]); x += roundf(kern * scale); } /* 将位图数据保存到1通道的png图像中 */ stbi_write_png("STB.png", bitmap_w, bitmap_h, 1, bitmap, bitmap_w); free(fontBuffer); free(bitmap); return 0; }
运行后能够见STB.png图片,效果以下:
3、总结
以上即是stb_truetype库的基本用法,能够看出使用过程比较简单,其中须要调整的参数主要是字体大小(字号),使用过程当中须要注意如下两点:
一、上面已经提过,这里再提一遍,在包含stb_truetype.h头文件的时候须要定义STB_TRUETYPE_IMPLEMENTATION,不然将会没法使用。
二、调用stb_truetype库函数传入的字符编码必须是unicode编码。