Builds again has on text rendering (makes sense)

This commit is contained in:
Edward R. Gonzalez 2025-01-07 10:17:46 -05:00
parent 3a245a1e9b
commit 6e01c39899
6 changed files with 132 additions and 99 deletions

View File

@ -286,8 +286,8 @@ generate_shapes_draw_list :: #force_inline proc ( ctx : ^Context, font : Font_ID
/* Core generator pipeline for shapes
If you'd like to make a custom draw procedure, this may either be directly used, or
should be straight forward to make an augmented derivative for a specific codepath.
If you'd like to make a custom draw procedure, this can either be used directly or
modified to create an augmented derivative for a specific code path.
This procedure has no awareness of layers. That should be handled by a higher-order codepath.
For this level of codepaths what matters is maximizing memory locality for:
@ -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
non_zero_resize_soa(glyph_pack, len(shape.glyphs))
resize_soa_non_zero(glyph_pack, len(shape.glyphs))
append_sub_pack :: #force_inline proc ( pack : ^[dynamic]i32, entry : i32 )
{
@ -754,12 +754,10 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
)
}
profile_begin("generate_cached_draw_list: to_cache")
if enable_debug_vis_tyeps {
colour.r = 1.0
colour.g = 1.0
colour.b = 1.0
}
profile_begin("generate_cached_draw_list: cached")
colour.r = max(colour.r, 1.0 * enable_debug_vis_type)
colour.g = max(colour.g, 1.0 * enable_debug_vis_type)
colour.b = max(colour.b, 1.0 * enable_debug_vis_type)
generate_cached_draw_list( draw_list, glyph_pack[:], cached, colour )
profile_end()
@ -769,11 +767,9 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
profile_end()
profile_begin("generate_cached_draw_list: to_cache")
if enable_debug_vis_tyeps {
colour.r = 0.80
colour.g = 0.25
colour.b = 0.25
}
colour.r = max(colour.r, 0.80 * enable_debug_vis_type)
colour.g = max(colour.g, 0.25 * enable_debug_vis_type)
colour.b = max(colour.b, 0.25 * enable_debug_vis_type)
generate_cached_draw_list( draw_list, glyph_pack[:], to_cache, colour )
profile_end()
}

View File

@ -1,6 +1,7 @@
package vetext
import "base:builtin"
resize_soa_non_zero :: non_zero_resize_soa
import "base:runtime"
import "core:hash"
ginger16 :: hash.ginger16
@ -105,11 +106,6 @@ peek :: proc {
peek_array,
}
pop_array :: proc {
builtin.pop,
// pop_safe,
}
resize :: proc {
builtin.resize_dynamic_array,
}

View File

@ -37,10 +37,10 @@ Entry_Default :: Entry {
}
// Ease of use encapsulation of common fields for a canvas space
Camera :: struct {
view : [dynamic]Vec2,
position : [dynamic]Vec2,
zoom : [dynamic]f32,
VPZ_Transform :: struct {
view : Vec2,
position : Vec2,
zoom : f32,
}
Scope_Stack :: struct {
@ -539,63 +539,74 @@ Used with snap_to_view_extent to enforce position snapping.
Position: Used with a draw procedure that uses relative positioning will offset the incoming position by the given amount.
Scale : Used with a draw procedure that uses relative scaling, will scale the procedures incoming scale by the given amount.
Zoom : Used with a draw procedure that uses scaling via zoom, will scale the procedure's incoming font size & scale based on an 'canvas' camera's notion of it.
The pkg_mapping.odin provides an explicit set of overloads for these:
scope()
push()
pop()
*/
@(deferred_none = pop_font)
scope_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) }
push_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) }
pop_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); pop_array(& ctx.stack.font) }
@(deferred_in = auto_pop_font)
scope_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) }
push_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); append(& ctx.stack.font, font ) }
pop_font :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.font) }
auto_pop_font :: #force_inline proc( ctx : ^Context, font : Font_ID ) { assert(ctx != nil); pop(& ctx.stack.font) }
@(deferred_none = pop_font_size)
scope_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) }
push_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) }
pop_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); pop_array(& ctx.stack.font_size) }
@(deferred_in = auto_pop_font_size)
scope_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) }
push_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); append(& ctx.stack.font_size, px_size) }
pop_font_size :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.font_size) }
auto_pop_font_size :: #force_inline proc( ctx : ^Context, px_size : f32 ) { assert(ctx != nil); pop(& ctx.stack.font_size) }
@(deferred_none = pop_colour )
scope_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) }
push_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) }
pop_colour :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop_array(& ctx.stack.colour) }
@(deferred_in = auto_pop_colour )
scope_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) }
push_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); append(& ctx.stack.colour, colour) }
pop_colour :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.colour) }
auto_pop_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); pop(& ctx.stack.colour) }
@(deferred_none = pop_view)
scope_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) }
push_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) }
pop_view :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop_array(& ctx.stack.view) }
@(deferred_in = auto_pop_view)
scope_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) }
push_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); append(& ctx.stack.view, view) }
pop_view :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop(& ctx.stack.view) }
auto_pop_view :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.view) }
@(deferred_none = pop_position)
scope_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) }
push_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) }
pop_position :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop_array( & ctx.stack.position) }
@(deferred_in = auto_pop_position)
scope_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) }
push_position :: #force_inline proc( ctx : ^Context, position : Vec2 ) { assert(ctx != nil); append(& ctx.stack.position, position ) }
pop_position :: #force_inline proc( ctx : ^Context ) { assert(ctx != nil); pop( & ctx.stack.position) }
auto_pop_position :: #force_inline proc( ctx : ^Context, view : Vec2 ) { assert(ctx != nil); pop( & ctx.stack.position) }
@(deferred_none = pop_scale)
scope_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { append(& ctx.stack.scale, scale ) }
push_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { append(& ctx.stack.scale, scale ) }
pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { pop_array(& ctx.stack.scale) }
@(deferred_in = auto_pop_scale)
scope_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); append(& ctx.stack.scale, scale ) }
push_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); append(& ctx.stack.scale, scale ) }
pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.scale) }
auto_pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.scale) }
@(deferred_none = pop_zoom )
scope_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom ) }
push_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom) }
pop_zoom :: #force_inline proc( ctx : ^Context ) { pop_array(& ctx.stack.zoom) }
@(deferred_in = auto_pop_zoom )
scope_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom ) }
push_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { append(& ctx.stack.zoom, zoom) }
pop_zoom :: #force_inline proc( ctx : ^Context ) { pop(& ctx.stack.zoom) }
auto_pop_zoom :: #force_inline proc( ctx : ^Context, zoom : f32 ) { pop(& ctx.stack.zoom) }
@(deferred_none = pop_camera)
scope_camera :: #force_inline proc( ctx : ^Context, camera : Camera ) {
@(deferred_in = auto_pop_vpz)
scope_vpz :: #force_inline proc( ctx : ^Context, camera : VPZ_Transform ) {
assert(ctx != nil)
append(& ctx.stack.view, camera.view )
append(& ctx.stack.position, camera.position )
append(& ctx.stack.zoom, camera.zoom )
}
push_camera :: #force_inline proc( ctx : ^Context, camera : Camera ) {
push_vpz :: #force_inline proc( ctx : ^Context, camera : VPZ_Transform ) {
assert(ctx != nil)
append(& ctx.stack.view, camera.view )
append(& ctx.stack.position, camera.position )
append(& ctx.stack.zoom, camera.zoom )
}
pop_camera :: #force_inline proc( ctx : ^Context ) {
pop_array(& ctx.stack.view )
pop_array(& ctx.stack.position)
pop_array(& ctx.stack.zoom )
pop_vpz :: #force_inline proc( ctx : ^Context ) {
assert(ctx != nil)
pop(& ctx.stack.view )
pop(& ctx.stack.position)
pop(& ctx.stack.zoom )
}
auto_pop_vpz :: #force_inline proc( ctx : ^Context, camera : VPZ_Transform ) {
assert(ctx != nil)
pop(& ctx.stack.view )
pop(& ctx.stack.position)
pop(& ctx.stack.zoom )
}
//#endregion("scoping")
@ -644,7 +655,7 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context,
assert( ctx != nil )
assert( font >= 0 && int(font) < len(ctx.entries) )
adjusted_position := get_snapped_position( ctx, position )
adjusted_position := get_snapped_position( ctx^, position )
entry := ctx.entries[ font ]
@ -658,6 +669,7 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context,
font_scale_upscale := parser_scale( entry.parser_info, px_upscale )
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer, ctx.px_scalar,
ctx.enable_draw_type_visualization,
adjusted_colour,
entry,
px_upscale,
@ -690,7 +702,7 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
ctx.cursor_pos = {}
entry := ctx.entries[ font ]
adjusted_position := get_snapped_position( ctx, position )
adjusted_position := get_snapped_position( ctx^, position )
colour := ctx.colour
colour.a = 1.0 + ctx.alpha_sharpen
@ -698,7 +710,7 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
// Does nothing when px_scalar is 1.0
target_px_size := px_size * ctx.px_scalar
target_scale := scale * (1 / ctx.px_scalar)
target_font_scale := parser_scale( entry.parser_info, px_upscale )
target_font_scale := parser_scale( entry.parser_info, target_px_size )
shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache,
font,
@ -708,6 +720,7 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
shaper_shape_text_uncached_advanced
)
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer, ctx.px_scalar,
ctx.enable_draw_type_visualization,
colour,
entry,
target_px_size,
@ -734,7 +747,7 @@ Text_Layer_Elem :: struct {
font : Font_ID,
px_size : f32,
zoom : f32,
colour : Colour,
colour : RGBAN,
}
// Batch a layer of text. Use get_draw_list_layer to process the layer immediately after.
@ -742,41 +755,59 @@ draw_text_layer :: #force_inline proc( ctx : ^Context, layer : []Text_Layer_Elem
{
profile(#procedure)
assert( ctx != nil )
assert( font >= 0 && int(font) < len(ctx.entries) )
assert( len(texts) > 0 )
assert( len(layer) > 0 )
for elem in layer
{
entry := ctx.entries[ elem.font ]
assert( elem.font >= 0 && int(elem.font) < len(ctx.entries) )
ctx.cursor_pos = {}
adjusted_position := get_snapped_position( ctx, position )
colour := ctx.colour
colour.a = 1.0 + ctx.alpha_sharpen
font_scale := parser_scale( entry.parser_info, px_size )
px_upscale := px_size * ctx.px_scalar
downscale := scale * (1 / ctx.px_scalar)
font_scale_upscale := parser_scale( entry.parser_info, px_upscale )
shapes := make( []Shaped_Text, len(texts) )
for str, id in texts
shapes := make( []Shaped_Text, len(layer) )
for elem, id in layer
{
assert( len(str) > 0 )
shape := shaper_shape_text_cached( str, & ctx.shaper_ctx, & ctx.shape_cache,
font,
entry := ctx.entries[ elem.font ]
ctx.cursor_pos = {}
// colour := ctx.colour
// colour.a = 1.0 + ctx.alpha_sharpen
// adjusted_position := get_snapped_position( ctx^, elem.position )
// font_scale := parser_scale( entry.parser_info, elem.px_size )
target_px_size := elem.px_size * ctx.px_scalar
// target_scale := elem.scale * (1 / ctx.px_scalar)
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,
elem.font,
entry,
px_upscale,
font_scale_upscale,
target_px_size,
target_font_scale,
shaper_shape_text_uncached_advanced
)
shapes[id] = shape
}
generate_shapes_draw_list(ctx, font, colour, entry, px_upscale, font_scale_upscale, position, downscale, shapes )
for elem, id in layer {
entry := ctx.entries[ elem.font ]
ctx.cursor_pos = {}
colour := ctx.colour
colour.a = 1.0 + ctx.alpha_sharpen
adjusted_position := get_snapped_position( ctx^, elem.position )
// font_scale := parser_scale( entry.parser_info, elem.px_size )
target_px_size := elem.px_size * ctx.px_scalar
target_scale := elem.scale * (1 / ctx.px_scalar)
target_font_scale := parser_scale( entry.parser_info, target_px_size )
generate_shapes_draw_list(ctx, elem.font, elem.colour, entry, target_px_size, target_font_scale, adjusted_position, target_scale, shapes )
}
}
}
@ -803,6 +834,7 @@ flush_draw_list :: #force_inline proc( ctx : ^Context ) {
ctx.draw_layer.calls_offset = 0
}
flush_draw_list_layer :: #force_inline proc( ctx : ^Context ) {
assert( ctx != nil )
ctx.draw_layer.vertices_offset = len(ctx.draw_list.vertices)

View File

@ -356,7 +356,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (197).txt", allocator = persistent_slab_allocator())
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (1022).txt", allocator = persistent_slab_allocator())
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gp.h", allocator = persistent_slab_allocator())
debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gp.h", allocator = persistent_slab_allocator())
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/ve_fontcache.h", allocator = persistent_slab_allocator())
alloc_error : AllocatorError; success : bool

View File

@ -927,7 +927,7 @@ draw_text_string_pos_norm :: #force_inline proc( text : string, id : FontID, fon
// ve.set_px_scalar( & font_provider_ctx.ve_ctx, config.font_size_screen_scalar )
ve.set_colour( & font_provider_ctx.ve_ctx, color_norm )
ve.draw_text( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), pos, draw_scale, text )
ve.draw_text_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), color_norm, {}, pos, draw_scale, 1.0, text )
return
}
@ -957,7 +957,7 @@ draw_text_shape_pos_norm :: #force_inline proc( shape : ShapedText, id : FontID,
// ve.set_px_scalar( & font_provider_ctx.ve_ctx, config.font_size_screen_scalar )
ve.set_colour( & font_provider_ctx.ve_ctx, color_norm )
ve.draw_text_shape( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), pos, screen_size_norm * scale, shape )
ve.draw_text_shape_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), color_norm, {}, pos, screen_size_norm * scale, 1.0, shape )
return
}
@ -998,7 +998,16 @@ draw_text_string_pos_extent_zoomed :: #force_inline proc( text : string, id : Fo
color_norm := normalize_rgba8(color)
ve.set_colour( & get_state().font_provider_ctx.ve_ctx, color_norm )
ve.draw_text( & get_state().font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), normalized_pos, text_scale, text )
ve.draw_text_normalized_space( & get_state().font_provider_ctx.ve_ctx,
ve_id,
f32(resolved_size),
color_norm,
{},
normalized_pos,
text_scale,
1.0,
text
)
}
draw_text_shape_pos_extent_zoomed :: #force_inline proc( shape : ShapedText, id : FontID, size : f32, pos, cam_offset, screen_size, screen_size_norm : Vec2, zoom : f32, color := Color_White )
@ -1009,7 +1018,7 @@ draw_text_shape_pos_extent_zoomed :: #force_inline proc( shape : ShapedText, id
zoom_adjust_size := size * zoom
// Over-sample font-size for any render under a camera
over_sample : f32 = f32(state.config.font_size_canvas_scalar)
over_sample : f32 = f32(app_config().text_size_canvas_scalar)
// zoom_adjust_size *= over_sample
pos_offset := (pos + cam_offset)
@ -1034,7 +1043,7 @@ draw_text_shape_pos_extent_zoomed :: #force_inline proc( shape : ShapedText, id
color_norm := normalize_rgba8(color)
// ve.set_px_scalar( & get_state().font_provider_ctx.ve_ctx, config.font_size_canvas_scalar )
ve.set_colour( & font_provider_ctx.ve_ctx, color_norm )
ve.draw_text_shape( & font_provider_ctx.ve_ctx, ve_id, f32_resolved_size, normalized_pos, text_scale, shape )
ve.draw_text_shape_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32_resolved_size, color_norm, {}, normalized_pos, text_scale, 1.0, shape )
}
// TODO(Ed): Eventually the workspace will need a viewport for drawing text

View File

@ -205,9 +205,9 @@ push-location $path_root
# $build_args += $flag_micro_architecture_native
$build_args += $flag_use_separate_modules
$build_args += $flag_thread_count + $CoreCount_Physical
$build_args += $flag_optimize_none
# $build_args += $flag_optimize_none
# $build_args += $flag_optimize_minimal
# $build_args += $flag_optimize_speed
$build_args += $flag_optimize_speed
# $build_args += $falg_optimize_aggressive
$build_args += $flag_debug
$build_args += $flag_pdb_name + $pdb