Restructured the codebase yet again but this time with compiler support for monlithic packages
So no need to stage generate symbolic links in a flat directory for the compiler
This commit is contained in:
		
							
								
								
									
										193
									
								
								code/sectr/font/provider.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								code/sectr/font/provider.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| package sectr | ||||
|  | ||||
| import "core:fmt" | ||||
| import "core:math" | ||||
| import "core:mem" | ||||
| import "core:path/filepath" | ||||
| import "core:os" | ||||
|  | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| Font_Largest_Px_Size :: 32 | ||||
|  | ||||
| Font_Size_Interval :: 2 | ||||
|  | ||||
| // Font_Default :: "" | ||||
| Font_Default            :: FontID { 0, "" } | ||||
| Font_Default_Point_Size :: 18.0 | ||||
|  | ||||
| Font_TTF_Default_Chars_Padding :: 4 | ||||
|  | ||||
| Font_Load_Use_Default_Size :: -1 | ||||
| Font_Load_Gen_ID           :: "" | ||||
|  | ||||
| Font_Atlas_Packing_Method :: enum u32 { | ||||
| 	Raylib_Basic  = 0, // Basic packing algo | ||||
| 	Skyeline_Rect = 1, // stb_pack_rect | ||||
| } | ||||
|  | ||||
| FontID  :: struct { | ||||
| 	key   : u64, | ||||
| 	label : string, | ||||
| } | ||||
| FontTag :: struct { | ||||
| 	key        : FontID, | ||||
| 	point_size : f32 | ||||
| } | ||||
|  | ||||
| FontGlyphsRender :: struct { | ||||
| 	size    : i32, | ||||
| 	count   : i32, | ||||
| 	padding : i32, | ||||
| 	texture : rl.Texture2D, | ||||
| 	recs    : [^]rl.Rectangle, // Characters rectangles in texture | ||||
| 	glyphs  : [^]rl.GlyphInfo, // Characters info data | ||||
| } | ||||
|  | ||||
| FontDef :: struct { | ||||
| 	path_file    : string, | ||||
|  | ||||
| 	// TODO(Ed) : you may have to store font data in the future if we render on demand | ||||
| 	// data         : []u8, | ||||
|  | ||||
| 	default_size : i32, | ||||
| 	size_table   : [Font_Largest_Px_Size / Font_Size_Interval] FontGlyphsRender, | ||||
| } | ||||
|  | ||||
| FontProviderData :: struct { | ||||
| 	// font_cache : HMapZPL(FontDef), | ||||
| 	font_cache : HMapChainedPtr(FontDef), | ||||
| } | ||||
|  | ||||
| font_provider_startup :: proc() | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	state := get_state() | ||||
| 	font_provider_data := & get_state().font_provider_data; using font_provider_data | ||||
|  | ||||
| 	font_cache_alloc_error : AllocatorError | ||||
| 	font_cache, font_cache_alloc_error = hmap_chained_init(FontDef, hmap_closest_prime(1 * Kilo), persistent_allocator(), dbg_name = "font_cache" ) | ||||
| 	verify( font_cache_alloc_error == AllocatorError.None, "Failed to allocate font_cache" ) | ||||
|  | ||||
| 	log("font_cache created") | ||||
| 	log("font_provider initialized") | ||||
| } | ||||
|  | ||||
| font_provider_shutdown :: proc() | ||||
| { | ||||
| 	font_provider_data := & get_state().font_provider_data; using font_provider_data | ||||
|  | ||||
| 	for & entry in font_cache.lookup | ||||
| 	{ | ||||
| 		if entry == nil do continue | ||||
|  | ||||
| 		def := entry.value | ||||
| 		for & px_render in def.size_table { | ||||
| 			using px_render | ||||
| 			rl.UnloadFontData( glyphs, count ) | ||||
| 			rl.UnloadTexture ( texture ) | ||||
| 			rl.MemFree( recs ) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| font_load :: proc( path_file : string, | ||||
| 	default_size : f32    = Font_Load_Use_Default_Size, | ||||
| 	desired_id   : string = Font_Load_Gen_ID | ||||
| ) -> FontID | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	log( str_fmt_tmp("Loading font: %v", path_file)) | ||||
| 	font_provider_data := & get_state().font_provider_data; using font_provider_data | ||||
|  | ||||
| 	font_data, read_succeded : = os.read_entire_file( path_file, context.temp_allocator ) | ||||
| 	verify( b32(read_succeded), str_fmt_tmp("Failed to read font file for: %v", path_file) ) | ||||
| 	font_data_size := cast(i32) len(font_data) | ||||
|  | ||||
| 	desired_id := desired_id | ||||
| 	// Use file name as key | ||||
| 	if len(desired_id) == 0 { | ||||
| 		// NOTE(Ed): This should never be used except for laziness so I'll be throwing a warning everytime. | ||||
| 		log("desired_key not provided, using file name. Give it a proper name!", LogLevel.Warning) | ||||
| 		// desired_id = cast(FontID) file_name_from_path(path_file) | ||||
| 		desired_id = file_name_from_path(path_file) | ||||
| 	} | ||||
|  | ||||
| 	default_size := default_size | ||||
| 	if default_size == Font_Load_Use_Default_Size { | ||||
| 		default_size = Font_Default_Point_Size | ||||
| 	} | ||||
|  | ||||
| 	key            := cast(u64) crc32( transmute([]byte) desired_id ) | ||||
| 	def, set_error := hmap_chained_set(font_cache, key, FontDef{}) | ||||
| 	verify( set_error == AllocatorError.None, "Failed to add new font entry to cache" ) | ||||
|  | ||||
| 	def.path_file    = path_file | ||||
| 	def.default_size = i32(points_to_pixels(default_size)) | ||||
|  | ||||
| 	// TODO(Ed): this is slow & eats quite a bit of memory early on. Setup a more on demand load for a specific size. | ||||
| 	// Also, we need to eventually switch to a SDF shader for rendering | ||||
|  | ||||
| 	// Render all sizes at once | ||||
| 	// Note(Ed) : We only generate textures for even multiples of the font. | ||||
| 	for font_size : i32 = Font_Size_Interval; font_size <= Font_Largest_Px_Size; font_size += Font_Size_Interval | ||||
| 	{ | ||||
| 		profile("font size render") | ||||
| 		id := (font_size / Font_Size_Interval) + (font_size % Font_Size_Interval) | ||||
|  | ||||
| 		px_render := & def.size_table[id - 1] | ||||
| 		using px_render | ||||
| 		size    = font_size | ||||
| 		count   = 95 // This is the default codepoint count from raylib when loading a font. | ||||
| 		padding = Font_TTF_Default_Chars_Padding | ||||
| 		glyphs  = rl.LoadFontData( raw_data(font_data), font_data_size, | ||||
| 			fontSize       = size, | ||||
| 			codepoints     = nil, | ||||
| 			codepointCount = count, | ||||
| 			type = rl.FontType.DEFAULT ) | ||||
| 		verify( glyphs != nil, str_fmt_tmp("Failed to load glyphs for font: %v at desired size: %v", desired_id, size ) ) | ||||
|  | ||||
| 		atlas  := rl.GenImageFontAtlas( glyphs, & recs, count, size, padding, i32(Font_Atlas_Packing_Method.Raylib_Basic) ) | ||||
| 		texture = rl.LoadTextureFromImage( atlas ) | ||||
|  | ||||
| 		// glyphs_slice := slice_ptr( glyphs, count ) | ||||
| 		// for glyph in glyphs_slice { | ||||
| 		// TODO(Ed) : See if above can properly reference | ||||
|  | ||||
| 		// NOTE(raylib): Update glyphs[i].image to use alpha, required to be used on image_draw_text() | ||||
| 		for glyph_id : i32 = 0; glyph_id < count; glyph_id += 1 { | ||||
| 			glyph := & glyphs[glyph_id] | ||||
|  | ||||
| 			rl.UnloadImage( glyph.image ) | ||||
| 			glyph.image = rl.ImageFromImage( atlas, recs[glyph_id] ) | ||||
| 		} | ||||
| 		rl.UnloadImage( atlas ) | ||||
| 	} | ||||
|  | ||||
| 	free_all( context.temp_allocator ) | ||||
| 	return { key, desired_id } | ||||
| } | ||||
|  | ||||
| Font_Use_Default_Size :: f32(0.0) | ||||
|  | ||||
| to_rl_Font :: proc( id : FontID, size := Font_Use_Default_Size ) -> rl.Font | ||||
| { | ||||
| 	font_provider_data := & get_state().font_provider_data; using font_provider_data | ||||
|  | ||||
| 	even_size := math.round(size * (1.0/f32(Font_Size_Interval))) * f32(Font_Size_Interval) | ||||
| 	size      := clamp( i32( even_size), 4, Font_Largest_Px_Size ) | ||||
| 	def       := hmap_chained_get( font_cache, id.key ) | ||||
| 	size       = size if size != i32(Font_Use_Default_Size) else def.default_size | ||||
|  | ||||
| 	id        := (size / Font_Size_Interval) + (size % Font_Size_Interval) | ||||
| 	px_render := & def.size_table[ id - 1 ] | ||||
|  | ||||
| 	rl_font : rl.Font | ||||
| 	rl_font.baseSize     = px_render.size | ||||
| 	rl_font.glyphCount   = px_render.count | ||||
| 	rl_font.glyphPadding = px_render.padding | ||||
| 	rl_font.glyphs       = px_render.glyphs | ||||
| 	rl_font.recs         = px_render.recs | ||||
| 	rl_font.texture      = px_render.texture | ||||
| 	return rl_font | ||||
| } | ||||
		Reference in New Issue
	
	Block a user