MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
GlyphGeometryNode.cpp
Go to the documentation of this file.
2
6
7#include <utf8proc.h>
8
10
12 std::string text,
13 float pen_x,
14 float pen_y,
15 float tolerance)
17 , m_text(std::move(text))
18 , m_pen_x(pen_x)
19 , m_pen_y(pen_y)
20 , m_tolerance(tolerance)
21{
25}
26
29 uint32_t pixel_size,
30 std::string text,
31 float pen_x,
32 float pen_y,
33 float tolerance)
35 , m_face(&face)
36 , m_pixel_size(pixel_size)
37 , m_text(std::move(text))
38 , m_pen_x(pen_x)
39 , m_pen_y(pen_y)
40 , m_tolerance(tolerance)
41{
45}
46
47void GlyphGeometryNode::set_text(std::string text)
48{
49 m_text = std::move(text);
51}
52
53void GlyphGeometryNode::set_pen(float pen_x, float pen_y)
54{
55 const glm::vec2 delta { pen_x - m_pen_x, pen_y - m_pen_y };
56 m_pen_x = pen_x;
57 m_pen_y = pen_y;
58 for (auto& offset : m_pen_offsets) {
59 offset += delta;
60 }
61 m_center.reset();
62 m_dirty = true;
63}
64
65void GlyphGeometryNode::set_center(std::optional<glm::vec2> center)
66{
67 m_center = center;
68 m_dirty = true;
69}
70
72{
73 m_color = color;
74 m_dirty = true;
75}
76
78{
79 m_thickness = thickness;
80 m_dirty = true;
81}
82
84{
85 m_outlines.clear();
86 m_pen_offsets.clear();
87
88 if (m_text.empty()) {
89 resize_vertex_buffer(0, false);
91 return;
92 }
93
94 float cursor_x = m_pen_x;
95 float cursor_y = m_pen_y;
96
97 const auto* bytes = reinterpret_cast<const utf8proc_uint8_t*>(m_text.data());
98 auto remaining = static_cast<utf8proc_ssize_t>(m_text.size());
99 utf8proc_ssize_t offset = 0;
100
101 while (offset < remaining) {
102 utf8proc_int32_t cp = 0;
103 const utf8proc_ssize_t n = utf8proc_iterate(bytes + offset, remaining - offset, &cp);
104
105 if (n <= 0) {
106 offset += 1;
107 continue;
108 }
109 offset += n;
110
111 if (cp < 0)
112 continue;
113
114 if (cp == '\n') {
115 const uint32_t px = m_face
119 : 0);
121 cursor_y += static_cast<float>(px);
122 continue;
123 }
124
125 if (cp == '\r')
126 continue;
127
129 ? Portal::Text::decompose_glyph(*m_face, static_cast<uint32_t>(cp), m_pixel_size, m_tolerance)
130 : Portal::Text::decompose_glyph(static_cast<uint32_t>(cp), m_tolerance);
131
132 m_pen_offsets.emplace_back(cursor_x, cursor_y);
133 m_outlines.push_back(std::move(outline));
134
135 cursor_x += static_cast<float>(m_outlines.back().advance_x);
136 }
137
139}
140
141void GlyphGeometryNode::set_pen_offsets(std::vector<glm::vec2> offsets)
142{
143 if (offsets.size() != m_outlines.size())
144 return;
145 m_pen_offsets = std::move(offsets);
146 m_vertex_data_dirty = true;
147}
148
150{
151 size_t total_pairs = 0;
152
153 for (const auto& ol : m_outlines) {
154 uint32_t prev_end = 0;
155 for (uint32_t end : ol.contour_ends) {
156 const uint32_t count = end - prev_end;
157 if (count >= 2)
158 total_pairs += count - 1;
159 prev_end = end;
160 }
161 }
162
163 std::vector<Kakshya::LineVertex> verts;
164 verts.reserve(total_pairs * 2);
165
166 for (size_t gi = 0; gi < m_outlines.size(); ++gi) {
167 const auto& ol = m_outlines[gi];
168 const glm::vec2 off = m_pen_offsets[gi];
169
170 uint32_t prev_end = 0;
171 for (uint32_t end : ol.contour_ends) {
172 const uint32_t count = end - prev_end;
173 if (count < 2) {
174 prev_end = end;
175 continue;
176 }
177
178 for (uint32_t pi = prev_end; pi < end - 1; ++pi) {
179 const glm::vec2 a = ol.points[pi] + off;
180 const glm::vec2 b = ol.points[pi + 1] + off;
181 verts.push_back({ .position = { a.x, a.y, 0.F }, .color = m_color, .thickness = m_thickness });
182 verts.push_back({ .position = { b.x, b.y, 0.F }, .color = m_color, .thickness = m_thickness });
183 }
184
185 prev_end = end;
186 }
187 }
188
189 set_vertices<Kakshya::LineVertex>(std::span { verts.data(), verts.size() });
190
191 auto layout = get_vertex_layout();
192 layout->vertex_count = static_cast<uint32_t>(verts.size());
193 set_vertex_layout(*layout);
194
195 m_vertex_data_dirty = true;
196 m_dirty = false;
197}
198
200{
202 return;
204}
205
206} // namespace MayaFlux::Nodes::GpuSync
uint64_t offset
Definition Composite.cpp:10
glm::vec3 color
Definition Decoder.cpp:97
float tolerance
uint32_t cursor_y
Definition InkPress.cpp:31
uint32_t cursor_x
Definition InkPress.cpp:30
size_t a
size_t b
size_t count
uint32_t px
bool m_vertex_data_dirty
Flag: vertex data or layout changed since last GPU upload.
std::optional< Kakshya::VertexLayout > get_vertex_layout() const
Get cached vertex layout.
void set_vertex_layout(const Kakshya::VertexLayout &layout)
Set cached vertex layout.
void resize_vertex_buffer(uint32_t vertex_count, bool preserve_data=false)
Resize vertex buffer to hold specified number of vertices.
void set_vertex_stride(size_t stride)
Set vertex stride (bytes per vertex)
Base class for nodes that generate 3D geometry data.
void compute_frame() override
Upload cached vertex data if dirty.
void set_pen(float pen_x, float pen_y)
Set pen origin for layout.
std::vector< Portal::Text::GlyphOutline > m_outlines
void set_pen_offsets(std::vector< glm::vec2 > offsets)
Override pen offsets for all glyphs.
void rebuild_outlines()
Rebuild outline geometry from the current text and pen settings.
void set_center(std::optional< glm::vec2 > center)
Place the text block so its bounding box center falls on center.
void set_thickness(float thickness)
Set uniform line thickness for all glyph contours.
void set_color(glm::vec3 color)
Set uniform color for all glyph contours.
void set_text(std::string text)
Replace the text string and rebuild outlines.
GlyphGeometryNode(std::string text, float pen_x=0.F, float pen_y=0.F, float tolerance=0.5F)
Construct from a UTF-8 string using the default font.
Owns a single FT_Face loaded from a file path.
Definition FontFace.hpp:24
uint32_t pixel_size() const
Pixel size passed at construction.
GlyphAtlas * get_default_glyph_atlas() const
Return the default GlyphAtlas, or nullptr if set_default_font() has not been called successfully.
GlyphOutline decompose_glyph(FontFace &face, uint32_t codepoint, uint32_t pixel_size, float tolerance)
Decompose a Unicode codepoint into a tessellated polyline outline.
Vertex type for line primitives (LINE_LIST / LINE_STRIP topology)
static VertexLayout for_lines(uint32_t stride=60)
Factory: layout for LineVertex (position, color, thickness, uv, normal, tangent)
Vector outline for a single glyph as a flat polyline sequence.