Many of you have probably wondered- how can I get rid of a font or any other single file from the drive when using a library like SFML, which needs to load a font from a file path.
So, how do I embed that data into the executable, so the resulting executable does not depend on those resource files anymore?
First of all, we have to get our resource. I have downloaded "BalooBhaijaan-Regular.ttf" font from google fonts.
Then, one should get the binary data of the given font. The easiest way to achieve this in my opinion is to use the linux "xxd" command with -i parameter which outputs in a C-style array.
Let's redirect the output to a file because It is usually going to be long if we are talking about true type fonts or larger images:
xxd -i BalooBhaijaan-Regular.ttf > font_data.txt
Create an empty C/C++ header or put the font data into an already existing file. I prefer using new header files as the output is going to be really long.
Of course, after pasting into your IDE you can change the array type to const as the content of a font usually doesn't change.
This is how it looks in my IDE:
You might of course wonder why is this a char array - simply because in a char array each "field" represents one byte.
As you might have noticed, xxd also creates another variable for us - the last variable in the font_data.txt is an unsigned int which informs us about the length of the array. We will need this later. Name of the "length-informing" integer is same as name of the array with "_len" suffix
Now, there are two ways to proceed:
1. load font from the memory using a builtin method (some libraries support it, SFML does)
2. create a "fake" file and load it
Lets talk about both cases
1.
This one is fairly simple, sfml supports loading file from memory given it's address and size, so we can just do this:
#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;
}
As you can see, loading it with a builtin function is really easy.
2.
Now it's time for a temporary file approach which i really do NOT recommend - most libraries support loading from memory and if you are making your own library you are going to end with having a memory load function anyway.
Whilst it is still possible to create a file just to read it to a font class and then remove it, I do not see any sense of using this method unless you are extremely annoyed by additional files in your folders.
Just for reference:
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With