9 , m_pixel_size(pixel_size)
10 , m_atlas_size(atlas_size)
12 m_texture = std::make_unique<Kakshya::TextureContainer>(
27 "GlyphAtlas::get_or_rasterize: FontFace not loaded");
31 if (
const FT_UInt idx = FT_Get_Char_Index(
m_face.
get_face(), codepoint); idx != 0) {
36 if (!fallback || !fallback->is_loaded()) {
39 if (
const FT_UInt idx = FT_Get_Char_Index(fallback->get_face(), codepoint); idx != 0) {
45 "GlyphAtlas: no glyph for codepoint U+{:04X} in primary or {} fallback face(s)",
46 static_cast<uint32_t
>(codepoint),
m_fallbacks.size());
52 auto& face_cache =
m_cache[&face];
53 if (
auto it = face_cache.find(glyph_index); it != face_cache.end()) {
61 return &
m_cache.at(&face).at(glyph_index);
72 if (!face || face->size ==
nullptr) {
75 const int32_t
h = (face->size->metrics.ascender - face->size->metrics.descender) >> 6;
82 if (!face || face->size ==
nullptr)
84 const int32_t
a = face->size->metrics.ascender >> 6;
93 "GlyphAtlas: growing {}x{} -> {}x{} (pixel_size={})",
101 std::vector<CachedGlyph> cached;
102 for (
const auto& [face, glyphs] :
m_cache) {
103 for (
const auto& glyph_entry : glyphs) {
104 cached.push_back({ face, glyph_entry.first });
109 m_texture = std::make_unique<Kakshya::TextureContainer>(
110 new_size, new_size, Portal::Graphics::ImageFormat::R8);
117 for (
const auto& c : cached) {
128 if (
const FT_Error err = FT_Set_Pixel_Sizes(face, 0,
m_pixel_size); err != 0) {
130 "FT_Set_Pixel_Sizes({}) failed: {}",
m_pixel_size,
static_cast<int>(err));
134 if (
const FT_Error err = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER); err != 0) {
136 "FT_Load_Glyph({}) failed: {}", glyph_index,
static_cast<int>(err));
140 const FT_Bitmap* bmp = &face->glyph->bitmap;
141 uint32_t gw = bmp->width;
142 uint32_t gh = bmp->rows;
144 constexpr uint32_t k_pad = 1;
158 if (
const FT_Error err = FT_Set_Pixel_Sizes(face, 0,
m_pixel_size); err != 0) {
160 "FT_Set_Pixel_Sizes({}) failed after growth: {}",
m_pixel_size,
static_cast<int>(err));
163 if (
const FT_Error err = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER); err != 0) {
165 "FT_Load_Glyph({}) failed after growth: {}", glyph_index,
static_cast<int>(err));
169 bmp = &face->glyph->bitmap;
181 "GlyphAtlas still full after growth to {}x{} at pixel_size={}",
190 "GlyphAtlas: TextureContainer pixel_bytes returned empty span");
196 for (uint32_t row = 0; row < gh; ++row) {
197 const uint8_t*
src = bmp->buffer +
static_cast<size_t>(row *
static_cast<uint32_t
>(std::abs(bmp->pitch)));
199 std::memcpy(
dst,
src, gw);
202 const float inv = 1.F /
static_cast<float>(
m_atlas_size);
213 m.
advance_x =
static_cast<int32_t
>(face->glyph->advance.x >> 6);
217 m_cache[&face_ref].emplace(glyph_index, m);
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
const std::vector< float > * pixels
FT_Face get_face() const
Raw FT_Face handle for use by GlyphAtlas.
bool is_loaded() const
Returns true after a successful load() call.
Owns a single FT_Face loaded from a file path.
std::unordered_map< FontFace *, std::unordered_map< FT_UInt, GlyphMetrics > > m_cache
Per-face glyph cache.
std::unique_ptr< Kakshya::TextureContainer > m_texture
bool rasterize(FontFace &face, FT_UInt glyph_index)
std::vector< FontFace * > m_fallbacks
void add_fallback(FontFace &face)
Register a fallback face, tried in order after the primary on a miss.
uint32_t line_height() const
Line advance in pixels for this atlas's pixel_size.
const GlyphMetrics * get_or_rasterize(FT_UInt glyph_index)
Return metrics for a glyph, rasterizing it into the atlas if needed.
void grow()
Double the atlas texture and re-rasterize every cached glyph into it.
const GlyphMetrics * get_or_rasterize_from(FontFace &face, FT_UInt glyph_index)
uint32_t ascender() const
Ascender in pixels for this atlas's pixel_size.
uint32_t atlas_size() const
Atlas texture dimension (width == height == atlas_size).
GlyphAtlas(FontFace &face, uint32_t pixel_size, uint32_t atlas_size=512)
Construct an atlas for a specific face and pixel size.
@ API
API calls from external code.
@ Portal
High-level user-facing API layer.
FT_UInt glyph_index
Glyph index within face (from FT_Get_Char_Index).
int32_t bearing_x
Horizontal bearing in pixels (from FT_GlyphSlot).
float uv_x0
Left UV edge in atlas texture.
float uv_x1
Right UV edge in atlas texture.
const FontFace * face
Face that produced this glyph (primary or fallback).
uint32_t height
Glyph bitmap height in pixels.
int32_t advance_x
Horizontal advance in pixels (26.6 fixed-point >> 6).
uint32_t width
Glyph bitmap width in pixels.
float uv_y0
Top UV edge in atlas texture.
int32_t bearing_y
Vertical bearing in pixels (from FT_GlyphSlot).
float uv_y1
Bottom UV edge in atlas texture.
Per-glyph layout and UV data produced by GlyphAtlas.