VEFontchange: codepath changes and bugfixing
This commit is contained in:
parent
8c7b3e2058
commit
c4c3bba20c
@ -13,29 +13,29 @@ Atlas_Region_Kind :: enum u8 {
|
||||
Atlas_Region :: struct {
|
||||
state : LRU_Cache,
|
||||
|
||||
width : i32,
|
||||
height : i32,
|
||||
|
||||
size : Vec2i,
|
||||
capacity : Vec2i,
|
||||
offset : Vec2i,
|
||||
|
||||
width : i32,
|
||||
height : i32,
|
||||
|
||||
next_idx : i32,
|
||||
}
|
||||
|
||||
Atlas :: struct {
|
||||
width : i32,
|
||||
height : i32,
|
||||
|
||||
glyph_padding : f32, // Padding to add to bounds_<width/height>_scaled for choosing which atlas region.
|
||||
glyph_over_scalar : f32, // Scalar to apply to bounds_<width/height>_scaled for choosing which atlas region.
|
||||
|
||||
region_a : Atlas_Region,
|
||||
region_b : Atlas_Region,
|
||||
region_c : Atlas_Region,
|
||||
region_d : Atlas_Region,
|
||||
|
||||
regions : [5] ^Atlas_Region,
|
||||
|
||||
glyph_padding : f32, // Padding to add to bounds_<width/height>_scaled for choosing which atlas region.
|
||||
glyph_over_scalar : f32, // Scalar to apply to bounds_<width/height>_scaled for choosing which atlas region.
|
||||
|
||||
width : i32,
|
||||
height : i32,
|
||||
}
|
||||
|
||||
atlas_region_bbox :: proc( region : Atlas_Region, local_idx : i32 ) -> (position, size: Vec2)
|
||||
|
@ -28,7 +28,7 @@ Glyph_Draw_Quad :: struct {
|
||||
src_scale : Vec2,
|
||||
}
|
||||
|
||||
Glyph_Pack_Entry :: struct {
|
||||
Glyph_Pack_Entry :: struct #packed {
|
||||
position : Vec2,
|
||||
|
||||
index : Glyph,
|
||||
@ -53,6 +53,7 @@ Glyph_Pack_Entry :: struct {
|
||||
|
||||
draw_quad : Glyph_Draw_Quad,
|
||||
draw_atlas_quad : Glyph_Draw_Quad,
|
||||
draw_quad_clear : Glyph_Draw_Quad,
|
||||
|
||||
// shape_id : i32,
|
||||
}
|
||||
@ -177,26 +178,21 @@ construct_filled_path :: #force_inline proc( draw_list : ^Draw_List, outside_poi
|
||||
}
|
||||
}
|
||||
|
||||
generate_glyph_pass_draw_list :: #force_inline proc(ctx : ^Context,
|
||||
// glyph_id : Glyph,
|
||||
// parser_info : Parser_Font_Info,
|
||||
glyph_shape : Parser_Glyph_Shape,
|
||||
curve_quality : f32,
|
||||
bounds : Range2,
|
||||
generate_glyph_pass_draw_list :: proc(draw_list : ^Draw_List, path : ^[dynamic]Vertex,
|
||||
glyph_shape : Parser_Glyph_Shape,
|
||||
curve_quality : f32,
|
||||
bounds : Range2,
|
||||
scale, translate : Vec2
|
||||
) -> b32
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
|
||||
// glyph_shape, error := parser_get_glyph_shape( parser_info, glyph_id )
|
||||
|
||||
outside := Vec2{bounds.p0.x - 21, bounds.p0.y - 33}
|
||||
|
||||
draw := Draw_Call_Default
|
||||
draw.pass = Frame_Buffer_Pass.Glyph
|
||||
draw.start_index = u32(len(ctx.draw_list.indices))
|
||||
draw.start_index = u32(len(draw_list.indices))
|
||||
|
||||
path := &ctx.temp_path
|
||||
clear(path)
|
||||
|
||||
step := 1.0 / curve_quality
|
||||
@ -204,7 +200,7 @@ generate_glyph_pass_draw_list :: #force_inline proc(ctx : ^Context,
|
||||
{
|
||||
case .Move:
|
||||
if len(path) > 0 {
|
||||
construct_filled_path(&ctx.draw_list, outside, path[:], scale, translate)
|
||||
construct_filled_path( draw_list, outside, path[:], scale, translate)
|
||||
clear(path)
|
||||
}
|
||||
fallthrough
|
||||
@ -235,63 +231,50 @@ generate_glyph_pass_draw_list :: #force_inline proc(ctx : ^Context,
|
||||
append( path, Vertex { pos = eval_point_on_bezier4(p0, p1, p2, p3, alpha) } )
|
||||
}
|
||||
|
||||
case:
|
||||
// case:
|
||||
// assert(false, "WTF")
|
||||
}
|
||||
|
||||
if len(path) > 0 {
|
||||
construct_filled_path(&ctx.draw_list, outside, path[:], scale, translate)
|
||||
construct_filled_path(draw_list, outside, path[:], scale, translate)
|
||||
}
|
||||
|
||||
draw.end_index = u32(len(ctx.draw_list.indices))
|
||||
draw.end_index = u32(len(draw_list.indices))
|
||||
if draw.end_index > draw.start_index {
|
||||
append( & ctx.draw_list.calls, draw)
|
||||
append( & draw_list.calls, draw)
|
||||
}
|
||||
|
||||
// parser_free_shape(parser_info, glyph_shape)
|
||||
return true
|
||||
}
|
||||
|
||||
cache_glyph_to_atlas :: #force_no_inline proc ( ctx : ^Context,
|
||||
cache_glyph_to_atlas :: #force_no_inline proc (
|
||||
#no_alias draw_list,
|
||||
glyph_buf_draw_list, glyph_buf_clear_list : ^Draw_List,
|
||||
glyph_buf_Batch_x : ^i32,
|
||||
glyph_buf_draw_list,
|
||||
glyph_buf_clear_list : ^Draw_List,
|
||||
glyph_buf_Batch_x : ^i32,
|
||||
|
||||
temp_path : ^[dynamic]Vertex,
|
||||
glyph_shape : Parser_Glyph_Shape,
|
||||
bounds : Range2,
|
||||
bounds_size_scaled : Vec2,
|
||||
atlas_size : Vec2,
|
||||
|
||||
glyph_padding : f32,
|
||||
glyph_buffer_size : Vec2,
|
||||
over_sample : Vec2,
|
||||
glyph_padding : f32,
|
||||
buf_transform : Transform,
|
||||
|
||||
atlas_size : Vec2,
|
||||
|
||||
buf_transform : Transform,
|
||||
|
||||
glyph_shape : Parser_Glyph_Shape,
|
||||
|
||||
bounds : Range2, // -> generate_glyph_pass_draw_list
|
||||
bounds_size : Vec2,
|
||||
|
||||
|
||||
region_pos : Vec2,
|
||||
region_size : Vec2,
|
||||
lru_code : u64,
|
||||
atlas_index : i32,
|
||||
entry : Entry,
|
||||
// region_kind : Atlas_Region_Kind,
|
||||
// region : ^Atlas_Region,
|
||||
over_sample : Vec2,
|
||||
|
||||
|
||||
// glyph_id : Glyph,
|
||||
// parser_info : Parser_Font_Info,
|
||||
region_pos : Vec2,
|
||||
region_size : Vec2,
|
||||
curve_quality : f32,
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
|
||||
batch_x := cast(f32) glyph_buf_Batch_x ^
|
||||
|
||||
glyph_buffer_pad := over_sample.x * glyph_padding
|
||||
batch_x := cast(f32) glyph_buf_Batch_x ^
|
||||
buffer_padding_scaled := glyph_padding * over_sample
|
||||
buffer_bounds_scale := bounds_size_scaled * over_sample
|
||||
|
||||
// Allocate a glyph glyph render target region (FBO)
|
||||
buffer_x_allocation := bounds_size.x * buf_transform.scale.x + glyph_buffer_pad + 2.0
|
||||
buffer_x_allocation := buffer_bounds_scale.x + buffer_padding_scaled.x + 2.0
|
||||
|
||||
// If we exceed the region availbe to draw on the buffer, flush the calls to reset the buffer
|
||||
if i32(batch_x + buffer_x_allocation) >= i32(glyph_buffer_size.x) {
|
||||
@ -299,16 +282,15 @@ cache_glyph_to_atlas :: #force_no_inline proc ( ctx : ^Context,
|
||||
batch_x = cast(f32) glyph_buf_Batch_x ^
|
||||
}
|
||||
|
||||
region_pos := region_pos
|
||||
|
||||
region_pos := region_pos
|
||||
dst_glyph_position := region_pos
|
||||
dst_glyph_size := ceil(bounds_size * entry.size_scale) + glyph_padding
|
||||
dst_size := (region_size)
|
||||
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 )
|
||||
|
||||
src_position := Vec2 { batch_x, 0 }
|
||||
src_size := (bounds_size * buf_transform.scale + over_sample * glyph_padding)
|
||||
src_size := (buffer_bounds_scale + buffer_padding_scaled)
|
||||
to_text_space( & src_position, & src_size, glyph_buffer_size )
|
||||
|
||||
clear_target_region : Draw_Call
|
||||
@ -342,25 +324,18 @@ cache_glyph_to_atlas :: #force_no_inline proc ( ctx : ^Context,
|
||||
append( & glyph_buf_clear_list.calls, clear_target_region )
|
||||
append( & glyph_buf_draw_list.calls, blit_to_atlas )
|
||||
|
||||
|
||||
|
||||
screen_space_translate := buf_transform.pos
|
||||
screen_space_scale := buf_transform.scale
|
||||
|
||||
screen_space_translate.x = (buf_transform.pos.x + batch_x)
|
||||
glyph_buf_Batch_x^ += i32(buffer_x_allocation)
|
||||
|
||||
to_screen_space( & screen_space_translate, & screen_space_scale, glyph_buffer_size )
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
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 )
|
||||
|
||||
// Render glyph to glyph render target (FBO)
|
||||
generate_glyph_pass_draw_list( ctx,
|
||||
// glyph_id,
|
||||
// parser_info,
|
||||
glyph_shape,
|
||||
entry.curve_quality, bounds, screen_space_scale, screen_space_translate )
|
||||
generate_glyph_pass_draw_list( draw_list, temp_path, glyph_shape, curve_quality, bounds, glyph_transform.scale, glyph_transform.pos )
|
||||
}
|
||||
|
||||
generate_oversized_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
generate_oversized_draw_list :: #force_no_inline proc( draw_list : ^Draw_List, temp_path : ^[dynamic]Vertex,
|
||||
colour : Colour,
|
||||
curve_quality : f32,
|
||||
glyph_shape : Parser_Glyph_Shape,
|
||||
bounds : Range2,
|
||||
@ -370,27 +345,19 @@ generate_oversized_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
{
|
||||
profile(#procedure)
|
||||
|
||||
generate_glyph_pass_draw_list( ctx,
|
||||
glyph_shape,
|
||||
curve_quality,
|
||||
bounds,
|
||||
glyph_pass_transform.scale,
|
||||
glyph_pass_transform.pos
|
||||
)
|
||||
|
||||
calls : [2]Draw_Call
|
||||
draw_to_target := & calls[0]
|
||||
{
|
||||
using draw_to_target
|
||||
pass = .Target_Uncached
|
||||
colour = ctx.colour
|
||||
start_index = u32(len(ctx.draw_list.indices))
|
||||
colour = colour
|
||||
start_index = u32(len(draw_list.indices))
|
||||
|
||||
blit_quad( & ctx.draw_list,
|
||||
blit_quad( draw_list,
|
||||
target_quad.dst_pos, target_quad.dst_pos + target_quad.dst_scale,
|
||||
target_quad.src_pos, target_quad.src_pos + target_quad.src_scale )
|
||||
|
||||
end_index = u32(len(ctx.draw_list.indices))
|
||||
end_index = u32(len(draw_list.indices))
|
||||
}
|
||||
clear_glyph_update := & calls[1]
|
||||
{
|
||||
@ -400,7 +367,15 @@ generate_oversized_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
clear_glyph_update.end_index = 0
|
||||
clear_glyph_update.clear_before_draw = true
|
||||
}
|
||||
append( & ctx.draw_list.calls, ..calls[:] )
|
||||
append( & draw_list.calls, ..calls[:] )
|
||||
|
||||
generate_glyph_pass_draw_list( draw_list, temp_path,
|
||||
glyph_shape,
|
||||
curve_quality,
|
||||
bounds,
|
||||
glyph_pass_transform.scale,
|
||||
glyph_pass_transform.pos
|
||||
)
|
||||
}
|
||||
|
||||
generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
@ -481,48 +456,57 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
glyph.region_kind = atlas_decide_region( atlas ^, glyph_buffer_size, glyph.bounds_size_scaled )
|
||||
glyph.over_sample = glyph_buffer.over_sample
|
||||
// glyph.over_sample = glyph_buffer.over_sample
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("atlas slot resolution & to_cache/cached segregation")
|
||||
for & glyph, index in glyph_pack
|
||||
{
|
||||
if glyph.region_kind == .None {
|
||||
assert(false, "FAILED TO ASSGIN REGION")
|
||||
continue
|
||||
}
|
||||
if glyph.region_kind == .E
|
||||
{
|
||||
glyph.over_sample = \
|
||||
glyph.bounds_size_scaled.x <= glyph_buffer_size.x / 2 &&
|
||||
glyph.bounds_size_scaled.y <= glyph_buffer_size.y / 2 ? \
|
||||
{2.0, 2.0} \
|
||||
: {1.0, 1.0}
|
||||
glyph.bounds_size_scaled.x <= glyph_buffer_size.x / 2 &&
|
||||
glyph.bounds_size_scaled.y <= glyph_buffer_size.y / 2 ? \
|
||||
{2.0, 2.0} \
|
||||
: {1.0, 1.0}
|
||||
append_sub_pack(oversized, cast(i32) index)
|
||||
continue
|
||||
}
|
||||
|
||||
glyph.over_sample = glyph_buffer.over_sample
|
||||
region := atlas.regions[glyph.region_kind]
|
||||
glyph.atlas_index = lru_get( & region.state, glyph.lru_code )
|
||||
|
||||
if ctx.temp_codepoint_seen_num <= i32(cap(ctx.temp_codepoint_seen))
|
||||
to_cache_check:
|
||||
{
|
||||
if glyph.atlas_index == - 1
|
||||
if ctx.temp_codepoint_seen_num <= i32(cap(ctx.temp_codepoint_seen))
|
||||
{
|
||||
// Check to see if we reached capacity for the atlas
|
||||
if region.next_idx > region.state.capacity
|
||||
if glyph.atlas_index == - 1
|
||||
{
|
||||
// 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
|
||||
// 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) {
|
||||
break to_cache_check
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, cast(i32) index)
|
||||
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, cast(i32) index)
|
||||
mark_batch_codepoint_seen(ctx, glyph.lru_code)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,18 +517,8 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("font parser shape generation")
|
||||
for id, index in sub_slice(to_cache) {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
}
|
||||
for id, index in sub_slice(oversized) {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
}
|
||||
profile_end()
|
||||
// ctx.colour = {}
|
||||
ctx.colour.a *= 1.0 + ctx.alpha_scalar
|
||||
|
||||
profile_begin("transform & quad compute")
|
||||
for id, index in sub_slice(cached)
|
||||
@ -561,6 +535,8 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
for id, index in sub_slice(to_cache)
|
||||
{
|
||||
glyph := & glyph_pack[id]
|
||||
|
||||
// Quad to for drawing atlas slot to target
|
||||
quad := & glyph.draw_quad
|
||||
quad.dst_pos = glyph.position + glyph.bounds_scaled.p0 * target_scale
|
||||
quad.dst_scale = glyph.scale * target_scale
|
||||
@ -568,71 +544,41 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
quad.src_pos = glyph.region_pos
|
||||
to_text_space( & quad.src_pos, & quad.src_scale, atlas_size )
|
||||
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
transform := & glyph.draw_transform
|
||||
transform.scale = entry.size_scale * glyph_buffer.over_sample
|
||||
transform.pos = -1 * glyph_pack[id].bounds.p0 * transform.scale + atlas.glyph_padding
|
||||
transform.pos = -1 * glyph.bounds.p0 * transform.scale + atlas.glyph_padding
|
||||
// Unlike with oversized, this cannot be finished here as its final value is dependent on glyph_buffer.batch_x allocation
|
||||
}
|
||||
for id, index in sub_slice(oversized)
|
||||
{
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
glyph := & glyph_pack[id]
|
||||
transform := glyph.draw_transform
|
||||
transform.scale = entry.size_scale * glyph_buffer.over_sample
|
||||
transform.pos = -1 * glyph_pack[id].bounds.p0 * transform.scale + atlas.glyph_padding
|
||||
to_screen_space( & transform.pos, & transform.scale, glyph_buffer_size )
|
||||
|
||||
glyph_padding := glyph_buffer.draw_padding
|
||||
|
||||
// Quad to draw during target pass
|
||||
quad := & glyph.draw_quad
|
||||
quad.dst_pos = glyph.position + glyph.bounds_scaled.p0 * target_scale - glyph_padding * target_scale
|
||||
quad.dst_scale = glyph.scale + glyph_padding * target_scale
|
||||
quad.src_scale = glyph.bounds_size_scaled * glyph.over_sample
|
||||
quad.src_pos = glyph.position
|
||||
to_text_space( & quad.src_pos, & quad.src_scale, atlas_size )
|
||||
to_text_space( & quad.src_pos, & quad.src_scale, atlas_size )
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("to_cache: caching to atlas")
|
||||
|
||||
for id, index in sub_slice(to_cache)
|
||||
{
|
||||
glyph := glyph_pack[id]
|
||||
cache_glyph_to_atlas( ctx,
|
||||
draw_list,
|
||||
& glyph_buffer.draw_list,
|
||||
& glyph_buffer.clear_draw_list,
|
||||
& glyph_buffer.batch_x,
|
||||
|
||||
atlas.glyph_padding,
|
||||
glyph_buffer_size,
|
||||
atlas_size,
|
||||
|
||||
glyph.draw_transform,
|
||||
|
||||
glyph.shape,
|
||||
glyph.bounds,
|
||||
glyph.bounds_size,
|
||||
glyph.region_pos,
|
||||
glyph.region_size,
|
||||
glyph.lru_code,
|
||||
glyph.atlas_index,
|
||||
entry,
|
||||
glyph.over_sample,
|
||||
|
||||
// glyph.index,
|
||||
// entry.parser_info,
|
||||
)
|
||||
mark_batch_codepoint_seen(ctx, glyph.lru_code)
|
||||
}
|
||||
|
||||
reset_batch_codepoint_state( ctx )
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
|
||||
profile_end()
|
||||
|
||||
|
||||
// The glyph buffer space transform for generate_glyph_pass_draw_list
|
||||
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 )
|
||||
// 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
|
||||
}
|
||||
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)
|
||||
@ -653,17 +599,115 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
append(& draw_list.calls, call)
|
||||
}
|
||||
}
|
||||
generate_cached_draw_list( draw_list, glyph_pack[:], sub_slice(to_cache), ctx.colour )
|
||||
generate_cached_draw_list( draw_list, glyph_pack[:], sub_slice(cached), ctx.colour )
|
||||
|
||||
reset_batch_codepoint_state( ctx )
|
||||
profile_begin("to_cache: caching to atlas")
|
||||
|
||||
// profile_begin("font parser shape generation")
|
||||
for id, index in sub_slice(to_cache) {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
}
|
||||
// profile_end()
|
||||
|
||||
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
|
||||
|
||||
glyph := glyph_pack[id]
|
||||
cache_glyph_to_atlas(
|
||||
draw_list,
|
||||
& glyph_buffer.draw_list,
|
||||
& glyph_buffer.clear_draw_list,
|
||||
& glyph_buffer.batch_x,
|
||||
|
||||
& ctx.temp_path,
|
||||
|
||||
glyph.shape,
|
||||
glyph.bounds,
|
||||
glyph.bounds_size_scaled,
|
||||
atlas_size,
|
||||
|
||||
glyph_buffer_size,
|
||||
glyph.over_sample,
|
||||
atlas.glyph_padding,
|
||||
glyph.draw_transform,
|
||||
|
||||
glyph.region_pos,
|
||||
glyph.region_size,
|
||||
entry.curve_quality,
|
||||
)
|
||||
|
||||
// call := Draw_Call_Default
|
||||
// call.pass = .Target
|
||||
// call.colour = ctx.colour
|
||||
|
||||
// profile("glyph")
|
||||
// call.start_index = u32(len(draw_list.indices))
|
||||
|
||||
// quad := glyph_pack[id].draw_quad
|
||||
// blit_quad(draw_list,
|
||||
// quad.dst_pos, quad.dst_pos + quad.dst_scale,
|
||||
// quad.src_pos, quad.src_pos + quad.src_scale
|
||||
// )
|
||||
// call.end_index = u32(len(draw_list.indices))
|
||||
// append(& draw_list.calls, call)
|
||||
}
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
|
||||
for id, index in sub_slice(to_cache) do parser_free_shape(entry.parser_info, glyph_pack[id].shape)
|
||||
profile_end()
|
||||
|
||||
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
|
||||
// flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
// generate_cached_draw_list( draw_list, glyph_pack[:], sub_slice(cached), ctx.colour )
|
||||
for id, index in sub_slice(cached)
|
||||
{
|
||||
call := Draw_Call_Default
|
||||
call.pass = .Target
|
||||
call.colour = ctx.colour
|
||||
|
||||
profile("glyph")
|
||||
call.start_index = u32(len(draw_list.indices))
|
||||
|
||||
quad := glyph_pack[id].draw_quad
|
||||
blit_quad(draw_list,
|
||||
quad.dst_pos, quad.dst_pos + quad.dst_scale,
|
||||
quad.src_pos, quad.src_pos + quad.src_scale
|
||||
)
|
||||
call.end_index = u32(len(draw_list.indices))
|
||||
append(& draw_list.calls, call)
|
||||
}
|
||||
reset_batch_codepoint_state( ctx )
|
||||
profile_end()
|
||||
|
||||
profile_begin("generate oversized glyphs draw_list")
|
||||
for id, index in sub_slice(oversized) {
|
||||
error : Allocator_Error
|
||||
glyph_pack[id].shape, error = parser_get_glyph_shape(entry.parser_info, glyph_pack[id].index)
|
||||
assert(error == .None)
|
||||
}
|
||||
|
||||
for id, index in sub_slice(oversized)
|
||||
{
|
||||
ctx.colour.r = 0.0
|
||||
ctx.colour.g = 0.0
|
||||
ctx.colour.b = 1.0
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
|
||||
glyph := glyph_pack[id]
|
||||
generate_oversized_draw_list(ctx,
|
||||
generate_oversized_draw_list(
|
||||
draw_list,
|
||||
& ctx.temp_path,
|
||||
ctx.colour,
|
||||
entry.curve_quality,
|
||||
glyph.shape,
|
||||
glyph.bounds,
|
||||
@ -673,12 +717,10 @@ generate_shape_draw_list :: #force_no_inline proc( ctx : ^Context,
|
||||
}
|
||||
profile_end()
|
||||
|
||||
reset_batch_codepoint_state( ctx )
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.batch_x)
|
||||
// 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)
|
||||
for id, index in sub_slice(to_cache) do parser_free_shape(entry.parser_info, glyph_pack[id].shape)
|
||||
profile_end()
|
||||
|
||||
cursor_pos = position + shaped.end_cursor_pos * target_scale
|
||||
|
@ -36,8 +36,6 @@ import "core:mem"
|
||||
arena_init :: mem.arena_init
|
||||
import "core:slice"
|
||||
|
||||
|
||||
|
||||
//#region("Proc overload mappings")
|
||||
|
||||
append :: proc {
|
||||
@ -51,15 +49,15 @@ append_soa :: proc {
|
||||
}
|
||||
|
||||
ceil :: proc {
|
||||
math.ceil_f16,
|
||||
math.ceil_f16le,
|
||||
math.ceil_f16be,
|
||||
math.ceil_f32,
|
||||
math.ceil_f32le,
|
||||
math.ceil_f32be,
|
||||
math.ceil_f64,
|
||||
math.ceil_f64le,
|
||||
math.ceil_f64be,
|
||||
ceil_f16,
|
||||
ceil_f16le,
|
||||
ceil_f16be,
|
||||
ceil_f32,
|
||||
ceil_f32le,
|
||||
ceil_f32be,
|
||||
ceil_f64,
|
||||
ceil_f64le,
|
||||
ceil_f64be,
|
||||
|
||||
ceil_vec2,
|
||||
}
|
||||
@ -70,15 +68,15 @@ clear :: proc {
|
||||
}
|
||||
|
||||
floor :: proc {
|
||||
math.floor_f16,
|
||||
math.floor_f16le,
|
||||
math.floor_f16be,
|
||||
math.floor_f32,
|
||||
math.floor_f32le,
|
||||
math.floor_f32be,
|
||||
math.floor_f64,
|
||||
math.floor_f64le,
|
||||
math.floor_f64be,
|
||||
floor_f16,
|
||||
floor_f16le,
|
||||
floor_f16be,
|
||||
floor_f32,
|
||||
floor_f32le,
|
||||
floor_f32be,
|
||||
floor_f64,
|
||||
floor_f64le,
|
||||
floor_f64be,
|
||||
|
||||
floor_vec2,
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ to_screen_space :: #force_inline proc "contextless" ( #no_alias position, scale
|
||||
pos_64 = pos_64 * quotient * 2.0 - 1.0
|
||||
scale_64 = scale_64 * quotient * 2.0
|
||||
|
||||
(position^) = { f32(pos_64.x), f32(pos_64.y) }
|
||||
(position^) = { f32(pos_64.x), f32(pos_64.y) }
|
||||
(scale^) = { f32(scale_64.x), f32(scale_64.y) }
|
||||
}
|
||||
else
|
||||
@ -98,7 +98,7 @@ to_screen_space :: #force_inline proc "contextless" ( #no_alias position, scale
|
||||
scale_32 := scale^
|
||||
|
||||
quotient : Vec2 = 1.0 / size
|
||||
pos = pos * quotient * 2.0 - 1.0
|
||||
pos = pos * quotient * 2.0 - 1.0
|
||||
scale_32 = scale_32 * quotient * 2.0
|
||||
|
||||
(position^) = pos
|
||||
@ -117,7 +117,7 @@ to_text_space :: #force_inline proc "contextless" ( #no_alias position, scale :
|
||||
pos_64 *= quotient
|
||||
scale_64 *= quotient
|
||||
|
||||
(position^) = { f32(pos_64.x), f32(pos_64.y) }
|
||||
(position^) = { f32(pos_64.x), f32(pos_64.y) }
|
||||
(scale^) = { f32(scale_64.x), f32(scale_64.y) }
|
||||
}
|
||||
else
|
||||
|
@ -14,7 +14,7 @@ import "core:c"
|
||||
import "core:math"
|
||||
import "core:slice"
|
||||
import stbtt "vendor:stb/truetype"
|
||||
import freetype "thirdparty:freetype"
|
||||
// import freetype "thirdparty:freetype"
|
||||
|
||||
Parser_Kind :: enum u32 {
|
||||
STB_TrueType,
|
||||
@ -26,7 +26,7 @@ Parser_Font_Info :: struct {
|
||||
kind : Parser_Kind,
|
||||
using _ : struct #raw_union {
|
||||
stbtt_info : stbtt.fontinfo,
|
||||
freetype_info : freetype.Face
|
||||
// freetype_info : freetype.Face
|
||||
},
|
||||
data : []byte,
|
||||
}
|
||||
@ -52,20 +52,20 @@ Parser_Glyph_Shape :: [dynamic]Parser_Glyph_Vertex
|
||||
|
||||
Parser_Context :: struct {
|
||||
kind : Parser_Kind,
|
||||
ft_library : freetype.Library,
|
||||
// ft_library : freetype.Library,
|
||||
}
|
||||
|
||||
parser_init :: proc( ctx : ^Parser_Context, kind : Parser_Kind )
|
||||
{
|
||||
switch kind
|
||||
{
|
||||
case .Freetype:
|
||||
result := freetype.init_free_type( & ctx.ft_library )
|
||||
assert( result == freetype.Error.Ok, "VEFontCache.parser_init: Failed to initialize freetype" )
|
||||
// switch kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// result := freetype.init_free_type( & ctx.ft_library )
|
||||
// assert( result == freetype.Error.Ok, "VEFontCache.parser_init: Failed to initialize freetype" )
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
// Do nothing intentional
|
||||
}
|
||||
// }
|
||||
|
||||
ctx.kind = kind
|
||||
}
|
||||
@ -76,22 +76,22 @@ parser_shutdown :: proc( ctx : ^Parser_Context ) {
|
||||
|
||||
parser_load_font :: proc( ctx : ^Parser_Context, label : string, data : []byte ) -> (font : Parser_Font_Info)
|
||||
{
|
||||
switch ctx.kind
|
||||
{
|
||||
case .Freetype:
|
||||
when ODIN_OS == .Windows {
|
||||
error := freetype.new_memory_face( ctx.ft_library, raw_data(data), cast(i32) len(data), 0, & font.freetype_info )
|
||||
if error != .Ok do return
|
||||
}
|
||||
else when ODIN_OS == .Linux {
|
||||
error := freetype.new_memory_face( ctx.ft_library, raw_data(data), cast(i64) len(data), 0, & font.freetype_info )
|
||||
if error != .Ok do return
|
||||
}
|
||||
// switch ctx.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// when ODIN_OS == .Windows {
|
||||
// error := freetype.new_memory_face( ctx.ft_library, raw_data(data), cast(i32) len(data), 0, & font.freetype_info )
|
||||
// if error != .Ok do return
|
||||
// }
|
||||
// else when ODIN_OS == .Linux {
|
||||
// error := freetype.new_memory_face( ctx.ft_library, raw_data(data), cast(i64) len(data), 0, & font.freetype_info )
|
||||
// if error != .Ok do return
|
||||
// }
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
success := stbtt.InitFont( & font.stbtt_info, raw_data(data), 0 )
|
||||
if ! success do return
|
||||
}
|
||||
// }
|
||||
|
||||
font.label = label
|
||||
font.data = data
|
||||
@ -101,122 +101,122 @@ parser_load_font :: proc( ctx : ^Parser_Context, label : string, data : []byte )
|
||||
|
||||
parser_unload_font :: proc( font : ^Parser_Font_Info )
|
||||
{
|
||||
switch font.kind {
|
||||
case .Freetype:
|
||||
error := freetype.done_face( font.freetype_info )
|
||||
assert( error == .Ok, "VEFontCache.parser_unload_font: Failed to unload freetype face" )
|
||||
// switch font.kind {
|
||||
// case .Freetype:
|
||||
// error := freetype.done_face( font.freetype_info )
|
||||
// assert( error == .Ok, "VEFontCache.parser_unload_font: Failed to unload freetype face" )
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
// Do Nothing
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
parser_find_glyph_index :: #force_inline proc "contextless" ( font : Parser_Font_Info, codepoint : rune ) -> (glyph_index : Glyph)
|
||||
{
|
||||
profile(#procedure)
|
||||
switch font.kind
|
||||
{
|
||||
case .Freetype:
|
||||
when ODIN_OS == .Windows {
|
||||
glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) codepoint )
|
||||
}
|
||||
else when ODIN_OS == .Linux {
|
||||
glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) codepoint )
|
||||
}
|
||||
return
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// when ODIN_OS == .Windows {
|
||||
// glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) codepoint )
|
||||
// }
|
||||
// else when ODIN_OS == .Linux {
|
||||
// glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) codepoint )
|
||||
// }
|
||||
// return
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
glyph_index = transmute(Glyph) stbtt.FindGlyphIndex( font.stbtt_info, codepoint )
|
||||
return
|
||||
}
|
||||
return Glyph(-1)
|
||||
// }
|
||||
// return Glyph(-1)
|
||||
}
|
||||
|
||||
parser_free_shape :: #force_inline proc( font : Parser_Font_Info, shape : Parser_Glyph_Shape )
|
||||
{
|
||||
switch font.kind
|
||||
{
|
||||
case .Freetype:
|
||||
delete(shape)
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// delete(shape)
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
stbtt.FreeShape( font.stbtt_info, transmute( [^]stbtt.vertex) raw_data(shape) )
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
parser_get_codepoint_horizontal_metrics :: #force_inline proc "contextless" ( font : Parser_Font_Info, codepoint : rune ) -> ( advance, to_left_side_glyph : i32 )
|
||||
{
|
||||
switch font.kind
|
||||
{
|
||||
case .Freetype:
|
||||
glyph_index : Glyph
|
||||
when ODIN_OS == .Windows {
|
||||
glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) codepoint )
|
||||
}
|
||||
else when ODIN_OS == .Linux {
|
||||
glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) codepoint )
|
||||
}
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// glyph_index : Glyph
|
||||
// when ODIN_OS == .Windows {
|
||||
// glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) codepoint )
|
||||
// }
|
||||
// else when ODIN_OS == .Linux {
|
||||
// glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) codepoint )
|
||||
// }
|
||||
|
||||
if glyph_index != 0
|
||||
{
|
||||
freetype.load_glyph( font.freetype_info, c.uint(codepoint), { .No_Bitmap, .No_Hinting, .No_Scale } )
|
||||
advance = i32(font.freetype_info.glyph.advance.x) >> 6
|
||||
to_left_side_glyph = i32(font.freetype_info.glyph.metrics.hori_bearing_x) >> 6
|
||||
}
|
||||
else
|
||||
{
|
||||
advance = 0
|
||||
to_left_side_glyph = 0
|
||||
}
|
||||
// if glyph_index != 0
|
||||
// {
|
||||
// freetype.load_glyph( font.freetype_info, c.uint(codepoint), { .No_Bitmap, .No_Hinting, .No_Scale } )
|
||||
// advance = i32(font.freetype_info.glyph.advance.x) >> 6
|
||||
// to_left_side_glyph = i32(font.freetype_info.glyph.metrics.hori_bearing_x) >> 6
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// advance = 0
|
||||
// to_left_side_glyph = 0
|
||||
// }
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
stbtt.GetCodepointHMetrics( font.stbtt_info, codepoint, & advance, & to_left_side_glyph )
|
||||
}
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
parser_get_codepoint_kern_advance :: #force_inline proc "contextless" ( font : Parser_Font_Info, prev_codepoint, codepoint : rune ) -> i32
|
||||
{
|
||||
switch font.kind
|
||||
{
|
||||
case .Freetype:
|
||||
prev_glyph_index : Glyph
|
||||
glyph_index : Glyph
|
||||
when ODIN_OS == .Windows {
|
||||
prev_glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) prev_codepoint )
|
||||
glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) codepoint )
|
||||
}
|
||||
else when ODIN_OS == .Linux {
|
||||
prev_glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) prev_codepoint )
|
||||
glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) codepoint )
|
||||
}
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// prev_glyph_index : Glyph
|
||||
// glyph_index : Glyph
|
||||
// when ODIN_OS == .Windows {
|
||||
// prev_glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) prev_codepoint )
|
||||
// glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, transmute(u32) codepoint )
|
||||
// }
|
||||
// else when ODIN_OS == .Linux {
|
||||
// prev_glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) prev_codepoint )
|
||||
// glyph_index = transmute(Glyph) freetype.get_char_index( font.freetype_info, cast(u64) codepoint )
|
||||
// }
|
||||
|
||||
if prev_glyph_index != 0 && glyph_index != 0
|
||||
{
|
||||
kerning : freetype.Vector
|
||||
font.freetype_info.driver.clazz.get_kerning( font.freetype_info, transmute(u32) prev_codepoint, transmute(u32) codepoint, & kerning )
|
||||
}
|
||||
// if prev_glyph_index != 0 && glyph_index != 0
|
||||
// {
|
||||
// kerning : freetype.Vector
|
||||
// font.freetype_info.driver.clazz.get_kerning( font.freetype_info, transmute(u32) prev_codepoint, transmute(u32) codepoint, & kerning )
|
||||
// }
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
kern := stbtt.GetCodepointKernAdvance( font.stbtt_info, prev_codepoint, codepoint )
|
||||
return kern
|
||||
}
|
||||
return -1
|
||||
// }
|
||||
// return -1
|
||||
}
|
||||
|
||||
parser_get_font_vertical_metrics :: #force_inline proc "contextless" ( font : Parser_Font_Info ) -> (ascent, descent, line_gap : i32 )
|
||||
{
|
||||
switch font.kind
|
||||
{
|
||||
case .Freetype:
|
||||
info := font.freetype_info
|
||||
ascent = i32(info.ascender)
|
||||
descent = i32(info.descender)
|
||||
line_gap = i32(info.height) - (ascent - descent)
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// info := font.freetype_info
|
||||
// ascent = i32(info.ascender)
|
||||
// descent = i32(info.descender)
|
||||
// line_gap = i32(info.height) - (ascent - descent)
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
stbtt.GetFontVMetrics( font.stbtt_info, & ascent, & descent, & line_gap )
|
||||
}
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
@ -250,13 +250,13 @@ parser_get_bounds :: #force_inline proc "contextless" ( font : Parser_Font_Info,
|
||||
|
||||
parser_get_glyph_shape :: #force_inline proc ( font : Parser_Font_Info, glyph_index : Glyph ) -> (shape : Parser_Glyph_Shape, error : Allocator_Error)
|
||||
{
|
||||
switch font.kind
|
||||
{
|
||||
case .Freetype:
|
||||
// TODO(Ed): Don't do this, going a completely different route for handling shapes.
|
||||
// This abstraction fails to be time-saving or performant.
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// // TODO(Ed): Don't do this, going a completely different route for handling shapes.
|
||||
// // This abstraction fails to be time-saving or performant.
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
stb_shape : [^]stbtt.vertex
|
||||
nverts := stbtt.GetGlyphShape( font.stbtt_info, cast(i32) glyph_index, & stb_shape )
|
||||
|
||||
@ -266,33 +266,33 @@ parser_get_glyph_shape :: #force_inline proc ( font : Parser_Font_Info, glyph_in
|
||||
shape_raw.cap = int(nverts)
|
||||
shape_raw.allocator = runtime.nil_allocator()
|
||||
error = Allocator_Error.None
|
||||
return
|
||||
}
|
||||
// return
|
||||
// }
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
parser_is_glyph_empty :: #force_inline proc "contextless" ( font : Parser_Font_Info, glyph_index : Glyph ) -> b32
|
||||
{
|
||||
switch font.kind
|
||||
{
|
||||
case .Freetype:
|
||||
error := freetype.load_glyph( font.freetype_info, cast(u32) glyph_index, { .No_Bitmap, .No_Hinting, .No_Scale } )
|
||||
if error == .Ok
|
||||
{
|
||||
if font.freetype_info.glyph.format == .Outline {
|
||||
return font.freetype_info.glyph.outline.n_points == 0
|
||||
}
|
||||
else if font.freetype_info.glyph.format == .Bitmap {
|
||||
return font.freetype_info.glyph.bitmap.width == 0 && font.freetype_info.glyph.bitmap.rows == 0;
|
||||
}
|
||||
}
|
||||
return false
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
// error := freetype.load_glyph( font.freetype_info, cast(u32) glyph_index, { .No_Bitmap, .No_Hinting, .No_Scale } )
|
||||
// if error == .Ok
|
||||
// {
|
||||
// if font.freetype_info.glyph.format == .Outline {
|
||||
// return font.freetype_info.glyph.outline.n_points == 0
|
||||
// }
|
||||
// else if font.freetype_info.glyph.format == .Bitmap {
|
||||
// return font.freetype_info.glyph.bitmap.width == 0 && font.freetype_info.glyph.bitmap.rows == 0;
|
||||
// }
|
||||
// }
|
||||
// return false
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
return stbtt.IsGlyphEmpty( font.stbtt_info, cast(c.int) glyph_index )
|
||||
}
|
||||
return false
|
||||
// }
|
||||
// return false
|
||||
}
|
||||
|
||||
parser_scale :: #force_inline proc "contextless" ( font : Parser_Font_Info, size : f32 ) -> f32
|
||||
@ -306,43 +306,43 @@ parser_scale :: #force_inline proc "contextless" ( font : Parser_Font_Info, size
|
||||
|
||||
parser_scale_for_pixel_height :: #force_inline proc "contextless" ( font : Parser_Font_Info, size : f32 ) -> f32
|
||||
{
|
||||
switch font.kind {
|
||||
case .Freetype:
|
||||
freetype.set_pixel_sizes( font.freetype_info, 0, cast(u32) size )
|
||||
size_scale := size / cast(f32)font.freetype_info.units_per_em
|
||||
return size_scale
|
||||
// switch font.kind {
|
||||
// case .Freetype:
|
||||
// freetype.set_pixel_sizes( font.freetype_info, 0, cast(u32) size )
|
||||
// size_scale := size / cast(f32)font.freetype_info.units_per_em
|
||||
// return size_scale
|
||||
|
||||
case.STB_TrueType:
|
||||
// case.STB_TrueType:
|
||||
return stbtt.ScaleForPixelHeight( font.stbtt_info, size )
|
||||
}
|
||||
return 0
|
||||
// }
|
||||
// return 0
|
||||
}
|
||||
|
||||
parser_scale_for_mapping_em_to_pixels :: #force_inline proc "contextless" ( font : Parser_Font_Info, size : f32 ) -> f32
|
||||
{
|
||||
switch font.kind {
|
||||
case .Freetype:
|
||||
Inches_To_CM :: cast(f32) 2.54
|
||||
Points_Per_CM :: cast(f32) 28.3465
|
||||
CM_Per_Point :: cast(f32) 1.0 / DPT_DPCM
|
||||
CM_Per_Pixel :: cast(f32) 1.0 / DPT_PPCM
|
||||
DPT_DPCM :: cast(f32) 72.0 * Inches_To_CM // 182.88 points/dots per cm
|
||||
DPT_PPCM :: cast(f32) 96.0 * Inches_To_CM // 243.84 pixels per cm
|
||||
DPT_DPI :: cast(f32) 72.0
|
||||
// switch font.kind {
|
||||
// case .Freetype:
|
||||
// Inches_To_CM :: cast(f32) 2.54
|
||||
// Points_Per_CM :: cast(f32) 28.3465
|
||||
// CM_Per_Point :: cast(f32) 1.0 / DPT_DPCM
|
||||
// CM_Per_Pixel :: cast(f32) 1.0 / DPT_PPCM
|
||||
// DPT_DPCM :: cast(f32) 72.0 * Inches_To_CM // 182.88 points/dots per cm
|
||||
// DPT_PPCM :: cast(f32) 96.0 * Inches_To_CM // 243.84 pixels per cm
|
||||
// DPT_DPI :: cast(f32) 72.0
|
||||
|
||||
// TODO(Ed): Don't assume the dots or pixels per inch.
|
||||
system_dpi :: DPT_DPI
|
||||
// // TODO(Ed): Don't assume the dots or pixels per inch.
|
||||
// system_dpi :: DPT_DPI
|
||||
|
||||
FT_Font_Size_Point_Unit :: 1.0 / 64.0
|
||||
FT_Point_10 :: 64.0
|
||||
// FT_Font_Size_Point_Unit :: 1.0 / 64.0
|
||||
// FT_Point_10 :: 64.0
|
||||
|
||||
points_per_em := (size / system_dpi ) * DPT_DPI
|
||||
freetype.set_char_size( font.freetype_info, 0, cast(freetype.F26Dot6) f32(points_per_em * FT_Point_10), cast(u32) DPT_DPI, cast(u32) DPT_DPI )
|
||||
size_scale := f32(f64(size) / cast(f64) font.freetype_info.units_per_em)
|
||||
return size_scale
|
||||
// points_per_em := (size / system_dpi ) * DPT_DPI
|
||||
// freetype.set_char_size( font.freetype_info, 0, cast(freetype.F26Dot6) f32(points_per_em * FT_Point_10), cast(u32) DPT_DPI, cast(u32) DPT_DPI )
|
||||
// size_scale := f32(f64(size) / cast(f64) font.freetype_info.units_per_em)
|
||||
// return size_scale
|
||||
|
||||
case .STB_TrueType:
|
||||
// case .STB_TrueType:
|
||||
return stbtt.ScaleForMappingEmToPixels( font.stbtt_info, size )
|
||||
}
|
||||
return 0
|
||||
// }
|
||||
// return 0
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package vefontcache
|
||||
|
||||
Shaped_Text :: struct {
|
||||
font : Font_ID,
|
||||
entry : ^Entry,
|
||||
|
||||
glyphs : [dynamic]Glyph,
|
||||
positions : [dynamic]Vec2,
|
||||
end_cursor_pos : Vec2,
|
||||
size : Vec2,
|
||||
entry : ^Entry,
|
||||
font : Font_ID,
|
||||
}
|
||||
|
||||
Shaped_Text_Cache :: struct {
|
||||
|
@ -46,8 +46,9 @@ Context :: struct {
|
||||
snap_width : f32,
|
||||
snap_height : f32,
|
||||
|
||||
colour : Colour,
|
||||
cursor_pos : Vec2,
|
||||
alpha_scalar : f32, // Will apply a multiplier to the colour's alpha which provides some sharpening of the edges.
|
||||
colour : Colour,
|
||||
cursor_pos : Vec2,
|
||||
|
||||
draw_layer : struct {
|
||||
vertices_offset : int,
|
||||
@ -116,7 +117,7 @@ Init_Glyph_Draw_Params :: struct {
|
||||
|
||||
Init_Glyph_Draw_Params_Default :: Init_Glyph_Draw_Params {
|
||||
over_sample = Vec2 { 4, 4 },
|
||||
buffer_batch = 8,
|
||||
buffer_batch = 4,
|
||||
draw_padding = Init_Atlas_Params_Default.glyph_padding,
|
||||
}
|
||||
|
||||
@ -151,10 +152,11 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
glyph_draw_params := Init_Glyph_Draw_Params_Default,
|
||||
shape_cache_params := Init_Shape_Cache_Params_Default,
|
||||
shaper_params := Init_Shaper_Params_Default,
|
||||
default_curve_quality : u32 = 6,
|
||||
alpha_sharpen := 0.2,
|
||||
default_curve_quality : u32 = 3,
|
||||
entires_reserve : u32 = 256,
|
||||
temp_path_reserve : u32 = 1024,
|
||||
temp_codepoint_seen_reserve : u32 = 1024,
|
||||
temp_path_reserve : u32 = 10 * 1024,
|
||||
temp_codepoint_seen_reserve : u32 = 10 * 1024,
|
||||
)
|
||||
{
|
||||
assert( ctx != nil, "Must provide a valid context" )
|
||||
@ -163,12 +165,14 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
ctx.backing = allocator
|
||||
context.allocator = ctx.backing
|
||||
|
||||
ctx.colour = { 1, 1, 1, 1 }
|
||||
|
||||
use_advanced_shaper = shaper_params.use_advanced_text_shaper
|
||||
shaper_ctx.adv_snap_small_font_threshold = f32(shaper_params.adv_snap_small_font_threshold)
|
||||
shaper_ctx.snap_glyph_position = shaper_params.snap_glyph_position
|
||||
|
||||
if default_curve_quality == 0 {
|
||||
default_curve_quality = 6
|
||||
default_curve_quality = 3
|
||||
}
|
||||
ctx.default_curve_quality = default_curve_quality
|
||||
|
||||
@ -267,7 +271,7 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
over_sample = glyph_draw_params.over_sample
|
||||
batch = cast(i32) glyph_draw_params.buffer_batch
|
||||
width = atlas.region_d.width * i32(over_sample.x) * batch
|
||||
height = atlas.region_d.height * i32(over_sample.y)
|
||||
height = atlas.region_d.height * i32(over_sample.y) //* (batch / 2)
|
||||
draw_padding = cast(f32) glyph_draw_params.draw_padding
|
||||
|
||||
draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = glyph_draw_params.buffer_batch * 2 )
|
||||
|
Loading…
Reference in New Issue
Block a user