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

◆ rasterize_quads()

MAYAFLUX_API void MayaFlux::Portal::Text::rasterize_quads ( std::span< const GlyphQuad >  quads,
GlyphAtlas &  atlas,
glm::vec4  color,
uint8_t *  dst,
uint32_t  buf_w,
uint32_t  buf_h 
)

Write glyph quads into a caller-provided RGBA8 pixel buffer.

Applies coverage-multiplied alpha blend per glyph cell, compositing over whatever is already in dst rather than overwriting it - a glyph's bounding box includes its own zero-coverage interior (the hole in an 'o' or 'e'), so composited blending is what keeps a pre-filled background intact under that hole instead of a low-coverage pixel punching it transparent. The destination buffer must be row-major RGBA8 with stride == buf_w * 4 bytes. Quads that fall outside [0, buf_w) x [0, buf_h) are clipped per pixel.

The typical usage pattern is:

auto layout = lay_out(text, atlas, 0.F, 0.F, wrap_w);
for (auto& q : layout.quads) { ... } // per-character transforms
rasterize_quads(layout.quads, atlas, color, pixels, w, h);
glm::vec3 color
Definition Decoder.cpp:97
const std::vector< float > * pixels
Definition Decoder.cpp:48
uint32_t h
Definition InkPress.cpp:29
double q
void rasterize_quads(std::span< const GlyphQuad > quads, GlyphAtlas &atlas, glm::vec4 color, uint8_t *dst, uint32_t buf_w, uint32_t buf_h)
Write glyph quads into a caller-provided RGBA8 pixel buffer.
Definition InkPress.cpp:244
LayoutResult lay_out(std::string_view text, GlyphAtlas &atlas, float pen_x, float pen_y, uint32_t wrap_w, uint32_t tab_width)
Lay out a UTF-8 string into a sequence of screen-space quads.
Parameters
quadsQuads produced by lay_out(), optionally mutated by the caller.
atlasSource atlas for coverage bitmaps.
colorRGBA glyph color in [0, 1].
dstDestination RGBA8 buffer. Stride is buf_w * 4 bytes.
buf_wBuffer width in pixels.
buf_hBuffer height in pixels.

Definition at line 244 of file InkPress.cpp.

251{
252 const uint8_t cr = static_cast<uint8_t>(std::clamp(color.r, 0.F, 1.F) * 255.F);
253 const uint8_t cg = static_cast<uint8_t>(std::clamp(color.g, 0.F, 1.F) * 255.F);
254 const uint8_t cb = static_cast<uint8_t>(std::clamp(color.b, 0.F, 1.F) * 255.F);
255 const uint8_t ca = static_cast<uint8_t>(std::clamp(color.a, 0.F, 1.F) * 255.F);
256
257 const Kakshya::TextureContainer& atlas_tex = atlas.texture();
258 const std::span<const uint8_t> atlas_pixels = atlas_tex.pixel_bytes(0);
259 const uint32_t atlas_size = atlas.atlas_size();
260
261 for (const auto& q : quads) {
262 const auto gx = static_cast<int32_t>(std::floor(q.x0));
263 const auto gy = static_cast<int32_t>(std::floor(q.y0));
264 const auto gw = static_cast<uint32_t>(std::ceil(q.x1 - q.x0));
265 const auto gh = static_cast<uint32_t>(std::ceil(q.y1 - q.y0));
266
267 const auto src_x = static_cast<uint32_t>(q.uv_x0 * static_cast<float>(atlas_size));
268 const auto src_y = static_cast<uint32_t>(q.uv_y0 * static_cast<float>(atlas_size));
269
270 for (uint32_t row = 0; row < gh; ++row) {
271 const int32_t dst_row = gy + static_cast<int32_t>(row);
272 if (dst_row < 0 || static_cast<uint32_t>(dst_row) >= buf_h) {
273 continue;
274 }
275
276 const uint8_t* src_row = atlas_pixels.data()
277 + static_cast<size_t>(src_y + row) * atlas_size + src_x;
278 uint8_t* dst_row_ptr = dst + static_cast<size_t>(dst_row) * buf_w * 4;
279
280 for (uint32_t col = 0; col < gw; ++col) {
281 const int32_t dst_col = gx + static_cast<int32_t>(col);
282 if (dst_col < 0 || static_cast<uint32_t>(dst_col) >= buf_w) {
283 continue;
284 }
285
286 const uint8_t coverage = src_row[col];
287 const uint32_t src_a = (static_cast<uint32_t>(coverage) * static_cast<uint32_t>(ca)) / 255U;
288
289 uint8_t* px = dst_row_ptr + static_cast<size_t>(dst_col) * 4;
290
291 const uint32_t dst_a = px[3];
292 const uint32_t blended_dst_a = (dst_a * (255U - src_a)) / 255U;
293 const uint32_t out_a = src_a + blended_dst_a;
294
295 if (out_a == 0U) {
296 px[0] = 0;
297 px[1] = 0;
298 px[2] = 0;
299 px[3] = 0;
300 } else {
301 px[0] = static_cast<uint8_t>((cr * src_a + px[0] * blended_dst_a) / out_a);
302 px[1] = static_cast<uint8_t>((cg * src_a + px[1] * blended_dst_a) / out_a);
303 px[2] = static_cast<uint8_t>((cb * src_a + px[2] * blended_dst_a) / out_a);
304 px[3] = static_cast<uint8_t>(out_a);
305 }
306 }
307 }
308 }
309}
uint32_t * dst
uint32_t px
float src_y
float src_x
std::span< const uint8_t > pixel_bytes(uint32_t layer=0) const
Read-only byte-level view over the pixel buffer.
SignalSourceContainer wrapping GPU texture data as addressable pixel bytes.
uint32_t atlas_size() const
Atlas texture dimension (width == height == atlas_size).
const Kakshya::TextureContainer & texture() const
The atlas texture as a TextureContainer (R8, atlas_size x atlas_size).

References MayaFlux::Portal::Text::GlyphAtlas::atlas_size(), color, dst, MayaFlux::Kakshya::TextureContainer::pixel_bytes(), px, q, src_x, src_y, and MayaFlux::Portal::Text::GlyphAtlas::texture().

Referenced by ink_quads().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: