Re-composite a UTF-8 string into an existing GPU texture.
Uploads in-place when content fits within the existing image dimensions. Reallocates and updates target when content height exceeds image height.
391{
392 if (!target) {
393 MF_ERROR(Journal::Component::Portal, Journal::Context::API,
394 "repress(VKImage): target is null");
395 return false;
396 }
397
398 GlyphAtlas* atlas = resolve_atlas(params.
atlas);
399 if (!atlas)
400 return false;
401
402 const uint32_t buf_w = target->get_width();
403 const uint32_t buf_h = target->get_height();
404
405 const uint32_t composite_h = std::max(buf_h,
406 static_cast<uint32_t>(atlas->line_height()));
407
408 const auto result = composite(text, *atlas, params.
color, buf_w, composite_h,
409 static_cast<float>(atlas->ascender()));
410 if (!result) {
411 MF_WARN(Journal::Component::Portal, Journal::Context::API,
412 "repress(VKImage): no glyphs produced for '{}'", std::string(text));
413 return false;
414 }
415
416 auto& loom = Portal::Graphics::get_texture_manager();
417
418 const uint32_t new_h = composite_h;
419 const bool needs_realloc = composite_h != buf_h || buf_w != target->get_width();
420
421 const size_t buf_bytes = static_cast<size_t>(buf_w) * new_h * 4;
422 std::vector<uint8_t>
pixels(buf_bytes, 0);
423
424 const uint32_t copy_h = std::min(result->h, new_h);
425 for (uint32_t row = 0; row < copy_h; ++row) {
426 std::memcpy(
427 pixels.data() +
static_cast<size_t>(row) * buf_w * 4,
428 result->pixels.data() + static_cast<size_t>(row) * buf_w * 4,
429 static_cast<size_t>(buf_w) * 4);
430 }
431
432 if (needs_realloc) {
433 target = loom.create_2d(buf_w, new_h, Portal::Graphics::ImageFormat::RGBA8,
434 nullptr, 1);
435 if (!target)
436 return false;
437 if (staging) {
438 loom.upload_data(target,
pixels.data(), buf_bytes, staging,
true);
439 } else {
440 loom.upload_data(target,
pixels.data(), buf_bytes);
441 }
442
443 MF_DEBUG(Journal::Component::Portal, Journal::Context::API,
444 "repress(VKImage): reallocated {}x{}", buf_w, new_h);
445 return true;
446 }
447
448 if (staging) {
449 loom.upload_data(target,
pixels.data(), buf_bytes, staging);
450 } else {
451 loom.upload_data(target,
pixels.data(), buf_bytes);
452 }
453
454 MF_DEBUG(Journal::Component::Portal, Journal::Context::API,
455 "repress(VKImage): updated {}x{} in-place", buf_w, buf_h);
456
457 return true;
458}
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::vector< uint8_t > pixels
GlyphAtlas * atlas
Glyph atlas to use. Null selects the TypeFaceFoundry default at call time.
glm::vec4 color
RGBA color applied to all glyphs.