MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TextSlice.cpp
Go to the documentation of this file.
1#include "TextSlice.hpp"
2
3#include "Atelier.hpp"
4
6
7namespace {
8
9 std::vector<std::weak_ptr<TextSlice>>& live_slices()
10 {
11 static std::vector<std::weak_ptr<TextSlice>> slices;
12 return slices;
13 }
14
15 bool& reflowing()
16 {
17 static bool active = false;
18 return active;
19 }
20
21 void reflow_others(const TextSlice* origin, const Text::GlyphAtlas* atlas)
22 {
23 if (reflowing()) {
24 return;
25 }
26 reflowing() = true;
27
28 auto& slices = live_slices();
29 std::erase_if(slices, [](const auto& slice) { return slice.expired(); });
30 for (const auto& weak : slices) {
31 if (auto slice = weak.lock();
32 slice && slice.get() != origin && slice->run().atlas() == atlas && slice->run().stale()) {
33 slice->refresh();
34 }
35 }
36
37 reflowing() = false;
38 }
39
40} // namespace
41
43 : m_target(std::move(target))
44 , m_bounds(bounds)
45 , m_run(std::move(params))
46{
47}
48
49std::shared_ptr<TextSlice> TextSlice::make(
50 FormaTarget target,
51 Kinesis::AABB2D bounds,
52 Text::PressParams params,
53 std::string_view text)
54{
55 auto slice = std::shared_ptr<TextSlice>(new TextSlice(std::move(target), bounds, std::move(params)));
56 live_slices().push_back(slice);
57 slice->set(text);
58 return slice;
59}
60
61void TextSlice::set(std::string_view text)
62{
63 m_run.set(text);
64 refresh();
65}
66
67void TextSlice::assign(std::string_view text, Text::PressParams params)
68{
69 m_run.assign(text, std::move(params));
70 refresh();
71}
72
78
79void TextSlice::set_tail(std::vector<Kakshya::MeshVertex> tail)
80{
81 m_tail = std::move(tail);
82 refresh();
83}
84
86{
88}
89
90bool TextSlice::alive() const
91{
92 const auto& buffer = m_target.buffer();
93 if (!buffer || buffer->needs_removal()) {
94 return false;
95 }
96 return m_target.slice() == 0 || buffer->has_slice(m_target.slice());
97}
98
100{
101 Text::GlyphAtlas* atlas = m_run.atlas();
102 if (!atlas || !alive()) {
103 return;
104 }
105
106 auto vertices = m_run.vertices(map(), 0);
107 vertices.insert(vertices.end(), m_tail.begin(), m_tail.end());
108
109 const auto gpu = atelier().atlas_image(*atlas).sync(*atlas);
110
111 const bool replaced = gpu && gpu != m_bound_image;
112 const bool superseded = replaced && m_bound_image;
113 if (replaced) {
114 m_target.bind_texture(0, gpu);
115 m_bound_image = gpu;
116 }
117
118 m_target.submit(vertices);
119
120 if (superseded) {
121 reflow_others(this, atlas);
122 }
123}
124
125} // namespace MayaFlux::Portal::Forma::internal
std::shared_ptr< NetworkGeometryBuffer > buffer
void submit(const std::vector< uint8_t > &bytes) const
Replace this target's geometry.
Definition Target.cpp:51
SliceId slice() const noexcept
Slice id, 0 when the handle means the whole buffer.
Definition Target.cpp:46
const std::shared_ptr< Buffers::FormaBuffer > & buffer() const noexcept
The underlying buffer; null for an empty handle.
Definition Target.cpp:40
void bind_texture(uint32_t array_index, const std::shared_ptr< Core::VKImage > &image) const
Bind a texture in the buffer's texture array.
Definition Target.cpp:63
Where an element's geometry and texture are written.
Definition Target.hpp:22
Text::AtlasImage & atlas_image(const Text::GlyphAtlas &atlas)
The GPU image of atlas, shared by every text slice drawing from it.
Definition Atelier.hpp:98
static std::shared_ptr< TextSlice > make(FormaTarget target, Kinesis::AABB2D bounds, Text::PressParams params, std::string_view text)
Draw text in bounds on target.
Definition TextSlice.cpp:49
void set_bounds(Kinesis::AABB2D bounds)
Move the text to a new region.
Definition TextSlice.cpp:73
std::shared_ptr< Core::VKImage > m_bound_image
Definition TextSlice.hpp:74
std::vector< Kakshya::MeshVertex > m_tail
Definition TextSlice.hpp:73
void set_tail(std::vector< Kakshya::MeshVertex > tail)
Replace the extra vertices drawn after the glyphs, such as a caret.
Definition TextSlice.cpp:79
void refresh()
Write the current state to the target. No-op once the target is gone.
Definition TextSlice.cpp:99
TextSlice(FormaTarget target, Kinesis::AABB2D bounds, Text::PressParams params)
Definition TextSlice.cpp:42
Kinesis::AABB2D bounds() const noexcept
Definition TextSlice.hpp:57
void assign(std::string_view text, Text::PressParams params)
Replace text and parameters together.
Definition TextSlice.cpp:67
Text::GlyphMap map() const noexcept
Layout pixels to NDC for the current bounds.
Definition TextSlice.cpp:85
void set(std::string_view text)
Replace the text.
Definition TextSlice.cpp:61
Text drawn as glyph quads into one FormaTarget.
Definition TextSlice.hpp:27
std::shared_ptr< Core::VKImage > sync(GlyphAtlas &atlas)
Bring the image up to date with atlas.
Definition AtlasImage.cpp:9
Rasterizes and packs glyphs from a FontFace into a TextureContainer.
glm::vec2 extent() const
Size in pixels the run is drawn at.
Definition TextRun.cpp:68
std::vector< Kakshya::MeshVertex > vertices(const GlyphMap &map, uint32_t slot)
Vertices for the background, if any, then every glyph.
Definition TextRun.cpp:86
GlyphAtlas * atlas() const
The atlas the run draws from: params().atlas, else the default.
Definition TextRun.cpp:38
void assign(std::string_view text, PressParams params)
Replace text and parameters together, laying out once.
Definition TextRun.cpp:31
void set(std::string_view text)
Replace the text and lay it out.
Definition TextRun.cpp:19
std::vector< double > slice(std::span< const double > data, double start_ratio, double end_ratio)
Extract a contiguous slice by ratio, returning a new vector.
Atelier & atelier()
Accessor for the process-wide Atelier.
Definition Atelier.hpp:304
Axis-aligned bounding rectangle in a 2D coordinate space.
Definition Bounds.hpp:63
static GlyphMap fit(Kinesis::AABB2D region, glm::vec2 source_px) noexcept
Map layout pixels [0, source_px] onto region, y flipped.
Definition GlyphMesh.cpp:5
Linear map from layout pixels to whatever space the vertices are drawn in.
Definition GlyphMesh.hpp:21
Construction parameters for press().
Definition InkPress.hpp:65