MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ rasterize()

bool MayaFlux::Portal::Text::GlyphAtlas::rasterize ( FontFace &  face,
FT_UInt  glyph_index 
)
private

Definition at line 124 of file GlyphAtlas.cpp.

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
146 if (m_cursor_x + gw + k_pad > m_atlas_size) {
147 m_cursor_x = 0;
148 m_cursor_y += m_shelf_height + k_pad;
149 m_shelf_height = 0;
150 }
151
152 if (m_cursor_y + gh + k_pad > m_atlas_size) {
153 grow();
154
155 // grow() re-rasterized every previously cached glyph, possibly from
156 // other faces, which overwrites face->glyph in between; reload
157 // this glyph before placing it in the now-larger atlas.
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
173 if (m_cursor_x + gw + k_pad > m_atlas_size) {
174 m_cursor_x = 0;
175 m_cursor_y += m_shelf_height + k_pad;
176 m_shelf_height = 0;
177 }
178
179 if (m_cursor_y + gh + k_pad > m_atlas_size) {
181 "GlyphAtlas still full after growth to {}x{} at pixel_size={}",
183 return false;
184 }
185 }
186
187 const std::span<uint8_t> pixels = m_texture->pixel_bytes(0);
188 if (pixels.empty()) {
190 "GlyphAtlas: TextureContainer pixel_bytes returned empty span");
191 return false;
192 }
193
194 const uint32_t stride = m_atlas_size;
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)));
198 uint8_t* dst = pixels.data() + static_cast<size_t>((m_cursor_y + row) * stride) + m_cursor_x;
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
219 m_cursor_x += gw + k_pad;
220 if (gh > m_shelf_height) {
221 m_shelf_height = gh;
222 }
223
224 m_dirty = true;
225 return true;
226}
#define MF_ERROR(comp, ctx,...)
const std::vector< float > * pixels
Definition Decoder.cpp:48
uint32_t * dst
const uint32_t * src
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.

References MayaFlux::Portal::Text::GlyphMetrics::advance_x, MayaFlux::Journal::API, MayaFlux::Portal::Text::GlyphMetrics::bearing_x, MayaFlux::Portal::Text::GlyphMetrics::bearing_y, dst, MayaFlux::Portal::Text::GlyphMetrics::face, MayaFlux::Portal::Text::FontFace::get_face(), MayaFlux::Portal::Text::GlyphMetrics::glyph_index, grow(), MayaFlux::Portal::Text::GlyphMetrics::height, m_atlas_size, m_cache, m_cursor_x, m_cursor_y, m_dirty, m_pixel_size, m_shelf_height, m_texture, MF_ERROR, pixels, MayaFlux::Journal::Portal, src, MayaFlux::Portal::Text::GlyphMetrics::uv_x0, MayaFlux::Portal::Text::GlyphMetrics::uv_x1, MayaFlux::Portal::Text::GlyphMetrics::uv_y0, MayaFlux::Portal::Text::GlyphMetrics::uv_y1, and MayaFlux::Portal::Text::GlyphMetrics::width.

Referenced by get_or_rasterize_from(), and grow().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: