From 93e43c2b195b8811253da28768c878c3e1f2e47c Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 28 Jun 2024 17:39:28 -0400 Subject: [PATCH] Updates for getting get_font_vertical_metrics, + other cleanup --- code/font/VEFontCache/VEFontCache.odin | 8 +++- code/font/VEFontCache/atlas.odin | 66 -------------------------- code/font/VEFontCache/draw.odin | 28 ----------- code/sectr/engine/render.odin | 64 +++++++++++++++---------- code/sectr/font/provider.odin | 11 ++++- 5 files changed, 53 insertions(+), 124 deletions(-) diff --git a/code/font/VEFontCache/VEFontCache.odin b/code/font/VEFontCache/VEFontCache.odin index 7dba58f..d6bff85 100644 --- a/code/font/VEFontCache/VEFontCache.odin +++ b/code/font/VEFontCache/VEFontCache.odin @@ -486,13 +486,17 @@ measure_text_size :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) - return shaped.size } -get_font_vertical_metrics :: #force_inline proc ( ctx : ^Context, font : FontID ) -> ( ascent, descent, line_gap : i32 ) +get_font_vertical_metrics :: #force_inline proc ( ctx : ^Context, font : FontID ) -> ( ascent, descent, line_gap : f32 ) { assert( ctx != nil ) assert( font >= 0 && int(font) < len(ctx.entries) ) entry := & ctx.entries[ font ] - ascent, descent, line_gap = parser_get_font_vertical_metrics( & entry.parser_info ) + 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) return } diff --git a/code/font/VEFontCache/atlas.odin b/code/font/VEFontCache/atlas.odin index c20a0fb..dd942ef 100644 --- a/code/font/VEFontCache/atlas.odin +++ b/code/font/VEFontCache/atlas.odin @@ -86,72 +86,6 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : i32 ) return } -// decide_codepoint_region :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph -// ) -> (region_kind : AtlasRegionKind, region : ^AtlasRegion, over_sample : Vec2) -// { -// if parser_is_glyph_empty( & entry.parser_info, glyph_index ) { -// region_kind = .None -// } - -// bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) -// bounds_width := f32(bounds_1.x - bounds_0.x) -// bounds_height := f32(bounds_1.y - bounds_0.y) - -// atlas := & ctx.atlas -// glyph_buffer := & ctx.glyph_buffer - -// glyph_padding := f32(atlas.glyph_padding) * 2 - -// bounds_width_scaled := cast(u32) (bounds_width * entry.size_scale + glyph_padding) -// bounds_height_scaled := cast(u32) (bounds_height * entry.size_scale + glyph_padding) - -// if bounds_width_scaled <= atlas.region_a.width && bounds_height_scaled <= atlas.region_a.height -// { -// // Region A for small glyphs. These are good for things such as punctuation. -// region_kind = .A -// region = & atlas.region_a -// } -// else if bounds_width_scaled <= atlas.region_b.width && bounds_height_scaled <= atlas.region_b.height -// { -// // Region B for tall glyphs. These are good for things such as european alphabets. -// region_kind = .B -// region = & atlas.region_b -// } -// else if bounds_width_scaled <= atlas.region_c.width && bounds_height_scaled <= atlas.region_c.height -// { -// // Region C for big glyphs. These are good for things such as asian typography. -// region_kind = .C -// region = & atlas.region_c -// } -// else if bounds_width_scaled <= atlas.region_d.width && bounds_height_scaled <= atlas.region_d.height -// { -// // Region D for huge glyphs. These are good for things such as titles and 4k. -// region_kind = .D -// region = & atlas.region_d -// } -// else if bounds_width_scaled <= glyph_buffer.width && bounds_height_scaled <= glyph_buffer.height -// { -// // Region 'E' for massive glyphs. These are rendered uncached and un-oversampled. -// region_kind = .E -// region = nil -// if bounds_width_scaled <= glyph_buffer.width / 2 && bounds_height_scaled <= glyph_buffer.height / 2 { -// over_sample = { 2.0, 2.0 } -// } -// else { -// over_sample = { 1.0, 1.0 } -// } -// return -// } -// else { -// region_kind = .None -// return -// } - -// over_sample = glyph_buffer.over_sample -// assert(region != nil) -// return -// } - decide_codepoint_region :: proc(ctx : ^Context, entry : ^Entry, glyph_index : Glyph ) -> (region_kind : AtlasRegionKind, region : ^AtlasRegion, over_sample : Vec2) { diff --git a/code/font/VEFontCache/draw.odin b/code/font/VEFontCache/draw.odin index 845311e..1e8ad8c 100644 --- a/code/font/VEFontCache/draw.odin +++ b/code/font/VEFontCache/draw.odin @@ -661,34 +661,6 @@ flush_glyph_buffer_to_atlas :: proc( ctx : ^Context ) } } -// flush_glyph_buffer_to_atlas :: proc( ctx : ^Context ) -// { -// // profile(#procedure) -// // Flush drawcalls to draw list -// if len(ctx.glyph_buffer.clear_draw_list.calls) > 0 { -// merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.clear_draw_list) -// clear_draw_list( & ctx.glyph_buffer.clear_draw_list) -// } - -// if len(ctx.glyph_buffer.draw_list.calls) > 0 { -// merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.draw_list) -// clear_draw_list( & ctx.glyph_buffer.draw_list) -// } - -// // Clear glyph_update_FBO -// if ctx.glyph_buffer.batch_x != 0 -// { -// call := DrawCall { -// pass = .Glyph, -// start_index = 0, -// end_index = 0, -// clear_before_draw = true, -// } -// append( & ctx.draw_list.calls, call) -// ctx.glyph_buffer.batch_x = 0 -// } -// } - // ve_fontcache_merge_drawlist merge_draw_list :: proc( dst, src : ^DrawList ) { diff --git a/code/sectr/engine/render.odin b/code/sectr/engine/render.odin index cef6124..bbb3f2b 100644 --- a/code/sectr/engine/render.odin +++ b/code/sectr/engine/render.odin @@ -87,18 +87,19 @@ render_mode_2d_workspace :: proc( screen_extent : Vec2, cam : Camera, input : In } // Visualize view bounds - when true + when false { - render_set_view_space(screen_extent) - // render_set_camera(cam) + render_set_view_space(screen_extent) + render_set_camera(cam) // This should apply the necessary transformation - view_bounds := view_get_bounds() - view_bounds.min *= 0.9 - view_bounds.max *= 0.9 - draw_rect( view_bounds, { 0, 0, 180, 30 } ) + view_bounds := view_get_bounds() - render_flush_gp() - } + // Draw the view bounds (should now appear as a rectangle covering the whole screen) + draw_rect(view_bounds, {0, 0, 180, 30}) + + render_flush_gp() + gp.reset_transform() +} render_set_view_space(screen_extent) render_set_camera(cam) @@ -110,7 +111,7 @@ render_mode_2d_workspace :: proc( screen_extent : Vec2, cam : Camera, input : In } when UI_Render_Method == .Depth_First { - render_ui_via_box_tree( ui.root, screen_extent, ve_ctx, ve_render, & cam ) + render_ui_via_box_tree( ui, screen_extent, ve_ctx, ve_render, & cam ) } } @@ -259,7 +260,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State if true { state.config.font_size_canvas_scalar = 2 zoom_adjust_size := 16 * state.project.workspace.cam.zoom - over_sample := zoom_adjust_size < 12 ? 1.0 : f32(state.config.font_size_canvas_scalar) + over_sample := f32(state.config.font_size_canvas_scalar) debug_text("font_size_canvas_scalar: %v", config.font_size_canvas_scalar) ve_id, resolved_size := font_provider_resolve_draw_id( default_font, zoom_adjust_size * over_sample ) debug_text("font_size resolved: %v px", resolved_size) @@ -282,7 +283,7 @@ render_screen_ui :: proc( screen_extent : Extents2, ui : ^UI_State, ve_ctx : ^ve } when UI_Render_Method == .Depth_First { - render_ui_via_box_tree( ui.root, screen_extent, ve_ctx, ve_render ) + render_ui_via_box_tree( ui, screen_extent, ve_ctx, ve_render ) } } @@ -307,6 +308,9 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : ve.flush_draw_list_layer( ve_ctx ) + screen_width := u32(screen_extent.x * 2) + screen_height := u32(screen_extent.y * 2) + for & draw_call in calls_layer_slice { watch := draw_call @@ -334,8 +338,8 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : } gfx.begin_pass( pass ) - // sokol_gfx.apply_viewport( 0,0, width, height, origin_top_left = true ) - // sokol_gfx.apply_scissor_rect( 0,0, width, height, origin_top_left = true ) + gfx.apply_viewport( 0,0, width, height, origin_top_left = true ) + gfx.apply_scissor_rect( 0,0, width, height, origin_top_left = true ) gfx.apply_pipeline( glyph_pipeline ) @@ -370,8 +374,8 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : } gfx.begin_pass( pass ) - // sokol_gfx.apply_viewport( 0, 0, width, height, origin_top_left = true ) - // sokol_gfx.apply_scissor_rect( 0, 0, width, height, origin_top_left = true ) + gfx.apply_viewport( 0, 0, width, height, origin_top_left = true ) + gfx.apply_scissor_rect( 0, 0, width, height, origin_top_left = true ) gfx.apply_pipeline( atlas_pipeline ) @@ -407,10 +411,8 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : pass.swapchain = sokol_glue.swapchain() gfx.begin_pass( pass ) - // width := u32(screen_extent.x * 2) - // height := u32(screen_extent.y * 2) - // sokol_gfx.apply_viewport( 0, 0, width, height, origin_top_left = true ) - // sokol_gfx.apply_scissor_rect( 0, 0, width, height, origin_top_left = true ) + gfx.apply_viewport( 0, 0, screen_width, screen_height, origin_top_left = true ) + gfx.apply_scissor_rect( 0, 0, screen_width, screen_height, origin_top_left = true ) gfx.apply_pipeline( screen_pipeline ) @@ -453,7 +455,7 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : } } -render_ui_via_box_tree :: proc( root : ^UI_Box, screen_extent : Vec2, ve_ctx : ^ve.Context, ve_render : VE_RenderData, cam : ^Camera = nil ) +render_ui_via_box_tree :: proc( ui : ^UI_State, screen_extent : Vec2, ve_ctx : ^ve.Context, ve_render : VE_RenderData, cam : ^Camera = nil ) { debug := get_state().debug default_font := get_state().default_font @@ -464,8 +466,14 @@ render_ui_via_box_tree :: proc( root : ^UI_Box, screen_extent : Vec2, ve_ctx : ^ text_enqueued : b32 = false shape_enqueued : b32 = false + render_set_view_space(screen_extent) + if cam != nil { + // gp.reset_transform() + // render_set_camera(cam^) // This should apply the necessary transformation + } + previous_layer : i32 = 0 - for box := root.first; box != nil; box = ui_box_tranverse_next_depth_first( box ) + for box := ui.root.first; box != nil; box = ui_box_tranverse_next_depth_first( box, bypass_intersection_test = false, ctx = ui ) { if box.ancestors != previous_layer { if shape_enqueued do render_flush_gp() @@ -474,6 +482,10 @@ render_ui_via_box_tree :: proc( root : ^UI_Box, screen_extent : Vec2, ve_ctx : ^ text_enqueued = false } + if ! intersects_range2(ui_view_bounds(ui), box.computed.bounds) { + continue + } + border_width := box.layout.border_width computed := box.computed font_size := box.layout.font_size @@ -482,11 +494,11 @@ render_ui_via_box_tree :: proc( root : ^UI_Box, screen_extent : Vec2, ve_ctx : ^ using computed - // profile("enqueue box") + profile("enqueue box") GP_Render: { - // profile("draw_shapes") + profile("draw_shapes") if style.bg_color.a != 0 { draw_rect( bounds, style.bg_color ) @@ -682,7 +694,7 @@ draw_text_string_pos_extent :: proc( content : string, id : FontID, size : f32, draw_text_string_pos_extent_zoomed :: proc( content : string, id : FontID, size : f32, pos : Vec2, cam : Camera, color := Color_White ) { - // profile(#procedure) + profile(#procedure) state := get_state(); using state cam_offset := Vec2 { @@ -701,7 +713,7 @@ draw_text_string_pos_extent_zoomed :: proc( content : string, id : FontID, size zoom_adjust_size := size * cam.zoom // Over-sample font-size for any render under a camera - over_sample : f32 = zoom_adjust_size <= 8 ? 1.0 : f32(state.config.font_size_canvas_scalar) + over_sample : f32 = f32(state.config.font_size_canvas_scalar) zoom_adjust_size *= over_sample ve_id, resolved_size := font_provider_resolve_draw_id( id, zoom_adjust_size ) diff --git a/code/sectr/font/provider.odin b/code/sectr/font/provider.odin index ec417cb..abf5bdf 100644 --- a/code/sectr/font/provider.odin +++ b/code/sectr/font/provider.odin @@ -99,7 +99,7 @@ font_load :: proc(path_file : string, def.path_file = path_file def.default_size = default_size - for font_size : i32 = clamp( Font_Size_Interval, 10, Font_Size_Interval ); font_size <= Font_Largest_Px_Size; font_size += Font_Size_Interval + for font_size : i32 = clamp( Font_Size_Interval, 2, Font_Size_Interval ); font_size <= Font_Largest_Px_Size; font_size += Font_Size_Interval { // logf("Loading at size %v", font_size) id := (font_size / Font_Size_Interval) + (font_size % Font_Size_Interval) @@ -121,7 +121,7 @@ font_provider_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Siz 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), 12, Font_Largest_Px_Size ) + 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.size_table[ id - 1 ] @@ -134,3 +134,10 @@ measure_text_size :: proc( text : string, font : FontID, font_size := Font_Use_D measured := ve.measure_text_size( & get_state().font_provider_ctx.ve_ctx, ve_id, 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 ) + ascent, descent, line_gap = ve.get_font_vertical_metrics( & get_state().font_provider_ctx.ve_ctx, ve_id ) + return +}