Some progress on fontstash

This commit is contained in:
Edward R. Gonzalez 2024-05-31 19:31:08 -04:00
parent f415eada0d
commit d63242ac9c
5 changed files with 145 additions and 68 deletions

View File

@ -47,9 +47,8 @@ atlas_add_skyline_level :: proc (ctx : ^Context, id : u64, x, y, width, height :
return
}
atlas_delete :: proc ( ctx : ^Context ) {
using ctx
array_free( ctx.atlas )
atlas_delete :: proc () {
delete(Module_Context.atlas)
}
atlas_expand :: proc( ctx : ^Context, width, height : i32 )
@ -65,18 +64,18 @@ atlas_expand :: proc( ctx : ^Context, width, height : i32 )
atlas_init :: proc( ctx : ^Context, width, height : i32, num_nodes : u32 = Init_Atlas_Nodes )
{
error : AllocatorError
ctx.atlas, error = init_reserve( AtlasNode, context.allocator, u64(num_nodes), dbg_name = "font atlas" )
ctx.atlas, error = make( Array(AtlasNode), u64(num_nodes), dbg_name = "font atlas" )
ensure(error != AllocatorError.None, "Failed to allocate font atlas")
ctx.width = width
ctx.height = height
array_append( & ctx.atlas, AtlasNode{ width = i16(width)} )
append( & ctx.atlas, AtlasNode{ width = i16(width)} )
}
atlas_insert :: proc( ctx : ^Context, id : u64, x, y, width : i32 ) -> (error : AllocatorError)
{
error = array_append_at( & ctx.atlas, AtlasNode{ i16(x), i16(y), i16(width) }, id )
error = append_at( & ctx.atlas, AtlasNode{ i16(x), i16(y), i16(width) }, id )
return
}
@ -88,7 +87,7 @@ atlas_reset :: proc( ctx : ^Context, width, height : i32 )
ctx.height = height
clear( ctx.atlas )
array_append( & ctx.atlas, AtlasNode{ width = i16(width)} )
append( & ctx.atlas, AtlasNode{ width = i16(width)} )
}
atlas_rect_fits :: proc( ctx : ^Context, location, width, height : i32 ) -> (max_height : i32)

View File

@ -0,0 +1,93 @@
package fontstash
import "base:runtime"
// Legacy of original implementation
// Not sure going to use
Params :: struct {
parser_kind : ParserKind,
width, height : i32,
quad_location : QuadLocation, // (flags)
render_create : RenderCreateProc,
render_resize : RenderResizeProc,
render_update : RenderUpdateProc,
render_draw : RenderDrawProc,
render_delete : RenderDelete,
}
CB_Resize :: #type proc(data : rawptr, width, height : u32 )
CB_Update :: #type proc(data : rawptr, dirty_rect : Rect, texture_data : rawptr )
Callbacks :: struct {
resize : CB_Resize,
update : CB_Update,
}
Context :: struct {
callstack_ctx : runtime.Context,
// params : Params,
parser_kind : ParserKind,
fonts : Array(Font),
// Atlas
atlas : Array(AtlasNode),
texture_data : []byte,
width, height : i32,
// ----
normalized_size : Vec2,
verts : [Vertex_Count * 2]f32,
tcoords : [Vertex_Count * 2]f32,
colors : [Vertex_Count ]f32,
vis_stack : StackFixed(VisState, Max_VisStates),
quad_location : QuadLocation,
// dirty rectangle of the texture regnion that was updated
dirty_rect : Rect,
handle_error : HandleErrorProc,
error_uptr : rawptr,
using callbacks : Callbacks,
}
// The package assumes this will exist so long as the owning runtime module is loaded and it has been initialized before usage.
Module_Context : ^Context
destroy_context :: proc()
{
using Module_Context
// for & font in array_to_slice(fonts) {
// }
delete( fonts )
delete( atlas )
}
// For usage during hot-reload, when the instance reference of a context is lost.
reload_context :: proc( ctx : ^Context )
{
Module_Context = ctx
using Module_Context
callstack_ctx = context
}
startup_context :: proc( ctx : ^Context, parser_kind : ParserKind, width, height : u32, quad_location : QuadLocation )
{
Module_Context = ctx
using Module_Context
callstack_ctx = context
error : AllocatorError
fonts, error = make( Array(Font), 8 )
assert( error == AllocatorError.None, "Failed to allocate fonts array" )
}

View File

@ -35,15 +35,15 @@ Range2_i16 :: struct #raw_union {
}
}
Vec2 :: [2]f32
Vec2 :: [2]f32
Vec2_i16 :: [2]i16
Rect :: [4]f32
Invalid :: -1
Hash_Lut_Size :: 256
Max_Fallbacks :: 20
Max_States :: 20
Max_VisStates :: 20
Vertex_Count :: 1024
Init_Atlas_Nodes :: 256
@ -105,7 +105,6 @@ Glyph :: struct {
}
Font :: struct {
parser_kind : ParserKind,
parser_data : ParserData,
name : string,
data : []byte,
@ -121,17 +120,8 @@ Font :: struct {
num_fallbacks : i32,
}
Params :: struct {
width, height : i32,
quad_location : QuadLocation, // (flags)
render_create : RenderCreateProc,
render_resize : RenderResizeProc,
render_update : RenderUpdateProc,
render_draw : RenderDrawProc,
render_delete : RenderDelete,
}
State :: struct {
// Visible State tracking used for sharing font visualization preferences.
VisState :: struct {
font : i32,
alignment : i32,
size : f32,
@ -158,28 +148,6 @@ TextIter :: struct {
end : string,
}
Context :: struct {
params : Params,
// Atlas
atlas : Array(AtlasNode),
texture_data : []byte,
width, height : i32,
// ----
normalized_size : Vec2,
verts : [Vertex_Count * 2]f32,
tcoords : [Vertex_Count * 2]f32,
colors : [Vertex_Count ]f32,
states : [Max_States]State,
num_states : i32,
handle_error : HandleErrorProc,
error_uptr : rawptr,
}
decode_utf8 :: proc( state : ^rune, codepoint : ^rune, to_decode : byte ) -> bool
{
UTF8_Accept :: 0
@ -217,4 +185,3 @@ decode_utf8 :: proc( state : ^rune, codepoint : ^rune, to_decode : byte ) -> boo
(state^) = cast(rune)(UTF8_Decode_Table[256 + (state^) * 16 + rune(type)])
return (state^) == UTF8_Accept
}

View File

@ -1,7 +1,5 @@
package fontstash
import "core:mem"
AllocatorError :: mem.Allocator_Error
@ -10,18 +8,28 @@ import "codebase:grime"
// asserts
ensure :: grime.ensure
verify :: grime.verify
// container
Array :: grime.Array
array_init_reserve :: grime.array_init_reserve
array_append :: grime.array_append
array_append_at :: grime.array_append_at
array_clear :: grime.array_clear
array_free :: grime.array_free
array_remove_at :: grime.array_remove_at
array_to_slice :: grime.array_to_slice
array_init :: grime.array_init
array_append :: grime.array_append
array_append_at :: grime.array_append_at
array_clear :: grime.array_clear
array_free :: grime.array_free
array_remove_at :: grime.array_remove_at
array_to_slice :: grime.array_to_slice
StackFixed :: grime.StackFixed
stack_clear :: grime.stack_clear
stack_push :: grime.stack_push
stack_pop :: grime.stack_pop
stack_peek_ref :: grime.stack_peek_ref
stack_peek :: grime.stack_peek
stack_push_contextless :: grime.stack_push_contextless
//#region("Proc overload mappings")
@ -32,19 +40,20 @@ append :: proc {
}
append_at :: proc {
array_append_at,
grime.array_append_at_slice,
grime.array_append_at_value,
}
clear :: proc {
array_clear,
}
free :: proc {
delete :: proc {
array_free,
}
init_reserve :: proc {
array_init_reserve,
make :: proc {
array_init,
}
remove_at :: proc {

View File

@ -10,41 +10,50 @@ ParserKind :: enum u32 {
ParserData :: struct #raw_union {
stbtt_info : stbtt.fontinfo,
// freetype_info :
// freetype_info :
}
ParserContext :: struct {
ft_library : freetype.Library
}
//#region("freetype")
ft_init :: proc() -> i32 {
using Module_Context
return 1
}
//#endregion("freetype")
//#region("stb_truetype")
fstash_tt_init :: proc( ctx : ^Context ) -> i32 { return 1 }
tt_init :: proc() -> i32 { return 1 }
fstash_tt_load_font :: proc( ctx : ^Context, parser_data : ^ParserData, data : []byte ) -> b32
tt_load_font :: proc( parser_data : ^ParserData, data : []byte ) -> b32
{
parser_data.stbtt_info.userdata = ctx
parser_data.stbtt_info.userdata = Module_Context
stb_error := stbtt.InitFont( & parser_data.stbtt_info, & data[0], 0 )
return stb_error
}
fstash_tt_get_font_metrics :: proc( parser_data : ^ParserData, ascent, descent, line_gap : ^i32 ) {
tt_get_font_metrics :: proc( parser_data : ^ParserData, ascent, descent, line_gap : ^i32 ) {
stbtt.GetFontVMetrics( & parser_data.stbtt_info, ascent, descent, line_gap )
}
fstash_tt_get_pixel_height_scale :: proc( parser_data : ^ParserData, size : f32 ) -> f32
tt_get_pixel_height_scale :: proc( parser_data : ^ParserData, size : f32 ) -> f32
{
return stbtt.ScaleForPixelHeight( & parser_data.stbtt_info, size )
}
fstash_tt_get_glyph_index :: proc( parser_data : ^ParserData, codepoint : rune ) -> i32
tt_get_glyph_index :: proc( parser_data : ^ParserData, codepoint : rune ) -> i32
{
return stbtt.FindGlyphIndex( & parser_data.stbtt_info, codepoint )
}
fstash_tt_build_glyph_bitmap :: proc( parser_data : ^ParserData, glyph_index : i32,
tt_build_glyph_bitmap :: proc( parser_data : ^ParserData, glyph_index : i32,
size, scale : f32, advance, left_side_bearing, x0, y0, x1, y1 : ^i32 ) -> i32
{
stbtt.GetGlyphHMetrics( & parser_data.stbtt_info, glyph_index, advance, left_side_bearing )
@ -52,13 +61,13 @@ fstash_tt_build_glyph_bitmap :: proc( parser_data : ^ParserData, glyph_index : i
return 1
}
fstash_tt_render_glyph_bitmap :: proc( parser_data : ^ParserData, output : [^]byte,
tt_render_glyph_bitmap :: proc( parser_data : ^ParserData, output : [^]byte,
out_width, out_height, out_stride : i32, scale_x, scale_y : f32, glyph_index : i32 )
{
stbtt.MakeGlyphBitmap( & parser_data.stbtt_info, output, out_width, out_height, out_stride, scale_x, scale_y, glyph_index )
}
fstash_tt_get_glyph_kern_advance :: proc( parser_data : ^ParserData, glyph_1, glyph_2 : i32 ) -> i32
tt_get_glyph_kern_advance :: proc( parser_data : ^ParserData, glyph_1, glyph_2 : i32 ) -> i32
{
return stbtt.GetGlyphKernAdvance( & parser_data.stbtt_info, glyph_1, glyph_2 )
}