15#include FT_TRUETYPE_TABLES_H
24 mRenderResourceContext(rrc),
25 mTextRenderer(textRenderer),
26 mFontName(std::filesystem::path(filepath).stem().string()),
28 mErrorResult(FT_Err_Ok),
32 static_cast<unsigned int>(
33 std::numeric_limits<FT_F26Dot6>::max() >> 6))
35 throw std::out_of_range(
"Font size exceeds FreeType supported range.");
38 const FT_F26Dot6 fontSize26Dot6 =
44 throw std::runtime_error{
"Failed to create new face!" };
50 throw std::runtime_error{
"Failed to set char size!" };
60 mRenderResourceContext(rrc),
61 mTextRenderer(textRenderer),
64 mErrorResult(FT_Err_Ok),
66 mFontFileBytes(fileBytes)
69 static_cast<unsigned int>(
70 std::numeric_limits<FT_F26Dot6>::max() >> 6))
72 throw std::out_of_range(
"Font size exceeds FreeType supported range.");
75 const FT_F26Dot6 fontSize26Dot6 =
81 throw std::runtime_error{
"Failed to create new face!" };
87 throw std::runtime_error{
"Failed to set char size!" };
106 std::uint32_t start = begin;
117 if (codePoints.empty())
120 std::vector<GlyphIndex> glyphs;
121 for (
auto codePoint : codePoints)
131 if (glyphIndexes.empty())
134 std::vector<GlyphIndex> lackingGlyphs;
135 for (
const auto& glyphIndex : glyphIndexes)
141 gi.
index = glyphIndex.index;
142 lackingGlyphs.push_back(gi);
145 if (!lackingGlyphs.empty())
161 throw std::runtime_error{
"Failed to load glyph!" };
167 throw std::runtime_error{
"Failed to render glyph!" };
172 const auto srcW =
mFace->glyph->bitmap.width;
173 const auto srcH =
mFace->glyph->bitmap.rows;
175 const auto dstW = srcW + padding * 2;
176 const auto dstH = srcH + padding * 2;
178 const auto bufferSize = dstW * dstH * 4;
179 std::vector<uint8_t> buffer(bufferSize, 0);
180 for (
unsigned int y = 0; y < srcH; ++y)
182 for (
unsigned int x = 0; x < srcW; ++x)
184 const size_t srcIndex =
185 static_cast<size_t>(y) *
static_cast<size_t>(srcW) +
186 static_cast<size_t>(x);
188 const uint8_t coverage =
189 mFace->glyph->bitmap.buffer[srcIndex];
192 static_cast<size_t>(x) +
static_cast<size_t>(padding);
195 static_cast<size_t>(y) +
static_cast<size_t>(padding);
198 (dstY *
static_cast<size_t>(dstW) + dstX) * 4U;
200 buffer[idx + 0] = coverage;
201 buffer[idx + 1] = coverage;
202 buffer[idx + 2] = coverage;
203 buffer[idx + 3] = coverage;
207 glyphMetrics.
width = srcW;
208 glyphMetrics.
height = srcH;
214 glyphMetrics.
advanceX = FreeType26Dot6ToPixelInt(
mFace->glyph->advance.x);
216 glyphMetrics.
padding = padding;
218 return std::pair(glyphMetrics,
ImageData(dstW, dstH, buffer));
224 glyphIndex.
index =
static_cast<std::uint32_t
>(FT_Get_Char_Index(
mFace,
static_cast<FT_ULong
>(codePoint)));
238 std::unordered_map<std::uint32_t, std::pair<GlyphMetrics, ImageData>> glyphs;
239 for (
auto codePoint = begin; codePoint <= end; ++codePoint)
259 const std::string fileName = textureName +
".png";
261 fontAtlas.WritePngFile(fullPath.string().c_str());
263 textureCache->LoadTexture(textureName, fontAtlas);
267 const std::string materialName = textureName +
"_Mat";
276 materialCache->AddMaterial(materialSettings);
277 Material* material = materialCache->GetMaterial(materialName);
278 material->
SetVec4(
"FontColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
279 material->
SetVec4(
"OutlineColor", glm::vec4(0, 0, 0, 1));
280 material->
SetFloat(
"OutlineThicknessPx", 0.0);
281 const float invW = 1.0f /
static_cast<float>(fontAtlas.GetWidth());
282 const float invH = 1.0f /
static_cast<float>(fontAtlas.GetHeight());
283 material->
SetFloat(
"InvAtlasSizeWidth", invW);
284 material->
SetFloat(
"InvAtlasSizeHeight", invH);
292 for (
auto& it : glyphs)
294 const std::uint32_t glyphIndex =
static_cast<std::uint32_t
>(FT_Get_Char_Index(
mFace,
static_cast<FT_ULong
>(it.first)));
295 mGlyphsByIndex[glyphIndex] = std::pair<GlyphMetrics, std::string>(it.second.first, materialName);
303 return FT_Get_Char_Index(
mFace, codePoint) != 0;
318 return search->second.first;
326 return std::string();
331 return std::string();
333 return search->second;
341 return std::string();
343 return search->second.second;
349 result.
index = FT_Get_Char_Index(
mFace, codePoint);
361 std::unordered_map<std::uint32_t, std::pair<GlyphMetrics, ImageData>> glyphs;
362 for (
auto glyphIndex : glyphIndexes)
381 const std::string fileName = textureName +
".png";
383 fontAtlas.WritePngFile(fullPath.string().c_str());
385 textureCache->LoadTexture(textureName, fontAtlas);
389 const std::string materialName = textureName +
"_Mat";
398 materialCache->AddMaterial(materialSettings);
399 Material* material = materialCache->GetMaterial(materialName);
400 material->
SetVec4(
"FontColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
401 material->
SetVec4(
"OutlineColor", glm::vec4(0, 0, 0, 1));
402 material->
SetFloat(
"OutlineThicknessPx", 0.0f);
403 const float invW = 1.0f /
static_cast<float>(fontAtlas.GetWidth());
404 const float invH = 1.0f /
static_cast<float>(fontAtlas.GetHeight());
405 material->
SetFloat(
"InvAtlasSizeWidth", invW);
406 material->
SetFloat(
"InvAtlasSizeHeight", invH);
414 for (
auto& it : glyphs)
416 mGlyphsByIndex[it.first] = std::pair<GlyphMetrics, std::string>(it.second.first, materialName);
422std::int32_t FontResources::FreeType26Dot6ToPixelInt(FT_Pos value)
424 const FT_Pos pixelValue = value >> 6;
426 if (pixelValue <
static_cast<FT_Pos
>(std::numeric_limits<std::int32_t>::min()) ||
427 pixelValue >
static_cast<FT_Pos
>(std::numeric_limits<std::int32_t>::max()))
429 throw std::out_of_range(
"FreeType metric exceeds int32_t range.");
432 return static_cast<std::int32_t
>(pixelValue);
const FontMetrics & GetFontMetrics() const
Returns global font metrics.
FontResources(RenderResourceContext rrc, TextRenderer *textRenderer, std::string filepath, unsigned int const fontSize)
Constructs font resources from a font file.
GlyphMetrics GetGlyphMetrics(GlyphIndex glyphIndex) const
Returns metrics for a specific glyph.
static std::uint32_t sMaxGlyphsPerFontAtlas
Maximum number of glyphs per font atlas.
~FontResources()
Releases all font-related resources.
std::pair< GlyphMetrics, ImageData > CreateGlyphBitmapBy(GlyphIndex glyphIndex)
Creates a bitmap and metrics for a glyph by index.
void LoadGlyphsFromCodePointRange(std::uint32_t begin, std::uint32_t end)
Preloads glyphs for a continuous Unicode range.
void CreateFontAtlasFromRange(std::uint32_t begin, std::uint32_t end)
Creates a font atlas for a continuous code point range.
FT_Face GetFontFace()
Returns the internal font face handle.
const unsigned int mFontSize
void StoreFontAtlasesInFiles(bool in)
Enables or disables storing generated font atlases on disk.
TextRenderer * mTextRenderer
std::unordered_map< std::uint32_t, std::pair< GlyphMetrics, std::string > > mGlyphsByIndex
std::string GetFontAtlasTextureName(GlyphIndex glyphIndex) const
Returns the texture name of the atlas containing the glyph.
std::string GetFontAtlasMaterialName(GlyphIndex glyphIndex) const
Returns the material name associated with the glyph.
static unsigned int sFontAtlasPaddingPx
Padding in pixels around glyphs inside atlases.
std::vector< uint8_t > mFontFileBytes
RenderResourceContext mRenderResourceContext
void EnsureGlyphs(const std::vector< std::uint32_t > &codePoints)
Ensures glyphs for the given Unicode code points exist.
std::unordered_map< std::string, std::string > mFontAtlases
GlyphIndex GetIndexFromCodePoint(std::uint32_t codePoint) const
Resolves a Unicode code point to a glyph index.
bool HasGlyph(uint32_t codePoint) const
Checks whether a glyph exists for a code point.
bool bStoreFontAtlasesInFiles
void CreateFontAtlasFromList(const std::vector< GlyphIndex > &glyphIndexes)
Creates a font atlas for a list of glyphs.
Represents raw 2D image data stored in memory.
Represents a material instance with parameter values, texture bindings, and rendering configuration.
void InitializeRenderResources()
Initializes backend-specific GPU resources associated with this material.
void SetVec4(const std::string &name, glm::vec4 value)
Sets a vec4 parameter for the material.
void AddTexture(const std::string &textureName)
Adds a texture name to the material's list of used textures.
void SetFloat(const std::string &name, float value)
Sets a float parameter for the material.
Central text system manager and font resource registry.
FT_Library & GetFontLibrary()
Returns the internal FreeType library instance.
bool CreateTextureAtlas(std::map< char, std::pair< unsigned int, unsigned int > > &texAtlasData, ImageData &texAtlasImage)
Creates a texture atlas from the stored image collection.
static std::filesystem::path GetContentFolderPath()
Returns absolute path to Content.
static const std::vector< MaterialParameterLayoutEntry > Font2DLayout
Global metrics describing font vertical layout.
Opaque glyph identifier within a font.
Metrics describing a single glyph and its atlas placement.
Settings required to define a material instance.
MaterialDomain materialDomain
ShadingModel shadingModel
std::string parentMaterialName
const std::vector< MaterialParameterLayoutEntry > * parameterLayout
Aggregates pointers to global rendering resource managers.
TextureCache * textureCache
MaterialCache * materialCache