11package main
22
3+ import " core:unicode/utf8"
4+ import " base:runtime"
35import clay " ../../clay-odin"
46import " core:math"
57import " core:strings"
@@ -16,24 +18,74 @@ clay_color_to_rl_color :: proc(color: clay.Color) -> rl.Color {
1618
1719raylib_fonts := [dynamic ]Raylib_Font{}
1820
19- measure_text :: proc " c " (text: clay.StringSlice, config: ^clay.TextElementConfig, userData: rawptr ) -> clay.Dimensions {
20- line_width: f32 = 0
21+ // Alias for compatibility, default to ascii support
22+ measure_text :: measure_text_ascii
2123
22- font := raylib_fonts[config.fontId].font
24+ measure_text_unicode :: proc " c" (text: clay.StringSlice, config: ^clay.TextElementConfig, userData: rawptr ) -> clay.Dimensions {
25+ // Needed for grapheme_count
26+ context = runtime.default_context ()
27+
28+ line_width: f32 = 0
29+
30+ font := raylib_fonts[config.fontId].font
31+ text_str := string (text.chars[:text.length])
2332
24- for i in 0 ..< text.length {
25- glyph_index := text.chars[i] - 32
33+ // This function seems somewhat expensive, if you notice performance issues, you could assume
34+ // - 1 codepoint per visual character (no grapheme clusters), where you can get the length from the loop
35+ // - 1 byte per visual character (ascii), where you can get the length with `text.length`
36+ // see `measure_text_ascii`
37+ grapheme_count, _, _ := utf8.grapheme_count (text_str)
38+
39+ for letter, byte_idx in text_str {
40+ glyph_index := rl.GetGlyphIndex (font, letter)
2641
2742 glyph := font.glyphs[glyph_index]
2843
29- if glyph.advanceX != 0 {
30- line_width += f32 (glyph.advanceX)
31- } else {
32- line_width += font.recs[glyph_index].width + f32 (glyph.offsetX)
33- }
34- }
44+ if glyph.advanceX != 0 {
45+ line_width += f32 (glyph.advanceX)
46+ } else {
47+ line_width += font.recs[glyph_index].width + f32 (font.glyphs[glyph_index].offsetX)
48+ }
49+ }
50+
51+ scaleFactor := f32 (config.fontSize) / f32 (font.baseSize)
52+
53+ // Note:
54+ // I'd expect this to be `grapheme_count - 1`,
55+ // but that seems to be one letterSpacing too small
56+ // maybe that's a raylib bug, maybe that's Clay?
57+ total_spacing := f32 (grapheme_count) * f32 (config.letterSpacing)
58+
59+ return {width = line_width * scaleFactor + total_spacing, height = f32 (config.fontSize)}
60+ }
61+
62+ measure_text_ascii :: proc " c" (text: clay.StringSlice, config: ^clay.TextElementConfig, userData: rawptr ) -> clay.Dimensions {
63+ line_width: f32 = 0
64+
65+ font := raylib_fonts[config.fontId].font
66+ text_str := string (text.chars[:text.length])
67+
68+ for i in 0 ..<len (text_str) {
69+ glyph_index := text_str[i] - 32
70+
71+ glyph := font.glyphs[glyph_index]
72+
73+ if glyph.advanceX != 0 {
74+ line_width += f32 (glyph.advanceX)
75+ } else {
76+ line_width += font.recs[glyph_index].width + f32 (font.glyphs[glyph_index].offsetX)
77+ }
78+ }
79+
80+ scaleFactor := f32 (config.fontSize) / f32 (font.baseSize)
81+
82+ // Note:
83+ // I'd expect this to be `len(text_str) - 1`,
84+ // but that seems to be one letterSpacing too small
85+ // maybe that's a raylib bug, maybe that's Clay?
86+ total_spacing := f32 (len (text_str)) * f32 (config.letterSpacing)
3587
36- return {width = line_width / 2 , height = f32 (config.fontSize)}
88+ return {width = line_width * scaleFactor + total_spacing , height = f32 (config.fontSize)}
3789}
3890
3991clay_raylib_render :: proc (render_commands: ^clay.ClayArray (clay.RenderCommand), allocator := context .temp_allocator) {
0 commit comments