mirror of
https://github.com/Ed94/VEFontCache-Odin.git
synced 2025-08-05 14:42:42 -07:00
Formating, name changes (making identifiers more idiomatic)
This commit is contained in:
@@ -6,33 +6,33 @@ The choice was made to keep the LRU cache implementation as close to the origina
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
PoolListIter :: i32
|
||||
PoolListValue :: u64
|
||||
Pool_ListIter :: i32
|
||||
Pool_ListValue :: u64
|
||||
|
||||
PoolListItem :: struct {
|
||||
prev : PoolListIter,
|
||||
next : PoolListIter,
|
||||
value : PoolListValue,
|
||||
Pool_List_Item :: struct {
|
||||
prev : Pool_ListIter,
|
||||
next : Pool_ListIter,
|
||||
value : Pool_ListValue,
|
||||
}
|
||||
|
||||
PoolList :: struct {
|
||||
items : [dynamic]PoolListItem,
|
||||
free_list : [dynamic]PoolListIter,
|
||||
front : PoolListIter,
|
||||
back : PoolListIter,
|
||||
Pool_List :: struct {
|
||||
items : [dynamic]Pool_List_Item,
|
||||
free_list : [dynamic]Pool_ListIter,
|
||||
front : Pool_ListIter,
|
||||
back : Pool_ListIter,
|
||||
size : i32,
|
||||
capacity : i32,
|
||||
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
|
||||
pool.items, error = make( [dynamic]PoolListItem, int(capacity) )
|
||||
error : Allocator_Error
|
||||
pool.items, error = make( [dynamic]Pool_List_Item, int(capacity) )
|
||||
assert( error == .None, "VEFontCache.pool_list_init : Failed to allocate items array")
|
||||
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")
|
||||
resize( & pool.free_list, capacity )
|
||||
|
||||
@@ -53,17 +53,17 @@ pool_list_init :: proc( pool : ^PoolList, capacity : i32, dbg_name : string = ""
|
||||
back = -1
|
||||
}
|
||||
|
||||
pool_list_free :: proc( pool : ^PoolList ) {
|
||||
pool_list_free :: proc( pool : ^Pool_List ) {
|
||||
delete( pool.items)
|
||||
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.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
|
||||
if size >= capacity do return
|
||||
@@ -90,7 +90,7 @@ pool_list_push_front :: proc( pool : ^PoolList, value : PoolListValue )
|
||||
size += 1
|
||||
}
|
||||
|
||||
pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter )
|
||||
pool_list_erase :: proc( pool : ^Pool_List, iter : Pool_ListIter )
|
||||
{
|
||||
using pool
|
||||
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
|
||||
|
||||
@@ -136,13 +136,13 @@ pool_list_move_to_front :: #force_inline proc( pool : ^PoolList, iter : PoolList
|
||||
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 )
|
||||
value := pool.items[ pool.back ].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
|
||||
assert( pool.back != -1 )
|
||||
|
||||
@@ -153,8 +153,10 @@ pool_list_pop_back :: #force_inline proc( pool : ^PoolList ) -> PoolListValue {
|
||||
|
||||
LRU_Link :: struct {
|
||||
pad_top : u64,
|
||||
|
||||
value : i32,
|
||||
ptr : PoolListIter,
|
||||
ptr : Pool_ListIter,
|
||||
|
||||
pad_bottom : u64,
|
||||
}
|
||||
|
||||
@@ -162,34 +164,34 @@ LRU_Cache :: struct {
|
||||
capacity : i32,
|
||||
num : i32,
|
||||
table : map[u64]LRU_Link,
|
||||
key_queue : PoolList,
|
||||
key_queue : Pool_List,
|
||||
}
|
||||
|
||||
LRU_init :: proc( cache : ^LRU_Cache, capacity : i32, dbg_name : string = "" ) {
|
||||
error : AllocatorError
|
||||
lru_init :: proc( cache : ^LRU_Cache, capacity : i32, dbg_name : string = "" ) {
|
||||
error : Allocator_Error
|
||||
cache.capacity = 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 )
|
||||
}
|
||||
|
||||
LRU_free :: proc( cache : ^LRU_Cache ) {
|
||||
lru_free :: proc( cache : ^LRU_Cache ) {
|
||||
pool_list_free( & cache.key_queue )
|
||||
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 )
|
||||
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]
|
||||
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 {
|
||||
pool_list_move_to_front(&cache.key_queue, link.ptr)
|
||||
return link.value
|
||||
@@ -197,7 +199,7 @@ LRU_get :: #force_inline proc( cache: ^LRU_Cache, key : u64 ) -> i32 {
|
||||
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 {
|
||||
evict := pool_list_peek_back( & cache.key_queue )
|
||||
return evict
|
||||
@@ -205,15 +207,15 @@ LRU_get_next_evicted :: #force_inline proc ( cache : ^LRU_Cache ) -> u64 {
|
||||
return 0xFFFFFFFFFFFFFFFF
|
||||
}
|
||||
|
||||
LRU_peek :: #force_inline proc ( cache : ^LRU_Cache, key : u64, must_find := false ) -> i32 {
|
||||
iter, success := LRU_find( cache, key, must_find )
|
||||
lru_peek :: #force_inline proc ( cache : ^LRU_Cache, key : u64, must_find := false ) -> i32 {
|
||||
iter, success := lru_find( cache, key, must_find )
|
||||
if success == false {
|
||||
return -1
|
||||
}
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
LRU_refresh :: proc( cache : ^LRU_Cache, key : u64 ) {
|
||||
link, success := LRU_find( cache, key )
|
||||
lru_refresh :: proc( cache : ^LRU_Cache, key : u64 ) {
|
||||
link, success := lru_find( cache, key )
|
||||
pool_list_erase( & cache.key_queue, link.ptr )
|
||||
pool_list_push_front( & cache.key_queue, key )
|
||||
link.ptr = cache.key_queue.front
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package vefontcache
|
||||
|
||||
AtlasRegionKind :: enum u8 {
|
||||
Atlas_Region_Kind :: enum u8 {
|
||||
None = 0x00,
|
||||
A = 0x41,
|
||||
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
|
||||
}
|
||||
|
||||
AtlasRegion :: struct {
|
||||
Atlas_Region :: struct {
|
||||
state : LRU_Cache,
|
||||
|
||||
width : i32,
|
||||
@@ -29,13 +29,13 @@ Atlas :: struct {
|
||||
|
||||
glyph_padding : i32,
|
||||
|
||||
region_a : AtlasRegion,
|
||||
region_b : AtlasRegion,
|
||||
region_c : AtlasRegion,
|
||||
region_d : AtlasRegion,
|
||||
region_a : Atlas_Region,
|
||||
region_b : Atlas_Region,
|
||||
region_c : Atlas_Region,
|
||||
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
|
||||
{
|
||||
@@ -79,14 +79,12 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : i32 )
|
||||
position.x += f32(atlas.region_d.offset.x)
|
||||
position.y += f32(atlas.region_d.offset.y)
|
||||
|
||||
case .Ignore: fallthrough
|
||||
case .None: fallthrough
|
||||
case .E:
|
||||
case .Ignore, .None, .E:
|
||||
}
|
||||
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) {
|
||||
return .None, nil, {}
|
||||
@@ -104,11 +102,11 @@ decide_codepoint_region :: proc(ctx : ^Context, entry : ^Entry, glyph_index : Gl
|
||||
bounds_height_scaled := i32(bounds_height * entry.size_scale + glyph_padding)
|
||||
|
||||
// Use a lookup table for faster region selection
|
||||
region_lookup := [4]struct { kind: AtlasRegionKind, region: ^AtlasRegion } {
|
||||
{ .A, & atlas.region_a },
|
||||
{ .B, & atlas.region_b },
|
||||
{ .C, & atlas.region_c },
|
||||
{ .D, & atlas.region_d },
|
||||
region_lookup := [4]struct { kind: Atlas_Region_Kind, region: ^Atlas_Region } {
|
||||
{ .A, & atlas.region_a },
|
||||
{ .B, & atlas.region_b },
|
||||
{ .C, & atlas.region_c },
|
||||
{ .D, & atlas.region_d },
|
||||
}
|
||||
|
||||
for region in region_lookup do if bounds_width_scaled <= region.region.width && bounds_height_scaled <= region.region.height {
|
||||
|
@@ -8,16 +8,16 @@ Vertex :: struct {
|
||||
u, v : f32,
|
||||
}
|
||||
|
||||
DrawCall :: struct {
|
||||
pass : FrameBufferPass,
|
||||
Draw_Call :: struct {
|
||||
pass : Frame_Buffer_Pass,
|
||||
start_index : u32,
|
||||
end_index : u32,
|
||||
clear_before_draw : b32,
|
||||
region : AtlasRegionKind,
|
||||
region : Atlas_Region_Kind,
|
||||
colour : Colour,
|
||||
}
|
||||
|
||||
DrawCall_Default :: DrawCall {
|
||||
Draw_Call_Default :: Draw_Call {
|
||||
pass = .None,
|
||||
start_index = 0,
|
||||
end_index = 0,
|
||||
@@ -26,14 +26,14 @@ DrawCall_Default :: DrawCall {
|
||||
colour = { 1.0, 1.0, 1.0, 1.0 }
|
||||
}
|
||||
|
||||
DrawList :: struct {
|
||||
Draw_List :: struct {
|
||||
vertices : [dynamic]Vertex,
|
||||
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...
|
||||
FrameBufferPass :: enum u32 {
|
||||
Frame_Buffer_Pass :: enum u32 {
|
||||
None = 0,
|
||||
Glyph = 1,
|
||||
Atlas = 2,
|
||||
@@ -41,7 +41,7 @@ FrameBufferPass :: enum u32 {
|
||||
Target_Uncached = 4,
|
||||
}
|
||||
|
||||
GlyphDrawBuffer :: struct {
|
||||
Glyph_Draw_Buffer :: struct {
|
||||
over_sample : Vec2,
|
||||
batch : i32,
|
||||
width : i32,
|
||||
@@ -49,11 +49,11 @@ GlyphDrawBuffer :: struct {
|
||||
draw_padding : i32,
|
||||
|
||||
batch_x : i32,
|
||||
clear_draw_list : DrawList,
|
||||
draw_list : DrawList,
|
||||
clear_draw_list : Draw_List,
|
||||
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)
|
||||
// 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...
|
||||
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 },
|
||||
translate := Vec2 { 0, 0 },
|
||||
debug_print_verbose : b32 = false
|
||||
@@ -106,7 +106,7 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en
|
||||
}
|
||||
|
||||
v_offset := cast(u32) len(draw_list.vertices)
|
||||
for point in path
|
||||
for point in path
|
||||
{
|
||||
transformed_point := Vertex {
|
||||
pos = point.pos * scale + translate,
|
||||
@@ -130,9 +130,9 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en
|
||||
|
||||
// Close the path by connecting the last vertex to the first two
|
||||
to_add := [3]u32 {
|
||||
v_offset,
|
||||
v_offset + cast(u32)(len(path) - 1),
|
||||
v_offset + 1
|
||||
v_offset,
|
||||
v_offset + cast(u32)(len(path) - 1),
|
||||
v_offset + 1
|
||||
}
|
||||
append( indices, ..to_add[:] )
|
||||
}
|
||||
@@ -158,8 +158,8 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en
|
||||
return false
|
||||
}
|
||||
|
||||
draw := DrawCall_Default
|
||||
draw.pass = FrameBufferPass.Glyph
|
||||
draw := Draw_Call_Default
|
||||
draw.pass = Frame_Buffer_Pass.Glyph
|
||||
draw.start_index = cast(u32) len(ctx.draw_list.indices)
|
||||
|
||||
contours := slice.from_ptr(cast( [^]i16) outline.contours, int(outline.n_contours))
|
||||
@@ -178,57 +178,57 @@ cache_glyph_freetype :: proc(ctx: ^Context, font: FontID, glyph_index: Glyph, en
|
||||
prev_point: Vec2
|
||||
first_point: Vec2
|
||||
|
||||
for idx := start_index; idx < end_index; idx += 1
|
||||
for idx := start_index; idx < end_index; idx += 1
|
||||
{
|
||||
current_pos := Vec2 { f32( points[idx].x ), f32( points[idx].y ) }
|
||||
if ( tags[idx] & 1 ) == 0
|
||||
{
|
||||
current_pos := Vec2 { f32( points[idx].x ), f32( points[idx].y ) }
|
||||
if ( tags[idx] & 1 ) == 0
|
||||
// If current point is off-curve
|
||||
if (idx == start_index || (tags[ idx - 1 ] & 1) != 0)
|
||||
{
|
||||
// If current point is off-curve
|
||||
if (idx == start_index || (tags[ idx - 1 ] & 1) != 0)
|
||||
{
|
||||
// current is the first or following an on-curve point
|
||||
prev_point = current_pos
|
||||
}
|
||||
else
|
||||
{
|
||||
// current and previous are off-curve, calculate midpoint
|
||||
midpoint := (prev_point + current_pos) * 0.5
|
||||
append( path, Vertex { pos = midpoint } ) // Add midpoint as on-curve point
|
||||
if idx < end_index - 1
|
||||
{
|
||||
// perform interp from prev_point to current_pos via midpoint
|
||||
step := 1.0 / entry.curve_quality
|
||||
for alpha : f32 = 0.0; alpha <= 1.0; alpha += step
|
||||
{
|
||||
bezier_point := eval_point_on_bezier3( prev_point, midpoint, current_pos, alpha )
|
||||
append( path, Vertex{ pos = bezier_point } )
|
||||
}
|
||||
}
|
||||
|
||||
prev_point = current_pos
|
||||
}
|
||||
// current is the first or following an on-curve point
|
||||
prev_point = current_pos
|
||||
}
|
||||
else
|
||||
{
|
||||
if idx == start_index {
|
||||
first_point = current_pos
|
||||
// current and previous are off-curve, calculate midpoint
|
||||
midpoint := (prev_point + current_pos) * 0.5
|
||||
append( path, Vertex { pos = midpoint } ) // Add midpoint as on-curve point
|
||||
if idx < end_index - 1
|
||||
{
|
||||
// perform interp from prev_point to current_pos via midpoint
|
||||
step := 1.0 / entry.curve_quality
|
||||
for alpha : f32 = 0.0; alpha <= 1.0; alpha += step
|
||||
{
|
||||
bezier_point := eval_point_on_bezier3( prev_point, midpoint, current_pos, alpha )
|
||||
append( path, Vertex{ pos = bezier_point } )
|
||||
}
|
||||
}
|
||||
if prev_point != (Vec2{}) {
|
||||
// there was an off-curve point before this
|
||||
append(path, Vertex{ pos = prev_point}) // Ensure previous off-curve is handled
|
||||
}
|
||||
append(path, Vertex{ pos = current_pos})
|
||||
prev_point = {}
|
||||
|
||||
prev_point = current_pos
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the contour is closed
|
||||
if path[0].pos != path[ len(path) - 1 ].pos {
|
||||
append(path, Vertex{pos = path[0].pos})
|
||||
else
|
||||
{
|
||||
if idx == start_index {
|
||||
first_point = current_pos
|
||||
}
|
||||
if prev_point != (Vec2{}) {
|
||||
// there was an off-curve point before this
|
||||
append(path, Vertex{ pos = prev_point}) // Ensure previous off-curve is handled
|
||||
}
|
||||
append(path, Vertex{ pos = current_pos})
|
||||
prev_point = {}
|
||||
}
|
||||
draw_filled_path(&ctx.draw_list, bounds_0, path[:], scale, translate, ctx.debug_print_verbose)
|
||||
clear(path)
|
||||
start_index = end_index
|
||||
}
|
||||
|
||||
// ensure the contour is closed
|
||||
if path[0].pos != path[ len(path) - 1 ].pos {
|
||||
append(path, Vertex{pos = path[0].pos})
|
||||
}
|
||||
draw_filled_path(&ctx.draw_list, bounds_0, path[:], scale, translate, ctx.debug_print_verbose)
|
||||
clear(path)
|
||||
start_index = end_index
|
||||
}
|
||||
|
||||
if len(path) > 0 {
|
||||
@@ -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)?
|
||||
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)
|
||||
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}
|
||||
|
||||
draw := DrawCall_Default
|
||||
draw.pass = FrameBufferPass.Glyph
|
||||
draw := Draw_Call_Default
|
||||
draw.pass = Frame_Buffer_Pass.Glyph
|
||||
draw.start_index = u32(len(ctx.draw_list.indices))
|
||||
|
||||
path := &ctx.temp_path
|
||||
@@ -276,8 +276,8 @@ cache_glyph :: proc(ctx : ^Context, font : FontID, glyph_index : Glyph, entry :
|
||||
{
|
||||
case .Move:
|
||||
if len(path) > 0 {
|
||||
draw_filled_path(&ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose)
|
||||
clear(path)
|
||||
draw_filled_path(&ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose)
|
||||
clear(path)
|
||||
}
|
||||
fallthrough
|
||||
|
||||
@@ -329,13 +329,13 @@ cache_glyph :: proc(ctx : ^Context, font : FontID, glyph_index : Glyph, entry :
|
||||
* draw_text_shape : Glyph
|
||||
*/
|
||||
cache_glyph_to_atlas :: proc( ctx : ^Context,
|
||||
font : FontID,
|
||||
font : Font_ID,
|
||||
glyph_index : Glyph,
|
||||
lru_code : u64,
|
||||
atlas_index : i32,
|
||||
entry : ^Entry,
|
||||
region_kind : AtlasRegionKind,
|
||||
region : ^AtlasRegion,
|
||||
region_kind : Atlas_Region_Kind,
|
||||
region : ^Atlas_Region,
|
||||
over_sample : Vec2 )
|
||||
{
|
||||
// profile(#procedure)
|
||||
@@ -356,24 +356,24 @@ cache_glyph_to_atlas :: proc( ctx : ^Context,
|
||||
{
|
||||
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)
|
||||
region.next_idx += 1
|
||||
assert( evicted == lru_code )
|
||||
}
|
||||
else
|
||||
{
|
||||
next_evict_codepoint := LRU_get_next_evicted( & region.state )
|
||||
next_evict_codepoint := lru_get_next_evicted( & region.state )
|
||||
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 )
|
||||
|
||||
evicted := LRU_put( & region.state, lru_code, atlas_index )
|
||||
evicted := lru_put( & region.state, lru_code, atlas_index )
|
||||
assert( evicted == next_evict_codepoint )
|
||||
}
|
||||
|
||||
assert( LRU_get( & region.state, lru_code ) != - 1 )
|
||||
assert( lru_get( & region.state, lru_code ) != - 1 )
|
||||
}
|
||||
|
||||
atlas := & ctx.atlas
|
||||
@@ -420,7 +420,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context,
|
||||
glyph_buffer.batch_x += i32(gwidth_scaled_px)
|
||||
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
|
||||
pass = .Atlas
|
||||
@@ -434,7 +434,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context,
|
||||
end_index = cast(u32) len(glyph_buffer.clear_draw_list.indices)
|
||||
}
|
||||
|
||||
blit_to_atlas : DrawCall
|
||||
blit_to_atlas : Draw_Call
|
||||
{
|
||||
using blit_to_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
|
||||
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,
|
||||
atlas_index : i32,
|
||||
region_kind : AtlasRegionKind,
|
||||
region : ^AtlasRegion,
|
||||
region_kind : Atlas_Region_Kind,
|
||||
region : ^Atlas_Region,
|
||||
over_sample : Vec2
|
||||
) -> b32
|
||||
{
|
||||
@@ -476,7 +476,7 @@ check_glyph_in_atlas :: #force_inline proc( ctx : ^Context, font : FontID, entry
|
||||
{
|
||||
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 )
|
||||
next_evict_codepoint := lru_get_next_evicted( & region.state )
|
||||
seen, success := ctx.temp_codepoint_seen[next_evict_codepoint]
|
||||
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 )
|
||||
}
|
||||
|
||||
assert( LRU_get( & region.state, lru_code ) != -1 )
|
||||
assert( lru_get( & region.state, lru_code ) != -1 )
|
||||
mark_batch_codepoint_seen( ctx, lru_code)
|
||||
return true
|
||||
}
|
||||
|
||||
// ve_fontcache_clear_drawlist
|
||||
clear_draw_list :: #force_inline proc ( draw_list : ^DrawList ) {
|
||||
// ve_fontcache_clear_Draw_List
|
||||
clear_draw_list :: #force_inline proc ( draw_list : ^Draw_List ) {
|
||||
clear( & draw_list.calls )
|
||||
clear( & draw_list.indices )
|
||||
clear( & draw_list.vertices )
|
||||
@@ -538,8 +538,8 @@ directly_draw_massive_glyph :: proc( ctx : ^Context,
|
||||
dst_size := glyph_dst_size * scale
|
||||
textspace_x_form( & glyph_position, & glyph_size, glyph_buffer_size )
|
||||
|
||||
// Add the glyph drawcall.
|
||||
calls : [2]DrawCall
|
||||
// Add the glyph Draw_Call.
|
||||
calls : [2]Draw_Call
|
||||
|
||||
draw_to_target := & calls[0]
|
||||
{
|
||||
@@ -549,8 +549,8 @@ directly_draw_massive_glyph :: proc( ctx : ^Context,
|
||||
start_index = u32(len(ctx.draw_list.indices))
|
||||
|
||||
blit_quad( & ctx.draw_list,
|
||||
dst, dst + dst_size,
|
||||
glyph_position, glyph_position + glyph_size )
|
||||
dst, dst + dst_size,
|
||||
glyph_position, glyph_position + glyph_size )
|
||||
|
||||
end_index = u32(len(ctx.draw_list.indices))
|
||||
}
|
||||
@@ -570,9 +570,9 @@ directly_draw_massive_glyph :: proc( ctx : ^Context,
|
||||
// outside_point represents the center point of the fan.
|
||||
//
|
||||
// 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
|
||||
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 },
|
||||
translate := Vec2 { 0, 0 },
|
||||
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,
|
||||
position, scale : Vec2,
|
||||
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 )
|
||||
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 )
|
||||
vbounds_0 := vec2(bounds_0)
|
||||
vbounds_1 := vec2(bounds_1)
|
||||
@@ -660,7 +660,7 @@ draw_text_batch :: proc(ctx: ^Context, entry: ^Entry, shaped: ^ShapedText,
|
||||
dst_scale := glyph_scale * scale
|
||||
textspace_x_form( & slot_position, & glyph_scale, atlas_size )
|
||||
|
||||
call := DrawCall_Default
|
||||
call := Draw_Call_Default
|
||||
call.pass = .Target
|
||||
call.colour = ctx.colour
|
||||
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.
|
||||
draw_text_shape :: proc( ctx : ^Context,
|
||||
font : FontID,
|
||||
font : Font_ID,
|
||||
entry : ^Entry,
|
||||
shaped : ^ShapedText,
|
||||
shaped : ^Shaped_Text,
|
||||
position, scale : Vec2,
|
||||
snap_width, snap_height : f32
|
||||
) -> (cursor_pos : Vec2)
|
||||
@@ -695,7 +695,7 @@ draw_text_shape :: proc( ctx : ^Context,
|
||||
lru_code := font_glyph_lru_code(entry.id, glyph_index)
|
||||
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
|
||||
|
||||
// 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 )
|
||||
{
|
||||
// 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.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
|
||||
if ctx.glyph_buffer.batch_x != 0
|
||||
{
|
||||
call := DrawCall_Default
|
||||
call := Draw_Call_Default
|
||||
call.pass = .Glyph
|
||||
call.start_index = 0
|
||||
call.end_index = 0
|
||||
@@ -739,11 +739,11 @@ flush_glyph_buffer_to_atlas :: proc( ctx : ^Context )
|
||||
}
|
||||
}
|
||||
|
||||
// ve_fontcache_merge_drawlist
|
||||
merge_draw_list :: proc( dst, src : ^DrawList )
|
||||
// ve_fontcache_merge_Draw_List
|
||||
merge_draw_list :: proc( dst, src : ^Draw_List )
|
||||
{
|
||||
// profile(#procedure)
|
||||
error : AllocatorError
|
||||
error : Allocator_Error
|
||||
|
||||
v_offset := cast(u32) len( dst.vertices )
|
||||
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)
|
||||
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 := \
|
||||
a.pass == b.pass &&
|
||||
a.end_index == b.start_index &&
|
||||
|
@@ -27,8 +27,8 @@ import "core:mem"
|
||||
Kilobyte :: mem.Kilobyte
|
||||
slice_ptr :: mem.slice_ptr
|
||||
|
||||
Allocator :: mem.Allocator
|
||||
AllocatorError :: mem.Allocator_Error
|
||||
Allocator :: mem.Allocator
|
||||
Allocator_Error :: mem.Allocator_Error
|
||||
|
||||
Arena :: mem.Arena
|
||||
arena_allocator :: mem.arena_allocator
|
||||
|
@@ -49,7 +49,7 @@ reload_map :: proc( self : ^map [$KeyType] $EntryType, 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 )
|
||||
return
|
||||
}
|
||||
@@ -71,9 +71,11 @@ reset_batch_codepoint_state :: #force_inline proc( ctx : ^Context ) {
|
||||
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 )
|
||||
{
|
||||
if true
|
||||
when USE_F64_PRECISION_ON_X_FORM_OPS
|
||||
{
|
||||
pos_64 := vec2_64_from_vec2(position^)
|
||||
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 )
|
||||
{
|
||||
if true
|
||||
when USE_F64_PRECISION_ON_X_FORM_OPS
|
||||
{
|
||||
pos_64 := vec2_64_from_vec2(position^)
|
||||
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,
|
||||
// allows the function to calculate the position of a point along the curve at any given fraction of its total length
|
||||
|
@@ -16,14 +16,14 @@ import "core:slice"
|
||||
import stbtt "vendor:stb/truetype"
|
||||
import freetype "thirdparty:freetype"
|
||||
|
||||
ParserKind :: enum u32 {
|
||||
Parser_Kind :: enum u32 {
|
||||
STB_TrueType,
|
||||
Freetype,
|
||||
}
|
||||
|
||||
ParserFontInfo :: struct {
|
||||
Parser_Font_Info :: struct {
|
||||
label : string,
|
||||
kind : ParserKind,
|
||||
kind : Parser_Kind,
|
||||
using _ : struct #raw_union {
|
||||
stbtt_info : stbtt.fontinfo,
|
||||
freetype_info : freetype.Face
|
||||
@@ -31,7 +31,7 @@ ParserFontInfo :: struct {
|
||||
data : []byte,
|
||||
}
|
||||
|
||||
GlyphVertType :: enum u8 {
|
||||
Glyph_Vert_Type :: enum u8 {
|
||||
None,
|
||||
Move = 1,
|
||||
Line,
|
||||
@@ -40,22 +40,22 @@ GlyphVertType :: enum u8 {
|
||||
}
|
||||
|
||||
// Based directly off of stb_truetype's vertex
|
||||
ParserGlyphVertex :: struct {
|
||||
Parser_Glyph_Vertex :: struct {
|
||||
x, y : i16,
|
||||
contour_x0, contour_y0 : i16,
|
||||
contour_x1, contour_y1 : i16,
|
||||
type : GlyphVertType,
|
||||
type : Glyph_Vert_Type,
|
||||
padding : u8,
|
||||
}
|
||||
// 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 {
|
||||
kind : ParserKind,
|
||||
Parser_Context :: struct {
|
||||
kind : Parser_Kind,
|
||||
ft_library : freetype.Library,
|
||||
}
|
||||
|
||||
parser_init :: proc( ctx : ^ParserContext, kind : ParserKind )
|
||||
parser_init :: proc( ctx : ^Parser_Context, kind : Parser_Kind )
|
||||
{
|
||||
switch kind
|
||||
{
|
||||
@@ -70,11 +70,11 @@ parser_init :: proc( ctx : ^ParserContext, kind : ParserKind )
|
||||
ctx.kind = kind
|
||||
}
|
||||
|
||||
parser_shutdown :: proc( ctx : ^ParserContext ) {
|
||||
parser_shutdown :: proc( ctx : ^Parser_Context ) {
|
||||
// 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
|
||||
{
|
||||
@@ -93,7 +93,7 @@ parser_load_font :: proc( ctx : ^ParserContext, label : string, data : []byte )
|
||||
return
|
||||
}
|
||||
|
||||
parser_unload_font :: proc( font : ^ParserFontInfo )
|
||||
parser_unload_font :: proc( font : ^Parser_Font_Info )
|
||||
{
|
||||
switch font.kind {
|
||||
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
|
||||
{
|
||||
@@ -120,7 +120,7 @@ parser_find_glyph_index :: #force_inline proc "contextless" ( font : ^ParserFont
|
||||
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
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -156,7 +156,7 @@ parser_get_codepoint_horizontal_metrics :: #force_inline proc "contextless" ( fo
|
||||
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
|
||||
{
|
||||
@@ -176,7 +176,7 @@ parser_get_codepoint_kern_advance :: #force_inline proc "contextless" ( font : ^
|
||||
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
|
||||
{
|
||||
@@ -192,7 +192,7 @@ parser_get_font_vertical_metrics :: #force_inline proc "contextless" ( font : ^P
|
||||
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
|
||||
{
|
||||
@@ -215,7 +215,7 @@ parser_get_glyph_box :: #force_inline proc ( font : ^ParserFontInfo, glyph_index
|
||||
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
|
||||
{
|
||||
@@ -232,14 +232,14 @@ parser_get_glyph_shape :: proc( font : ^ParserFontInfo, glyph_index : Glyph ) ->
|
||||
shape_raw.len = int(nverts)
|
||||
shape_raw.cap = int(nverts)
|
||||
shape_raw.allocator = runtime.nil_allocator()
|
||||
error = AllocatorError.None
|
||||
error = Allocator_Error.None
|
||||
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
|
||||
{
|
||||
@@ -262,7 +262,7 @@ parser_is_glyph_empty :: #force_inline proc "contextless" ( font : ^ParserFontIn
|
||||
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 ? \
|
||||
parser_scale_for_pixel_height( font, -size ) \
|
||||
@@ -271,7 +271,7 @@ parser_scale :: #force_inline proc "contextless" ( font : ^ParserFontInfo, size
|
||||
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 {
|
||||
case .Freetype:
|
||||
@@ -285,7 +285,7 @@ parser_scale_for_pixel_height :: #force_inline proc "contextless" ( font : ^Pars
|
||||
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 {
|
||||
case .Freetype:
|
||||
|
@@ -1,14 +1,14 @@
|
||||
package vefontcache
|
||||
|
||||
ShapedText :: struct {
|
||||
Shaped_Text :: struct {
|
||||
glyphs : [dynamic]Glyph,
|
||||
positions : [dynamic]Vec2,
|
||||
end_cursor_pos : Vec2,
|
||||
size : Vec2,
|
||||
}
|
||||
|
||||
ShapedTextCache :: struct {
|
||||
storage : [dynamic]ShapedText,
|
||||
Shaped_Text_Cache :: struct {
|
||||
storage : [dynamic]Shaped_Text,
|
||||
state : LRU_Cache,
|
||||
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)
|
||||
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
|
||||
|
||||
lru_code : u64
|
||||
@@ -33,23 +33,23 @@ shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, en
|
||||
shape_cache := & ctx.shape_cache
|
||||
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.next_cache_id < i32(state.capacity) {
|
||||
shape_cache_idx = shape_cache.next_cache_id
|
||||
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
|
||||
{
|
||||
next_evict_idx := LRU_get_next_evicted( state )
|
||||
next_evict_idx := lru_get_next_evicted( state )
|
||||
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 )
|
||||
|
||||
LRU_put( state, lru_code, shape_cache_idx )
|
||||
lru_put( state, lru_code, 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 ]
|
||||
}
|
||||
|
||||
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)
|
||||
assert( ctx != nil )
|
||||
@@ -106,7 +106,7 @@ shape_text_uncached :: proc( ctx : ^Context, font : FontID, text_utf8 : string,
|
||||
prev_codepoint = rune(0)
|
||||
continue
|
||||
}
|
||||
if abs( entry.size ) <= Advance_Snap_Smallfont_Size {
|
||||
if abs( entry.size ) <= ADVANCE_SNAP_SMALLFONT_SIZE {
|
||||
position.x = position.x
|
||||
}
|
||||
|
||||
|
@@ -6,35 +6,35 @@ Note(Ed): The only reason I didn't directly use harfbuzz is because hamza exists
|
||||
import "core:c"
|
||||
import "thirdparty:harfbuzz"
|
||||
|
||||
ShaperKind :: enum {
|
||||
Shaper_Kind :: enum {
|
||||
Naive = 0,
|
||||
Harfbuzz = 1,
|
||||
}
|
||||
|
||||
ShaperContext :: struct {
|
||||
Shaper_Context :: struct {
|
||||
hb_buffer : harfbuzz.Buffer,
|
||||
}
|
||||
|
||||
ShaperInfo :: struct {
|
||||
Shaper_Info :: struct {
|
||||
blob : harfbuzz.Blob,
|
||||
face : harfbuzz.Face,
|
||||
font : harfbuzz.Font,
|
||||
}
|
||||
|
||||
shaper_init :: proc( ctx : ^ShaperContext )
|
||||
shaper_init :: proc( ctx : ^Shaper_Context )
|
||||
{
|
||||
ctx.hb_buffer = harfbuzz.buffer_create()
|
||||
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 {
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
shaper_unload_font :: proc( ctx : ^ShaperInfo )
|
||||
shaper_unload_font :: proc( ctx : ^Shaper_Info )
|
||||
{
|
||||
using ctx
|
||||
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 )
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
// profile(#procedure)
|
||||
@@ -69,7 +69,7 @@ shaper_shape_from_text :: proc( ctx : ^ShaperContext, info : ^ShaperInfo, output
|
||||
line_height := (ascent - descent + line_gap) * size_scale
|
||||
|
||||
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,
|
||||
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
|
||||
continue
|
||||
}
|
||||
if abs( size ) <= Advance_Snap_Smallfont_Size
|
||||
if abs( size ) <= ADVANCE_SNAP_SMALLFONT_SIZE
|
||||
{
|
||||
(position^) = ceil( position^ )
|
||||
}
|
||||
|
@@ -7,15 +7,15 @@ package vefontcache
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
Advance_Snap_Smallfont_Size :: 0
|
||||
ADVANCE_SNAP_SMALLFONT_SIZE :: 0
|
||||
|
||||
FontID :: distinct i64
|
||||
Font_ID :: distinct i64
|
||||
Glyph :: distinct i32
|
||||
|
||||
Entry :: struct {
|
||||
parser_info : ParserFontInfo,
|
||||
shaper_info : ShaperInfo,
|
||||
id : FontID,
|
||||
parser_info : Parser_Font_Info,
|
||||
shaper_info : Shaper_Info,
|
||||
id : Font_ID,
|
||||
used : b32,
|
||||
curve_quality : f32,
|
||||
size : f32,
|
||||
@@ -32,8 +32,8 @@ Entry_Default :: Entry {
|
||||
Context :: struct {
|
||||
backing : Allocator,
|
||||
|
||||
parser_ctx : ParserContext,
|
||||
shaper_ctx : ShaperContext,
|
||||
parser_ctx : Parser_Context,
|
||||
shaper_ctx : Shaper_Context,
|
||||
|
||||
entries : [dynamic]Entry,
|
||||
|
||||
@@ -54,10 +54,10 @@ Context :: struct {
|
||||
calls_offset : int,
|
||||
},
|
||||
|
||||
draw_list : DrawList,
|
||||
draw_list : Draw_List,
|
||||
atlas : Atlas,
|
||||
glyph_buffer : GlyphDrawBuffer,
|
||||
shape_cache : ShapedTextCache,
|
||||
glyph_buffer : Glyph_Draw_Buffer,
|
||||
shape_cache : Shaped_Text_Cache,
|
||||
|
||||
default_curve_quality : i32,
|
||||
text_shape_adv : b32,
|
||||
@@ -69,23 +69,23 @@ Context :: struct {
|
||||
|
||||
//#region("lifetime")
|
||||
|
||||
InitAtlasRegionParams :: struct {
|
||||
Init_Atlas_Region_Params :: struct {
|
||||
width : u32,
|
||||
height : u32,
|
||||
}
|
||||
|
||||
InitAtlasParams :: struct {
|
||||
width : u32,
|
||||
height : u32,
|
||||
glyph_padding : u32,
|
||||
Init_Atlas_Params :: struct {
|
||||
width : u32,
|
||||
height : u32,
|
||||
glyph_padding : u32,
|
||||
|
||||
region_a : InitAtlasRegionParams,
|
||||
region_b : InitAtlasRegionParams,
|
||||
region_c : InitAtlasRegionParams,
|
||||
region_d : InitAtlasRegionParams,
|
||||
region_a : Init_Atlas_Region_Params,
|
||||
region_b : Init_Atlas_Region_Params,
|
||||
region_c : Init_Atlas_Region_Params,
|
||||
region_d : Init_Atlas_Region_Params,
|
||||
}
|
||||
|
||||
InitAtlasParams_Default :: InitAtlasParams {
|
||||
Init_Atlas_Params_Default :: Init_Atlas_Params {
|
||||
width = 4096,
|
||||
height = 2048,
|
||||
glyph_padding = 4,
|
||||
@@ -108,34 +108,34 @@ InitAtlasParams_Default :: InitAtlasParams {
|
||||
}
|
||||
}
|
||||
|
||||
InitGlyphDrawParams :: struct {
|
||||
over_sample : Vec2i,
|
||||
buffer_batch : u32,
|
||||
draw_padding : u32,
|
||||
Init_Glyph_Draw_Params :: struct {
|
||||
over_sample : Vec2i,
|
||||
buffer_batch : u32,
|
||||
draw_padding : u32,
|
||||
}
|
||||
|
||||
InitGlyphDrawParams_Default :: InitGlyphDrawParams {
|
||||
Init_Glyph_Draw_Params_Default :: Init_Glyph_Draw_Params {
|
||||
over_sample = { 8, 8 },
|
||||
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,
|
||||
reserve_length : u32,
|
||||
}
|
||||
|
||||
InitShapeCacheParams_Default :: InitShapeCacheParams {
|
||||
capacity = 8 * 1024,
|
||||
reserve_length = 256,
|
||||
Init_Shape_Cache_Params_Default :: Init_Shape_Cache_Params {
|
||||
capacity = 8 * 1024,
|
||||
reserve_length = 256,
|
||||
}
|
||||
|
||||
// ve_fontcache_init
|
||||
startup :: proc( ctx : ^Context, parser_kind : ParserKind,
|
||||
startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
allocator := context.allocator,
|
||||
atlas_params := InitAtlasParams_Default,
|
||||
glyph_draw_params := InitGlyphDrawParams_Default,
|
||||
shape_cache_params := InitShapeCacheParams_Default,
|
||||
atlas_params := Init_Atlas_Params_Default,
|
||||
glyph_draw_params := Init_Glyph_Draw_Params_Default,
|
||||
shape_cache_params := Init_Shape_Cache_Params_Default,
|
||||
use_advanced_text_shaper : b32 = true,
|
||||
snap_shape_position : b32 = true,
|
||||
default_curve_quality : u32 = 3,
|
||||
@@ -158,7 +158,7 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
|
||||
}
|
||||
ctx.default_curve_quality = default_curve_quality
|
||||
|
||||
error : AllocatorError
|
||||
error : Allocator_Error
|
||||
entries, error = make( [dynamic]Entry, len = 0, cap = entires_reserve )
|
||||
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 )
|
||||
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")
|
||||
|
||||
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
|
||||
|
||||
@@ -194,8 +194,8 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind,
|
||||
}
|
||||
assert( capacity.x * capacity.y == expected_cap )
|
||||
|
||||
error : AllocatorError
|
||||
LRU_init( & state, capacity.x * capacity.y )
|
||||
error : Allocator_Error
|
||||
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_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.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")
|
||||
|
||||
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 )
|
||||
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" )
|
||||
|
||||
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)
|
||||
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" )
|
||||
|
||||
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 )
|
||||
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" )
|
||||
|
||||
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.calls, allocator )
|
||||
|
||||
LRU_reload( & atlas.region_a.state, allocator)
|
||||
LRU_reload( & atlas.region_b.state, allocator)
|
||||
LRU_reload( & atlas.region_c.state, allocator)
|
||||
LRU_reload( & atlas.region_d.state, allocator)
|
||||
lru_reload( & atlas.region_a.state, allocator)
|
||||
lru_reload( & atlas.region_b.state, allocator)
|
||||
lru_reload( & atlas.region_c.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 {
|
||||
stroage_entry := & shape_cache.storage[idx]
|
||||
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( & shape_cache.storage, allocator )
|
||||
LRU_reload( & shape_cache.state, allocator )
|
||||
lru_reload( & shape_cache.state, allocator )
|
||||
}
|
||||
|
||||
// ve_foncache_shutdown
|
||||
@@ -330,10 +330,10 @@ shutdown :: proc( ctx : ^Context )
|
||||
delete( draw_list.indices )
|
||||
delete( draw_list.calls )
|
||||
|
||||
LRU_free( & atlas.region_a.state )
|
||||
LRU_free( & atlas.region_b.state )
|
||||
LRU_free( & atlas.region_c.state )
|
||||
LRU_free( & atlas.region_d.state )
|
||||
lru_free( & atlas.region_a.state )
|
||||
lru_free( & atlas.region_b.state )
|
||||
lru_free( & atlas.region_c.state )
|
||||
lru_free( & atlas.region_d.state )
|
||||
|
||||
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
|
||||
stroage_entry := & shape_cache.storage[idx]
|
||||
@@ -342,7 +342,7 @@ shutdown :: proc( ctx : ^Context )
|
||||
delete( glyphs )
|
||||
delete( positions )
|
||||
}
|
||||
LRU_free( & shape_cache.state )
|
||||
lru_free( & shape_cache.state )
|
||||
|
||||
delete( glyph_buffer.draw_list.vertices )
|
||||
delete( glyph_buffer.draw_list.indices )
|
||||
@@ -357,7 +357,7 @@ shutdown :: proc( ctx : ^Context )
|
||||
}
|
||||
|
||||
// ve_fontcache_load
|
||||
load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32, glyph_curve_quality : u32 = 0 ) -> (font_id : 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( len(data) > 0 )
|
||||
@@ -386,9 +386,9 @@ load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32,
|
||||
shaper_info = shaper_load_font( & shaper_ctx, label, data, transmute(rawptr) id )
|
||||
|
||||
size = size_px
|
||||
size_scale = size_px < 0.0 ? \
|
||||
size_scale = size_px < 0.0 ? \
|
||||
parser_scale_for_pixel_height( & parser_info, -size_px ) \
|
||||
: parser_scale_for_mapping_em_to_pixels( & parser_info, size_px )
|
||||
: parser_scale_for_mapping_em_to_pixels( & parser_info, size_px )
|
||||
|
||||
if glyph_curve_quality == 0 {
|
||||
curve_quality = f32(ctx.default_curve_quality)
|
||||
@@ -397,15 +397,15 @@ load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32,
|
||||
curve_quality = f32(glyph_curve_quality)
|
||||
}
|
||||
}
|
||||
entry.id = FontID(id)
|
||||
ctx.entries[ id ].id = FontID(id)
|
||||
entry.id = Font_ID(id)
|
||||
ctx.entries[ id ].id = Font_ID(id)
|
||||
|
||||
font_id = FontID(id)
|
||||
font_id = Font_ID(id)
|
||||
return
|
||||
}
|
||||
|
||||
// ve_fontcache_unload
|
||||
unload_font :: proc( ctx : ^Context, font : FontID )
|
||||
unload_font :: proc( ctx : ^Context, font : Font_ID )
|
||||
{
|
||||
assert( ctx != nil )
|
||||
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)
|
||||
}
|
||||
|
||||
get_cursor_pos :: #force_inline proc "contextless" ( ctx : ^Context ) -> Vec2 { return ctx.cursor_pos }
|
||||
set_colour :: #force_inline proc "contextless" ( ctx : ^Context, colour : Colour ) { ctx.colour = colour }
|
||||
get_cursor_pos :: #force_inline proc( ctx : ^Context ) -> Vec2 { assert(ctx != nil); return ctx.cursor_pos }
|
||||
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)
|
||||
assert( ctx != nil )
|
||||
@@ -463,14 +463,14 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position,
|
||||
return true
|
||||
}
|
||||
|
||||
// ve_fontcache_drawlist
|
||||
get_draw_list :: proc( ctx : ^Context, optimize_before_returning := true ) -> ^DrawList {
|
||||
// ve_fontcache_Draw_List
|
||||
get_draw_list :: proc( ctx : ^Context, optimize_before_returning := true ) -> ^Draw_List {
|
||||
assert( ctx != nil )
|
||||
if optimize_before_returning do optimize_draw_list( & ctx.draw_list, 0 )
|
||||
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 )
|
||||
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 : ]
|
||||
@@ -479,7 +479,7 @@ get_draw_list_layer :: proc( ctx : ^Context, optimize_before_returning := true )
|
||||
return
|
||||
}
|
||||
|
||||
// ve_fontcache_flush_drawlist
|
||||
// ve_fontcache_flush_Draw_List
|
||||
flush_draw_list :: proc( ctx : ^Context ) {
|
||||
assert( ctx != nil )
|
||||
using ctx
|
||||
@@ -501,7 +501,7 @@ flush_draw_list_layer :: proc( ctx : ^Context ) {
|
||||
|
||||
//#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)
|
||||
assert( ctx != nil )
|
||||
@@ -512,7 +512,7 @@ measure_text_size :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) -
|
||||
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( font >= 0 && int(font) < len(ctx.entries) )
|
||||
|
Reference in New Issue
Block a user