From 7488a6828e6a693343250fb09cc28da3c53d3123 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 29 Dec 2024 17:30:00 -0500 Subject: [PATCH] Text improvements * Added clear_atlas_region_caches & clear_shape_cache to VEFontCache (Used on hot-reload by the pototype's font provider) * Made glyph_draw's over_sample a vec2 for initialization (incase user wants to do some float value multiple of 4x4) * ADVANCE_SNAP_SMALLFONT_SIZE made a runtime option: Shaper_Context.adv_snap_small_font_threshold * Large imporvement to text hinting and general rendering of text --- code/font/vefontcache/LRU.odin | 29 +++++++++ code/font/vefontcache/draw.odin | 59 ++++++++--------- code/font/vefontcache/mappings.odin | 6 ++ code/font/vefontcache/shaped_text.odin | 6 +- code/font/vefontcache/shaper.odin | 32 +++++---- code/font/vefontcache/vefontcache.odin | 90 ++++++++++++++++++++------ code/sectr/engine/render.odin | 4 +- code/sectr/engine/update.odin | 5 +- code/sectr/font/provider.odin | 6 +- code/sectr/ui/tests.odin | 3 +- 10 files changed, 171 insertions(+), 69 deletions(-) diff --git a/code/font/vefontcache/LRU.odin b/code/font/vefontcache/LRU.odin index c263c0b..0d4893a 100644 --- a/code/font/vefontcache/LRU.odin +++ b/code/font/vefontcache/LRU.odin @@ -63,6 +63,26 @@ pool_list_reload :: proc( pool : ^Pool_List, allocator : Allocator ) { reload_array( & pool.free_list, allocator ) } +pool_list_clear :: proc( pool: ^Pool_List ) { + using pool + clear(& items) + clear(& free_list) + resize( & pool.items, cap(pool.items) ) + resize( & pool.free_list, cap(pool.free_list) ) + + for id in 0 ..< capacity { + free_list[id] = i32(id) + items[id] = { + prev = -1, + next = -1, + } + } + + front = -1 + back = -1 + size = 0 +} + pool_list_push_front :: proc( pool : ^Pool_List, value : Pool_ListValue ) { using pool @@ -186,6 +206,15 @@ lru_reload :: #force_inline proc( cache : ^LRU_Cache, allocator : Allocator ) { pool_list_reload( & cache.key_queue, allocator ) } +lru_clear :: proc ( cache : ^LRU_Cache ) { + for key, value in cache.table { + cache.table[key] = {} + } + pool_list_clear( & cache.key_queue ) + clear(& cache.table) + cache.num = 0 +} + lru_find :: #force_inline proc "contextless" ( cache : ^LRU_Cache, key : u64, must_find := false ) -> (LRU_Link, bool) { link, success := cache.table[key] return link, success diff --git a/code/font/vefontcache/draw.odin b/code/font/vefontcache/draw.odin index 03794d3..c101191 100644 --- a/code/font/vefontcache/draw.odin +++ b/code/font/vefontcache/draw.odin @@ -272,6 +272,7 @@ cache_glyph :: proc(ctx : ^Context, font : Font_ID, glyph_index : Glyph, entry : path := &ctx.temp_path clear(path) + step := 1.0 / entry.curve_quality for edge in shape do #partial switch edge.type { case .Move: @@ -290,7 +291,6 @@ cache_glyph :: proc(ctx : ^Context, font : Font_ID, glyph_index : Glyph, entry : p1 := Vec2{ f32(edge.contour_x0), f32(edge.contour_y0) } p2 := Vec2{ f32(edge.x), f32(edge.y) } - step := 1.0 / entry.curve_quality for index : f32 = 1; index <= entry.curve_quality; index += 1 { alpha := index * step append( path, Vertex { pos = eval_point_on_bezier3(p0, p1, p2, alpha) } ) @@ -303,7 +303,6 @@ cache_glyph :: proc(ctx : ^Context, font : Font_ID, glyph_index : Glyph, entry : p2 := Vec2{ f32(edge.contour_x1), f32(edge.contour_y1) } p3 := Vec2{ f32(edge.x), f32(edge.y) } - step := 1.0 / entry.curve_quality for index : f32 = 1; index <= entry.curve_quality; index += 1 { alpha := index * step append( path, Vertex { pos = eval_point_on_bezier4(p0, p1, p2, p3, alpha) } ) @@ -342,10 +341,9 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, // Get hb_font text metrics. These are unscaled! bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) - bounds_size := Vec2 { - f32(bounds_1.x - bounds_0.x), - f32(bounds_1.y - bounds_0.y) - } + vbounds_0 := vec2(bounds_0) + vbounds_1 := vec2(bounds_1) + bounds_size := vbounds_1 - vbounds_0 // E region is special case and not cached to atlas. if region_kind == .None || region_kind == .E do return @@ -390,33 +388,35 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, debug_total_cached += 1 } - // Draw oversized glyph to update FBO + // Draw oversized glyph to glyph render target (FBO) glyph_draw_scale := over_sample * entry.size_scale - glyph_draw_translate := -1 * vec2(bounds_0) * glyph_draw_scale + vec2( glyph_padding ) - glyph_draw_translate.x = cast(f32) (i32(glyph_draw_translate.x + 0.9999999)) - glyph_draw_translate.y = cast(f32) (i32(glyph_draw_translate.y + 0.9999999)) + glyph_draw_translate := -1 * vbounds_0 * glyph_draw_scale + vec2( glyph_padding ) + // glyph_draw_translate.x = cast(f32) (i32(glyph_draw_translate.x + 0.9999999)) + // glyph_draw_translate.y = cast(f32) (i32(glyph_draw_translate.y + 0.9999999)) + // glyph_draw_translate = floor(glyph_draw_translate) + // glyph_draw_translate = ceil(glyph_draw_translate) - // Allocate a glyph_update_FBO region - gwidth_scaled_px := bounds_size.x * glyph_draw_scale.x + 1.0 + over_sample.x * glyph_padding + // Allocate a glyph glyph render target region (FBO) + gwidth_scaled_px := bounds_size.x * glyph_draw_scale.x + over_sample.x * glyph_padding + 1.0 if i32(f32(glyph_buffer.batch_x) + gwidth_scaled_px) >= i32(glyph_buffer.width) { flush_glyph_buffer_to_atlas( ctx ) } // Calculate the src and destination regions - slot_position, slot_szie := atlas_bbox( atlas, region_kind, atlas_index ) + slot_position, slot_size := atlas_bbox( atlas, region_kind, atlas_index ) dst_glyph_position := slot_position - dst_glyph_size := bounds_size * entry.size_scale + glyph_padding - dst_size := slot_szie + dst_glyph_size := ceil(bounds_size * entry.size_scale + glyph_padding) + dst_size := (slot_size) screenspace_x_form( & dst_glyph_position, & dst_glyph_size, atlas_size ) screenspace_x_form( & slot_position, & dst_size, atlas_size ) src_position := Vec2 { f32(glyph_buffer.batch_x), 0 } - src_size := bounds_size * glyph_draw_scale + over_sample * glyph_padding + src_size := (bounds_size * glyph_draw_scale + over_sample * glyph_padding) textspace_x_form( & src_position, & src_size, glyph_buffer_size ) // Advance glyph_update_batch_x and calculate final glyph drawing transform - glyph_draw_translate.x += f32(glyph_buffer.batch_x) + glyph_draw_translate.x = (glyph_draw_translate.x + f32(glyph_buffer.batch_x)) glyph_buffer.batch_x += i32(gwidth_scaled_px) screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_size ) @@ -451,8 +451,8 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, append( & glyph_buffer.clear_draw_list.calls, clear_target_region ) append( & glyph_buffer.draw_list.calls, blit_to_atlas ) - // Render glyph to glyph_update_FBO - cache_glyph( ctx, font, glyph_index, entry, vec2(bounds_0), vec2(bounds_1), glyph_draw_scale, glyph_draw_translate ) + // Render glyph to glyph render target (FBO) + cache_glyph( ctx, font, glyph_index, entry, vbounds_0, vbounds_1, glyph_draw_scale, glyph_draw_translate ) } // If the glyuph is found in the atlas, nothing occurs, otherwise, the glyph call is setup to catch it to the atlas @@ -525,17 +525,14 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, // Figure out the source rect. glyph_position := Vec2 {} - glyph_size := vec2(glyph_padding_dbl) + glyph_size := vec2(glyph_padding) glyph_dst_size := glyph_size + bounds_scaled glyph_size += bounds_scaled * over_sample // Figure out the destination rect. - bounds_0_scaled := Vec2 { - cast(f32) i32(bounds_0.x * entry.size_scale - 0.5), - cast(f32) i32(bounds_0.y * entry.size_scale - 0.5), - } - dst := position + scale * bounds_0_scaled - glyph_padding * scale - dst_size := glyph_dst_size * scale + bounds_0_scaled := floor(bounds_0 * entry.size_scale - 0.5) + dst := position + scale * bounds_0_scaled - glyph_padding * scale + dst_size := glyph_dst_size * scale textspace_x_form( & glyph_position, & glyph_size, glyph_buffer_size ) // Add the glyph Draw_Call. @@ -557,7 +554,7 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, clear_glyph_update := & calls[1] { - // Clear glyph_update_FBO. + // Clear glyph render target (FBO) clear_glyph_update.pass = .Glyph clear_glyph_update.start_index = 0 clear_glyph_update.end_index = 0 @@ -638,7 +635,7 @@ draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^Shaped_Text, bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) vbounds_0 := vec2(bounds_0) vbounds_1 := vec2(bounds_1) - bounds_size := Vec2 { vbounds_1.x - vbounds_0.x, vbounds_1.y - vbounds_0.y } + bounds_size := vbounds_1 - vbounds_0 shaped_position := shaped.positions[index] glyph_translate := position + (shaped_position) * scale @@ -652,10 +649,10 @@ draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^Shaped_Text, } else if atlas_index != -1 { - // Draw cacxhed glyph + // Draw cached glyph slot_position, _ := atlas_bbox( atlas, region_kind, atlas_index ) glyph_scale := bounds_size * entry.size_scale + glyph_padding - bounds_0_scaled := ceil(vbounds_0 * entry.size_scale) + bounds_0_scaled := ceil(vbounds_0 * entry.size_scale - 0.5 ) dst := glyph_translate + bounds_0_scaled * scale dst_scale := glyph_scale * scale textspace_x_form( & slot_position, & glyph_scale, atlas_size ) @@ -726,7 +723,7 @@ flush_glyph_buffer_to_atlas :: proc( ctx : ^Context ) clear_draw_list( & ctx.glyph_buffer.draw_list ) clear_draw_list( & ctx.glyph_buffer.clear_draw_list ) - // Clear glyph_update_FBO + // Clear glyph render target (FBO) if ctx.glyph_buffer.batch_x != 0 { call := Draw_Call_Default diff --git a/code/font/vefontcache/mappings.odin b/code/font/vefontcache/mappings.odin index 7cb620a..f6afc8d 100644 --- a/code/font/vefontcache/mappings.odin +++ b/code/font/vefontcache/mappings.odin @@ -33,6 +33,7 @@ import "core:mem" Arena :: mem.Arena arena_allocator :: mem.arena_allocator arena_init :: mem.arena_init +import "core:slice" //#region("Proc overload mappings") @@ -58,6 +59,7 @@ ceil :: proc { clear :: proc { clear_dynamic_array, + clear_map, } floor :: proc { @@ -74,6 +76,10 @@ floor :: proc { floor_vec2, } +fill :: proc { + slice.fill, +} + make :: proc { make_dynamic_array, make_dynamic_array_len, diff --git a/code/font/vefontcache/shaped_text.odin b/code/font/vefontcache/shaped_text.odin index 7a5ea45..59ac8bb 100644 --- a/code/font/vefontcache/shaped_text.odin +++ b/code/font/vefontcache/shaped_text.odin @@ -74,9 +74,9 @@ shape_text_uncached :: proc( ctx : ^Context, font : Font_ID, text_utf8 : string, line_gap := f32(line_gap_i32) line_height := (ascent - descent + line_gap) * entry.size_scale - if ctx.text_shape_adv + if ctx.use_advanced_shaper { - shaper_shape_from_text( & ctx.shaper_ctx, ctx.snap_shape_pos, & entry.shaper_info, output, text_utf8, ascent_i32, descent_i32, line_gap_i32, entry.size, entry.size_scale ) + shaper_shape_from_text( & ctx.shaper_ctx, & entry.shaper_info, output, text_utf8, ascent_i32, descent_i32, line_gap_i32, entry.size, entry.size_scale ) return } else @@ -106,7 +106,7 @@ shape_text_uncached :: proc( ctx : ^Context, font : Font_ID, text_utf8 : string, prev_codepoint = rune(0) continue } - if abs( entry.size ) <= ADVANCE_SNAP_SMALLFONT_SIZE { + if abs( entry.size ) <= ctx.shaper_ctx.adv_snap_small_font_threshold { position.x = ceil(position.x) } diff --git a/code/font/vefontcache/shaper.odin b/code/font/vefontcache/shaper.odin index 7ce795d..df61c8f 100644 --- a/code/font/vefontcache/shaper.odin +++ b/code/font/vefontcache/shaper.odin @@ -14,8 +14,8 @@ Shaper_Kind :: enum { Shaper_Context :: struct { hb_buffer : harfbuzz.Buffer, - snap_glyph_pos : b32, - adv_snap_small_font_threshold : u32, + snap_glyph_position : b32, + adv_snap_small_font_threshold : f32, } Shaper_Info :: struct { @@ -54,7 +54,7 @@ shaper_unload_font :: proc( ctx : ^Shaper_Info ) if blob != nil do harfbuzz.blob_destroy( blob ) } -shaper_shape_from_text :: proc( ctx : ^Shaper_Context, snap_shape_pos : b32, info : ^Shaper_Info, output :^Shaped_Text, text_utf8 : string, +shaper_shape_from_text :: proc( ctx : ^Shaper_Context, info : ^Shaper_Info, output :^Shaped_Text, text_utf8 : string, ascent, descent, line_gap : i32, size, size_scale : f32 ) { // profile(#procedure) @@ -69,13 +69,13 @@ shaper_shape_from_text :: proc( ctx : ^Shaper_Context, snap_shape_pos : b32, inf max_line_width := f32(0) line_count := 1 - line_height := (ascent - descent + line_gap) * size_scale + line_height := ((ascent - descent + line_gap) * size_scale) position, vertical_position : f32 shape_run :: proc( buffer : harfbuzz.Buffer, script : harfbuzz.Script, font : harfbuzz.Font, output : ^Shaped_Text, position, vertical_position, max_line_width: ^f32, line_count: ^int, ascent, descent, line_gap, size, size_scale: f32, - snap_shape_pos : b32 ) + snap_shape_pos : b32, adv_snap_small_font_threshold : f32 ) { // Set script and direction. We use the system's default langauge. // script = HB_SCRIPT_LATIN @@ -105,11 +105,11 @@ shaper_shape_from_text :: proc( ctx : ^Shaper_Context, snap_shape_pos : b32, inf (max_line_width^) = max( max_line_width^, position^ ) (position^) = 0.0 (vertical_position^) -= line_height - (vertical_position^) = vertical_position^ + (vertical_position^) = floor(vertical_position^) (line_count^) += 1 continue } - if abs( size ) <= ADVANCE_SNAP_SMALLFONT_SIZE + if abs( size ) <= adv_snap_small_font_threshold { (position^) = ceil( position^ ) } @@ -124,8 +124,8 @@ shaper_shape_from_text :: proc( ctx : ^Shaper_Context, snap_shape_pos : b32, inf v_pos += offset_y if snap_shape_pos { - pos = floor(pos) - v_pos = floor(v_pos) + pos = ceil(pos) + v_pos = ceil(v_pos) } append( & output.positions, Vec2 {pos, v_pos}) @@ -160,13 +160,23 @@ shaper_shape_from_text :: proc( ctx : ^Shaper_Context, snap_shape_pos : b32, inf } // End current run since we've encountered a script change. - shape_run( ctx.hb_buffer, current_script, info.font, output, & position, & vertical_position, & max_line_width, & line_count, ascent, descent, line_gap, size, size_scale, snap_shape_pos ) + shape_run( + ctx.hb_buffer, current_script, info.font, output, + & position, & vertical_position, & max_line_width, & line_count, + ascent, descent, line_gap, size, size_scale, + ctx.snap_glyph_position, ctx.adv_snap_small_font_threshold + ) harfbuzz.buffer_add( ctx.hb_buffer, hb_codepoint, codepoint == '\n' ? 1 : 0 ) current_script = script } // End the last run if needed - shape_run( ctx.hb_buffer, current_script, info.font, output, & position, & vertical_position, & max_line_width, & line_count, ascent, descent, line_gap, size, size_scale, snap_shape_pos ) + shape_run( + ctx.hb_buffer, current_script, info.font, output, + & position, & vertical_position, & max_line_width, & line_count, + ascent, descent, line_gap, size, size_scale, + ctx.snap_glyph_position, ctx.adv_snap_small_font_threshold + ) // Set the final size output.size.x = max_line_width diff --git a/code/font/vefontcache/vefontcache.odin b/code/font/vefontcache/vefontcache.odin index 47a2133..5bb7318 100644 --- a/code/font/vefontcache/vefontcache.odin +++ b/code/font/vefontcache/vefontcache.odin @@ -7,8 +7,6 @@ package vefontcache import "base:runtime" -ADVANCE_SNAP_SMALLFONT_SIZE :: 10 - Font_ID :: distinct i64 Glyph :: distinct i32 @@ -59,14 +57,12 @@ Context :: struct { shape_cache : Shaped_Text_Cache, default_curve_quality : i32, - text_shape_adv : b32, - snap_shape_pos : b32, + use_advanced_shaper : b32, debug_print : b32, debug_print_verbose : b32, } -//#region("lifetime") Init_Atlas_Region_Params :: struct { width : u32, @@ -110,17 +106,29 @@ Init_Atlas_Params_Default :: Init_Atlas_Params { } Init_Glyph_Draw_Params :: struct { - over_sample : Vec2i, + over_sample : Vec2, buffer_batch : u32, draw_padding : u32, } Init_Glyph_Draw_Params_Default :: Init_Glyph_Draw_Params { - over_sample = { 4, 4 }, + over_sample = Vec2 { 4, 4 }, buffer_batch = 4, draw_padding = Init_Atlas_Params_Default.glyph_padding, } +Init_Shaper_Params :: struct { + use_advanced_text_shaper : b32, + snap_glyph_position : b32, + adv_snap_small_font_threshold : u32, +} + +Init_Shaper_Params_Default :: Init_Shaper_Params { + use_advanced_text_shaper = true, + snap_glyph_position = true, + adv_snap_small_font_threshold = 0, +} + Init_Shape_Cache_Params :: struct { capacity : u32, reserve_length : u32, @@ -131,14 +139,15 @@ Init_Shape_Cache_Params_Default :: Init_Shape_Cache_Params { reserve_length = 256, } +//#region("lifetime") + // ve_fontcache_init startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType, allocator := context.allocator, atlas_params := Init_Atlas_Params_Default, glyph_draw_params := Init_Glyph_Draw_Params_Default, shape_cache_params := Init_Shape_Cache_Params_Default, - use_advanced_text_shaper : b32 = true, - snap_shape_position : b32 = true, + shaper_params := Init_Shaper_Params_Default, default_curve_quality : u32 = 3, entires_reserve : u32 = 512, temp_path_reserve : u32 = 1024, @@ -151,8 +160,9 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType, ctx.backing = allocator context.allocator = ctx.backing - snap_shape_pos = snap_shape_position - text_shape_adv = use_advanced_text_shaper + use_advanced_shaper = shaper_params.use_advanced_text_shaper + shaper_ctx.adv_snap_small_font_threshold = f32(shaper_params.adv_snap_small_font_threshold) + shaper_ctx.snap_glyph_position = shaper_params.snap_glyph_position if default_curve_quality == 0 { default_curve_quality = 3 @@ -243,7 +253,7 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType, // Note(From original author): We can actually go over VE_FONTCACHE_GLYPHDRAW_BUFFER_BATCH batches due to smart packing! { using glyph_buffer - over_sample = vec2(glyph_draw_params.over_sample) + over_sample = glyph_draw_params.over_sample batch = cast(i32) glyph_draw_params.buffer_batch width = atlas.region_d.width * i32(over_sample.x) * batch height = atlas.region_d.height * i32(over_sample.y) @@ -310,7 +320,6 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator ) reload_array( & glyph_buffer.clear_draw_list.vertices, allocator ) reload_array( & shape_cache.storage, allocator ) - lru_reload( & shape_cache.state, allocator ) } // ve_foncache_shutdown @@ -442,8 +451,8 @@ draw_text :: proc( ctx : ^Context, font : Font_ID, text_utf8 : string, position, ctx.cursor_pos = {} position := position - if ctx.snap_width > 0 do position.x = cast(f32) cast(u32) (position.x * ctx.snap_width + 0.5) / ctx.snap_width - if ctx.snap_height > 0 do position.y = cast(f32) cast(u32) (position.y * ctx.snap_height + 0.5) / ctx.snap_height + if ctx.snap_width > 0 do position.x = ceil(position.x * ctx.snap_width ) / ctx.snap_width + if ctx.snap_height > 0 do position.y = ceil(position.y * ctx.snap_height) / ctx.snap_height entry := & ctx.entries[ font ] @@ -520,10 +529,55 @@ get_font_vertical_metrics :: #force_inline proc ( ctx : ^Context, font : Font_ID entry := & ctx.entries[ font ] ascent_i32, descent_i32, line_gap_i32 := parser_get_font_vertical_metrics( & entry.parser_info ) - ascent = ceil(f32(ascent_i32) * entry.size_scale) - descent = ceil(f32(descent_i32) * entry.size_scale) - line_gap = ceil(f32(line_gap_i32) * entry.size_scale) + ascent = (f32(ascent_i32) * entry.size_scale) + descent = (f32(descent_i32) * entry.size_scale) + line_gap = (f32(line_gap_i32) * entry.size_scale) return } //#endregion("metrics") + +// Can be used with hot-reload +clear_atlas_region_caches :: proc(ctx : ^Context) +{ + lru_clear(& ctx.atlas.region_a.state) + lru_clear(& ctx.atlas.region_b.state) + lru_clear(& ctx.atlas.region_c.state) + lru_clear(& ctx.atlas.region_d.state) + + ctx.atlas.region_a.next_idx = 0 + ctx.atlas.region_b.next_idx = 0 + ctx.atlas.region_c.next_idx = 0 + ctx.atlas.region_d.next_idx = 0 +} + +// Can be used with hot-reload +clear_shape_cache :: proc (ctx : ^Context) +{ + lru_clear(& ctx.shape_cache.state) + + using ctx + for idx : i32 = 0; idx < cast(i32) cap(shape_cache.storage); idx += 1 { + stroage_entry := & shape_cache.storage[idx] + using stroage_entry + + end_cursor_pos = {} + size = {} + + clear(& glyphs) + // fill(glyphs[:], 0) + + clear(& positions) + // fill(positions[:], 0) + + clear(& draw_list.calls) + // fill(draw_list.calls[:], Draw_Call{}) + + clear(& draw_list.indices) + // fill(draw_list.indices[:], 0) + + clear(& draw_list.vertices) + // fill(draw_list.vertices[:], Vertex{}) + } + ctx.shape_cache.next_cache_id = 0 +} diff --git a/code/sectr/engine/render.odin b/code/sectr/engine/render.odin index 6684c72..62b03a2 100644 --- a/code/sectr/engine/render.odin +++ b/code/sectr/engine/render.odin @@ -807,7 +807,7 @@ draw_text_string_pos_norm :: proc( content : string, id : FontID, size : f32, po color_norm := normalize_rgba8(color) ve.set_colour( & font_provider_ctx.ve_ctx, color_norm ) - ve.draw_text( & font_provider_ctx.ve_ctx, ve_id, content, pos, Vec2{1 / width, 1 / height} * scale * (1/config.font_size_screen_scalar) ) + ve.draw_text( & font_provider_ctx.ve_ctx, ve_id, content, pos, Vec2{1 / width, 1 / height} * scale * (1 / config.font_size_screen_scalar) ) return } @@ -853,7 +853,7 @@ draw_text_string_pos_extent_zoomed :: proc( content : string, id : FontID, size { f32_resolved_size := f32(resolved_size) diff_scalar := 1 + (zoom_adjust_size - f32_resolved_size) / f32_resolved_size - text_scale = diff_scalar * screen_scale + text_scale = diff_scalar * screen_scale text_scale.x = clamp( text_scale.x, 0, screen_size.x ) text_scale.y = clamp( text_scale.y, 0, screen_size.y ) } diff --git a/code/sectr/engine/update.odin b/code/sectr/engine/update.odin index 73429a2..ac66729 100644 --- a/code/sectr/engine/update.odin +++ b/code/sectr/engine/update.odin @@ -325,7 +325,7 @@ update :: proc( delta_time : f64 ) -> b32 flags = frame_style_flags, anchor = {}, // alignment = { 0.5, 0.5 }, - font_size = 12, + font_size = 14, text_alignment = { 0.0, 0.0 }, // corner_radii = { 0.2, 0.2, 0.2, 0.2 }, pos = { 0, 0 }, @@ -334,7 +334,8 @@ update :: proc( delta_time : f64 ) -> b32 } scope( default_layout ) frame_style_default := UI_Style { - bg_color = Color_BG_TextBox, + // bg_color = Color_BG_TextBox, + bg_color = Color_Transparent, font = default_font, text_color = Color_White, } diff --git a/code/sectr/font/provider.odin b/code/sectr/font/provider.odin index eb3eadb..2ec9a8f 100644 --- a/code/sectr/font/provider.odin +++ b/code/sectr/font/provider.odin @@ -43,7 +43,8 @@ font_provider_startup :: proc( ctx : ^FontProviderContext ) font_cache, error = make( HMapChained(FontDef), hmap_closest_prime(1 * Kilo), persistent_allocator(), dbg_name = "font_cache" ) verify( error == AllocatorError.None, "Failed to allocate font_cache" ) - ve.startup( & ve_ctx, .STB_TrueType, allocator = persistent_slab_allocator(), use_advanced_text_shaper = true ) + ve.startup( & ve_ctx, .STB_TrueType, allocator = persistent_slab_allocator() ) + ve_ctx.glyph_buffer.over_sample = { 4,4 } log("VEFontCached initialized") // provider_data.ve_ctx.debug_print = true // provider_data.ve_ctx.debug_print_verbose = true @@ -52,8 +53,11 @@ font_provider_startup :: proc( ctx : ^FontProviderContext ) font_provider_reload :: proc( ctx : ^FontProviderContext ) { + ctx.ve_ctx.glyph_buffer.over_sample = { 4,4 } * 1.0 hmap_chained_reload( ctx.font_cache, persistent_allocator()) ve.hot_reload( & ctx.ve_ctx, persistent_slab_allocator() ) + ve.clear_atlas_region_caches(& ctx.ve_ctx) + ve.clear_shape_cache(& ctx.ve_ctx) } font_provider_shutdown :: proc( ctx : ^FontProviderContext ) diff --git a/code/sectr/ui/tests.odin b/code/sectr/ui/tests.odin index d28eaf8..dd6cc6b 100644 --- a/code/sectr/ui/tests.odin +++ b/code/sectr/ui/tests.odin @@ -163,8 +163,9 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default : text_layout.flags = { // .Origin_At_Anchor_Center, .Fixed_Position_X, .Fixed_Position_Y, - .Fixed_Width, .Fixed_Height, + // .Fixed_Width, .Fixed_Height, } + // text_layout.font_size = 16 text_layout.text_alignment = { 0.0, 0.5 } text_layout.alignment = { 0.0, 1.0 } text_layout.size.min = { 1600, 14 }