| 408 | } |
| 409 | |
| 410 | void Gui::text(const Vector3 &pos, u32 font_size, const char *str, StringId64 font, StringId64 material, const Color4 &color) |
| 411 | { |
| 412 | const MaterialResource *mr = (MaterialResource *)_resource_manager->get(RESOURCE_TYPE_MATERIAL, material); |
| 413 | _material_manager->create_material(mr); |
| 414 | |
| 415 | const FontResource *fr = (FontResource *)_resource_manager->get(RESOURCE_TYPE_FONT, font); |
| 416 | const f32 scale = (f32)font_size / (f32)fr->font_size; |
| 417 | |
| 418 | VertexData *vd = (VertexData *)_buffer->vertex_buffer_end(); |
| 419 | u16 *id = (u16 *)_buffer->index_buffer_end(); |
| 420 | |
| 421 | u32 num_vertices = 0; |
| 422 | u32 num_indices = 0; |
| 423 | |
| 424 | u32 cp; |
| 425 | u32 state = 0; |
| 426 | f32 pen_x = 0.0f; |
| 427 | f32 pen_y = 0.0f; |
| 428 | const GlyphData deffault_glyph = {}; |
| 429 | |
| 430 | for (const u8 *ch = (u8 *)str; *ch; ++ch) { |
| 431 | if (utf8::decode(&state, &cp, *ch) != UTF8_ACCEPT) |
| 432 | continue; |
| 433 | |
| 434 | if (cp == '\n') { |
| 435 | pen_x = 0.0f; |
| 436 | pen_y -= scale*fr->font_size; |
| 437 | continue; |
| 438 | } else if (cp == '\t') { |
| 439 | pen_x += scale*font_size*4; |
| 440 | continue; |
| 441 | } |
| 442 | |
| 443 | const GlyphData *glyph = font_resource::glyph(fr, cp, &deffault_glyph); |
| 444 | const f32 baseline = glyph->height - glyph->y_offset; |
| 445 | const f32 x_offset = fsign(pen_x) * scale*glyph->x_offset; |
| 446 | |
| 447 | // Glyph position coords. |
| 448 | const f32 x0 = pen_x + pos.x + x_offset; |
| 449 | const f32 y0 = pen_y + pos.y - scale*baseline; |
| 450 | const f32 x1 = fround(x0 + scale*glyph->width); |
| 451 | const f32 y1 = fround(y0 + scale*glyph->height); |
| 452 | |
| 453 | pen_x += scale*glyph->x_advance; |
| 454 | |
| 455 | // Glyph atlas coords. |
| 456 | const f32 u0 = glyph->x / fr->texture_size; |
| 457 | const f32 v1 = glyph->y / fr->texture_size; // Upper-left char corner |
| 458 | const f32 u1 = glyph->width / fr->texture_size + u0; |
| 459 | const f32 v0 = glyph->height / fr->texture_size + v1; // Bottom-left char corner |
| 460 | |
| 461 | const u32 abgr = to_abgr(color); |
| 462 | |
| 463 | // Fill vertex buffer. |
| 464 | vd[0].pos.x = x0; |
| 465 | vd[0].pos.y = y0; |
| 466 | vd[0].pos.z = 0.0f; |
| 467 | vd[0].uv.x = u0; |
no test coverage detected