这个实例是记录FreeType的基本用法,通过加载字体,选择单个字符,获取该字符轮廓的多边形的一个例子,也许对于一些图形学软件中会有所保存,以此记录。
以windows平台为例,下载freetype源码编译完全静态库(lib或是lib+dll这个随意),配置好include、lib,添加到自己的工程中,具体代码如下
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <ostream>
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_GLYPH_H
class Point {
public:
double x;
double y;
public:
Point() = default;
explicit Point(double _x, double _y) :x(_x), y(_y) {
}
virtual ~Point() {}
Point(const Point&& pSrc)
{
this->x = pSrc.x;
this->y = pSrc.y;
}
Point& operator=(const Point&& pSrc)
{
if (&pSrc != this) {
x = pSrc.x;
y = pSrc.y;
}
return *this;
}
};
void polygonToSvg(std::string outName,const std::vector<Point>& vertices)
{
std::ofstream svgFile(outName.c_str(),std::fstream::out);
if (svgFile.is_open()) {
svgFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
svgFile << "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1920px\" height=\"1500px\" > /n";//不设置大小,默认尺寸会显示不全
//该方法绘制出来的路径走向的
//std::string path = "M";//移动到第一个顶点 所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。
//for (const auto& vertex : vertices) {
// path += " " + std::to_string(vertex.x) + "," + std::to_string(vertex.y) + " ";
//}
//path += "Z";
//svgFile << "<path d=\"" << path << "\" stroke=\"black\" fill=\"transparent\"/>\n";
//该方法是绘制多边形
std::string polygonStr;
for (const auto& vertex : vertices) {
polygonStr += " " + std::to_string(vertex.x) + "," + std::to_string(vertex.y) + " ";
}
svgFile << "<polygon points=\"" << polygonStr << "\" style=\"fill:transparent; stroke:purple; \" /> \n";
svgFile << "</svg>\n";
svgFile.flush();
svgFile.close();
}
}
int main()
{
FT_Library ft;
if (FT_Init_FreeType(&ft)) {
std::cerr << "Could not initialize FreeType Library" << std::endl;
return -1;
}
FT_Face face;
if (FT_New_Face(ft, "arial.ttf", 0, &face)) {
std::cerr << "Could not open font" << std::endl;
return -1;
}
FT_Set_Char_Size(face,8,8,100,100);//该方法暂时未研究用途
FT_Set_Pixel_Sizes(face, 0, 16);
//FT_LOAD_NO_BITMAP 标志用于告诉FreeType不要加载位图数据。即不适用点阵
//FT_LOAD_NO_SCALE 不考虑字体大小,FT_Set_Pixel_Sizes不起作用,但也大的离谱
//FT_LOAD_RENDER,看不出来却别,指在默认加载 glyph 之后,立即输出 slot->bitmap 的内容,不用之,你不能在 FT_Load_Char 之后,立即使用 slot->bitmap。
//方法一:FT_Load_Char
//FT_Load_Char(face, '0', FT_LOAD_NO_SCALE |FT_LOAD_NO_BITMAP);
//FT_Load_Char(face, '0', FT_LOAD_RENDER);
方法二:FT_Load_Glyph
FT_ULong symbol = '1';
FT_UInt charIndex = FT_Get_Char_Index(face, symbol);
FT_Load_Glyph(face, charIndex, FT_LOAD_NO_BITMAP);
//注意直接参数设置为char,转换后的字符是错误的,不可以像如下这样使用
//FT_Load_Glyph(face, '0', FT_LOAD_NO_BITMAP);
FT_GlyphSlot g = face->glyph;
//通过指定 FT_RENDER_MODE_NORMAL 模式,您可以要求FreeType渲染字形的轮廓。
FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL);
//std::vector<Point> contours(g->bitmap.width * g->bitmap.rows);
//int contourIndex = 0;
//for (int i = 0; i < g->bitmap.width * g->bitmap.rows; ++i) {
// if (g->bitmap.buffer[i] > 0) {
// double x = (i % g->bitmap.width) *10.0 ;
// double y = (i / g->bitmap.width) *10.0;
// contours[contourIndex++] = Point(x ,y);
// }
//}
//contours.resize(contourIndex);
//FT_Outline 结构包含了字形的轮廓数据。
FT_Outline outline = g->outline;
int index = 0;
std::vector<Point> contours(outline.n_points);
for (int i = 0; i < outline.n_points; ++i) {
contours[index++]=std::move(Point(outline.points[i].x, outline.points[i].y));
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
//绘制出来的图形都是倒着的,闭合的图形最后的轮廓不是闭合的
polygonToSvg("FontPolygon.svg", contours);
return 1;
}