VEFontCache: Fixed oversized drawing
* Added ENABLE_DRAW_TYPE_VIS * Added DISABLE_PROFILING * Some cleanup of unused codepaths *
This commit is contained in:
parent
f6e7741bf3
commit
049633bdc5
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 )
|
||||
|
@ -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)
|
||||
|
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user