Compare commits

...

2 Commits

4 changed files with 81 additions and 202 deletions

View File

@ -271,24 +271,24 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType, // N
for idx : u32 = 0; idx < shape_cache_params.capacity; idx += 1
{
stroage_entry := & shape_cache.storage[idx]
storage_entry := & shape_cache.storage[idx]
stroage_entry.glyph, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve )
storage_entry.glyph, 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.position, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve )
storage_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" )
stroage_entry.visible, error = make( [dynamic]i32, len = 0, cap = shape_cache_params.reserve )
storage_entry.visible, error = make( [dynamic]i32, len = 0, cap = shape_cache_params.reserve )
assert( error == .None, "VEFontCache.init : Failed to allocate visible array for shape cache storage" )
stroage_entry.atlas_lru_code, error = make( [dynamic]Atlas_Key, len = 0, cap = shape_cache_params.reserve )
storage_entry.atlas_lru_code, error = make( [dynamic]Atlas_Key, len = 0, cap = shape_cache_params.reserve )
assert( error == .None, "VEFontCache.init : Failed to allocate atlas_lru_code array for shape cache storage" )
stroage_entry.region_kind, error = make( [dynamic]Atlas_Region_Kind, len = 0, cap = shape_cache_params.reserve )
storage_entry.region_kind, error = make( [dynamic]Atlas_Region_Kind, len = 0, cap = shape_cache_params.reserve )
assert( error == .None, "VEFontCache.init : Failed to allocate region_kind array for shape cache storage" )
stroage_entry.bounds, error = make( [dynamic]Range2, len = 0, cap = shape_cache_params.reserve )
storage_entry.bounds, error = make( [dynamic]Range2, len = 0, cap = shape_cache_params.reserve )
assert( error == .None, "VEFontCache.init : Failed to allocate bounds array for shape cache storage" )
}
}
@ -415,7 +415,7 @@ 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.glyph, allocator)
reload_array( & storage_entry.glyph, allocator)
reload_array( & storage_entry.position, allocator)
reload_array( & storage_entry.visible, allocator)
reload_array( & storage_entry.atlas_lru_code, allocator)
@ -604,11 +604,11 @@ clear_shape_cache :: proc (ctx : ^Context)
{
lru_clear(& ctx.shape_cache.state)
for idx : i32 = 0; idx < cast(i32) cap(ctx.shape_cache.storage); idx += 1 {
stroage_entry := & ctx.shape_cache.storage[idx]
stroage_entry.end_cursor_pos = {}
stroage_entry.size = {}
clear(& stroage_entry.glyph)
clear(& stroage_entry.position)
storage_entry := & ctx.shape_cache.storage[idx]
storage_entry.end_cursor_pos = {}
storage_entry.size = {}
clear(& storage_entry.glyph)
clear(& storage_entry.position)
}
ctx.shape_cache.next_cache_id = 0
}
@ -1196,6 +1196,10 @@ get_font_vertical_metrics :: #force_inline proc ( ctx : Context, font : Font_ID,
//#region("miscellaneous")
get_font_entry :: #force_inline proc "contextless" ( ctx : ^Context, font : Font_ID ) -> Entry {
return ctx.entries[font]
}
get_cursor_pos :: #force_inline proc "contextless" ( ctx : Context ) -> Vec2 { return ctx.cursor_pos }
// Will normalize the value of the position and scale based on the provided view.
@ -1203,19 +1207,14 @@ get_cursor_pos :: #force_inline proc "contextless" ( ctx : Context ) -> Vec2 { r
// (Does nothing if view is 1 or 0)
get_normalized_position_scale :: #force_inline proc "contextless" ( position, scale, view : Vec2 ) -> (position_norm, scale_norm : Vec2)
{
snap_quotient := 1 / Vec2 { max(view.x, 1), max(view.y, 1) }
should_snap := view * snap_quotient
should_snap := cast(f32) i32(view.x > 0 && view.y > 0)
view_quotient := 1 / Vec2 { max(view.x, 1), max(view.y, 1) }
snapped_position := position
snapped_position.x = ceil(position.x * view.x) * snap_quotient.x
snapped_position.y = ceil(position.y * view.y) * snap_quotient.y
position_snapped := ceil(position) * view_quotient * should_snap
position_norm = position * view_quotient
snapped_position *= should_snap
snapped_position.x = max(snapped_position.x, position.x)
snapped_position.y = max(snapped_position.y, position.y)
position_norm = snapped_position
scale_norm = scale * snap_quotient
position_norm = max(position_snapped, position_norm)
scale_norm = scale * view_quotient
return
}
@ -1242,6 +1241,25 @@ resolve_zoom_size_scale :: #force_inline proc "contextless" (
return
}
resolve_px_scalar_size :: #force_inline proc "contextless" ( parser_info : Parser_Font_Info, px_size, px_scalar : f32, norm_scale : Vec2
) -> (target_px_size, target_font_scale : f32, target_scale : Vec2 )
{
target_px_size = px_size * px_scalar
target_scale = norm_scale * (1 / px_scalar)
target_font_scale = parser_scale( parser_info, target_px_size )
return
}
snap_normalized_position_to_view :: #force_inline proc "contextless" ( position, view : Vec2 ) -> (position_snapped : Vec2)
{
should_snap := cast(f32) i32(view.x > 0 && view.y > 0)
view_quotient := 1 / Vec2 { max(view.x, 1), max(view.y, 1) }
position_snapped = ceil(position * view) * view_quotient * should_snap
position_snapped = max(position, position_snapped)
return
}
set_alpha_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.alpha_sharpen = scalar }
set_px_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.px_scalar = scalar }
set_zoom_px_interval :: #force_inline proc( ctx : ^Context, interval : i32 ) { assert(ctx != nil); ctx.zoom_px_interval = f32(interval) }

View File

@ -58,10 +58,6 @@ render_mode_2d_workspace :: proc( screen_extent : Vec2, cam : Camera, input : In
font_provider_set_px_scalar( app_config().text_size_canvas_scalar )
// TODO(Ed): Eventually will be the viewport extents
// ve.configure_snap( ve_ctx, u32(screen_size.x), u32(screen_size.y) )
// ve.configure_snap( ve_ctx, 0, 0 )
Render_Debug:
{
profile("render_reference_dots (workspace)")
@ -125,7 +121,6 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
screen_ratio := screen_size.x * ( 1.0 / screen_size.y )
font_provider_set_px_scalar( app_config().text_size_screen_scalar )
// ve.configure_snap( ve_ctx, u32(screen_size.x), u32(screen_size.y) )
render_screen_ui( screen_extent, screen_ui, ve_ctx, ve_render )
@ -161,8 +156,8 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
font := font
if font.key == Font_Default.key do font = default_font
shape := shape_text_cached( content, font, size, 1.0 )
draw_text_shape_pos_extent( shape, font, size, pos, color )
shape := shape_text_cached( content, font, size )
ve.draw_shape_view_space(& get_state().font_provider_ctx.ve_ctx, normalize_rgba8(color), get_screen_extent() * 2, screen_to_render_pos(pos), 1.0, 1.0, shape)
}
debug_text :: proc( format : string, args : ..any )
@ -177,8 +172,8 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
position.y -= debug.draw_debug_text_y
content := str_fmt( format, ..args )
text_size := measure_text_size( content, default_font, 16.0, 0.0 )
debug_draw_text( content, position, 16.0 )
text_size := measure_text_size( content, default_font, 12.0, 0.0 )
debug_draw_text( content, position, 12.0 )
debug.draw_debug_text_y += text_size.y
}
@ -281,7 +276,6 @@ render_screen_ui :: proc( screen_extent : Extents2, ui : ^UI_State, ve_ctx : ^ve
render_list_box := array_to_slice( ui.render_list_box )
render_list_text := array_to_slice( ui.render_list_text )
render_ui_via_box_list( render_list_box, render_list_text, screen_extent, ve_ctx, ve_render )
// render_ui_via_box_list( render_list, screen_extent, ve_ctx, ve_render )
}
when UI_Render_Method == .Depth_First
{
@ -415,8 +409,7 @@ 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_size_norm := (1.0 / screen_size)
screen_size := screen_extent * 2
layer_left : b32 = true
for layer_left
@ -484,12 +477,16 @@ render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_
if len(entry.text) == 0 do continue
text_enqueued = true
ve_id := font_provider_font_def(entry.font)
color := normalize_rgba8(entry.color)
if cam != nil {
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 )
// 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 )
canvas_position := ws_view_to_render_pos(entry.position)
ve.draw_text_view_space(ve_ctx, ve_id, entry.font_size, color, screen_size, canvas_position, 1.0, cam.zoom, entry.text )
}
else {
draw_text_string_pos_extent( entry.text, font, entry.font_size, entry.position, entry.color )
screen_position := screen_to_render_pos(entry.position)
ve.draw_text_view_space(ve_ctx, ve_id, entry.font_size, color, screen_size, screen_position, 1.0, 1.0, entry.text)
}
}
@ -675,6 +672,19 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render :
#region("Helpers")
draw_shape :: proc(color : RGBAN, screen_size, position, scale : Vec2, zoom : f32, shape : ShapedText)
{
ve_ctx := & get_state().font_provider_ctx.ve_ctx
ve.draw_shape_view_space(ve_ctx, color, screen_size, position, scale, zoom, shape )
}
draw_text :: proc(font : FontID, px_size : f32, color : RGBAN, screen_size, position, scale : Vec2, zoom : f32, text : string)
{
ve_ctx := & get_state().font_provider_ctx.ve_ctx
ve_id := font_provider_font_def(font)
ve.draw_text_view_space(ve_ctx, ve_id, px_size, color, screen_size, position, scale, zoom, text )
}
draw_filled_circle :: proc(x, y, radius: f32, edges: int)
{
if edges < 3 do return // Need at least 3 edges to form a shape
@ -850,147 +860,6 @@ draw_rect_rounded_border :: proc(rect: Range2, radii: [4]f32, border_width: f32,
draw_corner_border(rect.max.x - bottom_right, rect.max.y - bottom_right, bottom_right, max(bottom_right - border_width, 0), 0, segments)
}
// Draw text using a string and normalized render coordinates
draw_text_string_pos_norm :: #force_inline proc( text : string, id : FontID, font_size : f32, pos : Vec2, color := Color_White, scale : f32 = 1.0 )
{
screen_extent := get_state().app_window.extent // TODO(Ed): Pass this in instead..
screen_size := screen_extent * 2
target_size := font_size
ve_id, resolved_size := font_provider_resolve_draw_id( id, target_size )
color_norm := normalize_rgba8(color)
screen_size_norm := 1 / screen_size
draw_scale := screen_size_norm * scale
ve_ctx := & get_state().font_provider_ctx.ve_ctx
ve.draw_text_normalized_space(ve_ctx,
ve_id,
f32(resolved_size),
color_norm,
pos,
draw_scale,
text
)
return
}
// 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 )
{
ve_id, resolved_size := font_provider_resolve_draw_id( id, font_size )
color_norm := normalize_rgba8(color)
screen_size_norm := 1 / get_screen_extent() * 0.5
ve.draw_shape_normalized_space( & get_state().font_provider_ctx.ve_ctx,
color_norm,
pos,
screen_size_norm * scale,
shape
)
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 using a string and extent-based screen coordinates
draw_text_string_pos_extent :: #force_inline proc( text : string, id : FontID, font_size : f32, pos : Vec2, color := Color_White )
{
profile(#procedure)
screen_extent := get_state().app_window.extent // TODO(Ed): Pass this in instead..
screen_size := screen_extent * 2
render_pos := screen_to_render_pos(pos)
normalized_pos := render_pos * (1.0 / screen_size)
draw_text_string_pos_norm( text, id, font_size, normalized_pos, color )
}
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(app_config().text_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 )
f32_resolved_size := f32(resolved_size)
text_scale : Vec2 = screen_size_norm
// if config.cam_zoom_mode == .Smooth
{
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_px_scalar( & get_state().font_provider_ctx.ve_ctx, config.font_size_canvas_scalar )
ve.draw_shape_normalized_space( & font_provider_ctx.ve_ctx,
color_norm,
normalized_pos,
text_scale,
shape
)
}
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.
config := app_config()
zoom_adjust_size := size * zoom
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 )
f32_resolved_size := f32(resolved_size)
text_scale : Vec2 = screen_size_norm
// if config.cam_zoom_mode == .Smooth
{
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 )
}
color_norm := normalize_rgba8(color)
ve.draw_text_normalized_space( & get_state().font_provider_ctx.ve_ctx,
ve_id,
f32(resolved_size),
color_norm,
normalized_pos,
text_scale,
text
)
}
// TODO(Ed): Eventually the workspace will need a viewport for drawing text
render_flush_gp :: #force_inline proc()

View File

@ -137,18 +137,10 @@ font_provider_set_snap_glyph_render_height :: #force_inline proc( should_snap :
Font_Use_Default_Size :: f32(0.0)
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
def := hmap_chained_get( font_cache, id.key )
size := size == 0.0 ? f32(def.default_size) : size
even_size := math.round(size * (1.0 / f32(Font_Size_Interval))) * f32(Font_Size_Interval)
resolved_size = clamp( i32( even_size), 2, Font_Largest_Px_Size )
id := (resolved_size / Font_Size_Interval) + (resolved_size % Font_Size_Interval)
ve_id = def.ve_id
return
font_provider_font_def :: #force_inline proc( font : FontID) -> ve.Font_ID {
provider := & get_state().font_provider_ctx;
def := hmap_chained_get( provider.font_cache, font.key )
return def.ve_id
}
measure_text_shape :: #force_inline proc( shape : ShapedText ) -> Vec2
@ -159,28 +151,28 @@ measure_text_shape :: #force_inline proc( shape : ShapedText ) -> 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, f32(size), text )
ve_id := font_provider_font_def(font)
measured := ve.measure_text_size( & get_state().font_provider_ctx.ve_ctx, ve_id, f32(font_size), text )
return measured
}
get_font_vertical_metrics :: #force_inline proc ( font : FontID, font_size := Font_Use_Default_Size ) -> ( ascent, descent, line_gap : f32 )
{
ve_id, size := font_provider_resolve_draw_id( font, font_size )
ve_id := font_provider_font_def(font)
ascent, descent, line_gap = ve.get_font_vertical_metrics( get_state().font_provider_ctx.ve_ctx, ve_id, font_size )
return
}
shape_text_cached_latin :: #force_inline proc( text : string, font : FontID, font_size := Font_Use_Default_Size, scalar : f32 ) -> ShapedText
shape_text_cached_latin :: #force_inline proc( text : string, font : FontID, font_size := Font_Use_Default_Size ) -> ShapedText
{
ve_id, size := font_provider_resolve_draw_id( font, font_size * scalar )
shape := ve.shape_text( & get_state().font_provider_ctx.ve_ctx, ve_id, f32(size), text, ve.shaper_shape_text_latin )
ve_id := font_provider_font_def(font)
shape := ve.shape_text( & get_state().font_provider_ctx.ve_ctx, ve_id, f32(font_size), text, ve.shaper_shape_text_latin )
return shape
}
shape_text_cached :: #force_inline proc( text : string, font : FontID, font_size := Font_Use_Default_Size, scalar : f32 ) -> ShapedText
shape_text_cached :: #force_inline proc( text : string, font : FontID, font_size := Font_Use_Default_Size ) -> ShapedText
{
ve_id, size := font_provider_resolve_draw_id( font, font_size * scalar )
shape := ve.shape_text( & get_state().font_provider_ctx.ve_ctx, ve_id, f32(size), text )
ve_id := font_provider_font_def(font)
shape := ve.shape_text( & get_state().font_provider_ctx.ve_ctx, ve_id, f32(font_size), text )
return shape
}

View File

@ -287,7 +287,7 @@ ui_graph_build_end :: proc( ui : ^UI_State )
{
if len(current.text) > 0 {
profile("text shape")
current.computed.text_shape = shape_text_cached( current.text, current.style.font, current.layout.font_size, 1.0 )
current.computed.text_shape = shape_text_cached( current.text, current.style.font, current.layout.font_size )
}
ui_box_compute_layout( current )
}