Progress on porting fontstash
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| package fontstash | ||||
|  | ||||
| import "base:runtime" | ||||
| import "core:slice" | ||||
|  | ||||
| // Legacy of original implementation | ||||
| // Not sure going to use | ||||
| @@ -15,12 +16,12 @@ Params :: struct { | ||||
| 	render_delete : RenderDelete, | ||||
| } | ||||
|  | ||||
| CB_Resize :: #type proc(data : rawptr, width, height : u32 ) | ||||
| CB_Update :: #type proc(data : rawptr, dirty_rect : Rect, texture_data : rawptr ) | ||||
| OnResizeProc :: #type proc(data : rawptr, width, height : u32 ) | ||||
| OnUpdateProc :: #type proc(data : rawptr, dirty_rect : Rect, texture_data : rawptr ) | ||||
|  | ||||
| Callbacks :: struct { | ||||
| 	resize : CB_Resize, | ||||
| 	update : CB_Update, | ||||
| 	resize : OnResizeProc, | ||||
| 	update : OnUpdateProc, | ||||
| } | ||||
|  | ||||
| Context :: struct { | ||||
| @@ -29,6 +30,7 @@ Context :: struct { | ||||
| 	// params : Params, | ||||
|  | ||||
| 	parser_kind : ParserKind, | ||||
| 	parser_ctx  : ParserContext, | ||||
|  | ||||
| 	fonts : Array(Font), | ||||
|  | ||||
| @@ -46,13 +48,13 @@ Context :: struct { | ||||
|  | ||||
| 	vis_stack  : StackFixed(VisState, Max_VisStates), | ||||
|  | ||||
| 	quad_location : QuadLocation, | ||||
| 	quad_loc : QuadLocation, | ||||
|  | ||||
| 	// dirty rectangle of the texture regnion that was updated | ||||
| 	dirty_rect : Rect, | ||||
|  | ||||
| 	handle_error : HandleErrorProc, | ||||
| 	error_uptr   : rawptr, | ||||
| 	handle_error   : HandleErrorProc, | ||||
| 	error_userdata : rawptr, | ||||
|  | ||||
| 	using callbacks : Callbacks, | ||||
| } | ||||
| @@ -64,11 +66,18 @@ destroy_context :: proc() | ||||
| { | ||||
| 	using Module_Context | ||||
|  | ||||
| 	// for & font in array_to_slice(fonts) { | ||||
| 	// } | ||||
| 	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. | ||||
| @@ -80,14 +89,60 @@ reload_context :: proc( ctx : ^Context ) | ||||
| 	callstack_ctx = context | ||||
| } | ||||
|  | ||||
| startup_context :: proc( ctx : ^Context, parser_kind : ParserKind, width, height : u32, quad_location : QuadLocation ) | ||||
| { | ||||
| 	Module_Context = ctx | ||||
| rest :: proc() { | ||||
| 	using Module_Context | ||||
|  | ||||
| 	callstack_ctx = 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() | ||||
| } | ||||
|   | ||||
| @@ -7,6 +7,15 @@ So The code was small enough that I mine as well learn it by porting for my use | ||||
| 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 | ||||
|   | ||||
| @@ -14,13 +14,14 @@ verify :: grime.verify | ||||
|  | ||||
| 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_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 | ||||
|  | ||||
| @@ -64,4 +65,8 @@ to_slice :: proc { | ||||
| 	array_to_slice, | ||||
| } | ||||
|  | ||||
| underlying_slice :: proc { | ||||
| 	array_underlying_slice, | ||||
| } | ||||
|  | ||||
| //#endregion("Proc overload mappings") | ||||
|   | ||||
| @@ -29,12 +29,12 @@ Array :: struct ( $ Type : typeid ) { | ||||
| array_underlying_slice :: proc(slice: []($ Type)) -> Array(Type) | ||||
| { | ||||
| 	if len(slice) == 0 { | ||||
| 			return nil | ||||
| 			return {nil} | ||||
| 	} | ||||
| 	array_size := size_of( Array(Type)) | ||||
| 	raw_data   := & slice[0] | ||||
| 	array_ptr  := cast( ^Array(Type)) ( uintptr(first_element_ptr) - uintptr(array_size)) | ||||
| 	return array_ptr ^ | ||||
| 	header_size := size_of( ArrayHeader(Type)) | ||||
| 	raw_data    := & slice[0] | ||||
| 	array       := transmute( Array(Type)) ( uintptr(raw_data) - uintptr(header_size)) | ||||
| 	return array | ||||
| } | ||||
|  | ||||
| array_to_slice          :: #force_inline proc( using self : Array($ Type) ) -> []Type { return slice_ptr( data, int(num))      } | ||||
| @@ -180,7 +180,10 @@ array_append_at_slice :: proc( using self : ^Array( $ Type ), items : []Type, id | ||||
| 	return AllocatorError.None | ||||
| } | ||||
|  | ||||
| // array_back :: proc( ) | ||||
| array_back :: proc( self : Array($Type) ) -> Type { | ||||
| 	value := self.data[self.num - 1] | ||||
| 	return value | ||||
| } | ||||
|  | ||||
| // array_push_back :: proc( using self : Array( $ Type)) -> b32 { | ||||
| // 	if num == capacity { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import "core:fmt" | ||||
| import "core:os" | ||||
| import "base:runtime" | ||||
|  | ||||
| // TODO(Ed): Make an async option... | ||||
| file_copy_sync :: proc( path_src, path_dst: string, allocator := context.allocator ) -> b32 | ||||
| { | ||||
|   file_size : i64 | ||||
|   | ||||
| @@ -70,15 +70,16 @@ render :: proc() | ||||
| 	// learnopengl.com/In-Practice/Text-Rendering | ||||
| 	if true | ||||
| 	{ | ||||
| 		profile("learngl_text_render_pass") | ||||
| 		using font_provider_data | ||||
|  | ||||
| 	  green_value := debug.gfx_clear_demo_pass_action.colors[0].clear_value.g + 0.01 | ||||
| 	  debug.gfx_clear_demo_pass_action.colors[0].clear_value.g = green_value > 1.0 ? 0.0 : green_value | ||||
| 	  sokol_gfx.begin_pass( sokol_gfx.Pass { | ||||
| 	  	action    = debug.gfx_clear_demo_pass_action, | ||||
| 	  	swapchain = sokol_glue.swapchain() | ||||
| 	  }) | ||||
| 		// sokol_gfx.begin_pass(sokol_gfx.Pass { action = pass_actions.bg_clear_black, swapchain = sokol_glue.swapchain() }) | ||||
| 	  // green_value := debug.gfx_clear_demo_pass_action.colors[0].clear_value.g + 0.01 | ||||
| 	  // debug.gfx_clear_demo_pass_action.colors[0].clear_value.g = green_value > 1.0 ? 0.0 : green_value | ||||
| 	  // sokol_gfx.begin_pass( sokol_gfx.Pass { | ||||
| 	  // 	action    = debug.gfx_clear_demo_pass_action, | ||||
| 	  // 	swapchain = sokol_glue.swapchain() | ||||
| 	  // }) | ||||
| 		sokol_gfx.begin_pass(sokol_gfx.Pass { action = pass_actions.bg_clear_black, swapchain = sokol_glue.swapchain() }) | ||||
| 		sokol_gfx.apply_pipeline( gfx_pipeline ) | ||||
| 		// sokol_gfx.update_buffer( gfx_vbuffer, sokol_gfx.Range{ , Font_Provider_Ggfx_Buffer_Size } ) | ||||
|  | ||||
| @@ -131,7 +132,7 @@ render :: proc() | ||||
| 				5 = { 1.0, 0.0 }, | ||||
| 			} | ||||
|  | ||||
| 			color : Vec3 = { 0.2, 0.2, 0.2 } | ||||
| 			color : Vec3 = { 1.0, 1.0, 1.0 } | ||||
| 			fs_uniform := Font_Glyph_Fs_Params { | ||||
| 				glyph_color = color | ||||
| 			} | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| /* Space | ||||
| 
 | ||||
| Provides various definitions for converting from one standard of measurement to another. | ||||
| Provides constructs and transformations in reguards to space. | ||||
| 
 | ||||
| 
 | ||||
| Ultimately the user's window ppcm (pixels-per-centimeter) determins how all virtual metric conventions are handled. | ||||
| */ | ||||
		Reference in New Issue
	
	Block a user