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
This commit is contained in:
Edward R. Gonzalez 2024-12-29 17:30:00 -05:00
parent 7eab6f9a7f
commit 7488a6828e
10 changed files with 171 additions and 69 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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)
}

View File

@ -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

View File

@ -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
}

View File

@ -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 )
}

View File

@ -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,
}

View File

@ -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 )

View File

@ -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 }