VEFontCache: Should be using odin arrays and maps excluisvely now for the package
This commit is contained in:
		| @@ -16,8 +16,8 @@ PoolListItem :: struct { | ||||
| } | ||||
|  | ||||
| PoolList :: struct { | ||||
| 	items     : Array( PoolListItem ), | ||||
| 	free_list : Array( PoolListIter ), | ||||
| 	items     : [dynamic]PoolListItem, | ||||
| 	free_list : [dynamic]PoolListIter, | ||||
| 	front     : PoolListIter, | ||||
| 	back      : PoolListIter, | ||||
| 	size      : u32, | ||||
| @@ -28,13 +28,13 @@ PoolList :: struct { | ||||
| pool_list_init :: proc( pool : ^PoolList, capacity : u32, dbg_name : string = "" ) | ||||
| { | ||||
| 	error : AllocatorError | ||||
| 	pool.items, error = make( Array( PoolListItem ), u64(capacity) ) | ||||
| 	pool.items, error = make( [dynamic]PoolListItem, u64(capacity) ) | ||||
| 	assert( error == .None, "VEFontCache.pool_list_init : Failed to allocate items array") | ||||
| 	array_resize( & pool.items, u64(capacity) ) | ||||
| 	resize( & pool.items, capacity ) | ||||
|  | ||||
| 	pool.free_list, error = make( Array( PoolListIter ), u64(capacity) ) | ||||
| 	pool.free_list, error = make( [dynamic]PoolListIter, u64(capacity) ) | ||||
| 	assert( error == .None, "VEFontCache.pool_list_init : Failed to allocate free_list array") | ||||
| 	array_resize( & pool.free_list, u64(capacity) ) | ||||
| 	resize( & pool.free_list, capacity ) | ||||
|  | ||||
| 	pool.capacity = capacity | ||||
|  | ||||
| @@ -42,8 +42,8 @@ pool_list_init :: proc( pool : ^PoolList, capacity : u32, dbg_name : string = "" | ||||
| 	using pool | ||||
|  | ||||
| 	for id in 0 ..< capacity { | ||||
| 		free_list.data[id] = i32(id) | ||||
| 		items.data[id] = { | ||||
| 		free_list[id] = i32(id) | ||||
| 		items[id] = { | ||||
| 			prev = -1, | ||||
| 			next = -1, | ||||
| 		} | ||||
| @@ -60,30 +60,32 @@ pool_list_free :: proc( pool : ^PoolList ) | ||||
|  | ||||
| pool_list_reload :: proc( pool : ^PoolList, allocator : Allocator ) | ||||
| { | ||||
| 	pool.items.backing     = allocator | ||||
| 	pool.free_list.backing = allocator | ||||
| 	reload_array( & pool.items, allocator ) | ||||
| 	reload_array( & pool.free_list, allocator ) | ||||
| } | ||||
|  | ||||
| pool_list_push_front :: proc( pool : ^PoolList, value : PoolListValue ) | ||||
| { | ||||
| 	using pool | ||||
| 	if size >= capacity do return | ||||
| 	assert( free_list.num > 0 ) | ||||
| 	assert( free_list.num == u64(capacity - size) ) | ||||
|  | ||||
| 	id := array_back( free_list ) | ||||
| 	length := len(free_list) | ||||
| 	assert( length > 0 ) | ||||
| 	assert( length == int(capacity - size) ) | ||||
|  | ||||
| 	id := free_list[ len(free_list) - 1 ] | ||||
| 	if pool.dbg_name != "" { | ||||
| 		logf("pool_list: back %v", id) | ||||
| 	} | ||||
| 	array_pop( free_list ) | ||||
| 	items.data[ id ].prev  = -1 | ||||
| 	items.data[ id ].next  = front | ||||
| 	items.data[ id ].value = value | ||||
| 	pop( & free_list ) | ||||
| 	items[ id ].prev  = -1 | ||||
| 	items[ id ].next  = front | ||||
| 	items[ id ].value = value | ||||
| 	if pool.dbg_name != "" { | ||||
| 		logf("pool_list: pushed %v into id %v", value, id) | ||||
| 	} | ||||
|  | ||||
| 	if front != -1 do items.data[ front ].prev = id | ||||
| 	if front != -1 do items[ front ].prev = id | ||||
| 	if back  == -1 do back = id | ||||
| 	front  = id | ||||
| 	size  += 1 | ||||
| @@ -94,14 +96,14 @@ pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter ) | ||||
| 	using pool | ||||
| 	if size <= 0 do return | ||||
| 	assert( iter >= 0 && iter < i32(capacity) ) | ||||
| 	assert( free_list.num == u64(capacity - size) ) | ||||
| 	assert( len(free_list) == int(capacity - size) ) | ||||
|  | ||||
| 	iter_node := & items.data[ iter ] | ||||
| 	iter_node := & items[ iter ] | ||||
| 	prev := iter_node.prev | ||||
| 	next := iter_node.next | ||||
|  | ||||
| 	if iter_node.prev != -1 do items.data[ prev ].next = iter_node.next | ||||
| 	if iter_node.next != -1 do items.data[ next ].prev = iter_node.prev | ||||
| 	if iter_node.prev != -1 do items[ prev ].next = iter_node.next | ||||
| 	if iter_node.next != -1 do items[ next ].prev = iter_node.prev | ||||
|  | ||||
| 	if front == iter do front = iter_node.next | ||||
| 	if back  == iter do back  = iter_node.prev | ||||
| @@ -121,17 +123,17 @@ pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| pool_list_peek_back :: #force_inline proc "contextless" ( pool : ^PoolList ) -> PoolListValue { | ||||
| 	// assert( pool.back != - 1 ) | ||||
| 	value := pool.items.data[ pool.back ].value | ||||
| pool_list_peek_back :: #force_inline proc ( pool : ^PoolList ) -> PoolListValue { | ||||
| 	assert( pool.back != - 1 ) | ||||
| 	value := pool.items[ pool.back ].value | ||||
| 	return value | ||||
| } | ||||
|  | ||||
| pool_list_pop_back :: #force_inline proc( pool : ^PoolList ) -> PoolListValue { | ||||
| 	if pool.size <= 0 do return 0 | ||||
| 	// assert( pool.back != -1 ) | ||||
| 	assert( pool.back != -1 ) | ||||
|  | ||||
| 	value := pool.items.data[ pool.back ].value | ||||
| 	value := pool.items[ pool.back ].value | ||||
| 	pool_list_erase( pool, pool.back ) | ||||
| 	return value | ||||
| } | ||||
| @@ -198,7 +200,7 @@ LRU_get :: #force_inline proc( cache : ^LRU_Cache, key : u64 ) -> i32 { | ||||
| 	return iter.value | ||||
| } | ||||
|  | ||||
| LRU_get_next_evicted :: #force_inline proc "contextless" ( 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 ) | ||||
|   | ||||
| @@ -58,7 +58,7 @@ Context :: struct { | ||||
|  | ||||
| 	entries : [dynamic]Entry, | ||||
|  | ||||
| 	temp_path               : Array(Vec2), | ||||
| 	temp_path               : [dynamic]Vec2, | ||||
| 	temp_codepoint_seen     : map[u64]bool, | ||||
| 	temp_codepoint_seen_num : u32, | ||||
|  | ||||
| @@ -170,19 +170,19 @@ init :: proc( ctx : ^Context, parser_kind : ParserKind, | ||||
| 	entries, error = make( [dynamic]Entry, entires_reserve ) | ||||
| 	assert(error == .None, "VEFontCache.init : Failed to allocate entries") | ||||
|  | ||||
| 	temp_path, error = make( Array(Vec2), u64(temp_path_reserve) ) | ||||
| 	temp_path, error = make( [dynamic]Vec2, temp_path_reserve ) | ||||
| 	assert(error == .None, "VEFontCache.init : Failed to allocate temp_path") | ||||
|  | ||||
| 	temp_codepoint_seen, error = make( map[u64]bool, hmap_closest_prime( uint(temp_codepoint_seen_reserve)) ) | ||||
| 	assert(error == .None, "VEFontCache.init : Failed to allocate temp_path") | ||||
|  | ||||
| 	draw_list.vertices, error = make( Array(Vertex), 4 * Kilobyte ) | ||||
| 	draw_list.vertices, error = make( [dynamic]Vertex, 4 * Kilobyte ) | ||||
| 	assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.vertices") | ||||
|  | ||||
| 	draw_list.indices, error = make( Array(u32), 8 * Kilobyte ) | ||||
| 	draw_list.indices, error = make( [dynamic]u32, 8 * Kilobyte ) | ||||
| 	assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.indices") | ||||
|  | ||||
| 	draw_list.calls, error = make( Array(DrawCall), 512 ) | ||||
| 	draw_list.calls, error = make( [dynamic]DrawCall, 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 ) { | ||||
| @@ -225,16 +225,16 @@ init :: proc( ctx : ^Context, parser_kind : ParserKind, | ||||
|  | ||||
| 	LRU_init( & shape_cache.state, shape_cache_params.capacity ) | ||||
|  | ||||
| 	shape_cache.storage, error = make( Array(ShapedText), u64(shape_cache_params.capacity) ) | ||||
| 	shape_cache.storage, error = make( [dynamic]ShapedText, 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 { | ||||
| 		stroage_entry := & shape_cache.storage.data[idx] | ||||
| 		stroage_entry := & shape_cache.storage[idx] | ||||
| 		using stroage_entry | ||||
| 		glyphs, error = make( Array(Glyph), cast(u64) shape_cache_params.reserve_length ) | ||||
| 		glyphs, error = make( [dynamic]Glyph, shape_cache_params.reserve_length ) | ||||
| 		assert( error == .None, "VEFontCache.init : Failed to allocate glyphs array for shape cache storage" ) | ||||
|  | ||||
| 		positions, error = make( Array(Vec2), cast(u64) shape_cache_params.reserve_length ) | ||||
| 		positions, error = make( [dynamic]Vec2, shape_cache_params.reserve_length ) | ||||
| 		assert( error == .None, "VEFontCache.init : Failed to allocate positions array for shape cache storage" ) | ||||
| 	} | ||||
|  | ||||
| @@ -247,22 +247,22 @@ init :: proc( ctx : ^Context, parser_kind : ParserKind, | ||||
| 		buffer_height = region_d.height * u32(over_sample.y) | ||||
| 		draw_padding  = glyph_draw_params.draw_padding | ||||
|  | ||||
| 		draw_list.calls, error = make( Array(DrawCall), cast(u64) glyph_draw_params.buffer_batch * 2 ) | ||||
| 		draw_list.calls, error = make( [dynamic]DrawCall, cast(u64) glyph_draw_params.buffer_batch * 2 ) | ||||
| 		assert( error == .None, "VEFontCache.init : Failed to allocate calls for draw_list" ) | ||||
|  | ||||
| 		draw_list.indices, error = make( Array(u32), cast(u64) glyph_draw_params.buffer_batch * 2 * 6 ) | ||||
| 		draw_list.indices, error = make( [dynamic]u32, cast(u64) glyph_draw_params.buffer_batch * 2 * 6 ) | ||||
| 		assert( error == .None, "VEFontCache.init : Failed to allocate indices array for draw_list" ) | ||||
|  | ||||
| 		draw_list.vertices, error = make( Array(Vertex), cast(u64) glyph_draw_params.buffer_batch * 2 * 4 ) | ||||
| 		draw_list.vertices, error = make( [dynamic]Vertex, 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( Array(DrawCall), cast(u64) glyph_draw_params.buffer_batch * 2 ) | ||||
| 		clear_draw_list.calls, error = make( [dynamic]DrawCall, cast(u64) 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( Array(u32), cast(u64) glyph_draw_params.buffer_batch * 2 * 4 ) | ||||
| 		clear_draw_list.indices, error = make( [dynamic]u32, cast(u64) glyph_draw_params.buffer_batch * 2 * 4 ) | ||||
| 		assert( error == .None, "VEFontCache.init : Failed to allocate calls for indices array for clear_draw_list" ) | ||||
|  | ||||
| 		clear_draw_list.vertices, error = make( Array(Vertex), cast(u64) glyph_draw_params.buffer_batch * 2 * 4 ) | ||||
| 		clear_draw_list.vertices, error = make( [dynamic]Vertex, glyph_draw_params.buffer_batch * 2 * 4 ) | ||||
| 		assert( error == .None, "VEFontCache.init : Failed to allocate vertices array for clear_draw_list" ) | ||||
| 	} | ||||
|  | ||||
| @@ -277,14 +277,13 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator ) | ||||
|  | ||||
| 	using ctx | ||||
|  | ||||
| 	// entries.backing   = allocator | ||||
| 	reload_array( & entries, allocator ) | ||||
| 	temp_path.backing = allocator | ||||
| 	reload_array( & temp_path, allocator ) | ||||
| 	reload_map( & ctx.temp_codepoint_seen, allocator ) | ||||
|  | ||||
| 	draw_list.vertices.backing  = allocator | ||||
| 	draw_list.indices.backing   = allocator | ||||
| 	draw_list.calls.backing     = allocator | ||||
| 	reload_array( & draw_list.vertices, 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) | ||||
| @@ -292,23 +291,23 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator ) | ||||
| 	LRU_reload( & atlas.region_d.state, allocator) | ||||
|  | ||||
| 	LRU_reload( & shape_cache.state, allocator ) | ||||
| 	for idx : u32 = 0; idx < u32(shape_cache.storage.capacity); idx += 1 { | ||||
| 		stroage_entry := & shape_cache.storage.data[idx] | ||||
| 	for idx : u32 = 0; idx < u32(len(shape_cache.storage)); idx += 1 { | ||||
| 		stroage_entry := & shape_cache.storage[idx] | ||||
| 		using stroage_entry | ||||
|  | ||||
| 		glyphs.backing    = allocator | ||||
| 		positions.backing = allocator | ||||
| 		reload_array( & glyphs, allocator ) | ||||
| 		reload_array( & positions, allocator ) | ||||
| 	} | ||||
|  | ||||
| 	atlas.draw_list.calls.backing    = allocator | ||||
| 	atlas.draw_list.indices.backing  = allocator | ||||
| 	atlas.draw_list.vertices.backing = allocator | ||||
| 	reload_array( & atlas.draw_list.calls, allocator ) | ||||
| 	reload_array( & atlas.draw_list.indices, allocator ) | ||||
| 	reload_array( & atlas.draw_list.vertices, allocator ) | ||||
|  | ||||
| 	atlas.clear_draw_list.calls.backing    = allocator | ||||
| 	atlas.clear_draw_list.indices.backing  = allocator | ||||
| 	atlas.clear_draw_list.vertices.backing = allocator | ||||
| 	reload_array( & atlas.clear_draw_list.calls, allocator ) | ||||
| 	reload_array( & atlas.clear_draw_list.indices, allocator ) | ||||
| 	reload_array( & atlas.clear_draw_list.vertices, allocator ) | ||||
|  | ||||
| 	shape_cache.storage.backing = allocator | ||||
| 	reload_array( & shape_cache.storage, allocator ) | ||||
| 	LRU_reload( & shape_cache.state, allocator ) | ||||
| } | ||||
|  | ||||
| @@ -455,42 +454,41 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, scale, | ||||
| 	// Note(Original Author): Figure out scaling so it fits within our box. | ||||
| 	draw := DrawCall_Default | ||||
| 	draw.pass        = FrameBufferPass.Glyph | ||||
| 	draw.start_index = u32(ctx.draw_list.indices.num) | ||||
| 	draw.start_index = u32(len(ctx.draw_list.indices)) | ||||
|  | ||||
| 	// Note(Original Author); | ||||
| 	// Draw the path using simplified version of https://medium.com/@evanwallace/easy-scalable-text-rendering-on-the-gpu-c3f4d782c5ac. | ||||
| 	// Instead of involving fragment shader code we simply make use of modern GPU ability to crunch triangles and brute force curve definitions. | ||||
| 	path := ctx.temp_path | ||||
| 	clear(path) | ||||
| 	clear( & path) | ||||
| 	for edge in shape	do switch edge.type | ||||
| 	{ | ||||
| 		case .Move: | ||||
| 			path_slice := array_to_slice(path) | ||||
| 			if path.num > 0 { | ||||
| 				draw_filled_path( & ctx.draw_list, outside, array_to_slice(path), scale, translate, ctx.debug_print_verbose ) | ||||
| 			if len(path) > 0 { | ||||
| 				draw_filled_path( & ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose ) | ||||
| 			} | ||||
| 			clear(path) | ||||
| 			clear( & path) | ||||
| 			fallthrough | ||||
|  | ||||
| 		case .Line: | ||||
| 			append( & path, Vec2{ f32(edge.x), f32(edge.y) }) | ||||
| 			append_elem( & path, Vec2{ f32(edge.x), f32(edge.y) }) | ||||
|  | ||||
| 		case .Curve: | ||||
| 			assert( path.num > 0 ) | ||||
| 			p0 := path.data[ path.num - 1 ] | ||||
| 			assert( len(path) > 0 ) | ||||
| 			p0 := path[ len(path) - 1 ] | ||||
| 			p1 := Vec2{ f32(edge.contour_x0), f32(edge.contour_y0) } | ||||
| 			p2 := Vec2{ f32(edge.x), f32(edge.y) } | ||||
|  | ||||
| 			step  := 1.0 / f32(ctx.curve_quality) | ||||
| 			alpha := step | ||||
| 			for index := i32(0); index < i32(ctx.curve_quality); index += 1 { | ||||
| 				append( & path, eval_point_on_bezier3( p0, p1, p2, alpha )) | ||||
| 				append_elem( & path, eval_point_on_bezier3( p0, p1, p2, alpha )) | ||||
| 				alpha += step | ||||
| 			} | ||||
|  | ||||
| 		case .Cubic: | ||||
| 			assert( path.num > 0 ) | ||||
| 			p0 := path.data[ path.num - 1] | ||||
| 			assert( len(path) > 0 ) | ||||
| 			p0 := path[ len(path) - 1] | ||||
| 			p1 := Vec2{ f32(edge.contour_x0), f32(edge.contour_y0) } | ||||
| 			p2 := Vec2{ f32(edge.contour_x1), f32(edge.contour_y1) } | ||||
| 			p3 := Vec2{ f32(edge.x), f32(edge.y) } | ||||
| @@ -498,19 +496,19 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, scale, | ||||
| 			step  := 1.0 / f32(ctx.curve_quality) | ||||
| 			alpha := step | ||||
| 			for index := i32(0); index < i32(ctx.curve_quality); index += 1 { | ||||
| 				append( & path, eval_point_on_bezier4( p0, p1, p2, p3, alpha )) | ||||
| 				append_elem( & path, eval_point_on_bezier4( p0, p1, p2, p3, alpha )) | ||||
| 				alpha += step | ||||
| 			} | ||||
|  | ||||
| 		case .None: | ||||
| 			assert(false, "Unknown edge type or invalid") | ||||
| 	} | ||||
| 	if path.num > 0 { | ||||
| 		draw_filled_path( & ctx.draw_list, outside, array_to_slice(path), scale, translate, ctx.debug_print_verbose ) | ||||
| 	if len(path) > 0 { | ||||
| 		draw_filled_path( & ctx.draw_list, outside, path[:], scale, translate, ctx.debug_print_verbose ) | ||||
| 	} | ||||
|  | ||||
| 	// Note(Original Author): Apend the draw call | ||||
| 	draw.end_index = cast(u32) ctx.draw_list.indices.num | ||||
| 	draw.end_index = cast(u32) len(ctx.draw_list.indices) | ||||
| 	if draw.end_index > draw.start_index { | ||||
| 		append(& ctx.draw_list.calls, draw) | ||||
| 	} | ||||
| @@ -624,16 +622,16 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph | ||||
| 		using call | ||||
| 		pass        = .Atlas | ||||
| 		region      = .Ignore | ||||
| 		start_index = u32(atlas.clear_draw_list.indices.num) | ||||
| 		start_index = cast(u32) len(atlas.clear_draw_list.indices) | ||||
| 		blit_quad( & atlas.clear_draw_list, dst_position, dst_position + dst_size, { 1.0, 1.0 }, { 1.0, 1.0 } ) | ||||
| 		end_index = u32(atlas.clear_draw_list.indices.num) | ||||
| 		end_index = cast(u32) len(atlas.clear_draw_list.indices) | ||||
| 		append( & atlas.clear_draw_list.calls, call ) | ||||
|  | ||||
| 		// Queue up a blit from glyph_update_FBO to the atlas | ||||
| 		region      = .None | ||||
| 		start_index = u32(atlas.draw_list.indices.num) | ||||
| 		start_index = cast(u32) len(atlas.draw_list.indices) | ||||
| 		blit_quad( & atlas.draw_list, dst_glyph_position, dst_position + dst_glyph_size, src_position, src_position + src_size ) | ||||
| 		end_index = u32(atlas.draw_list.indices.num) | ||||
| 		end_index = cast(u32) len(atlas.draw_list.indices) | ||||
| 		append( & atlas.draw_list.calls, call ) | ||||
| 	} | ||||
|  | ||||
| @@ -664,9 +662,9 @@ measure_text_size :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) - | ||||
| 	entry   := & ctx.entries[ font ] | ||||
| 	padding := cast(f32) atlas.glyph_padding | ||||
|  | ||||
| 	for index : i32 = 0; index < i32(shaped.glyphs.num); index += 1 | ||||
| 	for index : i32 = 0; index < i32(len(shaped.glyphs)); index += 1 | ||||
| 	{ | ||||
| 		glyph_index := shaped.glyphs.data[ index ] | ||||
| 		glyph_index := shaped.glyphs[ index ] | ||||
| 		if is_empty( ctx, entry, glyph_index ) do continue | ||||
|  | ||||
| 		bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) | ||||
|   | ||||
| @@ -21,9 +21,9 @@ DrawCall_Default :: DrawCall { | ||||
| } | ||||
|  | ||||
| DrawList :: struct { | ||||
| 	vertices : Array(Vertex), | ||||
| 	indices  : Array(u32), | ||||
| 	calls    : Array(DrawCall), | ||||
| 	vertices : [dynamic]Vertex, | ||||
| 	indices  : [dynamic]u32, | ||||
| 	calls    : [dynamic]DrawCall, | ||||
| } | ||||
|  | ||||
| FrameBufferPass :: enum u32 { | ||||
| @@ -51,31 +51,31 @@ blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : 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", | ||||
| 		// p0.x, p0.y, p1.x, p1.y, uv0.x, uv0.y, uv1.x, uv1.y); | ||||
| 	v_offset := cast(u32) draw_list.vertices.num | ||||
| 	v_offset := cast(u32) len(draw_list.vertices) | ||||
|  | ||||
| 	vertex := Vertex { | ||||
| 		{p0.x, p0.y}, | ||||
| 		uv0.x, uv0.y | ||||
| 	} | ||||
| 	append( & draw_list.vertices, vertex ) | ||||
| 	append_elem( & draw_list.vertices, vertex ) | ||||
|  | ||||
| 	vertex = Vertex { | ||||
| 		{p0.x, p1.y}, | ||||
| 		uv0.x, uv1.y | ||||
| 	} | ||||
| 	append( & draw_list.vertices, vertex ) | ||||
| 	append_elem( & draw_list.vertices, vertex ) | ||||
|  | ||||
| 	vertex = Vertex { | ||||
| 		{p1.x, p0.y}, | ||||
| 		uv1.x, uv0.y | ||||
| 	} | ||||
| 	append( & draw_list.vertices, vertex ) | ||||
| 	append_elem( & draw_list.vertices, vertex ) | ||||
|  | ||||
| 	vertex = Vertex { | ||||
| 		{p1.x, p1.y}, | ||||
| 		uv1.x, uv1.y | ||||
| 	} | ||||
| 	append( & draw_list.vertices, vertex ) | ||||
| 	append_elem( & draw_list.vertices, vertex ) | ||||
|  | ||||
| 	quad_indices : []u32 = { | ||||
| 		0, 1, 2, | ||||
| @@ -91,9 +91,9 @@ blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1} | ||||
|  | ||||
| // ve_fontcache_clear_drawlist | ||||
| clear_draw_list :: #force_inline proc ( draw_list : ^DrawList ) { | ||||
| 	clear( draw_list.calls ) | ||||
| 	clear( draw_list.indices ) | ||||
| 	clear( draw_list.vertices ) | ||||
| 	clear( & draw_list.calls ) | ||||
| 	clear( & draw_list.indices ) | ||||
| 	clear( & draw_list.vertices ) | ||||
| } | ||||
|  | ||||
| directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Glyph, bounds_0 : Vec2i, bounds_width, bounds_height : i32, over_sample, position, scale : Vec2 ) | ||||
| @@ -140,9 +140,9 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Gly | ||||
| 		using call | ||||
| 		pass        = .Target_Uncached | ||||
| 		colour      = ctx.colour | ||||
| 		start_index = u32(ctx.draw_list.indices.num) | ||||
| 		start_index = u32(len(ctx.draw_list.indices)) | ||||
| 		blit_quad( & ctx.draw_list, dst, dst + dst_size, glyph_position, glyph_position + glyph_size ) | ||||
| 		end_index   = u32(ctx.draw_list.indices.num) | ||||
| 		end_index   = u32(len(ctx.draw_list.indices)) | ||||
| 		append( & ctx.draw_list.calls, call ) | ||||
| 	} | ||||
|  | ||||
| @@ -222,10 +222,10 @@ draw_cached_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph, | ||||
| 		using call | ||||
| 		pass        = .Target | ||||
| 		colour      = ctx.colour | ||||
| 		start_index = cast(u32) ctx.draw_list.indices.num | ||||
| 		start_index = cast(u32) len(ctx.draw_list.indices) | ||||
|  | ||||
| 		blit_quad( & ctx.draw_list, dst, dst + dst_scale, glyph_atlas_position, glyph_atlas_position + glyph_scale ) | ||||
| 		end_index   = cast(u32) ctx.draw_list.indices.num | ||||
| 		end_index   = cast(u32) len(ctx.draw_list.indices) | ||||
| 	} | ||||
| 	append( & ctx.draw_list.calls, call ) | ||||
| 	return true | ||||
| @@ -252,7 +252,7 @@ draw_filled_path :: proc( draw_list : ^DrawList, outside_point : Vec2, path : [] | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	v_offset := cast(u32) draw_list.vertices.num | ||||
| 	v_offset := cast(u32) len(draw_list.vertices) | ||||
| 	for point in path { | ||||
| 		vertex := Vertex { | ||||
| 			pos = point * scale + translate, | ||||
| @@ -262,7 +262,7 @@ draw_filled_path :: proc( draw_list : ^DrawList, outside_point : Vec2, path : [] | ||||
| 		append( & draw_list.vertices, vertex ) | ||||
| 	} | ||||
|  | ||||
| 	outside_vertex := cast(u32) draw_list.vertices.num | ||||
| 	outside_vertex := cast(u32) len(draw_list.vertices) | ||||
| 	{ | ||||
| 		vertex := Vertex { | ||||
| 			pos = outside_point * scale + translate, | ||||
| @@ -416,8 +416,8 @@ draw_text_batch :: proc( ctx : ^Context, entry : ^Entry, shaped : ^ShapedText, b | ||||
| 	for index := batch_start_idx; index < batch_end_idx; index += 1 | ||||
| 	{ | ||||
| 		// profile(#procedure) | ||||
| 		glyph_index       := shaped.glyphs.data[ index ] | ||||
| 		shaped_position   := shaped.positions.data[index] | ||||
| 		glyph_index       := shaped.glyphs[ index ] | ||||
| 		shaped_position   := shaped.positions[index] | ||||
| 		glyph_translate   := position + shaped_position * scale | ||||
| 		glyph_cached      := draw_cached_glyph( ctx, entry, glyph_index, glyph_translate, scale) | ||||
| 		assert( glyph_cached == true ) | ||||
| @@ -430,9 +430,9 @@ draw_text_shape :: proc( ctx : ^Context, font : FontID, entry : ^Entry, shaped : | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	batch_start_idx : i32 = 0 | ||||
| 	for index : i32 = 0; index < i32(shaped.glyphs.num); index += 1 | ||||
| 	for index : i32 = 0; index < i32(len(shaped.glyphs)); index += 1 | ||||
| 	{ | ||||
| 		glyph_index := shaped.glyphs.data[ index ] | ||||
| 		glyph_index := shaped.glyphs[ index ] | ||||
| 		if is_empty( ctx, entry, glyph_index )              do continue | ||||
| 		if can_batch_glyph( ctx, font, entry, glyph_index ) do continue | ||||
|  | ||||
| @@ -449,7 +449,7 @@ draw_text_shape :: proc( ctx : ^Context, font : FontID, entry : ^Entry, shaped : | ||||
| 		batch_start_idx = index | ||||
| 	} | ||||
|  | ||||
| 	draw_text_batch( ctx, entry, shaped, batch_start_idx, i32(shaped.glyphs.num), position, scale ) | ||||
| 	draw_text_batch( ctx, entry, shaped, batch_start_idx, i32(len(shaped.glyphs)), position, scale ) | ||||
| 	reset_batch_codepoint_state( ctx ) | ||||
| 	cursor_pos = position + shaped.end_cursor_pos * scale | ||||
| 	return | ||||
| @@ -501,22 +501,24 @@ merge_draw_list :: proc( dst, src : ^DrawList ) | ||||
| 	// profile(#procedure) | ||||
| 	error : AllocatorError | ||||
|  | ||||
| 	v_offset := cast(u32) dst.vertices.num | ||||
| 	v_offset := cast(u32) len( dst.vertices ) | ||||
| 	// for index : u32 = 0; index < cast(u32) src.vertices.num; index += 1 { | ||||
| 	// 	error = append( & dst.vertices, src.vertices.data[index] ) | ||||
| 	// 	assert( error == .None ) | ||||
| 	// } | ||||
| 	error = append( & dst.vertices, src.vertices ) | ||||
| 	num_appended : int | ||||
| 	num_appended, error = append_elems( & dst.vertices, ..src.vertices[:] ) | ||||
| 	assert( error == .None ) | ||||
|  | ||||
| 	i_offset := cast(u32) dst.indices.num | ||||
| 	for index : u32 = 0; index < cast(u32) src.indices.num; index += 1 { | ||||
| 		error = append( & dst.indices, src.indices.data[index] + v_offset ) | ||||
| 	i_offset := cast(u32) len(dst.indices) | ||||
| 	for index : u32 = 0; index < cast(u32) len(src.indices); index += 1 { | ||||
| 		ignored : int | ||||
| 		ignored, error = append( & dst.indices, src.indices[index] + v_offset ) | ||||
| 		assert( error == .None ) | ||||
| 	} | ||||
|  | ||||
| 	for index : u32 = 0; index < cast(u32) src.calls.num; index += 1 { | ||||
| 		src_call := src.calls.data[ index ] | ||||
| 	for index : u32 = 0; index < cast(u32) len(src.calls); index += 1 { | ||||
| 		src_call := src.calls[ index ] | ||||
| 		src_call.start_index += i_offset | ||||
| 		src_call.end_index   += i_offset | ||||
| 		append( & dst.calls, src_call ) | ||||
| @@ -529,14 +531,12 @@ optimize_draw_list :: proc( draw_list : ^DrawList, call_offset : u64 ) | ||||
| 	// profile(#procedure) | ||||
| 	assert( draw_list != nil ) | ||||
|  | ||||
| 	calls := array_to_slice(draw_list.calls) | ||||
|  | ||||
| 	write_index : u64 = call_offset | ||||
| 	for index : u64 = 1 + call_offset; index < u64(draw_list.calls.num); index += 1 | ||||
| 	for index : u64 = 1 + call_offset; index < cast(u64) len(draw_list.calls); index += 1 | ||||
| 	{ | ||||
| 		assert( write_index <= index ) | ||||
| 		draw_0 := & draw_list.calls.data[ write_index ] | ||||
| 		draw_1 := & draw_list.calls.data[ index ] | ||||
| 		draw_0 := & draw_list.calls[ write_index ] | ||||
| 		draw_1 := & draw_list.calls[ index ] | ||||
|  | ||||
| 		merge : b32 = true | ||||
| 		if draw_0.pass      != draw_1.pass        do merge = false | ||||
| @@ -557,11 +557,11 @@ optimize_draw_list :: proc( draw_list : ^DrawList, call_offset : u64 ) | ||||
| 			// logf("can't merge %v : %v %v", draw_0.pass, write_index, index ) | ||||
| 			write_index += 1 | ||||
| 			if write_index != index { | ||||
| 				draw_2 := & draw_list.calls.data[ write_index ] | ||||
| 				draw_2 := & draw_list.calls[ write_index ] | ||||
| 				draw_2^ = draw_1^ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	resize( & draw_list.calls, u64(write_index + 1) ) | ||||
| 	resize( & draw_list.calls, write_index + 1 ) | ||||
| } | ||||
|   | ||||
| @@ -89,7 +89,9 @@ append :: proc { | ||||
| 	grime.array_append_slice, | ||||
| 	grime.array_append_value, | ||||
|  | ||||
| 	// append_elem, append_elems, append_elem_string, | ||||
| 	append_elem, | ||||
| 	// append_elems,  | ||||
| 	// append_elem_string, | ||||
| } | ||||
|  | ||||
| append_at :: proc { | ||||
| @@ -101,6 +103,8 @@ clear :: proc { | ||||
| 	array_clear, | ||||
| 	hmap_chained_clear, | ||||
| 	hmap_zpl_clear, | ||||
|  | ||||
| 	clear_dynamic_array, | ||||
| } | ||||
|  | ||||
| delete :: proc { | ||||
| @@ -134,6 +138,8 @@ remove_at :: proc { | ||||
|  | ||||
| resize :: proc { | ||||
| 	array_resize, | ||||
|  | ||||
| 	resize_dynamic_array, | ||||
| } | ||||
|  | ||||
| set :: proc { | ||||
|   | ||||
| @@ -3,13 +3,13 @@ package VEFontCache | ||||
| import "core:math" | ||||
|  | ||||
| ShapedText :: struct { | ||||
| 	glyphs         : Array(Glyph), | ||||
| 	positions      : Array(Vec2), | ||||
| 	glyphs         : [dynamic]Glyph, | ||||
| 	positions      : [dynamic]Vec2, | ||||
| 	end_cursor_pos : Vec2, | ||||
| } | ||||
|  | ||||
| ShapedTextCache :: struct { | ||||
| 	storage       : Array(ShapedText), | ||||
| 	storage       : [dynamic]ShapedText, | ||||
| 	state         : LRU_Cache, | ||||
| 	next_cache_id : i32, | ||||
| } | ||||
| @@ -54,10 +54,10 @@ shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) - | ||||
| 			LRU_put( state, hash, shape_cache_idx ) | ||||
| 		} | ||||
|  | ||||
| 		shape_text_uncached( ctx, font, & shape_cache.storage.data[ shape_cache_idx ], text_utf8 ) | ||||
| 		shape_text_uncached( ctx, font, & shape_cache.storage[ shape_cache_idx ], text_utf8 ) | ||||
| 	} | ||||
|  | ||||
| 	return & shape_cache.storage.data[ shape_cache_idx ] | ||||
| 	return & shape_cache.storage[ shape_cache_idx ] | ||||
| } | ||||
|  | ||||
| shape_text_uncached :: proc( ctx : ^Context, font : FontID, output : ^ShapedText, text_utf8 : string ) | ||||
| @@ -69,8 +69,8 @@ shape_text_uncached :: proc( ctx : ^Context, font : FontID, output : ^ShapedText | ||||
| 	use_full_text_shape := ctx.text_shape_adv | ||||
| 	entry := & ctx.entries[ font ] | ||||
|  | ||||
| 	clear( output.glyphs ) | ||||
| 	clear( output.positions ) | ||||
| 	clear( & output.glyphs ) | ||||
| 	clear( & output.positions ) | ||||
|  | ||||
| 	ascent, descent, line_gap := parser_get_font_vertical_metrics( & entry.parser_info ) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user