move freetype function to its own file to declutter draw.odin

This commit is contained in:
Edward R. Gonzalez 2025-01-02 18:16:46 -05:00
parent b427f1fbc8
commit 44c97eec71
2 changed files with 183 additions and 170 deletions

View File

@ -122,164 +122,6 @@ blit_quad :: #force_inline proc ( draw_list : ^Draw_List, p0 : Vec2 = {0, 0}, p1
return
}
// 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 )
// }
// }
// 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
// }
// 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
// }
// 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)
// 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)
// 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
// 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 = {}
// }
// }
// // 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)
// }
// 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
// }
// TODO(Ed): Is it better to cache the glyph vertices for when it must be re-drawn (directly or two atlas)?
generate_glyph_pass_draw_list :: #force_inline proc(ctx : ^Context,
glyph_index : Glyph,
glyph_shape : Parser_Glyph_Shape,
@ -674,20 +516,34 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
for & glyph, index in glyph_pack
{
region := atlas.regions[glyph.region_kind]
glyph.atlas_index = lru_get( & region.state, glyph.lru_code )
glyph.in_atlas, glyph.should_cache = check_and_reserve_slot_in_atlas( ctx ^, glyph.index, glyph.lru_code, & glyph.atlas_index, region )
if ctx.temp_codepoint_seen_num <= i32(cap(ctx.temp_codepoint_seen))
{
if glyph.atlas_index == - 1
{
// Check to see if we reached capacity for the atlas
if region.next_idx > region.state.capacity
{
// We will evict LRU. We must predict which LRU will get evicted, and if it's something we've seen then we need to take slowpath and flush batch.
next_evict_codepoint := lru_get_next_evicted( region.state )
found, success := ctx.temp_codepoint_seen[next_evict_codepoint]
assert(success != false)
if (found) {
continue
}
}
profile("append to_cache")
glyph.atlas_index = atlas_reserve_slot(region, glyph.lru_code)
glyph.region_pos, glyph.region_size = atlas_region_bbox(region ^, glyph.atlas_index)
append_sub_pack(to_cache, glyph)
continue
}
}
glyph.region_pos, glyph.region_size = atlas_region_bbox(region ^, glyph.atlas_index)
if glyph.should_cache {
profile("append to_cache")
append_sub_pack(to_cache, glyph)
}
else {
profile("append cached")
append_sub_pack(cached, glyph)
}
append_sub_pack(cached, glyph)
mark_batch_codepoint_seen(ctx, glyph.lru_code)
}
profile_end()

View File

@ -0,0 +1,157 @@
// 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 )
// }
// }
// 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
// }
// 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
// }
// 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)
// 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)
// 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
// 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 = {}
// }
// }
// // 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)
// }
// 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
// }