diff --git a/bindings/odin/examples/clay-official-website/clay_renderer_raylib.odin b/bindings/odin/examples/clay-official-website/clay_renderer_raylib.odin index ff624aa..792bb40 100644 --- a/bindings/odin/examples/clay-official-website/clay_renderer_raylib.odin +++ b/bindings/odin/examples/clay-official-website/clay_renderer_raylib.odin @@ -1,5 +1,7 @@ package main +import "core:unicode/utf8" +import "base:runtime" import clay "../../clay-odin" import "core:math" import "core:strings" @@ -17,23 +19,40 @@ clay_color_to_rl_color :: proc(color: clay.Color) -> rl.Color { raylib_fonts := [dynamic]Raylib_Font{} measure_text :: proc "c" (text: clay.StringSlice, config: ^clay.TextElementConfig, userData: rawptr) -> clay.Dimensions { - line_width: f32 = 0 + // Needed for grapheme_count + context = runtime.default_context() + + line_width: f32 = 0 + + font := raylib_fonts[config.fontId].font + text_str := string(text.chars[:text.length]) - font := raylib_fonts[config.fontId].font + // This function seems somewhat expensive, if you notice performance issues, you could assume + // - 1 codepoint per visual character (no grapheme clusters), where you can get the length from the loop + // - 1 byte per visual character (ascii), where you can get the length with `text.length` + grapheme_count, _, _ := utf8.grapheme_count(text_str) - for i in 0 ..< text.length { - glyph_index := text.chars[i] - 32 + for letter, byte_idx in text_str { + glyph_index := rl.GetGlyphIndex(font, letter) glyph := font.glyphs[glyph_index] - if glyph.advanceX != 0 { - line_width += f32(glyph.advanceX) - } else { - line_width += font.recs[glyph_index].width + f32(glyph.offsetX) - } - } + if glyph.advanceX != 0 { + line_width += f32(glyph.advanceX) + } else { + line_width += font.recs[glyph_index].width + f32(font.glyphs[glyph_index].offsetX) + } + } - return {width = line_width / 2, height = f32(config.fontSize)} + scaleFactor := f32(config.fontSize) / f32(font.baseSize) + + // Note: + // I'd expect this to be `grapheme_count - 1`, + // but that seems to be one letterSpacing too small + // maybe that's a raylib bug, maybe that's Clay? + total_spacing := f32(grapheme_count) * f32(config.letterSpacing) + + return {width = line_width * scaleFactor + total_spacing, height = f32(config.fontSize)} } clay_raylib_render :: proc(render_commands: ^clay.ClayArray(clay.RenderCommand), allocator := context.temp_allocator) {