125{
126 FT_Face face = face_ref.get_face();
127
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));
131 return false;
132 }
133
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));
137 return false;
138 }
139
140 const FT_Bitmap* bmp = &face->glyph->bitmap;
141 uint32_t gw = bmp->width;
142 uint32_t gh = bmp->rows;
143
144 constexpr uint32_t k_pad = 1;
145
150 }
151
154
155
156
157
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));
161 return false;
162 }
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));
166 return false;
167 }
168
169 bmp = &face->glyph->bitmap;
170 gw = bmp->width;
171 gh = bmp->rows;
172
177 }
178
181 "GlyphAtlas still full after growth to {}x{} at pixel_size={}",
183 return false;
184 }
185 }
186
190 "GlyphAtlas: TextureContainer pixel_bytes returned empty span");
191 return false;
192 }
193
195
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);
200 }
201
202 const float inv = 1.F /
static_cast<float>(
m_atlas_size);
203
204 GlyphMetrics m;
205 m.uv_x0 =
static_cast<float>(
m_cursor_x) * inv;
206 m.uv_y0 =
static_cast<float>(
m_cursor_y) * inv;
207 m.uv_x1 =
static_cast<float>(
m_cursor_x + gw) * inv;
208 m.uv_y1 =
static_cast<float>(
m_cursor_y + gh) * inv;
209 m.bearing_x = face->glyph->bitmap_left;
210 m.bearing_y = face->glyph->bitmap_top;
211 m.width = gw;
212 m.height = gh;
213 m.advance_x = static_cast<int32_t>(face->glyph->advance.x >> 6);
214 m.face = &face_ref;
215 m.glyph_index = glyph_index;
216
217 m_cache[&face_ref].emplace(glyph_index, m);
218
222 }
223
225 return true;
226}
#define MF_ERROR(comp, ctx,...)
const std::vector< float > * pixels
std::unordered_map< FontFace *, std::unordered_map< FT_UInt, GlyphMetrics > > m_cache
Per-face glyph cache.
std::unique_ptr< Kakshya::TextureContainer > m_texture
void grow()
Double the atlas texture and re-rasterize every cached glyph into it.
@ API
API calls from external code.
@ Portal
High-level user-facing API layer.