8#include <utility/graphic/text/font.hpp>
15namespace utility::graphic
21 if (FT_Init_FreeType(
reinterpret_cast<FT_Library *
>(&
_ftLibrary))) {
22 throw std::runtime_error(
"Could not initialize FreeType library.");
25 for (
const auto &fontAsset: fontAssets) {
26 auto buffer = std::make_shared<std::vector<uint8_t>>();
27 const std::string content = fontAsset.content();
28 buffer->assign(content.begin(), content.end());
32 if (FT_New_Memory_Face(
34 reinterpret_cast<const FT_Byte *
>(buffer->data()),
35 static_cast<FT_Long
>(buffer->size()), 0, &face)) {
36 throw std::runtime_error(
37 "Could not load font " + fontAsset.path() +
": "
38 + FT_Error_String(FT_Err_Cannot_Open_Resource));
40 _faces[fontAsset.path()] = face;
49 for (
const auto &[_, face]:
_faces) {
50 FT_Done_Face(
static_cast<FT_Face
>(face));
53 FT_Done_FreeType(
reinterpret_cast<FT_Library
>(
_ftLibrary));
63 auto fontSizedIt =
_sizes.find({
"", fontSize });
64 if (fontSizedIt !=
_sizes.end()) {
65 return fontSizedIt->second->_ascender;
72 auto fontSizedIt =
_sizes.find({
"", fontSize });
73 if (fontSizedIt !=
_sizes.end()) {
74 return fontSizedIt->second->_descender;
81 auto fontSizedIt =
_sizes.find({
"", fontSize });
82 if (fontSizedIt !=
_sizes.end()) {
83 return fontSizedIt->second->_lineHeight;
92 std::vector<Glyph> glyphs;
93 glyphs.reserve(codePoints.size());
94 std::map<std::string, std::shared_ptr<FontSized>> dirtyFontSizeds;
96 for (
const auto &codePoint: codePoints) {
99 if (faceName.empty()) {
105 std::shared_ptr<FontSized> fontSized;
106 auto fontSizedIt =
_sizes.find(key);
108 if (fontSizedIt ==
_sizes.end()) {
110 std::make_shared<FontSized>(fontSize,
_faces.at(faceName));
111 _sizes.emplace(key, fontSized);
113 fontSized = fontSizedIt->second;
116 const bool hadGlyph = fontSized->hasGlyph(codePoint);
117 glyphs.push_back(fontSized->generateGlyph(codePoint));
119 dirtyFontSizeds[faceName] = fontSized;
124 for (
const auto &[faceName, fontSized]: dirtyFontSizeds) {
126 fontSized->getAtlas());
137 double maxBottom = 0.0;
139 for (
const auto &codePoint: codePoints) {
141 if (faceName.empty()) {
145 auto fontSizedIt =
_sizes.find(key);
146 if (fontSizedIt ==
_sizes.end()) {
152 std::max(maxTop,
static_cast<double>(metric.
bearing[1]));
153 maxBottom = std::max(
155 static_cast<double>(metric.
size[1] - metric.
bearing[1]));
158 fontSizedIt->second->measureGlyph(codePoint);
161 std::max(maxTop,
static_cast<double>(metric.
bearing[1]));
162 maxBottom = std::max(
164 static_cast<double>(metric.
size[1] - metric.
bearing[1]));
169 static_cast<float>(maxTop + maxBottom) };
174 std::vector<std::string> fontPaths;
175 for (
const auto &[fontPath, _]:
_faces) {
176 fontPaths.push_back(fontPath);
185 for (
const auto &[_, face]:
_faces) {
186 if (!face ||
static_cast<FT_Face
>(face)->num_glyphs == 0) {
198 for (
const auto &[_, face]:
_faces) {
199 if (FT_Get_Char_Index(
static_cast<FT_Face
>(face), codepoint) != 0) {
216 for (
const auto &[faceName, face]:
_faces) {
218 FT_Get_Char_Index(
static_cast<FT_Face
>(face), codePoint);
219 if (glyphIndex != 0) {
The FontSized class represents a specific size of a font face, managing the glyphs and texture atlas ...
Glyph measureGlyph(uint32_t codePoint) const
Compute glyph metrics for a code point without rasterizing or mutating the texture atlas.
std::vector< std::string > getFontPaths(void) const
Retrieves the paths of the loaded font assets.
float getLineHeight(uint32_t fontSize) const
Retrieves the line height for the specified font size.
std::map< FontSizedKey, std::shared_ptr< FontSized > > _sizes
Map of font sizes to their corresponding FontSized objects.
bool hasGlyph(char32_t codepoint) const
Checks if the font contains a glyph for the specified Unicode code point.
~Font()
Destructs the Font object, releasing any allocated resources.
float getAscender(uint32_t fontSize) const
Retrieves the ascender value for the specified font size.
bool isLoaded(void) const
Checks if the font has been successfully loaded.
std::string _getFaceNameForGlyph(uint32_t codePoint) const
Retrieves the font face name associated with a specific Unicode code point.
std::map< std::string, void * > _faces
Map of font paths to their corresponding FreeType face objects.
std::function< void(std::string, std::shared_ptr< Texture >)> onNewTextureCreated
Member function to set a callback that is called when a new texture atlas is created for a font size.
std::map< std::string, std::shared_ptr< std::vector< uint8_t > > > _faceBuffers
In-memory buffers backing FreeType faces.
float getDescender(uint32_t fontSize) const
Retrieves the descender value for the specified font size.
math::Vector2F measureText(uint32_t fontSize, const codePointString &codePoints) const
Measure the bounding size of a string of code points without rasterizing or mutating any glyph atlas.
Font(const std::vector< File > &fontAssets)
Constructs a Font object by loading font data from the provided file assets.
void * _ftLibrary
FreeType library instance used for managing font resources.
std::vector< Glyph > processCodePoints(uint32_t fontSize, const codePointString &codePoints)
Processes a string of Unicode code points to generate glyphs for rendering text.
3D vector class inheriting from glm::vec3.
std::vector< uint32_t > codePointString
A type representing a string of Unicode code points.
A struct representing a unique key for identifying a specific font face and size combination.
The Glyph struct represents a single character's visual representation in a font atlas.
math::Vector2F size
Size of the glyph in pixels (width and height).
math::Vector2F bearing
Bearing of the glyph, representing the offset from the baseline to the top-left corner of the glyph.
float advance
Advance value, specifying the horizontal distance to advance the cursor after rendering the glyph.