WIP - VEFontCache: Rendering 3k lines of whitespace ast is 16 ms rn...
This commit is contained in:
@ -158,7 +158,8 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
|
||||
|
||||
font := font
|
||||
if font.key == Font_Default.key do font = default_font
|
||||
draw_text_string_pos_extent( content, font, size, pos, color )
|
||||
shape := shape_text_cached( content, font, size, app_config().font_size_screen_scalar )
|
||||
draw_text_shape_pos_extent( shape, font, size, pos, color )
|
||||
}
|
||||
|
||||
debug_text :: proc( format : string, args : ..any )
|
||||
@ -578,8 +579,8 @@ render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_
|
||||
cam != nil ? cam.position.y : 0,
|
||||
}
|
||||
|
||||
screen_size := screen_extent * 2
|
||||
screen_scaled := (1.0 / screen_size)
|
||||
screen_size := screen_extent * 2
|
||||
screen_size_norm := (1.0 / screen_size)
|
||||
|
||||
layer_left : b32 = true
|
||||
for layer_left
|
||||
@ -646,10 +647,12 @@ render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_
|
||||
text_id += 1
|
||||
|
||||
if cam != nil {
|
||||
draw_text_string_pos_extent_zoomed( entry.text, font, entry.font_size, entry.position, cam_offset, screen_size, screen_scaled, cam.zoom, entry.color )
|
||||
// draw_text_shape_pos_extent_zoomed( entry.shape, font, entry.font_size, entry.position, cam_offset, screen_size, screen_size_norm, cam.zoom, entry.color )
|
||||
draw_text_string_pos_extent_zoomed( entry.text, font, entry.font_size, entry.position, cam_offset, screen_size, screen_size_norm, cam.zoom, entry.color )
|
||||
}
|
||||
else {
|
||||
draw_text_string_pos_extent( entry.text, font, entry.font_size, entry.position, entry.color )
|
||||
// draw_text_string_pos_extent( entry.shape, font, entry.font_size, entry.position, entry.color )
|
||||
}
|
||||
}
|
||||
|
||||
@ -897,34 +900,64 @@ draw_rect_rounded_border :: proc(rect: Range2, radii: [4]f32, border_width: f32,
|
||||
}
|
||||
|
||||
// Draw text using a string and normalized render coordinates
|
||||
draw_text_string_pos_norm :: proc( content : string, id : FontID, size : f32, pos : Vec2, color := Color_White, scale : f32 = 1.0 )
|
||||
draw_text_string_pos_norm :: #force_inline proc( text : string, id : FontID, font_size : f32, pos : Vec2, color := Color_White, scale : f32 = 1.0 )
|
||||
{
|
||||
state := get_state(); using state
|
||||
width := app_window.extent.x * 2
|
||||
height := app_window.extent.y * 2
|
||||
|
||||
ve_id, resolved_size := font_provider_resolve_draw_id( id, size * config.font_size_screen_scalar )
|
||||
ve_id, resolved_size := font_provider_resolve_draw_id( id, font_size * config.font_size_screen_scalar )
|
||||
color_norm := normalize_rgba8(color)
|
||||
|
||||
screen_size_norm := Vec2{1 / width, 1 / height}
|
||||
|
||||
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, text, pos, screen_size_norm * scale * (1 / config.font_size_screen_scalar) )
|
||||
return
|
||||
}
|
||||
|
||||
// Draw text using a string and extent-based screen coordinates
|
||||
draw_text_string_pos_extent :: proc( content : string, id : FontID, size : f32, pos : Vec2, color := Color_White )
|
||||
draw_text_string_pos_extent :: #force_inline proc( text : string, id : FontID, font_size : f32, pos : Vec2, color := Color_White )
|
||||
{
|
||||
// profile(#procedure)
|
||||
profile(#procedure)
|
||||
state := get_state(); using state
|
||||
screen_size := app_window.extent * 2
|
||||
render_pos := screen_to_render_pos(pos)
|
||||
normalized_pos := render_pos * (1.0 / screen_size)
|
||||
draw_text_string_pos_norm( content, id, size, normalized_pos, color )
|
||||
draw_text_string_pos_norm( text, id, font_size, normalized_pos, color )
|
||||
}
|
||||
|
||||
draw_text_string_pos_extent_zoomed :: #force_inline proc( content : string, id : FontID, size : f32, pos, cam_offset, screen_size, screen_scaled : Vec2, zoom : f32, color := Color_White )
|
||||
// Draw text using a string and normalized render coordinates
|
||||
draw_text_shape_pos_norm :: #force_inline proc( shape : ShapedText, id : FontID, font_size : f32, pos : Vec2, color := Color_White, scale : f32 = 1.0 )
|
||||
{
|
||||
// profile(#procedure)
|
||||
state := get_state(); using state
|
||||
width := app_window.extent.x * 2
|
||||
height := app_window.extent.y * 2
|
||||
|
||||
ve_id, resolved_size := font_provider_resolve_draw_id( id, font_size * config.font_size_screen_scalar )
|
||||
color_norm := normalize_rgba8(color)
|
||||
|
||||
screen_size_norm := Vec2{1 / width, 1 / height}
|
||||
|
||||
ve.set_colour( & font_provider_ctx.ve_ctx, color_norm )
|
||||
ve.draw_text_shape( & font_provider_ctx.ve_ctx, ve_id, shape, pos, screen_size_norm * scale * (1 / config.font_size_screen_scalar) )
|
||||
return
|
||||
}
|
||||
|
||||
// Draw text using a string and extent-based screen coordinates
|
||||
draw_text_shape_pos_extent :: #force_inline proc( shape : ShapedText, id : FontID, font_size : f32, pos : Vec2, color := Color_White )
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state(); using state
|
||||
screen_size := app_window.extent * 2
|
||||
render_pos := screen_to_render_pos(pos)
|
||||
normalized_pos := render_pos * (1.0 / screen_size)
|
||||
draw_text_shape_pos_norm( shape, id, font_size, normalized_pos, color )
|
||||
}
|
||||
|
||||
draw_text_string_pos_extent_zoomed :: #force_inline proc( text : string, id : FontID, size : f32, pos, cam_offset, screen_size, screen_size_norm : Vec2, zoom : f32, color := Color_White )
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state(); using state // TODO(Ed): Remove usage of direct access to entire mutable state.
|
||||
|
||||
zoom_adjust_size := size * zoom
|
||||
@ -935,16 +968,16 @@ draw_text_string_pos_extent_zoomed :: #force_inline proc( content : string, id :
|
||||
|
||||
pos_offset := (pos + cam_offset)
|
||||
render_pos := ws_view_to_render_pos(pos)
|
||||
normalized_pos := render_pos * screen_scaled
|
||||
normalized_pos := render_pos * screen_size_norm
|
||||
|
||||
ve_id, resolved_size := font_provider_resolve_draw_id( id, zoom_adjust_size )
|
||||
|
||||
text_scale : Vec2 = screen_scaled
|
||||
text_scale : Vec2 = screen_size_norm
|
||||
// if config.cam_zoom_mode == .Smooth
|
||||
{
|
||||
f32_resolved_size := f32(resolved_size)
|
||||
diff_scalar := 1 + (zoom_adjust_size - f32_resolved_size) / f32_resolved_size
|
||||
text_scale = diff_scalar * screen_scaled
|
||||
text_scale = diff_scalar * screen_size_norm
|
||||
text_scale.x = clamp( text_scale.x, 0, screen_size.x )
|
||||
text_scale.y = clamp( text_scale.y, 0, screen_size.y )
|
||||
}
|
||||
@ -954,7 +987,42 @@ draw_text_string_pos_extent_zoomed :: #force_inline proc( content : string, id :
|
||||
|
||||
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, normalized_pos, text_scale )
|
||||
ve.draw_text( & font_provider_ctx.ve_ctx, ve_id, text, normalized_pos, text_scale )
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state(); using state // TODO(Ed): Remove usage of direct access to entire mutable state.
|
||||
|
||||
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)
|
||||
zoom_adjust_size *= over_sample
|
||||
|
||||
pos_offset := (pos + cam_offset)
|
||||
render_pos := ws_view_to_render_pos(pos)
|
||||
normalized_pos := render_pos * screen_size_norm
|
||||
|
||||
ve_id, resolved_size := font_provider_resolve_draw_id( id, zoom_adjust_size )
|
||||
|
||||
text_scale : Vec2 = screen_size_norm
|
||||
// if config.cam_zoom_mode == .Smooth
|
||||
{
|
||||
f32_resolved_size := f32(resolved_size)
|
||||
diff_scalar := 1 + (zoom_adjust_size - f32_resolved_size) / f32_resolved_size
|
||||
text_scale = diff_scalar * screen_size_norm
|
||||
text_scale.x = clamp( text_scale.x, 0, screen_size.x )
|
||||
text_scale.y = clamp( text_scale.y, 0, screen_size.y )
|
||||
}
|
||||
|
||||
// Down-sample back
|
||||
text_scale /= over_sample
|
||||
|
||||
color_norm := normalize_rgba8(color)
|
||||
ve.set_colour( & font_provider_ctx.ve_ctx, color_norm )
|
||||
ve.draw_text_shape( & font_provider_ctx.ve_ctx, ve_id, shape, normalized_pos, text_scale )
|
||||
}
|
||||
|
||||
// TODO(Ed): Eventually the workspace will need a viewport for drawing text
|
||||
|
@ -34,6 +34,8 @@ FontProviderContext :: struct
|
||||
using render : VE_RenderData,
|
||||
}
|
||||
|
||||
ShapedText :: ve.Shaped_Text
|
||||
|
||||
font_provider_startup :: proc( ctx : ^FontProviderContext )
|
||||
{
|
||||
profile(#procedure)
|
||||
@ -116,7 +118,7 @@ font_load :: proc(path_file : string,
|
||||
|
||||
Font_Use_Default_Size :: f32(0.0)
|
||||
|
||||
font_provider_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Size ) -> (ve_id :ve.Font_ID, resolved_size : i32)
|
||||
font_provider_resolve_draw_id :: #force_inline proc( id : FontID, size := Font_Use_Default_Size ) -> (ve_id :ve.Font_ID, resolved_size : i32)
|
||||
{
|
||||
provider_data := get_state().font_provider_ctx; using provider_data
|
||||
|
||||
@ -130,7 +132,7 @@ font_provider_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Siz
|
||||
return
|
||||
}
|
||||
|
||||
measure_text_size :: proc( text : string, font : FontID, font_size := Font_Use_Default_Size, spacing : f32 ) -> Vec2
|
||||
measure_text_size :: #force_inline proc( text : string, font : FontID, font_size := Font_Use_Default_Size, spacing : f32 ) -> Vec2
|
||||
{
|
||||
ve_id, size := font_provider_resolve_draw_id( font, font_size )
|
||||
measured := ve.measure_text_size( & get_state().font_provider_ctx.ve_ctx, ve_id, text )
|
||||
@ -143,3 +145,10 @@ get_font_vertical_metrics :: #force_inline proc ( font : FontID, font_size := Fo
|
||||
ascent, descent, line_gap = ve.get_font_vertical_metrics( & get_state().font_provider_ctx.ve_ctx, ve_id )
|
||||
return
|
||||
}
|
||||
|
||||
shape_text_cached :: #force_inline proc( text : string, font : FontID, font_size := Font_Use_Default_Size, scalar : f32 ) -> ShapedText
|
||||
{
|
||||
ve_id, size := font_provider_resolve_draw_id( font, font_size * scalar )
|
||||
shape := ve.shape_text_advanced( & get_state().font_provider_ctx.ve_ctx, ve_id, text )
|
||||
return shape
|
||||
}
|
||||
|
@ -58,13 +58,21 @@ UI_ScalarConstraint :: struct {
|
||||
|
||||
UI_Scalar2 :: [Axis2.Count]UI_Scalar
|
||||
|
||||
// UI_BoxFlags_Stack_Size :: 512
|
||||
UI_Layout_Stack_Size :: 512
|
||||
UI_Style_Stack_Size :: 512
|
||||
UI_Parent_Stack_Size :: 512
|
||||
// UI_Built_Boxes_Array_Size :: 8
|
||||
UI_Built_Boxes_Array_Size :: 56 * Kilobyte
|
||||
UI_BoxCache_TableSize :: 8 * Kilobyte
|
||||
// The UI_Box's actual positioning and sizing
|
||||
// There is an excess of rectangles here for debug puproses.
|
||||
UI_Computed :: struct {
|
||||
// anchors : Range2, // Bounds for anchors within parent
|
||||
// margins : Range2, // Bounds for margins within parent
|
||||
padding : Range2, // Bounds for padding's starting bounds (will be offset by border if there is one), only here for debug vis
|
||||
|
||||
bounds : Range2, // Bounds for box itself
|
||||
content : Range2, // Bounds for content (text or children)
|
||||
text_shape : ShapedText, // Text string processed into shape optimial for processing by text draw_list generator.
|
||||
text_pos : Vec2, // Position of text within content
|
||||
text_size : Vec2, // Size of text within content
|
||||
fresh : b32, // If the auto-layout has been computed for the current frame
|
||||
}
|
||||
|
||||
|
||||
UI_RenderEntry :: struct {
|
||||
info : UI_RenderBoxInfo,
|
||||
@ -75,16 +83,6 @@ UI_RenderEntry :: struct {
|
||||
|
||||
UI_RenderLayer :: DLL_NodeFL(UI_RenderEntry)
|
||||
|
||||
// UI_RenderBoxInfo :: struct {
|
||||
// using computed : UI_Computed,
|
||||
// using style : UI_Style,
|
||||
// text : StrRunesPair,
|
||||
// font_size : UI_Scalar,
|
||||
// border_width : UI_Scalar,
|
||||
// label : StrRunesPair,
|
||||
// layer_signal : b32,
|
||||
// }
|
||||
|
||||
UI_RenderBoxInfo :: struct {
|
||||
bounds : Range2,
|
||||
corner_radii : [Corner.Count]f32,
|
||||
@ -96,6 +94,7 @@ UI_RenderBoxInfo :: struct {
|
||||
|
||||
UI_RenderTextInfo :: struct {
|
||||
text : string,
|
||||
shape : ShapedText,
|
||||
position : Vec2,
|
||||
color : RGBA8,
|
||||
font : FontID,
|
||||
@ -110,6 +109,14 @@ UI_RenderMethod :: enum u32 {
|
||||
|
||||
UI_Render_Method :: UI_RenderMethod.Layers
|
||||
|
||||
// UI_BoxFlags_Stack_Size :: 512
|
||||
UI_Layout_Stack_Size :: 512
|
||||
UI_Style_Stack_Size :: 512
|
||||
UI_Parent_Stack_Size :: 512
|
||||
// UI_Built_Boxes_Array_Size :: 8
|
||||
UI_Built_Boxes_Array_Size :: 56 * Kilobyte
|
||||
UI_BoxCache_TableSize :: 8 * Kilobyte
|
||||
|
||||
// TODO(Ed): Rename to UI_Context
|
||||
UI_State :: struct {
|
||||
// TODO(Ed) : Use these?
|
||||
@ -267,7 +274,20 @@ ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
for current := ui.root.first; current != nil;
|
||||
current = ui_box_tranverse_next_depth_first( current, bypass_intersection_test = true, ctx = ui )
|
||||
{
|
||||
if ! current.computed.fresh {
|
||||
if ! current.computed.fresh
|
||||
{
|
||||
if len(current.text.str) > 0 {
|
||||
app_window := get_state().app_window
|
||||
screen_extent := app_window.extent
|
||||
screen_size := screen_extent * 2
|
||||
screen_size_norm := 1 / screen_size
|
||||
|
||||
font_size_screen_scalar := app_config().font_size_screen_scalar
|
||||
|
||||
// over_sample : f32 = f32(get_state().config.font_size_canvas_scalar)
|
||||
|
||||
current.computed.text_shape = shape_text_cached( current.text.str, current.style.font, current.layout.font_size, 1.0 )
|
||||
}
|
||||
ui_box_compute_layout( current )
|
||||
}
|
||||
|
||||
@ -288,10 +308,11 @@ ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
array_append(& ui.render_list_box, entry_box)
|
||||
|
||||
// TODO(Ed): It may be better to let VEFontCache handle processing empty strings.
|
||||
if len(current.text.str) > 0
|
||||
{
|
||||
// if len(current.text.str) > 0
|
||||
// {
|
||||
entry_text := UI_RenderTextInfo {
|
||||
text = current.text.str,
|
||||
shape = current.computed.text_shape,
|
||||
position = current.computed.text_pos,
|
||||
color = current.style.text_color,
|
||||
font = current.style.font,
|
||||
@ -299,7 +320,7 @@ ui_graph_build_end :: proc( ui : ^UI_State )
|
||||
}
|
||||
entry_text.layer_signal = different_ancestory
|
||||
array_append(& ui.render_list_text, entry_text)
|
||||
}
|
||||
// }
|
||||
|
||||
previous_layer = current.ancestors
|
||||
}
|
||||
|
@ -46,21 +46,6 @@ UI_Align_Presets :: UI_Align_Presets_Struct {
|
||||
text_centered = {0.5, 0.5},
|
||||
}
|
||||
|
||||
|
||||
// The UI_Box's actual positioning and sizing
|
||||
// There is an excess of rectangles here for debug puproses.
|
||||
UI_Computed :: struct {
|
||||
// anchors : Range2, // Bounds for anchors within parent
|
||||
// margins : Range2, // Bounds for margins within parent
|
||||
padding : Range2, // Bounds for padding's starting bounds (will be offset by border if there is one), only here for debug vis
|
||||
|
||||
bounds : Range2, // Bounds for box itself
|
||||
content : Range2, // Bounds for content (text or children)
|
||||
text_pos : Vec2, // Position of text within content
|
||||
text_size : Vec2, // Size of text within content
|
||||
fresh : b32, // If the auto-layout has been computed for the current frame
|
||||
}
|
||||
|
||||
UI_LayoutDirection_XY :: enum(i32) {
|
||||
Left_To_Right,
|
||||
Right_to_Left,
|
||||
|
@ -5,7 +5,7 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
ancestors_layout_required : b32 = false,
|
||||
root_layout_required : b32 = false )
|
||||
{
|
||||
// profile("Layout Box")
|
||||
profile("Layout Box")
|
||||
state := get_state()
|
||||
ui := state.ui_context
|
||||
using box
|
||||
@ -73,12 +73,15 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
text_size : Vec2
|
||||
if len(box.text.str) > 0
|
||||
{
|
||||
if layout.font_size == computed.text_size.y {
|
||||
text_size = computed.text_size
|
||||
}
|
||||
else {
|
||||
text_size = cast(Vec2) measure_text_size( box.text.str, style.font, layout.font_size, 0 )
|
||||
}
|
||||
|
||||
|
||||
text_size = computed.text_shape.size
|
||||
// if layout.font_size == computed.text_size.y {
|
||||
// text_size = computed.text_size
|
||||
// }
|
||||
// else {
|
||||
// text_size = cast(Vec2) measure_text_size( box.text.str, style.font, layout.font_size, 0 )
|
||||
// }
|
||||
}
|
||||
|
||||
if size_to_text {
|
||||
|
Reference in New Issue
Block a user