diff --git a/code/font/vefontcache/LRU.odin b/code/font/vefontcache/LRU.odin index 8018bc5..3659719 100644 --- a/code/font/vefontcache/LRU.odin +++ b/code/font/vefontcache/LRU.odin @@ -63,7 +63,8 @@ pool_list_reload :: proc( pool : ^Pool_List, allocator : Allocator ) { reload_array( & pool.free_list, allocator ) } -pool_list_clear :: proc( pool: ^Pool_List ) { +pool_list_clear :: proc( pool: ^Pool_List ) +{ using pool clear(& items) clear(& free_list) @@ -219,8 +220,8 @@ lru_find :: #force_inline proc "contextless" ( cache : LRU_Cache, key : u32, mus lru_get :: #force_inline proc ( cache: ^LRU_Cache, key : u32 ) -> i32 #no_bounds_check { if link, ok := &cache.table[ key ]; ok { - pool_list_move_to_front(&cache.key_queue, link.ptr) - return link.value + pool_list_move_to_front(&cache.key_queue, link.ptr) + return link.value } return -1 } diff --git a/code/font/vefontcache/draw.odin b/code/font/vefontcache/draw.odin index d0d3019..88d32f1 100644 --- a/code/font/vefontcache/draw.odin +++ b/code/font/vefontcache/draw.odin @@ -54,8 +54,6 @@ Glyph_Pack_Entry :: struct #packed { draw_quad : Glyph_Draw_Quad, draw_atlas_quad : Glyph_Draw_Quad, draw_quad_clear : Glyph_Draw_Quad, - - // shape_id : i32, } Draw_Call :: struct { @@ -286,12 +284,12 @@ cache_glyph_to_atlas :: #force_no_inline proc ( dst_glyph_position := region_pos dst_glyph_size := (bounds_size_scaled) + glyph_padding dst_size := region_size - to_screen_space( & dst_glyph_position, & dst_glyph_size, atlas_size ) - to_screen_space( & region_pos, & dst_size, atlas_size ) + to_glyph_buffer_space( & dst_glyph_position, & dst_glyph_size, atlas_size ) + to_glyph_buffer_space( & region_pos, & dst_size, atlas_size ) src_position := Vec2 { batch_x, 0 } src_size := (buffer_bounds_scale + buffer_padding_scaled) - to_text_space( & src_position, & src_size, glyph_buffer_size ) + to_target_space( & src_position, & src_size, glyph_buffer_size ) clear_target_region : Draw_Call { @@ -328,7 +326,7 @@ cache_glyph_to_atlas :: #force_no_inline proc ( glyph_transform := buf_transform glyph_transform.pos.x += batch_x (glyph_buf_Batch_x ^) += i32(buffer_x_allocation) - to_screen_space( & glyph_transform.pos, & glyph_transform.scale, glyph_buffer_size ) + to_glyph_buffer_space( & glyph_transform.pos, & glyph_transform.scale, glyph_buffer_size ) // Render glyph to glyph render target (FBO) generate_glyph_pass_draw_list( draw_list, temp_path, glyph_shape, curve_quality, bounds, glyph_transform.scale, glyph_transform.pos ) @@ -343,10 +341,12 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, { profile(#procedure) + colour := ctx.colour + colour.a = 1.0 + ctx.alpha_scalar + atlas := & ctx.atlas glyph_buffer := & ctx.glyph_buffer draw_list := & ctx.draw_list - colour := ctx.colour atlas_glyph_pad := atlas.glyph_padding atlas_size := Vec2 { f32(atlas.width), f32(atlas.height) } glyph_buffer_size := Vec2 { f32(glyph_buffer.width), f32(glyph_buffer.height) } @@ -374,8 +374,8 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, profile_begin("index") for & glyph, index in glyph_pack { - // glyph.shape_id = cast(i32) index - glyph.index = shaped.glyphs[ index ] + glyph.index = shaped.glyphs[ index ] + glyph.lru_code = font_glyph_lru_code(entry.id, glyph.index) } profile_end() @@ -389,13 +389,9 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, profile_begin("bounds") for & glyph, index in glyph_pack { - glyph.lru_code = font_glyph_lru_code(entry.id, glyph.index) - } - for & glyph, index in glyph_pack - { - glyph.bounds = parser_get_bounds( entry.parser_info, glyph.index ) - glyph.bounds_scaled = { glyph.bounds.p0 * entry.size_scale, glyph.bounds.p1 * entry.size_scale } - glyph.bounds_size = glyph.bounds.p1 - glyph.bounds.p0 + glyph.bounds = parser_get_bounds( entry.parser_info, glyph.index ) + glyph.bounds_scaled = { glyph.bounds.p0 * entry.size_scale, glyph.bounds.p1 * entry.size_scale } + glyph.bounds_size = glyph.bounds.p1 - glyph.bounds.p0 glyph.bounds_size_scaled = glyph.bounds_size * entry.size_scale glyph.scale = glyph.bounds_size_scaled + atlas.glyph_padding } @@ -467,9 +463,6 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, } profile_end() - // ctx.colour = {} - ctx.colour.a *= 1.0 + ctx.alpha_scalar - profile_begin("transform & quad compute") for id, index in sub_slice(cached) { @@ -480,7 +473,7 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, quad.dst_scale = (glyph.scale) * target_scale quad.src_scale = (glyph.scale) quad.src_pos = (glyph.region_pos) - to_text_space( & quad.src_pos, & quad.src_scale, atlas_size ) + to_target_space( & quad.src_pos, & quad.src_scale, atlas_size ) } for id, index in sub_slice(to_cache) { @@ -492,7 +485,7 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, quad.dst_scale = (glyph.scale) * target_scale quad.src_scale = (glyph.scale) quad.src_pos = (glyph.region_pos) - to_text_space( & quad.src_pos, & quad.src_scale, atlas_size ) + to_target_space( & quad.src_pos, & quad.src_scale, atlas_size ) // The glyph buffer space transform for generate_glyph_pass_draw_list transform := & glyph.draw_transform @@ -505,30 +498,26 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, glyph := & glyph_pack[id] // The glyph buffer space transform for generate_glyph_pass_draw_list - transform := glyph.draw_transform + transform := & glyph.draw_transform transform.scale = entry.size_scale * glyph.over_sample transform.pos = -1 * glyph.bounds.p0 * transform.scale + vec2(atlas.glyph_padding) - to_screen_space( & transform.pos, & transform.scale, glyph_buffer_size ) + to_glyph_buffer_space( & transform.pos, & transform.scale, glyph_buffer_size ) // Oversized will use a cleared glyph_buffer every time. glyph_padding := vec2(glyph_buffer.draw_padding) - target_scale := target_scale - // target_scale = Vec2{ 1, 1} - // Quad to draw during target pass, every quad := & glyph.draw_quad quad.dst_pos = glyph.position + glyph.bounds_scaled.p0 * target_scale - glyph_padding * target_scale quad.dst_scale = (glyph.bounds_size_scaled + glyph_padding) * target_scale quad.src_pos = {} quad.src_scale = glyph.bounds_size_scaled * glyph.over_sample + glyph_padding - to_text_space( & quad.src_pos, & quad.src_scale, glyph_buffer_size ) - - dummy := 1 - dummy += 1 + to_target_space( & quad.src_pos, & quad.src_scale, glyph_buffer_size ) } profile_end() + profile_end() + generate_cached_draw_list :: #force_inline proc (draw_list : ^Draw_List, glyph_pack : #soa[]Glyph_Pack_Entry, sub_pack : []i32, colour : Colour ) { profile(#procedure) @@ -560,9 +549,11 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, for id, index in sub_slice(to_cache) { profile("glyph") - ctx.colour.r = 0.80 - ctx.colour.g = 0.25 - ctx.colour.b = 0.25 + when ENABLE_DRAW_TYPE_VIS { + colour.r = 0.80 + colour.g = 0.25 + colour.b = 0.25 + } glyph := glyph_pack[id] cache_glyph_to_atlas( @@ -574,7 +565,7 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, & ctx.temp_path, glyph.shape, - glyph.bounds, + glyph.bounds_scaled, glyph.bounds_size_scaled, atlas_size, @@ -596,13 +587,18 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, generate_cached_draw_list( draw_list, glyph_pack[:], sub_slice(to_cache), ctx.colour ) profile_begin("generate_cached_draw_list: to_cache") - ctx.colour.r = 1.0 - ctx.colour.g = 1.0 - ctx.colour.b = 1.0 + + when ENABLE_DRAW_TYPE_VIS { + colour.r = 1.0 + colour.g = 1.0 + colour.b = 1.0 + } generate_cached_draw_list( draw_list, glyph_pack[:], sub_slice(cached), ctx.colour ) reset_batch_codepoint_state( ctx ) profile_end() + flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x) + profile_begin("generate oversized glyphs draw_list") for id, index in sub_slice(oversized) { error : Allocator_Error @@ -613,7 +609,7 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, for id, index in sub_slice(oversized) { flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x) - + generate_glyph_pass_draw_list( draw_list, & ctx.temp_path, glyph_pack[id].shape, entry.curve_quality, @@ -622,9 +618,11 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, glyph_pack[id].draw_transform.pos ) - ctx.colour.r = 0.0 - ctx.colour.g = 0.0 - ctx.colour.b = 1.0 + when ENABLE_DRAW_TYPE_VIS { + colour.r = 1.0 + colour.g = 1.0 + colour.b = 0.0 + } target_quad := glyph_pack[id].draw_quad @@ -633,7 +631,7 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, { using draw_to_target pass = .Target_Uncached - colour = colour + colour = ctx.colour start_index = u32(len(draw_list.indices)) blit_quad( draw_list, @@ -652,10 +650,7 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context, } append( & draw_list.calls, ..calls[:] ) } - profile_end() - - // flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x) - + profile_begin("font parser shape cleanup") for id, index in sub_slice(oversized) do parser_free_shape(entry.parser_info, glyph_pack[id].shape) profile_end() diff --git a/code/font/vefontcache/freetype_wip.odin b/code/font/vefontcache/freetype_wip.odin index e70cfd2..8458182 100644 --- a/code/font/vefontcache/freetype_wip.odin +++ b/code/font/vefontcache/freetype_wip.odin @@ -1,158 +1,163 @@ package vefontcache +when false { +// TODO(Ed): Freetype support + // 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: Font_ID, glyph_index: Glyph, entry: ^Entry, bounds_0, bounds_1: Vec2, scale, translate: Vec2) -> b32 -// { -// draw_filled_path_freetype :: proc( draw_list : ^Draw_List, 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 ) -// } -// } +cache_glyph_freetype :: proc(ctx: ^Context, font: Font_ID, glyph_index: Glyph, entry: ^Entry, bounds_0, bounds_1: Vec2, scale, translate: Vec2) -> b32 +{ + draw_filled_path_freetype :: proc( draw_list : ^Draw_List, 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 ) -// } + 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[:] ) -// } + 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[:] ) -// } -// } + // 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 -// } + if glyph_index == Glyph(0) { + return false + } -// face := entry.parser_info.freetype_info -// error := freetype.load_glyph(face, u32(glyph_index), {.No_Bitmap, .No_Scale}) -// if error != .Ok { -// return false -// } + face := entry.parser_info.freetype_info + error := freetype.load_glyph(face, u32(glyph_index), {.No_Bitmap, .No_Scale}) + if error != .Ok { + return false + } -// glyph := face.glyph -// if glyph.format != .Outline { -// return false -// } + glyph := face.glyph + if glyph.format != .Outline { + return false + } -// outline := &glyph.outline -// if outline.n_points == 0 { -// return false -// } + outline := &glyph.outline + if outline.n_points == 0 { + return false + } -// draw := Draw_Call_Default -// draw.pass = Frame_Buffer_Pass.Glyph -// draw.start_index = cast(u32) len(ctx.draw_list.indices) + draw := Draw_Call_Default + draw.pass = Frame_Buffer_Pass.Glyph + 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)) -// tags := slice.from_ptr(cast( [^]u8) outline.tags, int(outline.n_points)) + 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)) + tags := slice.from_ptr(cast( [^]u8) outline.tags, int(outline.n_points)) -// path := &ctx.temp_path -// clear(path) + path := &ctx.temp_path + clear(path) -// outside := Vec2{ bounds_0.x - 21, bounds_0.y - 33 } + outside := Vec2{ bounds_0.x - 21, bounds_0.y - 33 } -// start_index: int = 0 -// for contour_index in 0 ..< int(outline.n_contours) -// { -// end_index := int(contours[contour_index]) + 1 -// prev_point : Vec2 -// first_point : Vec2 + start_index: int = 0 + for contour_index in 0 ..< int(outline.n_contours) + { + end_index := int(contours[contour_index]) + 1 + prev_point : Vec2 + first_point : Vec2 -// for idx := start_index; idx < end_index; idx += 1 -// { -// current_pos := Vec2 { f32( points[idx].x ), f32( points[idx].y ) } -// if ( tags[idx] & 1 ) == 0 -// { -// // If current point is off-curve -// if (idx == start_index || (tags[ idx - 1 ] & 1) != 0) -// { -// // current is the first or following an on-curve point -// prev_point = current_pos -// } -// else -// { -// // current and previous are off-curve, calculate midpoint -// midpoint := (prev_point + current_pos) * 0.5 -// append( path, Vertex { pos = midpoint } ) // Add midpoint as on-curve point -// if idx < end_index - 1 -// { -// // perform interp from prev_point to current_pos via midpoint -// step := 1.0 / entry.curve_quality -// for alpha : f32 = 0.0; alpha <= 1.0; alpha += step -// { -// bezier_point := eval_point_on_bezier3( prev_point, midpoint, current_pos, alpha ) -// append( path, Vertex{ pos = bezier_point } ) -// } -// } + for idx := start_index; idx < end_index; idx += 1 + { + current_pos := Vec2 { f32( points[idx].x ), f32( points[idx].y ) } + if ( tags[idx] & 1 ) == 0 + { + // If current point is off-curve + if (idx == start_index || (tags[ idx - 1 ] & 1) != 0) + { + // current is the first or following an on-curve point + prev_point = current_pos + } + else + { + // current and previous are off-curve, calculate midpoint + midpoint := (prev_point + current_pos) * 0.5 + append( path, Vertex { pos = midpoint } ) // Add midpoint as on-curve point + if idx < end_index - 1 + { + // perform interp from prev_point to current_pos via midpoint + step := 1.0 / entry.curve_quality + for alpha : f32 = 0.0; alpha <= 1.0; alpha += step + { + bezier_point := eval_point_on_bezier3( prev_point, midpoint, current_pos, alpha ) + append( path, Vertex{ pos = bezier_point } ) + } + } -// prev_point = current_pos -// } -// } -// else -// { -// if idx == start_index { -// first_point = current_pos -// } -// if prev_point != (Vec2{}) { -// // there was an off-curve point before this -// append(path, Vertex{ pos = prev_point}) // Ensure previous off-curve is handled -// } -// append(path, Vertex{ pos = current_pos}) -// prev_point = {} -// } -// } + prev_point = current_pos + } + } + else + { + if idx == start_index { + first_point = current_pos + } + if prev_point != (Vec2{}) { + // there was an off-curve point before this + append(path, Vertex{ pos = prev_point}) // Ensure previous off-curve is handled + } + append(path, Vertex{ pos = current_pos}) + prev_point = {} + } + } -// // ensure the contour is closed -// if path[0].pos != path[ len(path) - 1 ].pos { -// append(path, Vertex{pos = path[0].pos}) -// } -// draw_filled_path(&ctx.draw_list, bounds_0, path[:], scale, translate) -// // draw_filled_path(&ctx.draw_list, bounds_0, path[:], scale, translate, ctx.debug_print_verbose) -// clear(path) -// start_index = end_index -// } + // ensure the contour is closed + if path[0].pos != path[ len(path) - 1 ].pos { + append(path, Vertex{pos = path[0].pos}) + } + draw_filled_path(&ctx.draw_list, bounds_0, path[:], scale, translate) + // draw_filled_path(&ctx.draw_list, bounds_0, path[:], scale, translate, ctx.debug_print_verbose) + clear(path) + start_index = end_index + } -// if len(path) > 0 { -// // draw_filled_path(&ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose) -// draw_filled_path(&ctx.draw_list, outside, path[:], scale, translate) -// } + if len(path) > 0 { + // draw_filled_path(&ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose) + draw_filled_path(&ctx.draw_list, outside, path[:], scale, translate) + } -// draw.end_index = cast(u32) len(ctx.draw_list.indices) -// if draw.end_index > draw.start_index { -// append( & ctx.draw_list.calls, draw) -// } + draw.end_index = cast(u32) len(ctx.draw_list.indices) + if draw.end_index > draw.start_index { + append( & ctx.draw_list.calls, draw) + } -// return true -// } + return true +} + +} diff --git a/code/font/vefontcache/mappings.odin b/code/font/vefontcache/mappings.odin index c46b9d1..8f8a275 100644 --- a/code/font/vefontcache/mappings.odin +++ b/code/font/vefontcache/mappings.odin @@ -35,6 +35,7 @@ import "core:mem" arena_allocator :: mem.arena_allocator arena_init :: mem.arena_init import "core:slice" +import "core:unicode" //#region("Proc overload mappings") @@ -117,9 +118,6 @@ vec2_64 :: proc { import "../../grime" - -DISABLE_PROFILING :: false - @(deferred_none = profile_end, disabled = DISABLE_PROFILING) profile :: #force_inline proc "contextless" ( name : string, loc := #caller_location ) { grime.profile_begin(name, loc) @@ -136,3 +134,4 @@ profile_end :: #force_inline proc "contextless" () { } //#endregion("Proc overload mappings") + diff --git a/code/font/vefontcache/misc.odin b/code/font/vefontcache/misc.odin index 3c62271..ebc79ca 100644 --- a/code/font/vefontcache/misc.odin +++ b/code/font/vefontcache/misc.odin @@ -62,13 +62,6 @@ font_glyph_lru_code :: #force_inline proc "contextless" ( font : Font_ID, glyph_ return } -is_glyph_empty :: #force_inline proc ( ctx : ^Context, entry : ^Entry, glyph_index : Glyph ) -> b32 -{ - if glyph_index == 0 do return true - if parser_is_glyph_empty( entry.parser_info, glyph_index ) do return true - return false -} - mark_batch_codepoint_seen :: #force_inline proc "contextless" ( ctx : ^Context, lru_code : u32 ) { ctx.temp_codepoint_seen[lru_code] = true ctx.temp_codepoint_seen_num += 1 @@ -79,56 +72,24 @@ reset_batch_codepoint_state :: #force_inline proc( ctx : ^Context ) { ctx.temp_codepoint_seen_num = 0 } -USE_F64_PRECISION_ON_X_FORM_OPS :: false - -to_screen_space :: #force_inline proc "contextless" ( #no_alias position, scale : ^Vec2, size : Vec2 ) +to_glyph_buffer_space :: #force_inline proc "contextless" ( #no_alias position, scale : ^Vec2, size : Vec2 ) { - when USE_F64_PRECISION_ON_X_FORM_OPS - { - pos_64 := vec2_64_from_vec2(position^) - scale_64 := vec2_64_from_vec2(scale^) + pos := position^ + scale_32 := scale^ - quotient : Vec2_64 = 1.0 / vec2_64(size) - pos_64 = pos_64 * quotient * 2.0 - 1.0 - scale_64 = scale_64 * quotient * 2.0 + quotient : Vec2 = 1.0 / size + pos = pos * quotient * 2.0 - 1.0 + scale_32 = scale_32 * quotient * 2.0 - (position^) = { f32(pos_64.x), f32(pos_64.y) } - (scale^) = { f32(scale_64.x), f32(scale_64.y) } - } - else - { - pos := position^ - scale_32 := scale^ - - quotient : Vec2 = 1.0 / size - pos = pos * quotient * 2.0 - 1.0 - scale_32 = scale_32 * quotient * 2.0 - - (position^) = pos - (scale^) = scale_32 - } + (position^) = pos + (scale^) = scale_32 } -to_text_space :: #force_inline proc "contextless" ( #no_alias position, scale : ^Vec2, size : Vec2 ) +to_target_space :: #force_inline proc "contextless" ( #no_alias position, scale : ^Vec2, size : Vec2 ) { - when USE_F64_PRECISION_ON_X_FORM_OPS - { - pos_64 := vec2_64_from_vec2(position^) - scale_64 := vec2_64_from_vec2(scale^) - - quotient : Vec2_64 = 1.0 / vec2_64(size) - pos_64 *= quotient - scale_64 *= quotient - - (position^) = { f32(pos_64.x), f32(pos_64.y) } - (scale^) = { f32(scale_64.x), f32(scale_64.y) } - } - else - { - quotient : Vec2 = 1.0 / size - (position^) *= quotient - (scale^) *= quotient - } + quotient : Vec2 = 1.0 / size + (position^) *= quotient + (scale^) *= quotient } USE_MANUAL_SIMD_FOR_BEZIER_OPS :: true diff --git a/code/font/vefontcache/parser.odin b/code/font/vefontcache/parser.odin index 95614e1..4da0b62 100644 --- a/code/font/vefontcache/parser.odin +++ b/code/font/vefontcache/parser.odin @@ -274,6 +274,7 @@ parser_get_glyph_shape :: #force_inline proc ( font : Parser_Font_Info, glyph_in parser_is_glyph_empty :: #force_inline proc "contextless" ( font : Parser_Font_Info, glyph_index : Glyph ) -> b32 { + // switch font.kind // { // case .Freetype: @@ -297,6 +298,7 @@ parser_is_glyph_empty :: #force_inline proc "contextless" ( font : Parser_Font_I parser_scale :: #force_inline proc "contextless" ( font : Parser_Font_Info, size : f32 ) -> f32 { + profile(#procedure) size_scale := size < 0.0 ? \ parser_scale_for_pixel_height( font, -size ) \ : parser_scale_for_mapping_em_to_pixels( font, size ) diff --git a/code/font/vefontcache/shaper.odin b/code/font/vefontcache/shaper.odin index 6615a57..a388300 100644 --- a/code/font/vefontcache/shaper.odin +++ b/code/font/vefontcache/shaper.odin @@ -263,7 +263,7 @@ shaper_shape_from_text_latin :: #force_inline proc( ctx : ^Context, font : Font_ } glyph_index := parser_find_glyph_index( entry.parser_info, codepoint ) - is_glyph_empty := parser_is_glyph_empty( entry.parser_info,glyph_index ) + is_glyph_empty := parser_is_glyph_empty( entry.parser_info, glyph_index ) if ! is_glyph_empty { append( & output.glyphs, glyph_index) diff --git a/code/font/vefontcache/vefontcache.odin b/code/font/vefontcache/vefontcache.odin index 8df1016..29c0fc9 100644 --- a/code/font/vefontcache/vefontcache.odin +++ b/code/font/vefontcache/vefontcache.odin @@ -7,6 +7,11 @@ package vefontcache import "base:runtime" +// White: Cached Hit, Red: Cache Miss, Yellow: Oversized +ENABLE_DRAW_TYPE_VIS :: false +// See: mappings.odin for profiling hookup +DISABLE_PROFILING :: true + Font_ID :: distinct i32 Glyph :: distinct i32 @@ -400,6 +405,7 @@ shutdown :: proc( ctx : ^Context ) // ve_fontcache_load load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32, glyph_curve_quality : u32 = 0 ) -> (font_id : Font_ID) { + profile(#procedure) assert( ctx != nil ) assert( len(data) > 0 ) using ctx @@ -423,8 +429,10 @@ load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32, using entry used = true + profile_begin("calling loaders") parser_info = parser_load_font( & parser_ctx, label, data ) shaper_info = shaper_load_font( & shaper_ctx, label, data ) + profile_end() size = size_px size_scale = parser_scale( parser_info, size )