diff --git a/Readme.md b/Readme.md index c04ac70..fa70c01 100644 --- a/Readme.md +++ b/Readme.md @@ -36,8 +36,8 @@ Note: freetype and harfbuzz could technically be gutted if the user removes thei ### Additional Features: -* Support for freetype (WIP, Untested) -* Add ability to conditionally compile dependencies (so that the user may not need to resolve those packages). +* Support for freetype (WIP, Currently a mess... and slow) +* Add ability to conditionally compile dependencies (so that the user may not need to resolve those packages). * Related to usage of //+build tags? * Ability to set a draw transform, viewport and projection * By default the library's position is in unsigned normalized render space diff --git a/backend/sokol/backend_sokol.odin b/backend/sokol/backend_sokol.odin index 5c7c72c..8207b9e 100644 --- a/backend/sokol/backend_sokol.odin +++ b/backend/sokol/backend_sokol.odin @@ -454,7 +454,7 @@ render_text_layer :: proc( screen_extent : ve.Vec2, ve_ctx : ^ve.Context, ctx : Range :: gfx.Range Shader_Stage :: gfx.Shader_Stage - vbuf_layer_slice, ibuf_layer_slice, calls_layer_slice := ve.get_draw_list_layer( ve_ctx, optimize_before_returning = false ) + vbuf_layer_slice, ibuf_layer_slice, calls_layer_slice := ve.get_draw_list_layer( ve_ctx, optimize_before_returning = true ) vbuf_ve_range := Range{ raw_data(vbuf_layer_slice), cast(u64) len(vbuf_layer_slice) * size_of(ve.Vertex) } ibuf_ve_range := Range{ raw_data(ibuf_layer_slice), cast(u64) len(ibuf_layer_slice) * size_of(u32) } diff --git a/examples/sokol_demo/sokol_demo.odin b/examples/sokol_demo/sokol_demo.odin index 8c5d8a7..0ba03c7 100644 --- a/examples/sokol_demo/sokol_demo.odin +++ b/examples/sokol_demo/sokol_demo.odin @@ -50,6 +50,8 @@ FONT_LOAD_GEN_ID :: "" // Working directory assumed to be the build folder PATH_FONTS :: "../fonts/" +OVER_SAMPLE_ZOOM : f32 : 2.0 // Adjust this value as needed, used by draw_text_zoomed_norm + FontID :: struct { label : string, } @@ -185,8 +187,6 @@ draw_text_string_pos_extent :: proc( content : string, id : FontID, size : f32, draw_text_string_pos_norm( content, id, size, normalized_pos, color ) } -OVER_SAMPLE_ZOOM : f32 : 2.0 // Adjust this value as needed - // Adapt the draw_text_string_pos_extent_zoomed procedure draw_text_zoomed_norm :: proc(content : string, id : FontID, size : f32, pos : Vec2, zoom : f32, color := COLOR_WHITE) { @@ -271,7 +271,7 @@ init :: proc "c" () case .DUMMY: fmt.println(">> using dummy backend") } - ve.startup( & demo_ctx.ve_ctx, .Freetype, allocator = context.allocator, snap_shape_position = false, use_advanced_text_shaper = true ) + ve.startup( & demo_ctx.ve_ctx, .STB_TrueType, allocator = context.allocator, snap_shape_position = false, use_advanced_text_shaper = true ) ve_sokol.setup_gfx_objects( & demo_ctx.render_ctx, & demo_ctx.ve_ctx, vert_cap = 1024 * 1024, index_cap = 1024 * 1024 ) error : mem.Allocator_Error diff --git a/vefontcache/draw.odin b/vefontcache/draw.odin index 53f81f4..85922d5 100644 --- a/vefontcache/draw.odin +++ b/vefontcache/draw.odin @@ -91,6 +91,54 @@ blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1} // TODO(Ed): glyph caching cannot be handled in a 'font parser' abstraction. Just going to have explicit procedures to grab info neatly... cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, entry: ^Entry, bounds_0, bounds_1: Vec2, scale, translate: Vec2) -> b32 { + + draw_filled_path_freetype :: proc( draw_list : ^DrawList, outside_point : Vec2, path : []Vertex, + scale := Vec2 { 1, 1 }, + translate := Vec2 { 0, 0 }, + debug_print_verbose : b32 = false + ) + { + if debug_print_verbose { + log("outline_path:") + for point in path { + vec := point.pos * scale + translate + logf(" %0.2f %0.2f", vec.x, vec.y ) + } + } + + v_offset := cast(u32) len(draw_list.vertices) + for point in path + { + transformed_point := Vertex { + pos = point.pos * scale + translate, + u = 0, + v = 0 + } + append( & draw_list.vertices, transformed_point ) + } + + if len(path) > 2 + { + indices := & draw_list.indices + for index : u32 = 1; index < cast(u32) len(path) - 1; index += 1 { + to_add := [3]u32 { + v_offset, + v_offset + index, + v_offset + index + 1 + } + append( indices, ..to_add[:] ) + } + + // Close the path by connecting the last vertex to the first two + to_add := [3]u32 { + v_offset, + v_offset + cast(u32)(len(path) - 1), + v_offset + 1 + } + append( indices, ..to_add[:] ) + } + } + if glyph_index == Glyph(0) { return false } @@ -113,7 +161,7 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en draw := DrawCall_Default draw.pass = FrameBufferPass.Glyph - draw.start_index = u32(len(ctx.draw_list.indices)) + draw.start_index = cast(u32) len(ctx.draw_list.indices) contours := slice.from_ptr(cast( [^]i16) outline.contours, int(outline.n_contours)) points := slice.from_ptr(cast( [^]freetype.Vector) outline.points, int(outline.n_points)) @@ -125,34 +173,57 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en outside := Vec2{ bounds_0.x - 21, bounds_0.y - 33 } start_index: int = 0 - for contour_index in 0.. 0 { - draw_filled_path_freetype(&ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose) + draw_filled_path(&ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose) } draw.end_index = cast(u32) len(ctx.draw_list.indices) @@ -172,56 +243,6 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en return true } -draw_filled_path_freetype :: proc( draw_list : ^DrawList, outside_point : Vec2, path : []Vertex, - scale := Vec2 { 1, 1 }, - translate := Vec2 { 0, 0 }, - debug_print_verbose : b32 = false -) -{ - if debug_print_verbose - { - log("outline_path:") - for point in path { - vec := point.pos * scale + translate - logf(" %0.2f %0.2f", vec.x, vec.y ) - } - } - - // Apply transformations and add vertices to the draw list - v_offset := cast(u32) len(draw_list.vertices) - for point in path { - transformed_point := Vertex { - pos = point.pos * scale + translate, - u = 0, // If texture coordinates are used, set appropriately - v = 0 - } - append( & draw_list.vertices, transformed_point ) - } - - // Ensure there's enough vertices to form at least one triangle - if len(path) > 2 { - indices := & draw_list.indices - - // Connect each vertex to form a triangle fan without an outside vertex - for index : u32 = 1; index < cast(u32) len(path) - 1; index += 1 { - to_add := [3]u32 { - v_offset, // Start vertex (first vertex of the path) - v_offset + index, // Current vertex - v_offset + index + 1 // Next vertex - } - append( indices, ..to_add[:] ) - } - - // Close the path by connecting the last vertex to the first two - to_add := [3]u32 { - v_offset, // First vertex - v_offset + cast(u32)(len(path) - 1), // Last vertex - v_offset + 1 // Second vertex, to close the loop - } - append( indices, ..to_add[:] ) - } -} - cache_glyph :: proc(ctx : ^Context, font : FontID, glyph_index : Glyph, entry : ^Entry, bounds_0, bounds_1 : Vec2, scale, translate : Vec2) -> b32 { // profile(#procedure) diff --git a/vefontcache/misc.odin b/vefontcache/misc.odin index e4919d0..f0b7393 100644 --- a/vefontcache/misc.odin +++ b/vefontcache/misc.odin @@ -121,7 +121,7 @@ textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, } } -Use_SIMD_For_Bezier_Ops :: true +Use_SIMD_For_Bezier_Ops :: false when ! Use_SIMD_For_Bezier_Ops {