Formating, name changes (making identifiers more idiomatic)

This commit is contained in:
2024-07-04 16:18:26 -04:00
parent 7c1c1fc315
commit 16319d9e43
10 changed files with 315 additions and 313 deletions

View File

@@ -41,7 +41,7 @@ COLOR_WHITE :: RGBA8 { 255, 255, 255, 255 }
FONT_LARGEST_PIXEL_SIZE :: 400 FONT_LARGEST_PIXEL_SIZE :: 400
FONT_SIZE_INTERVAL :: 2 FONT_SIZE_INTERVAL :: 2
FONT_DEFAULT :: FontID { "" } FONT_DEFAULT :: Font_ID { "" }
FONT_DEFAULT_SIZEZ :: 12.0 FONT_DEFAULT_SIZEZ :: 12.0
FONT_LOAD_USE_DEFAULT_SIZE :: -1 FONT_LOAD_USE_DEFAULT_SIZE :: -1
@@ -52,17 +52,17 @@ PATH_FONTS :: "../fonts/"
OVER_SAMPLE_ZOOM : f32 : 2.0 // Adjust this value as needed, used by draw_text_zoomed_norm OVER_SAMPLE_ZOOM : f32 : 2.0 // Adjust this value as needed, used by draw_text_zoomed_norm
FontID :: struct { Font_ID :: struct {
label : string, label : string,
} }
FontDef :: struct { FontDef :: struct {
path_file : string, path_file : string,
default_size : i32, default_size : i32,
size_table : [FONT_LARGEST_PIXEL_SIZE / FONT_SIZE_INTERVAL] ve.FontID, size_table : [FONT_LARGEST_PIXEL_SIZE / FONT_SIZE_INTERVAL] ve.Font_ID,
} }
DemoContext :: struct { Demo_Context :: struct {
ve_ctx : ve.Context, ve_ctx : ve.Context,
render_ctx : ve_sokol.Context, render_ctx : ve_sokol.Context,
font_ids : map[string]FontDef, font_ids : map[string]FontDef,
@@ -70,43 +70,43 @@ DemoContext :: struct {
// Values between 1, & -1 on Y axis // Values between 1, & -1 on Y axis
mouse_scroll : Vec2, mouse_scroll : Vec2,
font_firacode : FontID, font_firacode : Font_ID,
font_logo : FontID, font_logo : Font_ID,
font_title : FontID, font_title : Font_ID,
font_print : FontID, font_print : Font_ID,
font_mono : FontID, font_mono : Font_ID,
font_small : FontID, font_small : Font_ID,
font_demo_sans : FontID, font_demo_sans : Font_ID,
font_demo_serif : FontID, font_demo_serif : Font_ID,
font_demo_script : FontID, font_demo_script : Font_ID,
font_demo_mono : FontID, font_demo_mono : Font_ID,
font_demo_chinese : FontID, font_demo_chinese : Font_ID,
font_demo_japanese : FontID, font_demo_japanese : Font_ID,
font_demo_korean : FontID, font_demo_korean : Font_ID,
font_demo_thai : FontID, font_demo_thai : Font_ID,
font_demo_arabic : FontID, font_demo_arabic : Font_ID,
font_demo_hebrew : FontID, font_demo_hebrew : Font_ID,
font_demo_raincode : FontID, font_demo_raincode : Font_ID,
font_demo_grid2 : FontID, font_demo_grid2 : Font_ID,
font_demo_grid3 : FontID, font_demo_grid3 : Font_ID,
screen_size : [2]f32, screen_size : [2]f32,
} }
demo_ctx : DemoContext demo_ctx : Demo_Context
font_load :: proc(path_file : string, font_load :: proc(path_file : string,
default_size : i32 = FONT_LOAD_USE_DEFAULT_SIZE, default_size : i32 = FONT_LOAD_USE_DEFAULT_SIZE,
desired_id : string = FONT_LOAD_GEN_ID, desired_id : string = FONT_LOAD_GEN_ID,
curve_quality : u32 = 3, curve_quality : u32 = 3,
) -> FontID ) -> Font_ID
{ {
msg := fmt.println("Loading font: %v", path_file) msg := fmt.println("Loading font: %v", path_file)
font_data, read_succeded : = os.read_entire_file( path_file ) font_data, read_succeded : = os.read_entire_file( path_file )
assert( bool(read_succeded), fmt.tprintf("Failed to read font file for: %v", path_file) ) assert( bool(read_succeded), fmt.tprintf("Failed to read font file for: %v", path_file) )
font_data_size := cast(i32) len(font_data) font_data_size := cast(i32) len(font_data)
font_firacode : FontID font_firacode : Font_ID
desired_id := desired_id desired_id := desired_id
@@ -134,13 +134,13 @@ font_firacode : FontID
(ve_id^) = ve_ret_id (ve_id^) = ve_ret_id
} }
fid := FontID { desired_id } fid := Font_ID { desired_id }
return fid return fid
} }
Font_Use_Default_Size :: f32(0.0) Font_Use_Default_Size :: f32(0.0)
font_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Size ) -> ( ve_id : ve.FontID, resolved_size : i32 ) font_resolve_draw_id :: proc( id : Font_ID, size := Font_Use_Default_Size ) -> ( ve_id : ve.Font_ID, resolved_size : i32 )
{ {
def := demo_ctx.font_ids[ id.label ] def := demo_ctx.font_ids[ id.label ]
size := size == 0.0 ? f32(def.default_size) : size size := size == 0.0 ? f32(def.default_size) : size
@@ -152,14 +152,14 @@ font_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Size ) -> (
return return
} }
measure_text_size :: proc( text : string, font : FontID, font_size := Font_Use_Default_Size, spacing : f32 ) -> Vec2 measure_text_size :: proc( text : string, font : Font_ID, font_size := Font_Use_Default_Size, spacing : f32 ) -> Vec2
{ {
ve_id, size := font_resolve_draw_id( font, font_size ) ve_id, size := font_resolve_draw_id( font, font_size )
measured := ve.measure_text_size( & demo_ctx.ve_ctx, ve_id, text ) measured := ve.measure_text_size( & demo_ctx.ve_ctx, ve_id, text )
return measured return measured
} }
get_font_vertical_metrics :: #force_inline proc ( font : FontID, font_size := Font_Use_Default_Size ) -> ( ascent, descent, line_gap : f32 ) get_font_vertical_metrics :: #force_inline proc ( font : Font_ID, font_size := Font_Use_Default_Size ) -> ( ascent, descent, line_gap : f32 )
{ {
ve_id, size := font_resolve_draw_id( font, font_size ) ve_id, size := font_resolve_draw_id( font, font_size )
ascent, descent, line_gap = ve.get_font_vertical_metrics( & demo_ctx.ve_ctx, ve_id ) ascent, descent, line_gap = ve.get_font_vertical_metrics( & demo_ctx.ve_ctx, ve_id )
@@ -167,7 +167,7 @@ get_font_vertical_metrics :: #force_inline proc ( font : FontID, font_size := Fo
} }
// Draw text using a string and normalized render coordinates // Draw text using a string and normalized render coordinates
draw_text_string_pos_norm :: proc( content : string, id : FontID, size : f32, pos : Vec2, color := COLOR_WHITE, scale : f32 = 1.0 ) draw_text_string_pos_norm :: proc( content : string, id : Font_ID, size : f32, pos : Vec2, color := COLOR_WHITE, scale : f32 = 1.0 )
{ {
width := demo_ctx.screen_size.x width := demo_ctx.screen_size.x
height := demo_ctx.screen_size.y height := demo_ctx.screen_size.y
@@ -181,14 +181,14 @@ draw_text_string_pos_norm :: proc( content : string, id : FontID, size : f32, po
} }
// Draw text using a string and extent-based screen coordinates // Draw text using a string and extent-based screen coordinates
draw_text_string_pos_extent :: proc( content : string, id : FontID, size : f32, pos : Vec2, color := COLOR_WHITE ) { draw_text_string_pos_extent :: proc( content : string, id : Font_ID, size : f32, pos : Vec2, color := COLOR_WHITE ) {
render_pos := pos + demo_ctx.screen_size * 0.5 render_pos := pos + demo_ctx.screen_size * 0.5
normalized_pos := render_pos * (1.0 / demo_ctx.screen_size) normalized_pos := render_pos * (1.0 / demo_ctx.screen_size)
draw_text_string_pos_norm( content, id, size, normalized_pos, color ) draw_text_string_pos_norm( content, id, size, normalized_pos, color )
} }
// Adapt the draw_text_string_pos_extent_zoomed procedure // Adapt the draw_text_string_pos_extent_zoomed procedure
draw_text_zoomed_norm :: proc(content : string, id : FontID, size : f32, pos : Vec2, zoom : f32, color := COLOR_WHITE) draw_text_zoomed_norm :: proc(content : string, id : Font_ID, size : f32, pos : Vec2, zoom : f32, color := COLOR_WHITE)
{ {
screen_size := demo_ctx.screen_size screen_size := demo_ctx.screen_size
screen_scale := Vec2{1.0 / screen_size.x, 1.0 / screen_size.y} screen_scale := Vec2{1.0 / screen_size.x, 1.0 / screen_size.y}

View File

@@ -6,33 +6,33 @@ The choice was made to keep the LRU cache implementation as close to the origina
import "base:runtime" import "base:runtime"
PoolListIter :: i32 Pool_ListIter :: i32
PoolListValue :: u64 Pool_ListValue :: u64
PoolListItem :: struct { Pool_List_Item :: struct {
prev : PoolListIter, prev : Pool_ListIter,
next : PoolListIter, next : Pool_ListIter,
value : PoolListValue, value : Pool_ListValue,
} }
PoolList :: struct { Pool_List :: struct {
items : [dynamic]PoolListItem, items : [dynamic]Pool_List_Item,
free_list : [dynamic]PoolListIter, free_list : [dynamic]Pool_ListIter,
front : PoolListIter, front : Pool_ListIter,
back : PoolListIter, back : Pool_ListIter,
size : i32, size : i32,
capacity : i32, capacity : i32,
dbg_name : string, dbg_name : string,
} }
pool_list_init :: proc( pool : ^PoolList, capacity : i32, dbg_name : string = "" ) pool_list_init :: proc( pool : ^Pool_List, capacity : i32, dbg_name : string = "" )
{ {
error : AllocatorError error : Allocator_Error
pool.items, error = make( [dynamic]PoolListItem, int(capacity) ) pool.items, error = make( [dynamic]Pool_List_Item, int(capacity) )
assert( error == .None, "VEFontCache.pool_list_init : Failed to allocate items array") assert( error == .None, "VEFontCache.pool_list_init : Failed to allocate items array")
resize( & pool.items, capacity ) resize( & pool.items, capacity )
pool.free_list, error = make( [dynamic]PoolListIter, len = 0, cap = int(capacity) ) pool.free_list, error = make( [dynamic]Pool_ListIter, len = 0, cap = int(capacity) )
assert( error == .None, "VEFontCache.pool_list_init : Failed to allocate free_list array") assert( error == .None, "VEFontCache.pool_list_init : Failed to allocate free_list array")
resize( & pool.free_list, capacity ) resize( & pool.free_list, capacity )
@@ -53,17 +53,17 @@ pool_list_init :: proc( pool : ^PoolList, capacity : i32, dbg_name : string = ""
back = -1 back = -1
} }
pool_list_free :: proc( pool : ^PoolList ) { pool_list_free :: proc( pool : ^Pool_List ) {
delete( pool.items) delete( pool.items)
delete( pool.free_list) delete( pool.free_list)
} }
pool_list_reload :: proc( pool : ^PoolList, allocator : Allocator ) { pool_list_reload :: proc( pool : ^Pool_List, allocator : Allocator ) {
reload_array( & pool.items, allocator ) reload_array( & pool.items, allocator )
reload_array( & pool.free_list, allocator ) reload_array( & pool.free_list, allocator )
} }
pool_list_push_front :: proc( pool : ^PoolList, value : PoolListValue ) pool_list_push_front :: proc( pool : ^Pool_List, value : Pool_ListValue )
{ {
using pool using pool
if size >= capacity do return if size >= capacity do return
@@ -90,7 +90,7 @@ pool_list_push_front :: proc( pool : ^PoolList, value : PoolListValue )
size += 1 size += 1
} }
pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter ) pool_list_erase :: proc( pool : ^Pool_List, iter : Pool_ListIter )
{ {
using pool using pool
if size <= 0 do return if size <= 0 do return
@@ -119,7 +119,7 @@ pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter )
} }
} }
pool_list_move_to_front :: #force_inline proc( pool : ^PoolList, iter : PoolListIter ) pool_list_move_to_front :: #force_inline proc( pool : ^Pool_List, iter : Pool_ListIter )
{ {
using pool using pool
@@ -136,13 +136,13 @@ pool_list_move_to_front :: #force_inline proc( pool : ^PoolList, iter : PoolList
front = iter front = iter
} }
pool_list_peek_back :: #force_inline proc ( pool : ^PoolList ) -> PoolListValue { pool_list_peek_back :: #force_inline proc ( pool : ^Pool_List ) -> Pool_ListValue {
assert( pool.back != - 1 ) assert( pool.back != - 1 )
value := pool.items[ pool.back ].value value := pool.items[ pool.back ].value
return value return value
} }
pool_list_pop_back :: #force_inline proc( pool : ^PoolList ) -> PoolListValue { pool_list_pop_back :: #force_inline proc( pool : ^Pool_List ) -> Pool_ListValue {
if pool.size <= 0 do return 0 if pool.size <= 0 do return 0
assert( pool.back != -1 ) assert( pool.back != -1 )
@@ -153,8 +153,10 @@ pool_list_pop_back :: #force_inline proc( pool : ^PoolList ) -> PoolListValue {
LRU_Link :: struct { LRU_Link :: struct {
pad_top : u64, pad_top : u64,
value : i32, value : i32,
ptr : PoolListIter, ptr : Pool_ListIter,
pad_bottom : u64, pad_bottom : u64,
} }
@@ -162,34 +164,34 @@ LRU_Cache :: struct {
capacity : i32, capacity : i32,
num : i32, num : i32,
table : map[u64]LRU_Link, table : map[u64]LRU_Link,
key_queue : PoolList, key_queue : Pool_List,
} }
LRU_init :: proc( cache : ^LRU_Cache, capacity : i32, dbg_name : string = "" ) { lru_init :: proc( cache : ^LRU_Cache, capacity : i32, dbg_name : string = "" ) {
error : AllocatorError error : Allocator_Error
cache.capacity = capacity cache.capacity = capacity
cache.table, error = make( map[u64]LRU_Link, uint(capacity) ) cache.table, error = make( map[u64]LRU_Link, uint(capacity) )
assert( error == .None, "VEFontCache.LRU_init : Failed to allocate cache's table") assert( error == .None, "VEFontCache.lru_init : Failed to allocate cache's table")
pool_list_init( & cache.key_queue, capacity, dbg_name = dbg_name ) pool_list_init( & cache.key_queue, capacity, dbg_name = dbg_name )
} }
LRU_free :: proc( cache : ^LRU_Cache ) { lru_free :: proc( cache : ^LRU_Cache ) {
pool_list_free( & cache.key_queue ) pool_list_free( & cache.key_queue )
delete( cache.table ) delete( cache.table )
} }
LRU_reload :: #force_inline proc( cache : ^LRU_Cache, allocator : Allocator ) { lru_reload :: #force_inline proc( cache : ^LRU_Cache, allocator : Allocator ) {
reload_map( & cache.table, allocator ) reload_map( & cache.table, allocator )
pool_list_reload( & cache.key_queue, allocator ) pool_list_reload( & cache.key_queue, allocator )
} }
LRU_find :: #force_inline proc "contextless" ( cache : ^LRU_Cache, key : u64, must_find := false ) -> (LRU_Link, bool) { lru_find :: #force_inline proc "contextless" ( cache : ^LRU_Cache, key : u64, must_find := false ) -> (LRU_Link, bool) {
link, success := cache.table[key] link, success := cache.table[key]
return link, success return link, success
} }
LRU_get :: #force_inline proc( cache: ^LRU_Cache, key : u64 ) -> i32 { lru_get :: #force_inline proc( cache: ^LRU_Cache, key : u64 ) -> i32 {
if link, ok := &cache.table[ key ]; ok { if link, ok := &cache.table[ key ]; ok {
pool_list_move_to_front(&cache.key_queue, link.ptr) pool_list_move_to_front(&cache.key_queue, link.ptr)
return link.value return link.value
@@ -197,7 +199,7 @@ LRU_get :: #force_inline proc( cache: ^LRU_Cache, key : u64 ) -> i32 {
return -1 return -1
} }
LRU_get_next_evicted :: #force_inline proc ( cache : ^LRU_Cache ) -> u64 { lru_get_next_evicted :: #force_inline proc ( cache : ^LRU_Cache ) -> u64 {
if cache.key_queue.size >= cache.capacity { if cache.key_queue.size >= cache.capacity {
evict := pool_list_peek_back( & cache.key_queue ) evict := pool_list_peek_back( & cache.key_queue )
return evict return evict
@@ -205,15 +207,15 @@ LRU_get_next_evicted :: #force_inline proc ( cache : ^LRU_Cache ) -> u64 {
return 0xFFFFFFFFFFFFFFFF return 0xFFFFFFFFFFFFFFFF
} }
LRU_peek :: #force_inline proc ( cache : ^LRU_Cache, key : u64, must_find := false ) -> i32 { lru_peek :: #force_inline proc ( cache : ^LRU_Cache, key : u64, must_find := false ) -> i32 {
iter, success := LRU_find( cache, key, must_find ) iter, success := lru_find( cache, key, must_find )
if success == false { if success == false {
return -1 return -1
} }
return iter.value return iter.value
} }
LRU_put :: #force_inline proc( cache : ^LRU_Cache, key : u64, value : i32 ) -> u64 lru_put :: #force_inline proc( cache : ^LRU_Cache, key : u64, value : i32 ) -> u64
{ {
if link, ok := & cache.table[ key ]; ok { if link, ok := & cache.table[ key ]; ok {
pool_list_move_to_front( & cache.key_queue, link.ptr ) pool_list_move_to_front( & cache.key_queue, link.ptr )
@@ -237,8 +239,8 @@ LRU_put :: #force_inline proc( cache : ^LRU_Cache, key : u64, value : i32 ) -> u
return evict return evict
} }
LRU_refresh :: proc( cache : ^LRU_Cache, key : u64 ) { lru_refresh :: proc( cache : ^LRU_Cache, key : u64 ) {
link, success := LRU_find( cache, key ) link, success := lru_find( cache, key )
pool_list_erase( & cache.key_queue, link.ptr ) pool_list_erase( & cache.key_queue, link.ptr )
pool_list_push_front( & cache.key_queue, key ) pool_list_push_front( & cache.key_queue, key )
link.ptr = cache.key_queue.front link.ptr = cache.key_queue.front

View File

@@ -1,6 +1,6 @@
package vefontcache package vefontcache
AtlasRegionKind :: enum u8 { Atlas_Region_Kind :: enum u8 {
None = 0x00, None = 0x00,
A = 0x41, A = 0x41,
B = 0x42, B = 0x42,
@@ -10,7 +10,7 @@ AtlasRegionKind :: enum u8 {
Ignore = 0xFF, // ve_fontcache_cache_glyph_to_atlas uses a -1 value in clear draw call Ignore = 0xFF, // ve_fontcache_cache_glyph_to_atlas uses a -1 value in clear draw call
} }
AtlasRegion :: struct { Atlas_Region :: struct {
state : LRU_Cache, state : LRU_Cache,
width : i32, width : i32,
@@ -29,13 +29,13 @@ Atlas :: struct {
glyph_padding : i32, glyph_padding : i32,
region_a : AtlasRegion, region_a : Atlas_Region,
region_b : AtlasRegion, region_b : Atlas_Region,
region_c : AtlasRegion, region_c : Atlas_Region,
region_d : AtlasRegion, region_d : Atlas_Region,
} }
atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : i32 ) -> (position, size: Vec2) atlas_bbox :: proc( atlas : ^Atlas, region : Atlas_Region_Kind, local_idx : i32 ) -> (position, size: Vec2)
{ {
switch region switch region
{ {
@@ -79,14 +79,12 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : i32 )
position.x += f32(atlas.region_d.offset.x) position.x += f32(atlas.region_d.offset.x)
position.y += f32(atlas.region_d.offset.y) position.y += f32(atlas.region_d.offset.y)
case .Ignore: fallthrough case .Ignore, .None, .E:
case .None: fallthrough
case .E:
} }
return return
} }
decide_codepoint_region :: proc(ctx : ^Context, entry : ^Entry, glyph_index : Glyph ) -> (region_kind : AtlasRegionKind, region : ^AtlasRegion, over_sample : Vec2) decide_codepoint_region :: proc(ctx : ^Context, entry : ^Entry, glyph_index : Glyph ) -> (region_kind : Atlas_Region_Kind, region : ^Atlas_Region, over_sample : Vec2)
{ {
if parser_is_glyph_empty(&entry.parser_info, glyph_index) { if parser_is_glyph_empty(&entry.parser_info, glyph_index) {
return .None, nil, {} return .None, nil, {}
@@ -104,7 +102,7 @@ decide_codepoint_region :: proc(ctx : ^Context, entry : ^Entry, glyph_index : Gl
bounds_height_scaled := i32(bounds_height * entry.size_scale + glyph_padding) bounds_height_scaled := i32(bounds_height * entry.size_scale + glyph_padding)
// Use a lookup table for faster region selection // Use a lookup table for faster region selection
region_lookup := [4]struct { kind: AtlasRegionKind, region: ^AtlasRegion } { region_lookup := [4]struct { kind: Atlas_Region_Kind, region: ^Atlas_Region } {
{ .A, & atlas.region_a }, { .A, & atlas.region_a },
{ .B, & atlas.region_b }, { .B, & atlas.region_b },
{ .C, & atlas.region_c }, { .C, & atlas.region_c },

View File

@@ -8,16 +8,16 @@ Vertex :: struct {
u, v : f32, u, v : f32,
} }
DrawCall :: struct { Draw_Call :: struct {
pass : FrameBufferPass, pass : Frame_Buffer_Pass,
start_index : u32, start_index : u32,
end_index : u32, end_index : u32,
clear_before_draw : b32, clear_before_draw : b32,
region : AtlasRegionKind, region : Atlas_Region_Kind,
colour : Colour, colour : Colour,
} }
DrawCall_Default :: DrawCall { Draw_Call_Default :: Draw_Call {
pass = .None, pass = .None,
start_index = 0, start_index = 0,
end_index = 0, end_index = 0,
@@ -26,14 +26,14 @@ DrawCall_Default :: DrawCall {
colour = { 1.0, 1.0, 1.0, 1.0 } colour = { 1.0, 1.0, 1.0, 1.0 }
} }
DrawList :: struct { Draw_List :: struct {
vertices : [dynamic]Vertex, vertices : [dynamic]Vertex,
indices : [dynamic]u32, indices : [dynamic]u32,
calls : [dynamic]DrawCall, calls : [dynamic]Draw_Call,
} }
// TODO(Ed): This was a rough translation of the raw values the orignal was using, need to give better names... // TODO(Ed): This was a rough translation of the raw values the orignal was using, need to give better names...
FrameBufferPass :: enum u32 { Frame_Buffer_Pass :: enum u32 {
None = 0, None = 0,
Glyph = 1, Glyph = 1,
Atlas = 2, Atlas = 2,
@@ -41,7 +41,7 @@ FrameBufferPass :: enum u32 {
Target_Uncached = 4, Target_Uncached = 4,
} }
GlyphDrawBuffer :: struct { Glyph_Draw_Buffer :: struct {
over_sample : Vec2, over_sample : Vec2,
batch : i32, batch : i32,
width : i32, width : i32,
@@ -49,11 +49,11 @@ GlyphDrawBuffer :: struct {
draw_padding : i32, draw_padding : i32,
batch_x : i32, batch_x : i32,
clear_draw_list : DrawList, clear_draw_list : Draw_List,
draw_list : DrawList, draw_list : Draw_List,
} }
blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1}, uv0 : Vec2 = {0, 0}, uv1 : Vec2 = {1, 1} ) blit_quad :: proc( draw_list : ^Draw_List, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1}, uv0 : Vec2 = {0, 0}, uv1 : Vec2 = {1, 1} )
{ {
// profile(#procedure) // profile(#procedure)
// logf("Blitting: xy0: %0.2f, %0.2f xy1: %0.2f, %0.2f uv0: %0.2f, %0.2f uv1: %0.2f, %0.2f", // logf("Blitting: xy0: %0.2f, %0.2f xy1: %0.2f, %0.2f uv0: %0.2f, %0.2f uv1: %0.2f, %0.2f",
@@ -89,9 +89,9 @@ blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1}
} }
// TODO(Ed): glyph caching cannot be handled in a 'font parser' abstraction. Just going to have explicit procedures to grab info neatly... // TODO(Ed): glyph caching cannot be handled in a 'font parser' abstraction. Just going to have explicit procedures to grab info neatly...
cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, entry: ^Entry, bounds_0, bounds_1: Vec2, scale, translate: Vec2) -> b32 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 : ^DrawList, outside_point : Vec2, path : []Vertex, draw_filled_path_freetype :: proc( draw_list : ^Draw_List, outside_point : Vec2, path : []Vertex,
scale := Vec2 { 1, 1 }, scale := Vec2 { 1, 1 },
translate := Vec2 { 0, 0 }, translate := Vec2 { 0, 0 },
debug_print_verbose : b32 = false debug_print_verbose : b32 = false
@@ -158,8 +158,8 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en
return false return false
} }
draw := DrawCall_Default draw := Draw_Call_Default
draw.pass = FrameBufferPass.Glyph draw.pass = Frame_Buffer_Pass.Glyph
draw.start_index = cast(u32) len(ctx.draw_list.indices) draw.start_index = cast(u32) len(ctx.draw_list.indices)
contours := slice.from_ptr(cast( [^]i16) outline.contours, int(outline.n_contours)) contours := slice.from_ptr(cast( [^]i16) outline.contours, int(outline.n_contours))
@@ -244,7 +244,7 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en
} }
// TODO(Ed): Is it better to cache the glyph vertices for when it must be re-drawn (directly or two atlas)? // TODO(Ed): Is it better to cache the glyph vertices for when it must be re-drawn (directly or two atlas)?
cache_glyph :: proc(ctx : ^Context, font : FontID, glyph_index : Glyph, entry : ^Entry, bounds_0, bounds_1 : Vec2, scale, translate : Vec2) -> b32 cache_glyph :: proc(ctx : ^Context, font : Font_ID, glyph_index : Glyph, entry : ^Entry, bounds_0, bounds_1 : Vec2, scale, translate : Vec2) -> b32
{ {
// profile(#procedure) // profile(#procedure)
if glyph_index == Glyph(0) { if glyph_index == Glyph(0) {
@@ -265,8 +265,8 @@ cache_glyph :: proc(ctx : ^Context, font : FontID, glyph_index : Glyph, entry :
outside := Vec2{bounds_0.x - 21, bounds_0.y - 33} outside := Vec2{bounds_0.x - 21, bounds_0.y - 33}
draw := DrawCall_Default draw := Draw_Call_Default
draw.pass = FrameBufferPass.Glyph draw.pass = Frame_Buffer_Pass.Glyph
draw.start_index = u32(len(ctx.draw_list.indices)) draw.start_index = u32(len(ctx.draw_list.indices))
path := &ctx.temp_path path := &ctx.temp_path
@@ -329,13 +329,13 @@ cache_glyph :: proc(ctx : ^Context, font : FontID, glyph_index : Glyph, entry :
* draw_text_shape : Glyph * draw_text_shape : Glyph
*/ */
cache_glyph_to_atlas :: proc( ctx : ^Context, cache_glyph_to_atlas :: proc( ctx : ^Context,
font : FontID, font : Font_ID,
glyph_index : Glyph, glyph_index : Glyph,
lru_code : u64, lru_code : u64,
atlas_index : i32, atlas_index : i32,
entry : ^Entry, entry : ^Entry,
region_kind : AtlasRegionKind, region_kind : Atlas_Region_Kind,
region : ^AtlasRegion, region : ^Atlas_Region,
over_sample : Vec2 ) over_sample : Vec2 )
{ {
// profile(#procedure) // profile(#procedure)
@@ -356,24 +356,24 @@ cache_glyph_to_atlas :: proc( ctx : ^Context,
{ {
if region.next_idx < region.state.capacity if region.next_idx < region.state.capacity
{ {
evicted := LRU_put( & region.state, lru_code, i32(region.next_idx) ) evicted := lru_put( & region.state, lru_code, i32(region.next_idx) )
atlas_index = i32(region.next_idx) atlas_index = i32(region.next_idx)
region.next_idx += 1 region.next_idx += 1
assert( evicted == lru_code ) assert( evicted == lru_code )
} }
else else
{ {
next_evict_codepoint := LRU_get_next_evicted( & region.state ) next_evict_codepoint := lru_get_next_evicted( & region.state )
assert( next_evict_codepoint != 0xFFFFFFFFFFFFFFFF ) assert( next_evict_codepoint != 0xFFFFFFFFFFFFFFFF )
atlas_index = LRU_peek( & region.state, next_evict_codepoint, must_find = true ) atlas_index = lru_peek( & region.state, next_evict_codepoint, must_find = true )
assert( atlas_index != -1 ) assert( atlas_index != -1 )
evicted := LRU_put( & region.state, lru_code, atlas_index ) evicted := lru_put( & region.state, lru_code, atlas_index )
assert( evicted == next_evict_codepoint ) assert( evicted == next_evict_codepoint )
} }
assert( LRU_get( & region.state, lru_code ) != - 1 ) assert( lru_get( & region.state, lru_code ) != - 1 )
} }
atlas := & ctx.atlas atlas := & ctx.atlas
@@ -420,7 +420,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context,
glyph_buffer.batch_x += i32(gwidth_scaled_px) glyph_buffer.batch_x += i32(gwidth_scaled_px)
screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_size ) screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_size )
clear_target_region : DrawCall clear_target_region : Draw_Call
{ {
using clear_target_region using clear_target_region
pass = .Atlas pass = .Atlas
@@ -434,7 +434,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context,
end_index = cast(u32) len(glyph_buffer.clear_draw_list.indices) end_index = cast(u32) len(glyph_buffer.clear_draw_list.indices)
} }
blit_to_atlas : DrawCall blit_to_atlas : Draw_Call
{ {
using blit_to_atlas using blit_to_atlas
pass = .Atlas pass = .Atlas
@@ -456,11 +456,11 @@ cache_glyph_to_atlas :: proc( ctx : ^Context,
} }
// If the glyuph is found in the atlas, nothing occurs, otherwise, the glyph call is setup to catch it to the atlas // If the glyuph is found in the atlas, nothing occurs, otherwise, the glyph call is setup to catch it to the atlas
check_glyph_in_atlas :: #force_inline proc( ctx : ^Context, font : FontID, entry : ^Entry, glyph_index : Glyph, check_glyph_in_atlas :: #force_inline proc( ctx : ^Context, font : Font_ID, entry : ^Entry, glyph_index : Glyph,
lru_code : u64, lru_code : u64,
atlas_index : i32, atlas_index : i32,
region_kind : AtlasRegionKind, region_kind : Atlas_Region_Kind,
region : ^AtlasRegion, region : ^Atlas_Region,
over_sample : Vec2 over_sample : Vec2
) -> b32 ) -> b32
{ {
@@ -476,7 +476,7 @@ check_glyph_in_atlas :: #force_inline proc( ctx : ^Context, font : FontID, entry
{ {
if region.next_idx > region.state.capacity { 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. // 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 ) next_evict_codepoint := lru_get_next_evicted( & region.state )
seen, success := ctx.temp_codepoint_seen[next_evict_codepoint] seen, success := ctx.temp_codepoint_seen[next_evict_codepoint]
assert(success != false) assert(success != false)
@@ -488,13 +488,13 @@ check_glyph_in_atlas :: #force_inline proc( ctx : ^Context, font : FontID, entry
cache_glyph_to_atlas( ctx, font, glyph_index, lru_code, atlas_index, entry, region_kind, region, over_sample ) cache_glyph_to_atlas( ctx, font, glyph_index, lru_code, atlas_index, entry, region_kind, region, over_sample )
} }
assert( LRU_get( & region.state, lru_code ) != -1 ) assert( lru_get( & region.state, lru_code ) != -1 )
mark_batch_codepoint_seen( ctx, lru_code) mark_batch_codepoint_seen( ctx, lru_code)
return true return true
} }
// ve_fontcache_clear_drawlist // ve_fontcache_clear_Draw_List
clear_draw_list :: #force_inline proc ( draw_list : ^DrawList ) { clear_draw_list :: #force_inline proc ( draw_list : ^Draw_List ) {
clear( & draw_list.calls ) clear( & draw_list.calls )
clear( & draw_list.indices ) clear( & draw_list.indices )
clear( & draw_list.vertices ) clear( & draw_list.vertices )
@@ -538,8 +538,8 @@ directly_draw_massive_glyph :: proc( ctx : ^Context,
dst_size := glyph_dst_size * scale dst_size := glyph_dst_size * scale
textspace_x_form( & glyph_position, & glyph_size, glyph_buffer_size ) textspace_x_form( & glyph_position, & glyph_size, glyph_buffer_size )
// Add the glyph drawcall. // Add the glyph Draw_Call.
calls : [2]DrawCall calls : [2]Draw_Call
draw_to_target := & calls[0] draw_to_target := & calls[0]
{ {
@@ -570,9 +570,9 @@ directly_draw_massive_glyph :: proc( ctx : ^Context,
// outside_point represents the center point of the fan. // outside_point represents the center point of the fan.
// //
// Note(Original Author): // Note(Original Author):
// WARNING: doesn't actually append drawcall; caller is responsible for actually appending the drawcall. // WARNING: doesn't actually append Draw_Call; caller is responsible for actually appending the Draw_Call.
// ve_fontcache_draw_filled_path // ve_fontcache_draw_filled_path
draw_filled_path :: proc( draw_list : ^DrawList, outside_point : Vec2, path : []Vertex, draw_filled_path :: proc( draw_list : ^Draw_List, outside_point : Vec2, path : []Vertex,
scale := Vec2 { 1, 1 }, scale := Vec2 { 1, 1 },
translate := Vec2 { 0, 0 }, translate := Vec2 { 0, 0 },
debug_print_verbose : b32 = false debug_print_verbose : b32 = false
@@ -615,7 +615,7 @@ draw_filled_path :: proc( draw_list : ^DrawList, outside_point : Vec2, path : []
} }
} }
draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^ShapedText, draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^Shaped_Text,
batch_start_idx, batch_end_idx : i32, batch_start_idx, batch_end_idx : i32,
position, scale : Vec2, position, scale : Vec2,
snap_width, snap_height : f32 ) snap_width, snap_height : f32 )
@@ -634,7 +634,7 @@ draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^ShapedText,
region_kind, region, over_sample := decide_codepoint_region( ctx, entry, glyph_index ) region_kind, region, over_sample := decide_codepoint_region( ctx, entry, glyph_index )
lru_code := font_glyph_lru_code( entry.id, glyph_index ) lru_code := font_glyph_lru_code( entry.id, glyph_index )
atlas_index := region_kind != .E ? LRU_get( & region.state, lru_code ) : -1 atlas_index := region_kind != .E ? lru_get( & region.state, lru_code ) : -1
bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index )
vbounds_0 := vec2(bounds_0) vbounds_0 := vec2(bounds_0)
vbounds_1 := vec2(bounds_1) vbounds_1 := vec2(bounds_1)
@@ -660,7 +660,7 @@ draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^ShapedText,
dst_scale := glyph_scale * scale dst_scale := glyph_scale * scale
textspace_x_form( & slot_position, & glyph_scale, atlas_size ) textspace_x_form( & slot_position, & glyph_scale, atlas_size )
call := DrawCall_Default call := Draw_Call_Default
call.pass = .Target call.pass = .Target
call.colour = ctx.colour call.colour = ctx.colour
call.start_index = u32(len(ctx.draw_list.indices)) call.start_index = u32(len(ctx.draw_list.indices))
@@ -677,9 +677,9 @@ draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^ShapedText,
// Helper for draw_text, all raw text content should be confirmed to be either formatting or visible shapes before getting cached. // Helper for draw_text, all raw text content should be confirmed to be either formatting or visible shapes before getting cached.
draw_text_shape :: proc( ctx : ^Context, draw_text_shape :: proc( ctx : ^Context,
font : FontID, font : Font_ID,
entry : ^Entry, entry : ^Entry,
shaped : ^ShapedText, shaped : ^Shaped_Text,
position, scale : Vec2, position, scale : Vec2,
snap_width, snap_height : f32 snap_width, snap_height : f32
) -> (cursor_pos : Vec2) ) -> (cursor_pos : Vec2)
@@ -695,7 +695,7 @@ draw_text_shape :: proc( ctx : ^Context,
lru_code := font_glyph_lru_code(entry.id, glyph_index) lru_code := font_glyph_lru_code(entry.id, glyph_index)
atlas_index := cast(i32) -1 atlas_index := cast(i32) -1
if region_kind != .E do atlas_index = LRU_get( & region.state, lru_code ) if region_kind != .E do atlas_index = lru_get( & region.state, lru_code )
if check_glyph_in_atlas( ctx, font, entry, glyph_index, lru_code, atlas_index, region_kind, region, over_sample ) do continue if check_glyph_in_atlas( ctx, font, entry, glyph_index, lru_code, atlas_index, region_kind, region, over_sample ) do continue
// We can no longer directly append the shape as it has missing glyphs in the atlas // We can no longer directly append the shape as it has missing glyphs in the atlas
@@ -720,7 +720,7 @@ draw_text_shape :: proc( ctx : ^Context,
flush_glyph_buffer_to_atlas :: proc( ctx : ^Context ) flush_glyph_buffer_to_atlas :: proc( ctx : ^Context )
{ {
// profile(#procedure) // profile(#procedure)
// Flush drawcalls to draw list // Flush Draw_Calls to draw list
merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.clear_draw_list ) merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.clear_draw_list )
merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.draw_list) merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.draw_list)
clear_draw_list( & ctx.glyph_buffer.draw_list ) clear_draw_list( & ctx.glyph_buffer.draw_list )
@@ -729,7 +729,7 @@ flush_glyph_buffer_to_atlas :: proc( ctx : ^Context )
// Clear glyph_update_FBO // Clear glyph_update_FBO
if ctx.glyph_buffer.batch_x != 0 if ctx.glyph_buffer.batch_x != 0
{ {
call := DrawCall_Default call := Draw_Call_Default
call.pass = .Glyph call.pass = .Glyph
call.start_index = 0 call.start_index = 0
call.end_index = 0 call.end_index = 0
@@ -739,11 +739,11 @@ flush_glyph_buffer_to_atlas :: proc( ctx : ^Context )
} }
} }
// ve_fontcache_merge_drawlist // ve_fontcache_merge_Draw_List
merge_draw_list :: proc( dst, src : ^DrawList ) merge_draw_list :: proc( dst, src : ^Draw_List )
{ {
// profile(#procedure) // profile(#procedure)
error : AllocatorError error : Allocator_Error
v_offset := cast(u32) len( dst.vertices ) v_offset := cast(u32) len( dst.vertices )
num_appended : int num_appended : int
@@ -766,11 +766,11 @@ merge_draw_list :: proc( dst, src : ^DrawList )
} }
} }
optimize_draw_list :: proc(draw_list: ^DrawList, call_offset: int) { optimize_draw_list :: proc(draw_list: ^Draw_List, call_offset: int) {
// profile(#procedure) // profile(#procedure)
assert(draw_list != nil) assert(draw_list != nil)
can_merge_draw_calls :: #force_inline proc "contextless" ( a, b : ^DrawCall ) -> bool { can_merge_draw_calls :: #force_inline proc "contextless" ( a, b : ^Draw_Call ) -> bool {
result := \ result := \
a.pass == b.pass && a.pass == b.pass &&
a.end_index == b.start_index && a.end_index == b.start_index &&

View File

@@ -28,7 +28,7 @@ import "core:mem"
slice_ptr :: mem.slice_ptr slice_ptr :: mem.slice_ptr
Allocator :: mem.Allocator Allocator :: mem.Allocator
AllocatorError :: mem.Allocator_Error Allocator_Error :: mem.Allocator_Error
Arena :: mem.Arena Arena :: mem.Arena
arena_allocator :: mem.arena_allocator arena_allocator :: mem.arena_allocator

View File

@@ -49,7 +49,7 @@ reload_map :: proc( self : ^map [$KeyType] $EntryType, allocator : Allocator ) {
raw.allocator = allocator raw.allocator = allocator
} }
font_glyph_lru_code :: #force_inline proc "contextless" ( font : FontID, glyph_index : Glyph ) -> (lru_code : u64) { font_glyph_lru_code :: #force_inline proc "contextless" ( font : Font_ID, glyph_index : Glyph ) -> (lru_code : u64) {
lru_code = u64(glyph_index) + ( ( 0x100000000 * u64(font) ) & 0xFFFFFFFF00000000 ) lru_code = u64(glyph_index) + ( ( 0x100000000 * u64(font) ) & 0xFFFFFFFF00000000 )
return return
} }
@@ -71,9 +71,11 @@ reset_batch_codepoint_state :: #force_inline proc( ctx : ^Context ) {
ctx.temp_codepoint_seen_num = 0 ctx.temp_codepoint_seen_num = 0
} }
USE_F64_PRECISION_ON_X_FORM_OPS :: false
screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 ) screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 )
{ {
if true when USE_F64_PRECISION_ON_X_FORM_OPS
{ {
pos_64 := vec2_64_from_vec2(position^) pos_64 := vec2_64_from_vec2(position^)
scale_64 := vec2_64_from_vec2(scale^) scale_64 := vec2_64_from_vec2(scale^)
@@ -101,7 +103,7 @@ screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2
textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 ) textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 )
{ {
if true when USE_F64_PRECISION_ON_X_FORM_OPS
{ {
pos_64 := vec2_64_from_vec2(position^) pos_64 := vec2_64_from_vec2(position^)
scale_64 := vec2_64_from_vec2(scale^) scale_64 := vec2_64_from_vec2(scale^)
@@ -121,9 +123,9 @@ textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2,
} }
} }
Use_SIMD_For_Bezier_Ops :: false USE_MANUAL_SIMD_FOR_BEZIER_OPS :: false
when ! Use_SIMD_For_Bezier_Ops when ! USE_MANUAL_SIMD_FOR_BEZIER_OPS
{ {
// For a provided alpha value, // For a provided alpha value,
// allows the function to calculate the position of a point along the curve at any given fraction of its total length // allows the function to calculate the position of a point along the curve at any given fraction of its total length

View File

@@ -16,14 +16,14 @@ import "core:slice"
import stbtt "vendor:stb/truetype" import stbtt "vendor:stb/truetype"
import freetype "thirdparty:freetype" import freetype "thirdparty:freetype"
ParserKind :: enum u32 { Parser_Kind :: enum u32 {
STB_TrueType, STB_TrueType,
Freetype, Freetype,
} }
ParserFontInfo :: struct { Parser_Font_Info :: struct {
label : string, label : string,
kind : ParserKind, kind : Parser_Kind,
using _ : struct #raw_union { using _ : struct #raw_union {
stbtt_info : stbtt.fontinfo, stbtt_info : stbtt.fontinfo,
freetype_info : freetype.Face freetype_info : freetype.Face
@@ -31,7 +31,7 @@ ParserFontInfo :: struct {
data : []byte, data : []byte,
} }
GlyphVertType :: enum u8 { Glyph_Vert_Type :: enum u8 {
None, None,
Move = 1, Move = 1,
Line, Line,
@@ -40,22 +40,22 @@ GlyphVertType :: enum u8 {
} }
// Based directly off of stb_truetype's vertex // Based directly off of stb_truetype's vertex
ParserGlyphVertex :: struct { Parser_Glyph_Vertex :: struct {
x, y : i16, x, y : i16,
contour_x0, contour_y0 : i16, contour_x0, contour_y0 : i16,
contour_x1, contour_y1 : i16, contour_x1, contour_y1 : i16,
type : GlyphVertType, type : Glyph_Vert_Type,
padding : u8, padding : u8,
} }
// A shape can be a dynamic array free_type or an opaque set of data handled by stb_truetype // A shape can be a dynamic array free_type or an opaque set of data handled by stb_truetype
ParserGlyphShape :: [dynamic]ParserGlyphVertex Parser_Glyph_Shape :: [dynamic]Parser_Glyph_Vertex
ParserContext :: struct { Parser_Context :: struct {
kind : ParserKind, kind : Parser_Kind,
ft_library : freetype.Library, ft_library : freetype.Library,
} }
parser_init :: proc( ctx : ^ParserContext, kind : ParserKind ) parser_init :: proc( ctx : ^Parser_Context, kind : Parser_Kind )
{ {
switch kind switch kind
{ {
@@ -70,11 +70,11 @@ parser_init :: proc( ctx : ^ParserContext, kind : ParserKind )
ctx.kind = kind ctx.kind = kind
} }
parser_shutdown :: proc( ctx : ^ParserContext ) { parser_shutdown :: proc( ctx : ^Parser_Context ) {
// TODO(Ed): Implement // TODO(Ed): Implement
} }
parser_load_font :: proc( ctx : ^ParserContext, label : string, data : []byte ) -> (font : ParserFontInfo) parser_load_font :: proc( ctx : ^Parser_Context, label : string, data : []byte ) -> (font : Parser_Font_Info)
{ {
switch ctx.kind switch ctx.kind
{ {
@@ -93,7 +93,7 @@ parser_load_font :: proc( ctx : ^ParserContext, label : string, data : []byte )
return return
} }
parser_unload_font :: proc( font : ^ParserFontInfo ) parser_unload_font :: proc( font : ^Parser_Font_Info )
{ {
switch font.kind { switch font.kind {
case .Freetype: case .Freetype:
@@ -105,7 +105,7 @@ parser_unload_font :: proc( font : ^ParserFontInfo )
} }
} }
parser_find_glyph_index :: #force_inline proc "contextless" ( font : ^ParserFontInfo, codepoint : rune ) -> (glyph_index : Glyph) parser_find_glyph_index :: #force_inline proc "contextless" ( font : ^Parser_Font_Info, codepoint : rune ) -> (glyph_index : Glyph)
{ {
switch font.kind switch font.kind
{ {
@@ -120,7 +120,7 @@ parser_find_glyph_index :: #force_inline proc "contextless" ( font : ^ParserFont
return Glyph(-1) return Glyph(-1)
} }
parser_free_shape :: proc( font : ^ParserFontInfo, shape : ParserGlyphShape ) parser_free_shape :: proc( font : ^Parser_Font_Info, shape : Parser_Glyph_Shape )
{ {
switch font.kind switch font.kind
{ {
@@ -132,7 +132,7 @@ parser_free_shape :: proc( font : ^ParserFontInfo, shape : ParserGlyphShape )
} }
} }
parser_get_codepoint_horizontal_metrics :: #force_inline proc "contextless" ( font : ^ParserFontInfo, codepoint : rune ) -> ( advance, to_left_side_glyph : i32 ) parser_get_codepoint_horizontal_metrics :: #force_inline proc "contextless" ( font : ^Parser_Font_Info, codepoint : rune ) -> ( advance, to_left_side_glyph : i32 )
{ {
switch font.kind switch font.kind
{ {
@@ -156,7 +156,7 @@ parser_get_codepoint_horizontal_metrics :: #force_inline proc "contextless" ( fo
return return
} }
parser_get_codepoint_kern_advance :: #force_inline proc "contextless" ( font : ^ParserFontInfo, prev_codepoint, codepoint : rune ) -> i32 parser_get_codepoint_kern_advance :: #force_inline proc "contextless" ( font : ^Parser_Font_Info, prev_codepoint, codepoint : rune ) -> i32
{ {
switch font.kind switch font.kind
{ {
@@ -176,7 +176,7 @@ parser_get_codepoint_kern_advance :: #force_inline proc "contextless" ( font : ^
return -1 return -1
} }
parser_get_font_vertical_metrics :: #force_inline proc "contextless" ( font : ^ParserFontInfo ) -> (ascent, descent, line_gap : i32 ) parser_get_font_vertical_metrics :: #force_inline proc "contextless" ( font : ^Parser_Font_Info ) -> (ascent, descent, line_gap : i32 )
{ {
switch font.kind switch font.kind
{ {
@@ -192,7 +192,7 @@ parser_get_font_vertical_metrics :: #force_inline proc "contextless" ( font : ^P
return return
} }
parser_get_glyph_box :: #force_inline proc ( font : ^ParserFontInfo, glyph_index : Glyph ) -> (bounds_0, bounds_1 : Vec2i) parser_get_glyph_box :: #force_inline proc ( font : ^Parser_Font_Info, glyph_index : Glyph ) -> (bounds_0, bounds_1 : Vec2i)
{ {
switch font.kind switch font.kind
{ {
@@ -215,7 +215,7 @@ parser_get_glyph_box :: #force_inline proc ( font : ^ParserFontInfo, glyph_index
return return
} }
parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) -> (shape : ParserGlyphShape, error : AllocatorError) parser_get_glyph_shape :: proc( font : ^Parser_Font_Info, glyph_index : Glyph ) -> (shape : Parser_Glyph_Shape, error : Allocator_Error)
{ {
switch font.kind switch font.kind
{ {
@@ -232,14 +232,14 @@ parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) ->
shape_raw.len = int(nverts) shape_raw.len = int(nverts)
shape_raw.cap = int(nverts) shape_raw.cap = int(nverts)
shape_raw.allocator = runtime.nil_allocator() shape_raw.allocator = runtime.nil_allocator()
error = AllocatorError.None error = Allocator_Error.None
return return
} }
return return
} }
parser_is_glyph_empty :: #force_inline proc "contextless" ( font : ^ParserFontInfo, glyph_index : Glyph ) -> b32 parser_is_glyph_empty :: #force_inline proc "contextless" ( font : ^Parser_Font_Info, glyph_index : Glyph ) -> b32
{ {
switch font.kind switch font.kind
{ {
@@ -262,7 +262,7 @@ parser_is_glyph_empty :: #force_inline proc "contextless" ( font : ^ParserFontIn
return false return false
} }
parser_scale :: #force_inline proc "contextless" ( font : ^ParserFontInfo, size : f32 ) -> f32 parser_scale :: #force_inline proc "contextless" ( font : ^Parser_Font_Info, size : f32 ) -> f32
{ {
size_scale := size < 0.0 ? \ size_scale := size < 0.0 ? \
parser_scale_for_pixel_height( font, -size ) \ parser_scale_for_pixel_height( font, -size ) \
@@ -271,7 +271,7 @@ parser_scale :: #force_inline proc "contextless" ( font : ^ParserFontInfo, size
return size_scale return size_scale
} }
parser_scale_for_pixel_height :: #force_inline proc "contextless" ( font : ^ParserFontInfo, size : f32 ) -> f32 parser_scale_for_pixel_height :: #force_inline proc "contextless" ( font : ^Parser_Font_Info, size : f32 ) -> f32
{ {
switch font.kind { switch font.kind {
case .Freetype: case .Freetype:
@@ -285,7 +285,7 @@ parser_scale_for_pixel_height :: #force_inline proc "contextless" ( font : ^Pars
return 0 return 0
} }
parser_scale_for_mapping_em_to_pixels :: #force_inline proc "contextless" ( font : ^ParserFontInfo, size : f32 ) -> f32 parser_scale_for_mapping_em_to_pixels :: #force_inline proc "contextless" ( font : ^Parser_Font_Info, size : f32 ) -> f32
{ {
switch font.kind { switch font.kind {
case .Freetype: case .Freetype:

View File

@@ -1,14 +1,14 @@
package vefontcache package vefontcache
ShapedText :: struct { Shaped_Text :: struct {
glyphs : [dynamic]Glyph, glyphs : [dynamic]Glyph,
positions : [dynamic]Vec2, positions : [dynamic]Vec2,
end_cursor_pos : Vec2, end_cursor_pos : Vec2,
size : Vec2, size : Vec2,
} }
ShapedTextCache :: struct { Shaped_Text_Cache :: struct {
storage : [dynamic]ShapedText, storage : [dynamic]Shaped_Text,
state : LRU_Cache, state : LRU_Cache,
next_cache_id : i32, next_cache_id : i32,
} }
@@ -19,11 +19,11 @@ shape_lru_hash :: #force_inline proc "contextless" ( hash : ^u64, bytes : []byte
} }
} }
shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, entry : ^Entry ) -> ^ShapedText shape_text_cached :: proc( ctx : ^Context, font : Font_ID, text_utf8 : string, entry : ^Entry ) -> ^Shaped_Text
{ {
// profile(#procedure) // profile(#procedure)
font := font font := font
font_bytes := slice_ptr( transmute(^byte) & font, size_of(FontID) ) font_bytes := slice_ptr( transmute(^byte) & font, size_of(Font_ID) )
text_bytes := transmute( []byte) text_utf8 text_bytes := transmute( []byte) text_utf8
lru_code : u64 lru_code : u64
@@ -33,23 +33,23 @@ shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, en
shape_cache := & ctx.shape_cache shape_cache := & ctx.shape_cache
state := & ctx.shape_cache.state state := & ctx.shape_cache.state
shape_cache_idx := LRU_get( state, lru_code ) shape_cache_idx := lru_get( state, lru_code )
if shape_cache_idx == -1 if shape_cache_idx == -1
{ {
if shape_cache.next_cache_id < i32(state.capacity) { if shape_cache.next_cache_id < i32(state.capacity) {
shape_cache_idx = shape_cache.next_cache_id shape_cache_idx = shape_cache.next_cache_id
shape_cache.next_cache_id += 1 shape_cache.next_cache_id += 1
evicted := LRU_put( state, lru_code, shape_cache_idx ) evicted := lru_put( state, lru_code, shape_cache_idx )
} }
else else
{ {
next_evict_idx := LRU_get_next_evicted( state ) next_evict_idx := lru_get_next_evicted( state )
assert( next_evict_idx != 0xFFFFFFFFFFFFFFFF ) assert( next_evict_idx != 0xFFFFFFFFFFFFFFFF )
shape_cache_idx = LRU_peek( state, next_evict_idx, must_find = true ) shape_cache_idx = lru_peek( state, next_evict_idx, must_find = true )
assert( shape_cache_idx != - 1 ) assert( shape_cache_idx != - 1 )
LRU_put( state, lru_code, shape_cache_idx ) lru_put( state, lru_code, shape_cache_idx )
} }
shape_entry := & shape_cache.storage[ shape_cache_idx ] shape_entry := & shape_cache.storage[ shape_cache_idx ]
@@ -59,7 +59,7 @@ shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, en
return & shape_cache.storage[ shape_cache_idx ] return & shape_cache.storage[ shape_cache_idx ]
} }
shape_text_uncached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, entry : ^Entry, output : ^ShapedText ) shape_text_uncached :: proc( ctx : ^Context, font : Font_ID, text_utf8 : string, entry : ^Entry, output : ^Shaped_Text )
{ {
// profile(#procedure) // profile(#procedure)
assert( ctx != nil ) assert( ctx != nil )
@@ -106,7 +106,7 @@ shape_text_uncached :: proc( ctx : ^Context, font : FontID, text_utf8 : string,
prev_codepoint = rune(0) prev_codepoint = rune(0)
continue continue
} }
if abs( entry.size ) <= Advance_Snap_Smallfont_Size { if abs( entry.size ) <= ADVANCE_SNAP_SMALLFONT_SIZE {
position.x = position.x position.x = position.x
} }

View File

@@ -6,35 +6,35 @@ Note(Ed): The only reason I didn't directly use harfbuzz is because hamza exists
import "core:c" import "core:c"
import "thirdparty:harfbuzz" import "thirdparty:harfbuzz"
ShaperKind :: enum { Shaper_Kind :: enum {
Naive = 0, Naive = 0,
Harfbuzz = 1, Harfbuzz = 1,
} }
ShaperContext :: struct { Shaper_Context :: struct {
hb_buffer : harfbuzz.Buffer, hb_buffer : harfbuzz.Buffer,
} }
ShaperInfo :: struct { Shaper_Info :: struct {
blob : harfbuzz.Blob, blob : harfbuzz.Blob,
face : harfbuzz.Face, face : harfbuzz.Face,
font : harfbuzz.Font, font : harfbuzz.Font,
} }
shaper_init :: proc( ctx : ^ShaperContext ) shaper_init :: proc( ctx : ^Shaper_Context )
{ {
ctx.hb_buffer = harfbuzz.buffer_create() ctx.hb_buffer = harfbuzz.buffer_create()
assert( ctx.hb_buffer != nil, "VEFontCache.shaper_init: Failed to create harfbuzz buffer") assert( ctx.hb_buffer != nil, "VEFontCache.shaper_init: Failed to create harfbuzz buffer")
} }
shaper_shutdown :: proc( ctx : ^ShaperContext ) shaper_shutdown :: proc( ctx : ^Shaper_Context )
{ {
if ctx.hb_buffer != nil { if ctx.hb_buffer != nil {
harfbuzz.buffer_destroy( ctx.hb_buffer ) harfbuzz.buffer_destroy( ctx.hb_buffer )
} }
} }
shaper_load_font :: proc( ctx : ^ShaperContext, label : string, data : []byte, user_data : rawptr ) -> (info : ShaperInfo) shaper_load_font :: proc( ctx : ^Shaper_Context, label : string, data : []byte, user_data : rawptr ) -> (info : Shaper_Info)
{ {
using info using info
blob = harfbuzz.blob_create( raw_data(data), cast(c.uint) len(data), harfbuzz.Memory_Mode.READONLY, user_data, nil ) blob = harfbuzz.blob_create( raw_data(data), cast(c.uint) len(data), harfbuzz.Memory_Mode.READONLY, user_data, nil )
@@ -43,7 +43,7 @@ shaper_load_font :: proc( ctx : ^ShaperContext, label : string, data : []byte, u
return return
} }
shaper_unload_font :: proc( ctx : ^ShaperInfo ) shaper_unload_font :: proc( ctx : ^Shaper_Info )
{ {
using ctx using ctx
if blob != nil do harfbuzz.font_destroy( font ) if blob != nil do harfbuzz.font_destroy( font )
@@ -51,7 +51,7 @@ shaper_unload_font :: proc( ctx : ^ShaperInfo )
if blob != nil do harfbuzz.blob_destroy( blob ) if blob != nil do harfbuzz.blob_destroy( blob )
} }
shaper_shape_from_text :: proc( ctx : ^ShaperContext, info : ^ShaperInfo, output :^ShapedText, text_utf8 : string, shaper_shape_from_text :: proc( ctx : ^Shaper_Context, info : ^Shaper_Info, output :^Shaped_Text, text_utf8 : string,
ascent, descent, line_gap : i32, size, size_scale : f32 ) ascent, descent, line_gap : i32, size, size_scale : f32 )
{ {
// profile(#procedure) // profile(#procedure)
@@ -69,7 +69,7 @@ shaper_shape_from_text :: proc( ctx : ^ShaperContext, info : ^ShaperInfo, output
line_height := (ascent - descent + line_gap) * size_scale line_height := (ascent - descent + line_gap) * size_scale
position, vertical_position : f32 position, vertical_position : f32
shape_run :: proc( buffer : harfbuzz.Buffer, script : harfbuzz.Script, font : harfbuzz.Font, output : ^ShapedText, shape_run :: proc( buffer : harfbuzz.Buffer, script : harfbuzz.Script, font : harfbuzz.Font, output : ^Shaped_Text,
position, vertical_position, max_line_width: ^f32, line_count: ^int, position, vertical_position, max_line_width: ^f32, line_count: ^int,
ascent, descent, line_gap, size, size_scale: f32 ) ascent, descent, line_gap, size, size_scale: f32 )
{ {
@@ -105,7 +105,7 @@ shaper_shape_from_text :: proc( ctx : ^ShaperContext, info : ^ShaperInfo, output
(line_count^) += 1 (line_count^) += 1
continue continue
} }
if abs( size ) <= Advance_Snap_Smallfont_Size if abs( size ) <= ADVANCE_SNAP_SMALLFONT_SIZE
{ {
(position^) = ceil( position^ ) (position^) = ceil( position^ )
} }

View File

@@ -7,15 +7,15 @@ package vefontcache
import "base:runtime" import "base:runtime"
Advance_Snap_Smallfont_Size :: 0 ADVANCE_SNAP_SMALLFONT_SIZE :: 0
FontID :: distinct i64 Font_ID :: distinct i64
Glyph :: distinct i32 Glyph :: distinct i32
Entry :: struct { Entry :: struct {
parser_info : ParserFontInfo, parser_info : Parser_Font_Info,
shaper_info : ShaperInfo, shaper_info : Shaper_Info,
id : FontID, id : Font_ID,
used : b32, used : b32,
curve_quality : f32, curve_quality : f32,
size : f32, size : f32,
@@ -32,8 +32,8 @@ Entry_Default :: Entry {
Context :: struct { Context :: struct {
backing : Allocator, backing : Allocator,
parser_ctx : ParserContext, parser_ctx : Parser_Context,
shaper_ctx : ShaperContext, shaper_ctx : Shaper_Context,
entries : [dynamic]Entry, entries : [dynamic]Entry,
@@ -54,10 +54,10 @@ Context :: struct {
calls_offset : int, calls_offset : int,
}, },
draw_list : DrawList, draw_list : Draw_List,
atlas : Atlas, atlas : Atlas,
glyph_buffer : GlyphDrawBuffer, glyph_buffer : Glyph_Draw_Buffer,
shape_cache : ShapedTextCache, shape_cache : Shaped_Text_Cache,
default_curve_quality : i32, default_curve_quality : i32,
text_shape_adv : b32, text_shape_adv : b32,
@@ -69,23 +69,23 @@ Context :: struct {
//#region("lifetime") //#region("lifetime")
InitAtlasRegionParams :: struct { Init_Atlas_Region_Params :: struct {
width : u32, width : u32,
height : u32, height : u32,
} }
InitAtlasParams :: struct { Init_Atlas_Params :: struct {
width : u32, width : u32,
height : u32, height : u32,
glyph_padding : u32, glyph_padding : u32,
region_a : InitAtlasRegionParams, region_a : Init_Atlas_Region_Params,
region_b : InitAtlasRegionParams, region_b : Init_Atlas_Region_Params,
region_c : InitAtlasRegionParams, region_c : Init_Atlas_Region_Params,
region_d : InitAtlasRegionParams, region_d : Init_Atlas_Region_Params,
} }
InitAtlasParams_Default :: InitAtlasParams { Init_Atlas_Params_Default :: Init_Atlas_Params {
width = 4096, width = 4096,
height = 2048, height = 2048,
glyph_padding = 4, glyph_padding = 4,
@@ -108,34 +108,34 @@ InitAtlasParams_Default :: InitAtlasParams {
} }
} }
InitGlyphDrawParams :: struct { Init_Glyph_Draw_Params :: struct {
over_sample : Vec2i, over_sample : Vec2i,
buffer_batch : u32, buffer_batch : u32,
draw_padding : u32, draw_padding : u32,
} }
InitGlyphDrawParams_Default :: InitGlyphDrawParams { Init_Glyph_Draw_Params_Default :: Init_Glyph_Draw_Params {
over_sample = { 8, 8 }, over_sample = { 8, 8 },
buffer_batch = 4, buffer_batch = 4,
draw_padding = InitAtlasParams_Default.glyph_padding, draw_padding = Init_Atlas_Params_Default.glyph_padding,
} }
InitShapeCacheParams :: struct { Init_Shape_Cache_Params :: struct {
capacity : u32, capacity : u32,
reserve_length : u32, reserve_length : u32,
} }
InitShapeCacheParams_Default :: InitShapeCacheParams { Init_Shape_Cache_Params_Default :: Init_Shape_Cache_Params {
capacity = 8 * 1024, capacity = 8 * 1024,
reserve_length = 256, reserve_length = 256,
} }
// ve_fontcache_init // ve_fontcache_init
startup :: proc( ctx : ^Context, parser_kind : ParserKind, startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
allocator := context.allocator, allocator := context.allocator,
atlas_params := InitAtlasParams_Default, atlas_params := Init_Atlas_Params_Default,
glyph_draw_params := InitGlyphDrawParams_Default, glyph_draw_params := Init_Glyph_Draw_Params_Default,
shape_cache_params := InitShapeCacheParams_Default, shape_cache_params := Init_Shape_Cache_Params_Default,
use_advanced_text_shaper : b32 = true, use_advanced_text_shaper : b32 = true,
snap_shape_position : b32 = true, snap_shape_position : b32 = true,
default_curve_quality : u32 = 3, default_curve_quality : u32 = 3,
@@ -158,7 +158,7 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
} }
ctx.default_curve_quality = default_curve_quality ctx.default_curve_quality = default_curve_quality
error : AllocatorError error : Allocator_Error
entries, error = make( [dynamic]Entry, len = 0, cap = entires_reserve ) entries, error = make( [dynamic]Entry, len = 0, cap = entires_reserve )
assert(error == .None, "VEFontCache.init : Failed to allocate entries") assert(error == .None, "VEFontCache.init : Failed to allocate entries")
@@ -174,10 +174,10 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
draw_list.indices, error = make( [dynamic]u32, len = 0, cap = 8 * Kilobyte ) draw_list.indices, error = make( [dynamic]u32, len = 0, cap = 8 * Kilobyte )
assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.indices") assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.indices")
draw_list.calls, error = make( [dynamic]DrawCall, len = 0, cap = 512 ) draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = 512 )
assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.calls") assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.calls")
init_atlas_region :: proc( region : ^AtlasRegion, params : InitAtlasParams, region_params : InitAtlasRegionParams, factor : Vec2i, expected_cap : i32 ) init_atlas_region :: proc( region : ^Atlas_Region, params : Init_Atlas_Params, region_params : Init_Atlas_Region_Params, factor : Vec2i, expected_cap : i32 )
{ {
using region using region
@@ -194,8 +194,8 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
} }
assert( capacity.x * capacity.y == expected_cap ) assert( capacity.x * capacity.y == expected_cap )
error : AllocatorError error : Allocator_Error
LRU_init( & state, capacity.x * capacity.y ) lru_init( & state, capacity.x * capacity.y )
} }
init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 ) init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 )
init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 ) init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 )
@@ -214,9 +214,9 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
atlas.region_d.offset.x = atlas.width / 2 atlas.region_d.offset.x = atlas.width / 2
atlas.region_d.offset.y = 0 atlas.region_d.offset.y = 0
LRU_init( & shape_cache.state, i32(shape_cache_params.capacity) ) lru_init( & shape_cache.state, i32(shape_cache_params.capacity) )
shape_cache.storage, error = make( [dynamic]ShapedText, shape_cache_params.capacity ) shape_cache.storage, error = make( [dynamic]Shaped_Text, shape_cache_params.capacity )
assert(error == .None, "VEFontCache.init : Failed to allocate shape_cache.storage") assert(error == .None, "VEFontCache.init : Failed to allocate shape_cache.storage")
for idx : u32 = 0; idx < shape_cache_params.capacity; idx += 1 { for idx : u32 = 0; idx < shape_cache_params.capacity; idx += 1 {
@@ -228,7 +228,7 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
positions, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve_length ) positions, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve_length )
assert( error == .None, "VEFontCache.init : Failed to allocate positions array for shape cache storage" ) assert( error == .None, "VEFontCache.init : Failed to allocate positions array for shape cache storage" )
draw_list.calls, error = make( [dynamic]DrawCall, len = 0, cap = glyph_draw_params.buffer_batch * 2 ) draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = glyph_draw_params.buffer_batch * 2 )
assert( error == .None, "VEFontCache.init : Failed to allocate calls for draw_list" ) assert( error == .None, "VEFontCache.init : Failed to allocate calls for draw_list" )
draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 6 ) draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 6 )
@@ -247,7 +247,7 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
height = atlas.region_d.height * i32(over_sample.y) height = atlas.region_d.height * i32(over_sample.y)
draw_padding = cast(i32) glyph_draw_params.draw_padding draw_padding = cast(i32) glyph_draw_params.draw_padding
draw_list.calls, error = make( [dynamic]DrawCall, len = 0, cap = glyph_draw_params.buffer_batch * 2 ) draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = glyph_draw_params.buffer_batch * 2 )
assert( error == .None, "VEFontCache.init : Failed to allocate calls for draw_list" ) assert( error == .None, "VEFontCache.init : Failed to allocate calls for draw_list" )
draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 6 ) draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 6 )
@@ -256,7 +256,7 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 ) draw_list.vertices, error = make( [dynamic]Vertex, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 )
assert( error == .None, "VEFontCache.init : Failed to allocate vertices array for draw_list" ) assert( error == .None, "VEFontCache.init : Failed to allocate vertices array for draw_list" )
clear_draw_list.calls, error = make( [dynamic]DrawCall, len = 0, cap = glyph_draw_params.buffer_batch * 2 ) clear_draw_list.calls, error = make( [dynamic]Draw_Call, len = 0, cap = glyph_draw_params.buffer_batch * 2 )
assert( error == .None, "VEFontCache.init : Failed to allocate calls for calls for clear_draw_list" ) assert( error == .None, "VEFontCache.init : Failed to allocate calls for calls for clear_draw_list" )
clear_draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 ) clear_draw_list.indices, error = make( [dynamic]u32, len = 0, cap = glyph_draw_params.buffer_batch * 2 * 4 )
@@ -285,12 +285,12 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator )
reload_array( & draw_list.indices, allocator ) reload_array( & draw_list.indices, allocator )
reload_array( & draw_list.calls, allocator ) reload_array( & draw_list.calls, allocator )
LRU_reload( & atlas.region_a.state, allocator) lru_reload( & atlas.region_a.state, allocator)
LRU_reload( & atlas.region_b.state, allocator) lru_reload( & atlas.region_b.state, allocator)
LRU_reload( & atlas.region_c.state, allocator) lru_reload( & atlas.region_c.state, allocator)
LRU_reload( & atlas.region_d.state, allocator) lru_reload( & atlas.region_d.state, allocator)
LRU_reload( & shape_cache.state, allocator ) lru_reload( & shape_cache.state, allocator )
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 { for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
stroage_entry := & shape_cache.storage[idx] stroage_entry := & shape_cache.storage[idx]
using stroage_entry using stroage_entry
@@ -308,7 +308,7 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator )
reload_array( & glyph_buffer.clear_draw_list.vertices, allocator ) reload_array( & glyph_buffer.clear_draw_list.vertices, allocator )
reload_array( & shape_cache.storage, allocator ) reload_array( & shape_cache.storage, allocator )
LRU_reload( & shape_cache.state, allocator ) lru_reload( & shape_cache.state, allocator )
} }
// ve_foncache_shutdown // ve_foncache_shutdown
@@ -330,10 +330,10 @@ shutdown :: proc( ctx : ^Context )
delete( draw_list.indices ) delete( draw_list.indices )
delete( draw_list.calls ) delete( draw_list.calls )
LRU_free( & atlas.region_a.state ) lru_free( & atlas.region_a.state )
LRU_free( & atlas.region_b.state ) lru_free( & atlas.region_b.state )
LRU_free( & atlas.region_c.state ) lru_free( & atlas.region_c.state )
LRU_free( & atlas.region_d.state ) lru_free( & atlas.region_d.state )
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 { for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
stroage_entry := & shape_cache.storage[idx] stroage_entry := & shape_cache.storage[idx]
@@ -342,7 +342,7 @@ shutdown :: proc( ctx : ^Context )
delete( glyphs ) delete( glyphs )
delete( positions ) delete( positions )
} }
LRU_free( & shape_cache.state ) lru_free( & shape_cache.state )
delete( glyph_buffer.draw_list.vertices ) delete( glyph_buffer.draw_list.vertices )
delete( glyph_buffer.draw_list.indices ) delete( glyph_buffer.draw_list.indices )
@@ -357,7 +357,7 @@ shutdown :: proc( ctx : ^Context )
} }
// ve_fontcache_load // ve_fontcache_load
load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32, glyph_curve_quality : u32 = 0 ) -> (font_id : FontID) load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32, glyph_curve_quality : u32 = 0 ) -> (font_id : Font_ID)
{ {
assert( ctx != nil ) assert( ctx != nil )
assert( len(data) > 0 ) assert( len(data) > 0 )
@@ -397,15 +397,15 @@ load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32,
curve_quality = f32(glyph_curve_quality) curve_quality = f32(glyph_curve_quality)
} }
} }
entry.id = FontID(id) entry.id = Font_ID(id)
ctx.entries[ id ].id = FontID(id) ctx.entries[ id ].id = Font_ID(id)
font_id = FontID(id) font_id = Font_ID(id)
return return
} }
// ve_fontcache_unload // ve_fontcache_unload
unload_font :: proc( ctx : ^Context, font : FontID ) unload_font :: proc( ctx : ^Context, font : Font_ID )
{ {
assert( ctx != nil ) assert( ctx != nil )
assert( font >= 0 && int(font) < len(ctx.entries) ) assert( font >= 0 && int(font) < len(ctx.entries) )
@@ -430,10 +430,10 @@ configure_snap :: #force_inline proc( ctx : ^Context, snap_width, snap_height :
ctx.snap_height = f32(snap_height) ctx.snap_height = f32(snap_height)
} }
get_cursor_pos :: #force_inline proc "contextless" ( ctx : ^Context ) -> Vec2 { return ctx.cursor_pos } get_cursor_pos :: #force_inline proc( ctx : ^Context ) -> Vec2 { assert(ctx != nil); return ctx.cursor_pos }
set_colour :: #force_inline proc "contextless" ( ctx : ^Context, colour : Colour ) { ctx.colour = colour } set_colour :: #force_inline proc( ctx : ^Context, colour : Colour ) { assert(ctx != nil); ctx.colour = colour }
draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position, scale : Vec2 ) -> b32 draw_text :: proc( ctx : ^Context, font : Font_ID, text_utf8 : string, position, scale : Vec2 ) -> b32
{ {
// profile(#procedure) // profile(#procedure)
assert( ctx != nil ) assert( ctx != nil )
@@ -463,14 +463,14 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position,
return true return true
} }
// ve_fontcache_drawlist // ve_fontcache_Draw_List
get_draw_list :: proc( ctx : ^Context, optimize_before_returning := true ) -> ^DrawList { get_draw_list :: proc( ctx : ^Context, optimize_before_returning := true ) -> ^Draw_List {
assert( ctx != nil ) assert( ctx != nil )
if optimize_before_returning do optimize_draw_list( & ctx.draw_list, 0 ) if optimize_before_returning do optimize_draw_list( & ctx.draw_list, 0 )
return & ctx.draw_list return & ctx.draw_list
} }
get_draw_list_layer :: proc( ctx : ^Context, optimize_before_returning := true ) -> (vertices : []Vertex, indices : []u32, calls : []DrawCall) { get_draw_list_layer :: proc( ctx : ^Context, optimize_before_returning := true ) -> (vertices : []Vertex, indices : []u32, calls : []Draw_Call) {
assert( ctx != nil ) assert( ctx != nil )
if optimize_before_returning do optimize_draw_list( & ctx.draw_list, ctx.draw_layer.calls_offset ) if optimize_before_returning do optimize_draw_list( & ctx.draw_list, ctx.draw_layer.calls_offset )
vertices = ctx.draw_list.vertices[ ctx.draw_layer.vertices_offset : ] vertices = ctx.draw_list.vertices[ ctx.draw_layer.vertices_offset : ]
@@ -479,7 +479,7 @@ get_draw_list_layer :: proc( ctx : ^Context, optimize_before_returning := true )
return return
} }
// ve_fontcache_flush_drawlist // ve_fontcache_flush_Draw_List
flush_draw_list :: proc( ctx : ^Context ) { flush_draw_list :: proc( ctx : ^Context ) {
assert( ctx != nil ) assert( ctx != nil )
using ctx using ctx
@@ -501,7 +501,7 @@ flush_draw_list_layer :: proc( ctx : ^Context ) {
//#region("metrics") //#region("metrics")
measure_text_size :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) -> (measured : Vec2) measure_text_size :: proc( ctx : ^Context, font : Font_ID, text_utf8 : string ) -> (measured : Vec2)
{ {
// profile(#procedure) // profile(#procedure)
assert( ctx != nil ) assert( ctx != nil )
@@ -512,7 +512,7 @@ measure_text_size :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) -
return shaped.size return shaped.size
} }
get_font_vertical_metrics :: #force_inline proc ( ctx : ^Context, font : FontID ) -> ( ascent, descent, line_gap : f32 ) get_font_vertical_metrics :: #force_inline proc ( ctx : ^Context, font : Font_ID ) -> ( ascent, descent, line_gap : f32 )
{ {
assert( ctx != nil ) assert( ctx != nil )
assert( font >= 0 && int(font) < len(ctx.entries) ) assert( font >= 0 && int(font) < len(ctx.entries) )