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

◆ impress()

MAYAFLUX_API ImpressResult MayaFlux::Portal::Text::impress ( const std::shared_ptr< Buffers::TextBuffer > &  target,
std::string_view  text,
glm::vec4  color = { 1.F, 1.F, 1.F, 1.F },
std::span< const StyleSpan >  spans = {} 
)

Append a UTF-8 string into an existing TextBuffer at the current cursor.

Does not clear existing content. Composites the new run into the pre-allocated budget region and advances the cursor. No VKImage reallocation occurs while the run fits within the vertical budget.

When the run would push the cursor past the vertical budget the texture is grown by k_grow_height_multiplier, the full accumulated text is recomposited against target->get_background(), and ImpressResult::Overflow is returned. The caller is responsible for rebuilding prior content after an overflow if accumulated state is not sufficient.

When the cursor would exceed render_bounds_h the run is rejected and ImpressResult::Overflow is returned without reallocation.

The atlas is always the TypeFaceFoundry default. If a non-default atlas was used at press() time, impress() will use the default instead. Mixing atlases on the same TextBuffer is undefined behaviour.

spans is offsets into this call's text, matching the byte_offset lay_out() assigns for this run. On the Overflow-and-regrow path the full accumulated text is recomposited using color and spans from this call alone; prior runs' own colors/spans are not retained, the same pre-existing limitation color already has on that path.

Parameters
targetExisting TextBuffer to append into.
textUTF-8 string to composite.
colorRGBA glyph color for any byte not covered by spans.
spansOptional per-byte-range color overrides, offsets into text.
Returns
ImpressResult::Ok or ImpressResult::Overflow.

Definition at line 582 of file InkPress.cpp.

587{
588 if (!target) {
589 MF_ERROR(Journal::Component::Portal, Journal::Context::API,
590 "impress: target buffer is null");
591 return ImpressResult::Overflow;
592 }
593
594 GlyphAtlas* atlas = resolve_atlas(nullptr);
595 if (!atlas) {
596 return ImpressResult::Overflow;
597 }
598
599 const uint32_t buf_w = target->get_budget_width();
600 const uint32_t buf_h = target->get_budget_height();
601 const uint32_t bound_h = target->get_render_bounds_h();
602 const auto pen_x = static_cast<float>(target->get_cursor_x());
603 const auto pen_y = static_cast<float>(target->get_cursor_y());
604
605 target->append_accumulated_text(text);
606
607 const LayoutResult layout = lay_out(text, *atlas, pen_x, pen_y, buf_w);
608
609 const auto pen_y_ceil = static_cast<uint32_t>(std::ceil(layout.final_pen_y));
610 const uint32_t new_cursor_y = pen_y_ceil;
611 const uint32_t content_h = pen_y_ceil + atlas->line_height();
612
613 if (content_h > bound_h) {
614 return ImpressResult::Overflow;
615 }
616
617 if (content_h > buf_h) {
618 const uint32_t new_h = std::min(content_h * k_grow_height_multiplier, bound_h);
619 const std::string accumulated = target->get_accumulated_text();
620 const glm::vec4 background = target->get_background();
621
622 const auto full = composite(accumulated, *atlas, color, buf_w, new_h,
623 static_cast<float>(atlas->line_height()), spans, background);
624 if (!full) {
625 return ImpressResult::Overflow;
626 }
627
628 target->resize_texture(buf_w, new_h);
629 target->set_budget(buf_w, new_h);
630
631 const size_t buf_bytes = static_cast<size_t>(buf_w) * new_h * 4;
632 std::vector<uint8_t> pixels = make_filled(buf_bytes, background);
633 const uint32_t copy_h = std::min(full->h, new_h);
634 for (uint32_t row = 0; row < copy_h; ++row) {
635 std::memcpy(
636 pixels.data() + static_cast<size_t>(row) * buf_w * 4,
637 full->pixels.data() + static_cast<size_t>(row) * buf_w * 4,
638 static_cast<size_t>(buf_w) * 4);
639 }
640
641 target->set_pixel_data(pixels.data(), buf_bytes);
642 target->get_cursor_x() = full->cursor_x;
643 target->get_cursor_y() = full->cursor_y;
644 target->set_accumulated_text(accumulated);
645
646 MF_DEBUG(Journal::Component::Portal, Journal::Context::API,
647 "impress: vertical grow -> {}x{}", buf_w, new_h);
648
649 return ImpressResult::Overflow;
650 }
651
652 auto& pixel_data = target->get_pixel_data_mutable();
653 rasterize_styled(layout.quads, *atlas, color, spans, pixel_data.data(), buf_w, buf_h);
654 target->mark_pixels_dirty();
655 target->get_cursor_x() = static_cast<uint32_t>(std::ceil(layout.final_pen_x));
656 target->get_cursor_y() = new_cursor_y;
657
658 MF_DEBUG(Journal::Component::Portal, Journal::Context::API,
659 "impress: '{}' at ({},{}) -> cursor ({},{})",
660 std::string(text),
661 static_cast<uint32_t>(pen_x), static_cast<uint32_t>(pen_y),
662 target->get_cursor_x(), target->get_cursor_y());
663
664 return ImpressResult::Ok;
665}
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
glm::vec3 color
Definition Decoder.cpp:97
std::vector< uint8_t > pixels
Definition InkPress.cpp:32

References MayaFlux::Journal::API, color, MayaFlux::Portal::Text::LayoutResult::final_pen_x, MayaFlux::Portal::Text::LayoutResult::final_pen_y, lay_out(), MayaFlux::Portal::Text::GlyphAtlas::line_height(), MF_DEBUG, MF_ERROR, Ok, Overflow, pixels, MayaFlux::Journal::Portal, and MayaFlux::Portal::Text::LayoutResult::quads.

+ Here is the call graph for this function: