Preparing to attempt to offload various metric calculations for a shape's glyphs to the shape itself from the draw list generator
This commit is contained in:
parent
fa627b4c4a
commit
18d8735c54
@ -13,14 +13,14 @@ Atlas_Region_Kind :: enum u8 {
|
||||
}
|
||||
|
||||
// Note(Ed): Using 16 bit hash had collision failures and no observable performance improvement (tried several 16-bit hashers)
|
||||
Atlas_Region_Key :: u32
|
||||
Atlas_Key :: u32
|
||||
|
||||
// TODO(Ed) It might perform better with a tailored made hashtable implementation for the LRU_Cache or dedicated array struct/procs for the Atlas.
|
||||
/* Essentially a sub-atlas of the atlas. There is a state cache per region that tracks the glyph inventory (what slot they occupy).
|
||||
Unlike the shape cache this one's fixed capacity (natrually) and the next avail slot is tracked.
|
||||
*/
|
||||
Atlas_Region :: struct {
|
||||
state : LRU_Cache(Atlas_Region_Key),
|
||||
state : LRU_Cache(Atlas_Key),
|
||||
|
||||
size : Vec2i,
|
||||
capacity : Vec2i,
|
||||
@ -54,7 +54,7 @@ Atlas :: struct {
|
||||
}
|
||||
|
||||
// Hahser for the atlas.
|
||||
atlas_glyph_lru_code :: #force_inline proc "contextless" ( font : Font_ID, px_size : f32, glyph_index : Glyph ) -> (lru_code : Atlas_Region_Key) {
|
||||
atlas_glyph_lru_code :: #force_inline proc "contextless" ( font : Font_ID, px_size : f32, glyph_index : Glyph ) -> (lru_code : Atlas_Key) {
|
||||
// lru_code = u32(glyph_index) + ( ( 0x10000 * u32(font) ) & 0xFFFF0000 )
|
||||
font := font
|
||||
glyph_index := glyph_index
|
||||
@ -65,6 +65,7 @@ atlas_glyph_lru_code :: #force_inline proc "contextless" ( font : Font_ID, px_si
|
||||
return
|
||||
}
|
||||
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_region_bbox :: #force_inline proc( region : Atlas_Region, local_idx : i32 ) -> (position, size: Vec2)
|
||||
{
|
||||
size = vec2(region.slot_size.x)
|
||||
@ -77,13 +78,17 @@ atlas_region_bbox :: #force_inline proc( region : Atlas_Region, local_idx : i32
|
||||
return
|
||||
}
|
||||
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_decide_region :: #force_inline proc "contextless" (atlas : Atlas, glyph_buffer_size : Vec2, bounds_size_scaled : Vec2 ) -> (region_kind : Atlas_Region_Kind)
|
||||
{
|
||||
profile(#procedure)
|
||||
glyph_padding_dbl := atlas.glyph_padding * 2
|
||||
padded_bounds := bounds_size_scaled + glyph_padding_dbl
|
||||
|
||||
for kind in 1 ..= 4 do if padded_bounds.x <= f32( atlas.regions[kind].slot_size.x) && padded_bounds.y <= f32(atlas.regions[kind].slot_size.y) {
|
||||
for kind in 1 ..= 4 do if
|
||||
padded_bounds.x <= f32(atlas.regions[kind].slot_size.x) &&
|
||||
padded_bounds.y <= f32(atlas.regions[kind].slot_size.y)
|
||||
{
|
||||
return cast(Atlas_Region_Kind) kind
|
||||
}
|
||||
|
||||
@ -93,8 +98,46 @@ atlas_decide_region :: #force_inline proc "contextless" (atlas : Atlas, glyph_bu
|
||||
return .None
|
||||
}
|
||||
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_decide_region_branchless :: #force_inline proc "contextless" (
|
||||
atlas: Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
bounds_size_scaled : Vec2,
|
||||
) -> Atlas_Region_Kind
|
||||
{
|
||||
profile(#procedure)
|
||||
|
||||
glyph_padding_dbl := atlas.glyph_padding * 2
|
||||
padded_bounds := bounds_size_scaled + glyph_padding_dbl
|
||||
|
||||
slot_size_region_a := vec2(atlas.region_a.slot_size)
|
||||
slot_size_region_b := vec2(atlas.region_b.slot_size)
|
||||
slot_size_region_c := vec2(atlas.region_c.slot_size)
|
||||
slot_size_region_d := vec2(atlas.region_d.slot_size)
|
||||
|
||||
within_a := padded_bounds.x <= slot_size_region_a.x && padded_bounds.y <= slot_size_region_a.y
|
||||
within_b := padded_bounds.x <= slot_size_region_b.x && padded_bounds.y <= slot_size_region_b.y
|
||||
within_c := padded_bounds.x <= slot_size_region_c.x && padded_bounds.y <= slot_size_region_c.y
|
||||
within_d := padded_bounds.x <= slot_size_region_d.x && padded_bounds.y <= slot_size_region_d.y
|
||||
within_buffer := padded_bounds.x <= glyph_buffer_size.x && padded_bounds.y <= glyph_buffer_size.y
|
||||
within_none := cast(i32) ! (within_a || within_b || within_c || within_d )
|
||||
|
||||
score_a := i32(within_a) * -5
|
||||
score_b := i32(within_b) * -4
|
||||
score_c := i32(within_c) * -3
|
||||
score_d := i32(within_d) * -2
|
||||
score_buffer := i32(within_buffer) * -1
|
||||
|
||||
which_ab := min(score_a, score_b)
|
||||
which_cd := min(score_c, score_d)
|
||||
which_region := min(which_ab, which_cd)
|
||||
resolved := min(which_region, score_buffer) + 6
|
||||
return Atlas_Region_Kind(resolved)
|
||||
}
|
||||
|
||||
// Grab an atlas LRU cache slot.
|
||||
atlas_reserve_slot :: #force_inline proc ( region : ^Atlas_Region, lru_code : Atlas_Region_Key ) -> (atlas_index : i32)
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_reserve_slot :: #force_inline proc ( region : ^Atlas_Region, lru_code : Atlas_Key ) -> (atlas_index : i32)
|
||||
{
|
||||
if region.next_idx < region.state.capacity
|
||||
{
|
||||
|
@ -41,11 +41,11 @@ Glyph_Draw_Quad :: struct {
|
||||
|
||||
// This is used by generate_shape_draw_list & batch_generate_glyphs_draw_list
|
||||
// to track relevant glyph data in soa format for pipelined processing
|
||||
Glyph_Pack_Entry :: struct {
|
||||
Glyph_Pack_Entry :: struct #packed {
|
||||
position : Vec2,
|
||||
|
||||
index : Glyph,
|
||||
lru_code : Atlas_Region_Key,
|
||||
lru_code : Atlas_Key,
|
||||
atlas_index : i32,
|
||||
in_atlas : b8,
|
||||
should_cache : b8,
|
||||
@ -103,7 +103,7 @@ Frame_Buffer_Pass :: enum u32 {
|
||||
}
|
||||
|
||||
Glyph_Batch_Cache :: struct {
|
||||
table : map[Atlas_Region_Key]b8,
|
||||
table : map[Atlas_Key]b8,
|
||||
num : i32,
|
||||
cap : i32,
|
||||
}
|
||||
@ -128,7 +128,7 @@ Glyph_Draw_Buffer :: struct{
|
||||
cached : [dynamic]i32,
|
||||
}
|
||||
|
||||
// Contructs a
|
||||
// Contructs a quad mesh for bliting a texture from one render target (src uv0 & 1) to the destination rendertarget (p0, p1)
|
||||
@(optimization_mode="favor_size")
|
||||
blit_quad :: #force_inline proc ( draw_list : ^Draw_List, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1}, uv0 : Vec2 = {0, 0}, uv1 : Vec2 = {1, 1} )
|
||||
{
|
||||
@ -330,7 +330,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
// font_scale := font_scale * px_scalar
|
||||
// target_scale := target_scale / px_scalar
|
||||
|
||||
mark_glyph_seen :: #force_inline proc "contextless" ( cache : ^Glyph_Batch_Cache, lru_code : Atlas_Region_Key ) {
|
||||
mark_glyph_seen :: #force_inline proc "contextless" ( cache : ^Glyph_Batch_Cache, lru_code : Atlas_Key ) {
|
||||
cache.table[lru_code] = true
|
||||
cache.num += 1
|
||||
}
|
||||
@ -348,7 +348,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
oversized := & glyph_buffer.oversized
|
||||
to_cache := & glyph_buffer.to_cache
|
||||
cached := & glyph_buffer.cached
|
||||
resize_soa_non_zero(glyph_pack, len(shape.glyphs))
|
||||
resize_soa_non_zero(glyph_pack, len(shape.glyph_id))
|
||||
|
||||
append_sub_pack :: #force_inline proc ( pack : ^[dynamic]i32, entry : i32 )
|
||||
{
|
||||
@ -361,7 +361,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
profile_begin("index")
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
glyph.index = shape.glyphs[ index ]
|
||||
glyph.index = shape.glyph_id[ index ]
|
||||
glyph.lru_code = atlas_glyph_lru_code(entry.id, px_size, glyph.index)
|
||||
}
|
||||
profile_end()
|
||||
@ -369,7 +369,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
profile_begin("translate")
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
glyph.position = target_position + (shape.positions[index]) * target_scale
|
||||
glyph.position = target_position + (shape.position[index]) * target_scale
|
||||
}
|
||||
profile_end()
|
||||
|
||||
@ -724,12 +724,12 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
|
||||
dst_glyph_pos := glyph.region_pos
|
||||
dst_glyph_size := glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
dst_glyph_size.y = ceil(dst_glyph_size.y) * glyph_buffer.snap_glyph_height // Note(Ed): Seems to improve hinting
|
||||
dst_glyph_size.y = max(dst_glyph_size.y, ceil(dst_glyph_size.y) * glyph_buffer.snap_glyph_height) // Note(Ed): Seems to improve hinting
|
||||
to_glyph_buffer_space( & dst_glyph_pos, & dst_glyph_size, atlas_size )
|
||||
|
||||
src_position := Vec2 { glyph.buffer_x, 0 }
|
||||
src_size := (glyph.bounds_size_scaled + atlas.glyph_padding) * glyph_buffer.over_sample
|
||||
src_size.y = ceil(src_size.y) * glyph_buffer.snap_glyph_height // Note(Ed): Seems to improve hinting
|
||||
src_size.y = max(src_size.y, ceil(src_size.y) * glyph_buffer.snap_glyph_height) // Note(Ed): Seems to improve hinting
|
||||
to_target_space( & src_position, & src_size, glyph_buffer_size )
|
||||
|
||||
blit_to_atlas : Draw_Call
|
||||
|
@ -26,10 +26,11 @@ Shape_Key :: u32
|
||||
your not going to be satisfied with keeping that in the iteration).
|
||||
*/
|
||||
Shaped_Text :: struct {
|
||||
glyphs : [dynamic]Glyph,
|
||||
positions : [dynamic]Vec2,
|
||||
// bounds : [dynamic]Range2, // TODO(Ed): Test tracking/resolving the bounds here, its expensive to resolve at the draw list generation stage.
|
||||
// region_kinds : [dynamic]Atlas_Region_Kind, // TODO(ed): test tracking/resolving the assigne atlas region here, for some reason as ^^.
|
||||
glyph_id : [dynamic]Glyph,
|
||||
position : [dynamic]Vec2,
|
||||
atlas_lru_code : [dynamic]Atlas_Key,
|
||||
region_kind : [dynamic]Atlas_Region_Kind,
|
||||
bound : [dynamic]Range2,
|
||||
end_cursor_pos : Vec2,
|
||||
size : Vec2,
|
||||
}
|
||||
@ -43,7 +44,15 @@ Shaped_Text_Cache :: struct {
|
||||
}
|
||||
|
||||
// Used by shaper_shape_text_cached, allows user to specify their own proc at compile-time without having to rewrite the caching implementation.
|
||||
Shaper_Shape_Text_Uncached_Proc :: #type proc( ctx : ^Shaper_Context, entry : Entry, font_px_Size, font_scale : f32, text_utf8 : string, output : ^Shaped_Text )
|
||||
Shaper_Shape_Text_Uncached_Proc :: #type proc( ctx : ^Shaper_Context,
|
||||
atlas : Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
entry : Entry,
|
||||
font_px_Size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
)
|
||||
|
||||
// Note(Ed): Not used..
|
||||
Shaper_Kind :: enum {
|
||||
@ -186,8 +195,8 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
|
||||
is_empty := parser_is_glyph_empty(entry.parser_info, glyph_id)
|
||||
if ! is_empty {
|
||||
append( & output.glyphs, glyph_id )
|
||||
append( & output.positions, glyph_pos)
|
||||
append( & output.glyph_id, glyph_id )
|
||||
append( & output.position, glyph_pos)
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,36 +262,67 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
}
|
||||
|
||||
shaper_shape_text_uncached_advanced :: #force_inline proc( ctx : ^Shaper_Context,
|
||||
entry : Entry,
|
||||
font_px_size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
atlas : Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
entry : Entry,
|
||||
font_px_size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
|
||||
clear( & output.glyphs )
|
||||
clear( & output.positions )
|
||||
clear( & output.glyph_id )
|
||||
clear( & output.position )
|
||||
|
||||
shaper_shape_harfbuzz( ctx, text_utf8, entry, font_px_size, font_scale, output )
|
||||
|
||||
// Resolve each glyphs: bounds, atlas lru, and the atlas region as we have everything we need now.
|
||||
|
||||
profile_begin("bounds")
|
||||
for id, index in output.glyph_id
|
||||
{
|
||||
// glyph.bounds = parser_get_bounds( entry.parser_info, glyph.index )
|
||||
// glyph.bounds_scaled = { glyph.bounds.p0 * font_scale, glyph.bounds.p1 * font_scale }
|
||||
// glyph.bounds_size = glyph.bounds.p1 - glyph.bounds.p0
|
||||
// glyph.bounds_size_scaled = glyph.bounds_size * font_scale
|
||||
// glyph.scale = glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("index")
|
||||
for id, index in output.glyph_id
|
||||
{
|
||||
// output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, px_size, glyph.index)
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("region")
|
||||
for id, index in output.glyph_id
|
||||
{
|
||||
// output.region_kind[index] = atlas_decide_region_branchless( atlas ^, glyph_buffer_size, glyph.bounds_size_scaled )
|
||||
}
|
||||
profile_end()
|
||||
}
|
||||
|
||||
// Basic western alphabet based shaping. Not that much faster than harfbuzz if at all.
|
||||
shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
||||
entry : Entry,
|
||||
font_px_Size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
||||
atlas : Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
entry : Entry,
|
||||
font_px_Size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
|
||||
clear( & output.glyphs )
|
||||
clear( & output.positions )
|
||||
clear( & output.glyph_id )
|
||||
clear( & output.position )
|
||||
|
||||
line_height := (entry.ascent - entry.descent + entry.line_gap) * font_scale
|
||||
|
||||
@ -315,8 +355,8 @@ shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
||||
is_glyph_empty := parser_is_glyph_empty( entry.parser_info, glyph_index )
|
||||
if ! is_glyph_empty
|
||||
{
|
||||
append( & output.glyphs, glyph_index)
|
||||
append( & output.positions, Vec2 {
|
||||
append( & output.glyph_id, glyph_index)
|
||||
append( & output.position, Vec2 {
|
||||
ceil(position.x),
|
||||
ceil(position.y)
|
||||
})
|
||||
@ -343,6 +383,8 @@ shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
||||
shaper_shape_text_cached :: proc( text_utf8 : string,
|
||||
ctx : ^Shaper_Context,
|
||||
shape_cache : ^Shaped_Text_Cache,
|
||||
atlas : Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
font : Font_ID,
|
||||
entry : Entry,
|
||||
font_px_size : f32,
|
||||
@ -384,7 +426,7 @@ shaper_shape_text_cached :: proc( text_utf8 : string,
|
||||
}
|
||||
|
||||
storage_entry := & shape_cache.storage[ shape_cache_idx ]
|
||||
shape_text_uncached( ctx, entry, font_px_size, font_scale, text_utf8, storage_entry )
|
||||
shape_text_uncached( ctx, atlas, glyph_buffer_size, entry, font_px_size, font_scale, text_utf8, storage_entry )
|
||||
|
||||
shaped_text = storage_entry ^
|
||||
return
|
||||
|
@ -8,7 +8,7 @@ package vetext
|
||||
import "base:runtime"
|
||||
|
||||
// See: mappings.odin for profiling hookup
|
||||
DISABLE_PROFILING :: true
|
||||
DISABLE_PROFILING :: false
|
||||
|
||||
Font_ID :: distinct i32
|
||||
Glyph :: distinct i32
|
||||
@ -271,10 +271,10 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
for idx : u32 = 0; idx < shape_cache_params.capacity; idx += 1 {
|
||||
stroage_entry := & shape_cache.storage[idx]
|
||||
|
||||
stroage_entry.glyphs, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve )
|
||||
stroage_entry.glyph_id, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate glyphs array for shape cache storage" )
|
||||
|
||||
stroage_entry.positions, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve )
|
||||
stroage_entry.position, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate positions array for shape cache storage" )
|
||||
}
|
||||
}
|
||||
@ -282,10 +282,11 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
Glyph_Buffer_Setup:
|
||||
{
|
||||
glyph_buffer := & ctx.glyph_buffer
|
||||
glyph_buffer.over_sample = { f32(glyph_draw_params.over_sample), f32(glyph_draw_params.over_sample) }
|
||||
glyph_buffer.size.x = atlas.region_d.slot_size.x * i32(glyph_buffer.over_sample.x) * i32(glyph_draw_params.buffer_glyph_limit)
|
||||
glyph_buffer.size.y = atlas.region_d.slot_size.y * i32(glyph_buffer.over_sample.y)
|
||||
glyph_buffer.draw_padding = cast(f32) glyph_draw_params.draw_padding
|
||||
glyph_buffer.snap_glyph_height = cast(f32) i32(glyph_draw_params.snap_glyph_height)
|
||||
glyph_buffer.over_sample = { f32(glyph_draw_params.over_sample), f32(glyph_draw_params.over_sample) }
|
||||
glyph_buffer.size.x = atlas.region_d.slot_size.x * i32(glyph_buffer.over_sample.x) * i32(glyph_draw_params.buffer_glyph_limit)
|
||||
glyph_buffer.size.y = atlas.region_d.slot_size.y * i32(glyph_buffer.over_sample.y)
|
||||
glyph_buffer.draw_padding = cast(f32) glyph_draw_params.draw_padding
|
||||
|
||||
buffer_limit := glyph_draw_params.buffer_glyph_limit
|
||||
batch_limit := glyph_draw_params.batch_glyph_limit
|
||||
@ -314,7 +315,7 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
batch_cache := & glyph_buffer.batch_cache
|
||||
batch_cache.cap = i32(glyph_draw_params.batch_glyph_limit)
|
||||
batch_cache.num = 0
|
||||
batch_cache.table, error = make( map[Atlas_Region_Key]b8, uint(glyph_draw_params.shape_gen_scratch_reserve) )
|
||||
batch_cache.table, error = make( map[Atlas_Key]b8, uint(glyph_draw_params.shape_gen_scratch_reserve) )
|
||||
assert(error == .None, "VEFontCache.init : Failed to allocate batch_cache")
|
||||
|
||||
glyph_buffer.glyph_pack,error = make_soa( #soa[dynamic]Glyph_Pack_Entry, length = 0, capacity = 1 * Kilobyte )
|
||||
@ -364,8 +365,8 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator )
|
||||
lru_reload( & shape_cache.state, allocator )
|
||||
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
|
||||
storage_entry := & shape_cache.storage[idx]
|
||||
reload_array( & storage_entry.glyphs, allocator )
|
||||
reload_array( & storage_entry.positions, allocator )
|
||||
reload_array( & storage_entry.glyph_id, allocator )
|
||||
reload_array( & storage_entry.position, allocator )
|
||||
}
|
||||
reload_array( & shape_cache.storage, allocator )
|
||||
|
||||
@ -412,8 +413,8 @@ shutdown :: proc( ctx : ^Context )
|
||||
|
||||
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
|
||||
storage_entry := & shape_cache.storage[idx]
|
||||
delete( storage_entry.glyphs )
|
||||
delete( storage_entry.positions )
|
||||
delete( storage_entry.glyph_id )
|
||||
delete( storage_entry.position )
|
||||
}
|
||||
lru_free( & shape_cache.state )
|
||||
|
||||
@ -447,8 +448,8 @@ clear_shape_cache :: proc (ctx : ^Context)
|
||||
stroage_entry := & ctx.shape_cache.storage[idx]
|
||||
stroage_entry.end_cursor_pos = {}
|
||||
stroage_entry.size = {}
|
||||
clear(& stroage_entry.glyphs)
|
||||
clear(& stroage_entry.positions)
|
||||
clear(& stroage_entry.glyph_id)
|
||||
clear(& stroage_entry.position)
|
||||
}
|
||||
ctx.shape_cache.next_cache_id = 0
|
||||
}
|
||||
@ -665,7 +666,7 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
font_scale := parser_scale( entry.parser_info, px_size )
|
||||
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
@ -704,16 +705,17 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
adjusted_position := get_snapped_position( ctx^, position )
|
||||
|
||||
|
||||
colour := ctx.colour
|
||||
colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
// Does nothing when px_scalar is 1.0
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache,
|
||||
shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache, ctx.atlas, vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
target_px_size,
|
||||
@ -782,7 +784,11 @@ draw_text_layer :: #force_inline proc( ctx : ^Context, layer : []Text_Layer_Elem
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
assert( len(elem.text) > 0 )
|
||||
shape := shaper_shape_text_cached( elem.text, & ctx.shaper_ctx, & ctx.shape_cache,
|
||||
shape := shaper_shape_text_cached( elem.text,
|
||||
& ctx.shaper_ctx,
|
||||
& ctx.shape_cache,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
elem.font,
|
||||
entry,
|
||||
target_px_size,
|
||||
@ -871,7 +877,17 @@ measure_text_size :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
px_size_upscaled := px_size * ctx.px_scalar
|
||||
font_scale_upscaled := parser_scale( entry.parser_info, px_size_upscaled )
|
||||
|
||||
shaped := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache, font, entry, px_size_upscaled, font_scale_upscaled, shaper_shape_text_uncached_advanced )
|
||||
shaped := shaper_shape_text_cached( text_utf8,
|
||||
& ctx.shaper_ctx,
|
||||
& ctx.shape_cache,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
px_size_upscaled,
|
||||
font_scale_upscaled,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
return shaped.size * downscale
|
||||
}
|
||||
|
||||
@ -905,7 +921,11 @@ shape_text_latin :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
px_size_upscaled := px_size * ctx.px_scalar
|
||||
font_scale_upscaled := parser_scale( entry.parser_info, px_size_upscaled )
|
||||
|
||||
return shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache,
|
||||
return shaper_shape_text_cached( text_utf8,
|
||||
& ctx.shaper_ctx,
|
||||
& ctx.shape_cache,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
px_size_upscaled,
|
||||
@ -925,7 +945,11 @@ shape_text_advanced :: #force_inline proc( ctx : ^Context, font : Font_ID, px_si
|
||||
px_size_upscaled := px_size * ctx.px_scalar
|
||||
font_scale_upscaled := parser_scale( entry.parser_info, px_size_upscaled )
|
||||
|
||||
return shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache,
|
||||
return shaper_shape_text_cached( text_utf8,
|
||||
& ctx.shaper_ctx,
|
||||
& ctx.shape_cache,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
px_size_upscaled,
|
||||
|
@ -15,7 +15,7 @@ set_profiler_module_context :: #force_inline proc "contextless" ( ctx : ^SpallPr
|
||||
Module_Context = ctx
|
||||
}
|
||||
|
||||
DISABLE_PROFILING :: true
|
||||
DISABLE_PROFILING :: false
|
||||
|
||||
@(deferred_none = profile_end, disabled = DISABLE_PROFILING)
|
||||
profile :: #force_inline proc "contextless" ( name : string, loc := #caller_location ) {
|
||||
|
@ -550,7 +550,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
else
|
||||
{
|
||||
clear( input_str )
|
||||
append( & input_str, to_runes(str_fmt("%v", config.text_size_canvas_scalar)))
|
||||
append( & input_str, to_runes(str_fmt("%v", config.text_snap_glyph_positions)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,7 +608,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
else
|
||||
{
|
||||
clear( input_str )
|
||||
append( & input_str, to_runes(str_fmt("%v", config.text_size_canvas_scalar)))
|
||||
append( & input_str, to_runes(str_fmt("%v", config.text_alpha_sharpen)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,8 +153,8 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
color_theme = App_Thm_Dusk
|
||||
|
||||
text_snap_glyph_positions = true
|
||||
text_size_screen_scalar = 1.0
|
||||
text_size_canvas_scalar = 1.0
|
||||
text_size_screen_scalar = 2.0
|
||||
text_size_canvas_scalar = 2.0
|
||||
text_alpha_sharpen = 0.25
|
||||
}
|
||||
|
||||
@ -526,7 +526,7 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
|
||||
config := & get_state().config
|
||||
debug := & get_state().debug
|
||||
|
||||
debug.draw_ui_box_bounds_points = true
|
||||
debug.draw_ui_box_bounds_points = false
|
||||
debug.draw_ui_padding_bounds = false
|
||||
debug.draw_ui_content_bounds = false
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user