C++实现FreeType获取字体轮廓并保存图形

       

        这个实例是记录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;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值