Re-composite a UTF-8 string into an existing TextBuffer.
Always clears the buffer to target->get_background() before compositing. Render bounds and atlas are read from the target buffer. When the target has a pre-allocated vertical budget the compositing bounds are the budget dimensions, so no VKImage rebuild occurs as long as content fits.
439{
440 if (!target) {
441 MF_ERROR(Journal::Component::Portal, Journal::Context::API,
442 "repress: target buffer is null");
443 return false;
444 }
445
446 GlyphAtlas* atlas = resolve_atlas(nullptr);
447 if (!atlas) {
448 return false;
449 }
450
451 target->clear_accumulated_text();
452 target->reset_cursor();
453
454 const uint32_t buf_w = target->get_budget_width();
455 const uint32_t buf_h = target->get_budget_height();
456 const uint32_t bound_h = target->get_render_bounds_h();
457 const glm::vec4 background = target->get_background();
458
459 const auto result = composite(text, *atlas,
color, buf_w, bound_h,
460 static_cast<float>(atlas->line_height()), spans, background);
461 if (!result) {
462 MF_WARN(Journal::Component::Portal, Journal::Context::API,
463 "repress: no glyphs produced for '{}'", std::string(text));
464 return false;
465 }
466
467 if (result->h > buf_h && policy == RedrawPolicy::Fit) {
468 const uint32_t new_h = std::min(result->h, bound_h);
469 target->resize_texture(buf_w, new_h);
470 target->set_budget(buf_w, new_h);
471 target->set_pixel_data(result->pixels.data(), result->pixels.size());
472 target->get_cursor_x() = result->cursor_x;
473 target->get_cursor_y() = result->cursor_y;
474 target->set_accumulated_text(text);
475
476 MF_DEBUG(Journal::Component::Portal, Journal::Context::API,
477 "repress(Fit): resized to {}x{}", buf_w, new_h);
478 return true;
479 }
480
481 const size_t buf_bytes = static_cast<size_t>(buf_w) * buf_h * 4;
482 std::vector<uint8_t> cleared = make_filled(buf_bytes, background);
483
484 const uint32_t copy_h = std::min(result->h, buf_h);
485 for (uint32_t row = 0; row < copy_h; ++row) {
486 std::memcpy(
487 cleared.data() + static_cast<size_t>(row) * buf_w * 4,
488 result->pixels.data() + static_cast<size_t>(row) * buf_w * 4,
489 static_cast<size_t>(buf_w) * 4);
490 }
491
492 target->set_pixel_data(cleared.data(), buf_bytes);
493 target->get_cursor_x() = result->cursor_x;
494 target->get_cursor_y() = result->cursor_y;
495
496 target->set_accumulated_text(text);
497
498 MF_DEBUG(Journal::Component::Portal, Journal::Context::API,
499 "repress(Clip): '{}' -> {}x{} into {}x{} budget",
500 std::string(text), buf_w, result->h, buf_w, buf_h);
501
502 return true;
503}
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)