Removing fontstash and RFont from codebase

Planning to instead just focus on using VEFontCache.
This commit is contained in:
Edward R. Gonzalez 2024-06-18 11:18:33 -04:00
parent d6cd65288f
commit 156ddcef97
6 changed files with 0 additions and 624 deletions

View File

@ -1,2 +0,0 @@
package RFont

View File

@ -1,131 +0,0 @@
package fontstash
atlas_add_rect :: proc( ctx : ^Context, )
{
}
atlas_add_skyline_level :: proc (ctx : ^Context, id : u64, x, y, width, height : i32 ) -> (error : AllocatorError)
{
error = atlas_insert( ctx, id, x, y + height, width)
if error != AllocatorError.None {
ensure( false, "Failed to insert into atlas")
return
}
// Delete skyline segments that fall under the shadow of the new segment.
for sky_id := id; sky_id < ctx.atlas.num; sky_id += 1
{
curr := & ctx.atlas.data[sky_id ]
next := & ctx.atlas.data[sky_id + 1]
if curr.x >= next.x + next.width do break
shrink := i16(next.x + next.width - curr.x)
curr.x += shrink
curr.width -= shrink
if curr.width > 0 do break
atlas_remove(ctx, sky_id)
sky_id -= 1
}
// Merge same height skyline segments that are next to each other.
for sky_id := id; sky_id < ctx.atlas.num - 1;
{
curr := & ctx.atlas.data[sky_id ]
next := & ctx.atlas.data[sky_id + 1]
if curr.y == next.y {
curr.width += next.width
atlas_remove(ctx, sky_id + 1)
}
else {
sky_id += 1
}
}
return
}
atlas_delete :: proc () {
delete(Module_Context.atlas)
}
atlas_expand :: proc( ctx : ^Context, width, height : i32 )
{
if width > ctx.width {
atlas_insert( ctx, ctx.atlas.num, ctx.width, 0, width - ctx.width )
}
ctx.width = width
ctx.height = height
}
atlas_init :: proc( ctx : ^Context, width, height : i32, num_nodes : u32 = Init_Atlas_Nodes )
{
error : AllocatorError
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
append( & ctx.atlas, AtlasNode{ width = i16(width)} )
}
atlas_insert :: proc( ctx : ^Context, id : u64, x, y, width : i32 ) -> (error : AllocatorError)
{
error = append_at( & ctx.atlas, AtlasNode{ i16(x), i16(y), i16(width) }, id )
return
}
atlas_remove :: #force_inline proc( ctx : ^Context, id : u64 ) { remove_at( ctx.atlas, id ) }
atlas_reset :: proc( ctx : ^Context, width, height : i32 )
{
ctx.width = width
ctx.height = height
clear( ctx.atlas )
append( & ctx.atlas, AtlasNode{ width = i16(width)} )
}
atlas_rect_fits :: proc( ctx : ^Context, location, width, height : i32 ) -> (max_height : i32)
{
// Checks if there is enough space at the location of skyline span 'i',
// and return the max height of all skyline spans under that at that location,
// (think tetris block being dropped at that position). Or -1 if no space found.
atlas := to_slice(ctx.atlas)
node := atlas[location]
space_left : i32
if i32(node.x) + width > ctx.width {
max_height = -1
return
}
space_left = width;
y := i32(node.y)
location := location
for ; space_left > 0;
{
if u64(location) == ctx.atlas.num {
max_height = -1
return
}
node := atlas[location]
y := max(y, i32(node.y))
if y + height > ctx.height {
max_height = -1
return
}
space_left -= i32(node.width)
location += 1
}
max_height = y
return
}

View File

@ -1,148 +0,0 @@
package fontstash
import "base:runtime"
import "core:slice"
// 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,
}
OnResizeProc :: #type proc(data : rawptr, width, height : u32 )
OnUpdateProc :: #type proc(data : rawptr, dirty_rect : Rect, texture_data : rawptr )
Callbacks :: struct {
resize : OnResizeProc,
update : OnUpdateProc,
}
Context :: struct {
callstack_ctx : runtime.Context,
// params : Params,
parser_kind : ParserKind,
parser_ctx : ParserContext,
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_loc : QuadLocation,
// dirty rectangle of the texture regnion that was updated
dirty_rect : Rect,
handle_error : HandleErrorProc,
error_userdata : 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) {
if font.free_data {
// delete(font.data)
}
// delete(font.name)
delete(font.glyphs)
}
delete( fonts )
delete( atlas )
delete( array_underlying_slice(texture_data) )
// delete( vis_stack )
}
// 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
}
rest :: proc() {
using Module_Context
// atlas_reset()
// dirty_rect_reset()
slice.zero(texture_data)
for & font in array_to_slice(fonts) {
// font_lut_reset( & font )
}
// atlas_add_white_rect(2, 2)
// push_vis_state()
// clear_vis_state()
}
// Its recommmended to use an allocator that can handle resizing efficiently for the atlas nodes & texture (at least)
startup_context :: proc( ctx : ^Context, parser_kind : ParserKind,
atlas_texture_width, atlas_texture_height : u32, quad_origin_location : QuadLocation,
allocator := context.allocator )
{
Module_Context = ctx
using Module_Context
width = cast(i32) atlas_texture_width
height = cast(i32) atlas_texture_height
quad_loc = quad_origin_location
context.allocator = allocator
callstack_ctx = context
error : AllocatorError
fonts, error = make( Array(Font), 8 )
assert( error == AllocatorError.None, "Failed to allocate fonts array" )
texture_data_array : Array(byte)
texture_data_array, error = make( Array(byte), u64(width * height) )
assert( error == AllocatorError.None, "Failed to allocate fonts array" )
texture_data = array_to_slice(texture_data_array)
// TODO(Ed): Verfiy and remove
{
quick_check := underlying_slice(texture_data)
assert( & texture_data_array.header == & quick_check )
}
atlas, error = make( Array(AtlasNode), Init_Atlas_Nodes )
assert( error == AllocatorError.None, "Failed to allocate fonts array" )
// dirty_rect_reset()
append(& atlas, AtlasNode { width = i16(width) })
// atlas_add_white_rect(2, 2)
// push_vis_state()
// clear_vis_state()
}

View File

@ -1,196 +0,0 @@
/*
Yet another port of fontstash.
I decided to use this instead of the odin port as it deviated from the original, making it difficult to sift through.
So The code was small enough that I mine as well learn it by porting for my use case.
TODO(Ed): Add docs here and throughout
TODO(Ed): This is unfinished...
Changes from fontstash:
* This was setup & tested for single-threaded tasks
* There is an assumed runtime context assigned on startup (user decides where the context memory is)
Influnce from Odin's vendor Port:
* Manages a lookup table for frequent glyphs
* Atlas can resize
* No scratch allocation, user can specify allocator
* Supports rendering with nanovg
Original author's copyright for fonstash.h:
------------------------------------------------------------------------------
Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
------------------------------------------------------------------------------
*/
package fontstash
Range2_i16 :: struct #raw_union {
using pts : Vec2_i16,
using xy : struct {
x0, y0, x1, y1 : i16,
}
}
Vec2 :: [2]f32
Vec2_i16 :: [2]i16
Rect :: [4]f32
Invalid :: -1
Hash_Lut_Size :: 256
Max_Fallbacks :: 20
Max_VisStates :: 20
Vertex_Count :: 1024
Init_Atlas_Nodes :: 256
FontLuts :: [Hash_Lut_Size]i32
FontFallbacks :: [Max_Fallbacks]i32
HandleErrorProc :: #type proc( uptr : rawptr, error, val : i32 )
RenderCreateProc :: #type proc( uptr : rawptr, width, height : i32 )
RenderResizeProc :: #type proc( uptr : rawptr, width, height : i32 )
RenderUpdateProc :: #type proc( uptr : rawptr, rect : ^i32, data : ^u8 )
RenderDrawProc :: #type proc( uptr : rawptr, verts : ^f32, tcoords : ^f32, colors : ^i32, num_verts : i32 )
RenderDelete :: #type proc( uptr : rawptr )
AlignFlag :: enum u32 {
Left,
Center,
Right,
Top,
Middle,
Bottom,
Baseline,
}
AlignFlags :: bit_set[ AlignFlag; u32 ]
// FONSflags
QuadLocation :: enum u32 {
Top_Left = 1,
Bottom_Left = 2,
}
Atlas :: struct {
dud : i32,
}
AtlasNode :: struct {
x, y, width : i16,
}
ErrorCode :: enum u32 {
Atlas_Full,
Scratch_Full,
States_Overflow,
States_Underflow,
}
Quad :: struct {
x0, y0, s0, t0 : f32,
x1, y1, s1, t1 : f32,
}
Glyph :: struct {
codepoint : rune,
index, next : i32,
size, blur : i16,
x_advance : i16,
box : Range2_i16,
offset : Vec2_i16,
}
Font :: struct {
parser_data : ParserData,
name : string,
data : []byte,
free_data : bool,
ascender : f32,
descender : f32,
line_height : f32,
glyphs : Array(Glyph),
lut : FontLuts,
fallbacks : FontFallbacks,
num_fallbacks : i32,
}
// Visible State tracking used for sharing font visualization preferences.
VisState :: struct {
font : i32,
alignment : i32,
size : f32,
color : [4]u8,
blur : f32,
spacing : f32,
}
TextIter :: struct {
x, y : f32,
next_x, next_y : f32,
scale, spacing : f32,
isize, iblur : i16,
font : ^Font,
prev_glyph_id : i32,
codepoint : rune,
utf8_state : rune,
str : string,
next : string,
end : string,
}
decode_utf8 :: proc( state : ^rune, codepoint : ^rune, to_decode : byte ) -> bool
{
UTF8_Accept :: 0
UTF8_Reject :: 1
@static UTF8_Decode_Table := [?]u8 {
// The first part of the table maps bytes to character classes that
// to reduce the size of the transition table and create bitmasks.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9F
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // A0..BF
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // C0..DF
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, // E0..FF
// The second part is a transition table that maps a combination
// of a state of the automaton and a character class to a state.
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
12,36,12,12,12,12,12,12,12,12,12,12,
}
to_decode_rune := rune(to_decode)
type := UTF8_Decode_Table[to_decode_rune]
// Update codepoint otherwise initialize it.
(codepoint^) = ((state^) != UTF8_Accept) ? \
((to_decode_rune & 0x3F) | ((codepoint^) << 6)) \
: ((0xFF >> type) & (to_decode_rune))
(state^) = cast(rune)(UTF8_Decode_Table[256 + (state^) * 16 + rune(type)])
return (state^) == UTF8_Accept
}

View File

@ -1,72 +0,0 @@
package fontstash
import "core:mem"
AllocatorError :: mem.Allocator_Error
import "codebase:grime"
// asserts
ensure :: grime.ensure
verify :: grime.verify
// container
Array :: grime.Array
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
array_underlying_slice :: grime.array_underlying_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")
append :: proc {
grime.array_append_array,
grime.array_append_slice,
grime.array_append_value,
}
append_at :: proc {
grime.array_append_at_slice,
grime.array_append_at_value,
}
clear :: proc {
array_clear,
}
delete :: proc {
array_free,
}
make :: proc {
array_init,
}
remove_at :: proc {
array_remove_at,
}
to_slice :: proc {
array_to_slice,
}
underlying_slice :: proc {
array_underlying_slice,
}
//#endregion("Proc overload mappings")

View File

@ -1,75 +0,0 @@
package fontstash
import stbtt "vendor:stb/truetype"
import freetype "thirdparty:freetype"
ParserKind :: enum u32 {
stb_true_type,
freetype,
}
ParserData :: struct #raw_union {
stbtt_info : stbtt.fontinfo,
// freetype_info :
}
ParserContext :: struct {
ft_library : freetype.Library
}
//#region("freetype")
ft_init :: proc() -> i32 {
using Module_Context
return 1
}
//#endregion("freetype")
//#region("stb_truetype")
tt_init :: proc() -> i32 { return 1 }
tt_load_font :: proc( parser_data : ^ParserData, data : []byte ) -> b32
{
parser_data.stbtt_info.userdata = Module_Context
stb_error := stbtt.InitFont( & parser_data.stbtt_info, & data[0], 0 )
return stb_error
}
tt_get_font_metrics :: proc( parser_data : ^ParserData, ascent, descent, line_gap : ^i32 ) {
stbtt.GetFontVMetrics( & parser_data.stbtt_info, ascent, descent, line_gap )
}
tt_get_pixel_height_scale :: proc( parser_data : ^ParserData, size : f32 ) -> f32
{
return stbtt.ScaleForPixelHeight( & parser_data.stbtt_info, size )
}
tt_get_glyph_index :: proc( parser_data : ^ParserData, codepoint : rune ) -> i32
{
return stbtt.FindGlyphIndex( & parser_data.stbtt_info, codepoint )
}
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 )
stbtt.GetGlyphBitmapBox( & parser_data.stbtt_info, glyph_index, scale, scale, x0, y0, x1, y1 )
return 1
}
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 )
}
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 )
}
//#endregion("stb_truetype")