许多人可能想知道 - 当使用像SFML这样需要从文件路径加载字体的库时,如何从驱动器中删除字体或任何其他单个文件。
那么,我如何将这些数据嵌入到可执行文件中,因此生成的可执行文件不再依赖于这些资源文件了?
答案 0 :(得分:3)
首先,我们必须得到我们的资源。我已经下载了#34; BalooBhaijaan-Regular.ttf"来自谷歌字体的字体
然后,应该得到给定字体的二进制数据。在我看来,最简单的方法是使用linux" xxd"带-i参数的命令,它以C风格的数组输出。
让我们将输出重定向到一个文件,因为如果我们谈论的是真正的字体或更大的图像,通常会很长:
xxd -i BalooBhaijaan-Regular.ttf > font_data.txt
创建一个空的C / C ++标头或将字体数据放入已存在的文件中。我更喜欢使用新的头文件,因为输出将非常长。
当然,在粘贴到IDE后,您可以将数组类型更改为const,因为字体的内容通常不会更改。
这是它在我的IDE中的样子:
您当然可能想知道为什么这是一个char数组 - 只是因为在char数组中每个"字段"代表一个字节。
您可能已经注意到,xxd还为我们创建了另一个变量 - font_data.txt中的最后一个变量是unsigned int,它告诉我们数组的长度。我们稍后会需要这个。 "长度通知"的名称整数与数组的名称相同,使用" _len"后缀
现在,有两种方法可以继续:
1.使用内置方法从内存加载字体(一些库支持它,SFML支持它)
2.创造一个"假的"归档并加载它
让我们谈谈两种情况。
1.
这个很简单,sfml支持从内存加载文件的地址和大小,所以我们可以这样做:
#include "BalooBhaijaanFont.hpp"
#include <SFML/Graphics.hpp>
int main(int argc, char** argv) {
sf::RenderWindow mainWindow(sf::VideoMode(200,100), L"TEST");
sf::Font fromMem;
fromMem.loadFromMemory(&BalooBhaijaan_Regular_ttf, BalooBhaijaan_Regular_ttf_len);
sf::Text text("WORKS!", fromMem);
while(mainWindow.isOpen()){
mainWindow.draw(text);
mainWindow.display();
}
return 0;
}
正如您所看到的,使用内置函数加载它非常简单。
2.
现在是时候采用临时文件方式了,我真的不建议 - 大多数库都支持从内存加载,如果你正在创建自己的库,你最终会以内存加载功能结束。
虽然仍然可以创建一个文件只是为了将其读取到字体类然后将其删除,但我没有看到使用此方法的任何意义,除非您对文件夹中的其他文件非常恼火。
仅供参考:
#include "BalooBhaijaanFont.hpp"
#include <SFML/Graphics.hpp>
int main(int argc, char** argv) {
sf::RenderWindow mainWindow(sf::VideoMode(200,100), L"TEST");
sf::Font fromFile;
{
FILE * tempFile = fopen("tmpfont.ttf", "wb");
fwrite( BalooBhaijaan_Regular_ttf, sizeof(char), BalooBhaijaan_Regular_ttf_len, tempFile );
fclose(tempFile);
fromFile.loadFromFile("tmpfont.ttf");
std::remove("tmpfont.ttf");
}
sf::Text text("WORKS!", fromFile);
while(mainWindow.isOpen()){
mainWindow.draw(text);
mainWindow.display();
}
return 0;
}