| 1 | // vtest build: !msvc |
| 2 | // vtest flaky: true |
| 3 | // vtest retry: 1 |
| 4 | module gg |
| 5 | |
| 6 | import fontstash |
| 7 | |
| 8 | const embedded_test_mono_font = $embed_file('@VEXEROOT/examples/assets/fonts/RobotoMono-Regular.ttf') |
| 9 | |
| 10 | fn new_test_text_context() (&Context, &fontstash.Context) { |
| 11 | return new_test_text_context_with_atlas(512, 512) |
| 12 | } |
| 13 | |
| 14 | fn new_test_text_context_with_atlas(width int, height int) (&Context, &fontstash.Context) { |
| 15 | mut fons := fontstash.create_internal(&C.FONSparams{ |
| 16 | width: width |
| 17 | height: height |
| 18 | flags: 0 |
| 19 | }) |
| 20 | assert fons != unsafe { nil } |
| 21 | font_id := fons.add_font_mem('mono', embedded_test_mono_font.to_bytes().clone(), true) |
| 22 | assert font_id != fontstash.invalid |
| 23 | fons.set_font(font_id) |
| 24 | fons.set_size(16) |
| 25 | fons.set_error_callback(expand_atlas_callback, fons) |
| 26 | return &Context{ |
| 27 | ft: &FT{ |
| 28 | fons: fons |
| 29 | } |
| 30 | font_inited: true |
| 31 | scale: 1.0 |
| 32 | }, fons |
| 33 | } |
| 34 | |
| 35 | fn text_advance_and_bounds_width(fons &fontstash.Context, text string) (f32, f32) { |
| 36 | mut bounds := [4]f32{} |
| 37 | advance := fons.text_bounds(0, 0, text, &bounds[0]) |
| 38 | return advance, bounds[2] - bounds[0] |
| 39 | } |
| 40 | |
| 41 | fn test_text_width_uses_font_advance_for_monospaced_fonts() { |
| 42 | ctx, fons := new_test_text_context() |
| 43 | defer { |
| 44 | fontstash.delete_internal(fons) |
| 45 | } |
| 46 | i_advance, i_bounds_width := text_advance_and_bounds_width(fons, 'i') |
| 47 | m_advance, m_bounds_width := text_advance_and_bounds_width(fons, 'm') |
| 48 | assert int(i_advance / ctx.scale) == int(m_advance / ctx.scale) |
| 49 | assert int(i_bounds_width / ctx.scale) != int(m_bounds_width / ctx.scale) |
| 50 | assert ctx.text_width('i') == int(i_advance / ctx.scale) |
| 51 | assert ctx.text_width('m') == int(m_advance / ctx.scale) |
| 52 | width, height := ctx.text_size('i') |
| 53 | assert width == ctx.text_width('i') |
| 54 | assert height > 0 |
| 55 | } |
| 56 | |
| 57 | fn test_text_width_counts_trailing_space_advance() { |
| 58 | ctx, fons := new_test_text_context() |
| 59 | defer { |
| 60 | fontstash.delete_internal(fons) |
| 61 | } |
| 62 | advance, bounds_width := text_advance_and_bounds_width(fons, 'a ') |
| 63 | assert int(advance / ctx.scale) > int(bounds_width / ctx.scale) |
| 64 | assert ctx.text_width('a ') == int(advance / ctx.scale) |
| 65 | width, _ := ctx.text_size('a ') |
| 66 | assert width == int(advance / ctx.scale) |
| 67 | } |
| 68 | |
| 69 | fn test_text_atlas_expands_on_overflow() { |
| 70 | _, fons := new_test_text_context_with_atlas(64, 64) |
| 71 | defer { |
| 72 | fontstash.delete_internal(fons) |
| 73 | } |
| 74 | before_width, before_height := fons.get_atlas_size() |
| 75 | mut bounds := [4]f32{} |
| 76 | for size in [48, 64, 80] { |
| 77 | fons.set_size(size) |
| 78 | _ = fons.text_bounds(0, 0, 'Some very long text here 0123456789', &bounds[0]) |
| 79 | } |
| 80 | after_width, after_height := fons.get_atlas_size() |
| 81 | assert after_width > before_width || after_height > before_height |
| 82 | } |
| 83 | |