MayaFlux 0.4.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 m_pen_x = pen_x;
56 m_pen_y = pen_y;
57 m_center.reset();
58 m_dirty = true;
59}
60
61void GlyphGeometryNode::set_center(std::optional<glm::vec2> center)
62{
63 m_center = center;
64 m_dirty = true;
65}
66
67void GlyphGeometryNode::set_color(glm::vec3 color)
68{
69 m_color = color;
70 m_dirty = true;
71}
72
74{
75 m_thickness = thickness;
76 m_dirty = true;
77}
78
80{
81 m_outlines.clear();
82 m_pen_offsets.clear();
83
84 if (m_text.empty()) {
85 resize_vertex_buffer(0, false);
87 return;
88 }
89
90 float cursor_x = m_pen_x;
91 float cursor_y = m_pen_y;
92
93 const auto* bytes = reinterpret_cast<const utf8proc_uint8_t*>(m_text.data());
94 auto remaining = static_cast<utf8proc_ssize_t>(m_text.size());
95 utf8proc_ssize_t offset = 0;
96
97 while (offset < remaining) {
98 utf8proc_int32_t cp = 0;
99 const utf8proc_ssize_t n = utf8proc_iterate(bytes + offset, remaining - offset, &cp);
100
101 if (n <= 0) {
102 offset += 1;
103 continue;
104 }
105 offset += n;
106
107 if (cp < 0)
108 continue;
109
110 if (cp == '\n') {
111 const uint32_t px = m_face
115 : 0);
117 cursor_y += static_cast<float>(px);
118 continue;
119 }
120
121 if (cp == '\r')
122 continue;
123
125 ? Portal::Text::decompose_glyph(*m_face, static_cast<uint32_t>(cp), m_pixel_size, m_tolerance)
126 : Portal::Text::decompose_glyph(static_cast<uint32_t>(cp), m_tolerance);
127
128 m_pen_offsets.emplace_back(cursor_x, cursor_y);
129 m_outlines.push_back(std::move(outline));
130
131 cursor_x += static_cast<float>(m_outlines.back().advance_x);
132 }
133
135}
136
137void GlyphGeometryNode::set_pen_offsets(std::vector<glm::vec2> offsets)
138{
139 if (offsets.size() != m_outlines.size())
140 return;
141 m_pen_offsets = std::move(offsets);
142 m_vertex_data_dirty = true;
143}
144
146{
147 size_t total_pairs = 0;
148
149 for (const auto& ol : m_outlines) {
150 uint32_t prev_end = 0;
151 for (uint32_t end : ol.contour_ends) {
152 const uint32_t count = end - prev_end;
153 if (count >= 2)
154 total_pairs += count - 1;
155 prev_end = end;
156 }
157 }
158
159 std::vector<Kakshya::LineVertex> verts;
160 verts.reserve(total_pairs * 2);
161
162 for (size_t gi = 0; gi < m_outlines.size(); ++gi) {
163 const auto& ol = m_outlines[gi];
164 const glm::vec2 off = m_pen_offsets[gi];
165
166 uint32_t prev_end = 0;
167 for (uint32_t end : ol.contour_ends) {
168 const uint32_t count = end - prev_end;
169 if (count < 2) {
170 prev_end = end;
171 continue;
172 }
173
174 for (uint32_t pi = prev_end; pi < end - 1; ++pi) {
175 const glm::vec2 a = ol.points[pi] + off;
176 const glm::vec2 b = ol.points[pi + 1] + off;
177 verts.push_back({ .position = { a.x, a.y, 0.F }, .color = m_color, .thickness = m_thickness });
178 verts.push_back({ .position = { b.x, b.y, 0.F }, .color = m_color, .thickness = m_thickness });
179 }
180
181 prev_end = end;
182 }
183 }
184
185 set_vertices<Kakshya::LineVertex>(std::span { verts.data(), verts.size() });
186
187 auto layout = get_vertex_layout();
188 layout->vertex_count = static_cast<uint32_t>(verts.size());
189 set_vertex_layout(*layout);
190
191 m_vertex_data_dirty = true;
192 m_dirty = false;
193}
194
196{
198 return;
200}
201
202} // namespace MayaFlux::Nodes::GpuSync
float tolerance
uint32_t cursor_y
Definition InkPress.cpp:30
uint32_t cursor_x
Definition InkPress.cpp:29
size_t a
size_t b
size_t count
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.