last cleanup before docs
This commit is contained in:
		| @@ -110,9 +110,6 @@ pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter ) | ||||
|  | ||||
| 	iter_node.prev  = -1 | ||||
| 	iter_node.next  = -1 | ||||
| 	// if pool.dbg_name != "" { | ||||
| 	// 	logf("pool_list: erased %v, at id %v", iter_node.value, iter) | ||||
| 	// } | ||||
| 	iter_node.value = 0 | ||||
| 	append( & free_list, iter ) | ||||
|  | ||||
| @@ -179,13 +176,6 @@ LRU_hash_key :: #force_inline proc( key : u64 ) -> ( hash : u64 ) { | ||||
| } | ||||
|  | ||||
| LRU_find :: #force_inline proc "contextless" ( cache : ^LRU_Cache, key : u64, must_find := false ) -> (LRU_Link, bool) { | ||||
| 	// hash := LRU_hash_key( key ) | ||||
| 	// link := get( cache.table, hash ) | ||||
| 	// if link == nil && must_find { | ||||
| 	// 	runtime.debug_trap() | ||||
| 	// 	link = get( cache.table, hash ) | ||||
| 	// } | ||||
|  | ||||
| 	link, success := cache.table[key] | ||||
| 	return link, success | ||||
| } | ||||
| @@ -218,7 +208,6 @@ LRU_peek :: #force_inline proc ( cache : ^LRU_Cache, key : u64, must_find := fal | ||||
|  | ||||
| LRU_put :: #force_inline proc ( cache : ^LRU_Cache, key : u64,  value : i32 ) -> u64 | ||||
| { | ||||
| 	// hash_key := LRU_hash_key( key ) | ||||
| 	iter, success := cache.table[key] | ||||
| 	if success { | ||||
| 		LRU_refresh( cache, key ) | ||||
| @@ -229,20 +218,11 @@ LRU_put :: #force_inline proc ( cache : ^LRU_Cache, key : u64,  value : i32 ) -> | ||||
| 	evict := key | ||||
| 	if cache.key_queue.size >= cache.capacity { | ||||
| 		evict = pool_list_pop_back( & cache.key_queue ) | ||||
|  | ||||
| 		// evict_hash := LRU_hash_key( evict ) | ||||
| 		// if cache.table.dbg_name != "" { | ||||
| 		// 	logf("%v: Evicted   %v with hash: %v", cache.table.dbg_name, evict, evict_hash) | ||||
| 		// } | ||||
| 		delete_key( & cache.table, evict ) | ||||
| 		cache.num -= 1 | ||||
| 	} | ||||
|  | ||||
| 	pool_list_push_front( & cache.key_queue, key ) | ||||
| 	// if cache.table.dbg_name != "" { | ||||
| 	// 	logf("%v: Pushed   %v with hash: %v", cache.table.dbg_name, key, hash_key ) | ||||
| 	// } | ||||
|  | ||||
| 	cache.table[key] = LRU_Link { | ||||
| 		value = value, | ||||
| 		ptr   = cache.key_queue.front | ||||
| @@ -253,9 +233,6 @@ LRU_put :: #force_inline proc ( cache : ^LRU_Cache, key : u64,  value : i32 ) -> | ||||
|  | ||||
| LRU_refresh :: proc( cache : ^LRU_Cache, key : u64 ) { | ||||
| 	link, success := LRU_find( cache, key ) | ||||
| 	// if cache.table.dbg_name != "" { | ||||
| 	// 	logf("%v: Refreshed %v", cache.table.dbg_name, key) | ||||
| 	// } | ||||
| 	pool_list_erase( & cache.key_queue, link.ptr ) | ||||
| 	pool_list_push_front( & cache.key_queue, key ) | ||||
| 	link.ptr = cache.key_queue.front | ||||
|   | ||||
| @@ -4,6 +4,8 @@ This is a port of the library base on [fork](https://github.com/hypernewbie/VEFo | ||||
|  | ||||
| Its original purpose was for use in game engines, however its rendeirng quality and performance is more than adequate for many other applications. | ||||
|  | ||||
| See: [docs/Readme.md](docs/Readme.md) for the library's interface | ||||
|  | ||||
| TODO (Making it a more idiomatic library): | ||||
|  | ||||
| * Setup freetype, harfbuzz, depedency management within the library | ||||
| @@ -25,7 +27,3 @@ TODO Additional Features: | ||||
| * Ability to set a draw transform, viewport and projection | ||||
|   * By default the library's position is in unsigned normalized render space | ||||
| * Allow curve_quality to be set on a per-font basis | ||||
|  | ||||
| TODO Optimizations: | ||||
|  | ||||
| * Support more granular handling of shapes by chunking any text from draw_text into visible and whitespace/formatting | ||||
|   | ||||
| @@ -21,9 +21,10 @@ Vec2    :: [2]f32 | ||||
| Vec2i   :: [2]i32 | ||||
| Vec2_64 :: [2]f64 | ||||
|  | ||||
| vec2_from_scalar  :: #force_inline proc "contextless" ( scalar : f32   ) -> Vec2    { return { scalar, scalar } } | ||||
| vec2_from_scalar  :: #force_inline proc "contextless" ( scalar : f32   ) -> Vec2    { return { scalar, scalar }} | ||||
| vec2_64_from_vec2 :: #force_inline proc "contextless" ( v2     : Vec2  ) -> Vec2_64 { return { f64(v2.x), f64(v2.y) }} | ||||
| vec2_from_vec2i   :: #force_inline proc( v2i    : Vec2i ) -> Vec2    { return { f32(v2i.x), f32(v2i.y) }} | ||||
| vec2_from_vec2i   :: #force_inline proc "contextless" ( v2i    : Vec2i ) -> Vec2    { return { f32(v2i.x), f32(v2i.y) }} | ||||
| vec2i_from_vec2   :: #force_inline proc "contextless" ( v2     : Vec2  ) -> Vec2i   { return { i32(v2.x), i32(v2.y) }} | ||||
|  | ||||
| FontID  :: distinct i64 | ||||
| Glyph   :: distinct i32 | ||||
| @@ -131,7 +132,7 @@ InitGlyphDrawParams :: struct { | ||||
| } | ||||
|  | ||||
| InitGlyphDrawParams_Default :: InitGlyphDrawParams { | ||||
| 	over_sample   = { 4, 4 }, | ||||
| 	over_sample   = { 8, 8 }, | ||||
| 	buffer_batch  = 4, | ||||
| 	draw_padding  = InitAtlasParams_Default.glyph_padding, | ||||
| } | ||||
| @@ -362,7 +363,6 @@ load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32 | ||||
| 		size_scale = size_px < 0.0 ?                               \ | ||||
| 			parser_scale_for_pixel_height( & parser_info, -size_px ) \ | ||||
| 		: parser_scale_for_mapping_em_to_pixels( & parser_info, size_px ) | ||||
| 		// size_scale = 1.0 | ||||
|  | ||||
| 		used = true | ||||
|  | ||||
| @@ -429,91 +429,11 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : | ||||
| 	text_utf8_bytes := transmute([]u8) text_utf8 | ||||
| 	text_chunk      : string | ||||
|  | ||||
| 	Text_As_Shape :: true | ||||
| 	when Text_As_Shape | ||||
| 	{ | ||||
| 		text_chunk = transmute(string) text_utf8_bytes[ : ] | ||||
| 		if len(text_chunk) > 0 { | ||||
| 			shaped        := shape_text_cached( ctx, font, text_chunk, entry ) | ||||
| 			ctx.cursor_pos = draw_text_shape( ctx, font, entry, shaped, position, scale, snap_width, snap_height ) | ||||
| 		} | ||||
| 	text_chunk = transmute(string) text_utf8_bytes[ : ] | ||||
| 	if len(text_chunk) > 0 { | ||||
| 		shaped        := shape_text_cached( ctx, font, text_chunk, entry ) | ||||
| 		ctx.cursor_pos = draw_text_shape( ctx, font, entry, shaped, position, scale, snap_width, snap_height ) | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		last_byte_offset : int = 0 | ||||
| 		byte_offset      : int = 0 | ||||
| 		for codepoint, offset in text_utf8 | ||||
| 		{ | ||||
| 			Rune_Space           :: ' ' | ||||
| 			Rune_Tab             :: '\t' | ||||
| 			Rune_Carriage_Return :: '\r' | ||||
| 			Rune_Line_Feed       :: '\n' | ||||
| 			// Rune_Tab_Vertical :: '\v' | ||||
|  | ||||
| 			byte_offset = offset | ||||
|  | ||||
| 			switch codepoint | ||||
| 			{ | ||||
| 				case Rune_Space: fallthrough | ||||
| 				case Rune_Tab: fallthrough | ||||
| 				case Rune_Line_Feed: fallthrough | ||||
| 				case Rune_Carriage_Return: | ||||
| 					if chunk_kind == .Formatting | ||||
| 					{ | ||||
| 						chunk_end        = byte_offset | ||||
| 						last_byte_offset = byte_offset | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						text_chunk = transmute(string) text_utf8_bytes[ chunk_start : byte_offset] | ||||
| 						if len(text_chunk) > 0 { | ||||
| 							shaped         := shape_text_cached( ctx, font, text_chunk, entry ) | ||||
| 							ctx.cursor_pos += draw_text_shape( ctx, font, entry, shaped, position, scale, snap_width, snap_height ) | ||||
| 						} | ||||
|  | ||||
| 						chunk_start = byte_offset | ||||
| 						chunk_end   = chunk_start | ||||
| 						chunk_kind  = .Formatting | ||||
|  | ||||
| 						last_byte_offset = byte_offset | ||||
| 						continue | ||||
| 					} | ||||
| 			} | ||||
|  | ||||
| 			// Visible Chunk | ||||
| 			if chunk_kind == .Visible { | ||||
| 				chunk_end        = byte_offset | ||||
| 				last_byte_offset = byte_offset | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				text_chunk = transmute(string) text_utf8_bytes[ chunk_start : byte_offset ] | ||||
| 				if len(text_chunk) > 0 { | ||||
| 					shaped         := shape_text_cached( ctx, font, text_chunk, entry ) | ||||
| 					ctx.cursor_pos += draw_text_shape( ctx, font, entry, shaped, position, scale, snap_width, snap_height ) | ||||
| 				} | ||||
|  | ||||
| 				chunk_start = byte_offset | ||||
| 				chunk_end   = chunk_start | ||||
| 				chunk_kind  = .Visible | ||||
|  | ||||
| 				last_byte_offset = byte_offset | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		text_chunk = transmute(string) text_utf8_bytes[ chunk_start : ] | ||||
| 		if len(text_chunk) > 0 { | ||||
| 			shaped         := shape_text_cached( ctx, font, text_chunk, entry ) | ||||
| 			ctx.cursor_pos += draw_text_shape( ctx, font, entry, shaped, position, scale, snap_width, snap_height ) | ||||
| 		} | ||||
|  | ||||
| 		chunk_start = byte_offset | ||||
| 		chunk_end   = chunk_start | ||||
| 		chunk_kind  = .Visible | ||||
|  | ||||
| 		last_byte_offset = byte_offset | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -87,8 +87,6 @@ blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1} | ||||
| 	for index : i32 = 0; index < 6; index += 1 { | ||||
| 		append( & draw_list.indices, v_offset + quad_indices[ index ] ) | ||||
| 	} | ||||
| 	// draw_list_vert_slice  := array_to_slice(draw_list.vertices) | ||||
| 	// draw_list_index_slice := array_to_slice(draw_list.indices) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @@ -100,9 +98,6 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	// No shpae to retrieve | ||||
| 	// if parser_is_glyph_empty( & entry.parser_info, glyph_index ) do return true | ||||
|  | ||||
| 	// Retrieve the shape definition from the parser. | ||||
| 	shape, error := parser_get_glyph_shape( & entry.parser_info, glyph_index ) | ||||
| 	assert( error == .None ) | ||||
| @@ -228,8 +223,10 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, | ||||
|  | ||||
| 	// Get hb_font text metrics. These are unscaled! | ||||
| 	bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) | ||||
| 	bounds_width  := f32(bounds_1.x - bounds_0.x) | ||||
| 	bounds_height := f32(bounds_1.y - bounds_0.y) | ||||
| 	bounds_size := Vec2 { | ||||
| 		f32(bounds_1.x - bounds_0.x), | ||||
| 		f32(bounds_1.y - bounds_0.y) | ||||
| 	} | ||||
|  | ||||
| 	// E region is special case and not cached to atlas. | ||||
| 	if region_kind == .None || region_kind == .E do return | ||||
| @@ -260,13 +257,11 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, | ||||
| 		assert( LRU_get( & region.state, lru_code ) != - 1 ) | ||||
| 	} | ||||
|  | ||||
| 	atlas               := & ctx.atlas | ||||
| 	atlas_width         := f32(atlas.width) | ||||
| 	atlas_height        := f32(atlas.height) | ||||
| 	glyph_buffer        := & ctx.glyph_buffer | ||||
| 	glyph_buffer_width  := f32(glyph_buffer.width) | ||||
| 	glyph_buffer_height := f32(glyph_buffer.height) | ||||
| 	glyph_padding       := cast(f32) atlas.glyph_padding | ||||
| 	atlas             := & ctx.atlas | ||||
| 	glyph_buffer      := & ctx.glyph_buffer | ||||
| 	atlas_size        := Vec2 { f32(atlas.width), f32(atlas.height) } | ||||
| 	glyph_buffer_size := Vec2 { f32(glyph_buffer.width), f32(glyph_buffer.height) } | ||||
| 	glyph_padding     := cast(f32) atlas.glyph_padding | ||||
|  | ||||
| 	if ctx.debug_print | ||||
| 	{ | ||||
| @@ -283,36 +278,28 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, | ||||
| 	glyph_draw_translate.y  = cast(f32) (i32(glyph_draw_translate.y + 0.9999999)) | ||||
|  | ||||
| 	// Allocate a glyph_update_FBO region | ||||
| 	gwidth_scaled_px := bounds_width * glyph_draw_scale.x + 1.0 + over_sample.x * glyph_padding | ||||
| 	gwidth_scaled_px := bounds_size.x * glyph_draw_scale.x + 1.0 + over_sample.x * glyph_padding | ||||
|   if i32(f32(glyph_buffer.batch_x) + gwidth_scaled_px) >= i32(glyph_buffer.width) { | ||||
| 		flush_glyph_buffer_to_atlas( ctx ) | ||||
| 	} | ||||
|  | ||||
| 	// Calculate the src and destination regions | ||||
| 	dst_position, slot_szie := atlas_bbox( atlas, region_kind, atlas_index ) | ||||
| 	dst_glyph_position := dst_position | ||||
| 	dst_glyph_width    := bounds_width  * entry.size_scale | ||||
| 	dst_glyph_height   := bounds_height * entry.size_scale | ||||
| 	dst_glyph_width    += glyph_padding | ||||
| 	dst_glyph_height   += glyph_padding | ||||
| 	slot_position, slot_szie := atlas_bbox( atlas, region_kind, atlas_index ) | ||||
|  | ||||
| 	dst_size       := slot_szie | ||||
| 	dst_glyph_size := Vec2 { dst_glyph_width, dst_glyph_height } | ||||
| 	screenspace_x_form( & dst_glyph_position, & dst_glyph_size, atlas_width, atlas_height ) | ||||
| 	screenspace_x_form( & dst_position,       & dst_size,       atlas_width, atlas_height ) | ||||
| 	dst_glyph_position := slot_position | ||||
| 	dst_glyph_size     := bounds_size * entry.size_scale + glyph_padding | ||||
| 	dst_size           := slot_szie | ||||
| 	screenspace_x_form( & dst_glyph_position, & dst_glyph_size, atlas_size ) | ||||
| 	screenspace_x_form( & slot_position,      & dst_size,       atlas_size ) | ||||
|  | ||||
| 	src_position := Vec2 { f32(glyph_buffer.batch_x), 0 } | ||||
| 	src_size     := Vec2 { | ||||
| 		bounds_width  * glyph_draw_scale.x, | ||||
| 		bounds_height * glyph_draw_scale.y, | ||||
| 	} | ||||
| 	src_size += over_sample * glyph_padding | ||||
| 	textspace_x_form( & src_position, & src_size, glyph_buffer_width, glyph_buffer_height ) | ||||
| 	src_size     := bounds_size * glyph_draw_scale + over_sample * glyph_padding | ||||
| 	textspace_x_form( & src_position, & src_size, glyph_buffer_size ) | ||||
|  | ||||
| 	// Advance glyph_update_batch_x and calculate final glyph drawing transform | ||||
| 	glyph_draw_translate.x += f32(glyph_buffer.batch_x) | ||||
| 	glyph_buffer.batch_x   += i32(gwidth_scaled_px) | ||||
| 	screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_width, glyph_buffer_height ) | ||||
| 	screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_size ) | ||||
|  | ||||
| 	call : DrawCall | ||||
| 	{ | ||||
| @@ -321,14 +308,22 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, | ||||
| 		pass        = .Atlas | ||||
| 		region      = .Ignore | ||||
| 		start_index = cast(u32) len(glyph_buffer.clear_draw_list.indices) | ||||
| 		blit_quad( & glyph_buffer.clear_draw_list, dst_position, dst_position + dst_size, { 1.0, 1.0 }, { 1.0, 1.0 } ) | ||||
|  | ||||
| 		blit_quad( & glyph_buffer.clear_draw_list, | ||||
| 			slot_position, slot_position + dst_size, | ||||
| 			{ 1.0, 1.0 },  { 1.0, 1.0 } ) | ||||
|  | ||||
| 		end_index = cast(u32) len(glyph_buffer.clear_draw_list.indices) | ||||
| 		append( & glyph_buffer.clear_draw_list.calls, call ) | ||||
|  | ||||
| 		// Queue up a blit from glyph_update_FBO to the atlas | ||||
| 		region      = .None | ||||
| 		start_index = cast(u32) len(glyph_buffer.draw_list.indices) | ||||
| 		blit_quad( & glyph_buffer.draw_list, dst_glyph_position, dst_position + dst_glyph_size, src_position, src_position + src_size ) | ||||
|  | ||||
| 		blit_quad( & glyph_buffer.draw_list, | ||||
| 			dst_glyph_position, slot_position + dst_glyph_size, | ||||
| 			src_position,       src_position  + src_size ) | ||||
|  | ||||
| 		end_index = cast(u32) len(glyph_buffer.draw_list.indices) | ||||
| 		append( & glyph_buffer.draw_list.calls, call ) | ||||
| 	} | ||||
| @@ -384,52 +379,40 @@ clear_draw_list :: #force_inline proc ( draw_list : ^DrawList ) { | ||||
| directly_draw_massive_glyph :: proc( ctx : ^Context, | ||||
| 	entry : ^Entry, | ||||
| 	glyph : Glyph, | ||||
| 	bounds_0,     bounds_1       : Vec2, | ||||
| 	bounds_width, bounds_height  : f32, | ||||
| 	bounds_0,    bounds_1        : Vec2, | ||||
| 	bounds_size                  : Vec2, | ||||
| 	over_sample, position, scale : Vec2 ) | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	flush_glyph_buffer_to_atlas( ctx ) | ||||
|  | ||||
| 	glyph_padding       := f32(ctx.atlas.glyph_padding) | ||||
| 	glyph_buffer_width  := f32(ctx.glyph_buffer.width) | ||||
| 	glyph_buffer_height := f32(ctx.glyph_buffer.height) | ||||
| 	glyph_padding     := f32(ctx.atlas.glyph_padding) | ||||
| 	glyph_buffer_size := Vec2 { f32(ctx.glyph_buffer.width), f32(ctx.glyph_buffer.height) } | ||||
|  | ||||
| 	// Draw un-antialiased glyph to update FBO. | ||||
| 	glyph_draw_scale     := over_sample * entry.size_scale | ||||
| 	glyph_draw_translate := -1 * bounds_0 * glyph_draw_scale + vec2_from_scalar(glyph_padding) | ||||
| 	screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_width, glyph_buffer_height ) | ||||
| 	screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_size ) | ||||
|  | ||||
| 	cache_glyph( ctx, entry.id, glyph, entry, bounds_0, bounds_1, glyph_draw_scale, glyph_draw_translate ) | ||||
|  | ||||
| 	glyph_padding_dbl := glyph_padding * 2 | ||||
| 	bounds_scaled     := Vec2 { bounds_width, bounds_height } * entry.size_scale | ||||
| 	bounds_scaled     := bounds_size * entry.size_scale | ||||
|  | ||||
| 	// Figure out the source rect. | ||||
| 	glyph_position   := Vec2 {} | ||||
| 	glyph_width      := bounds_scaled.x * over_sample.x | ||||
| 	glyph_height     := bounds_scaled.y * over_sample.y | ||||
| 	glyph_dst_width  := bounds_scaled.x | ||||
| 	glyph_dst_height := bounds_scaled.y | ||||
| 	glyph_height     += glyph_padding_dbl | ||||
| 	glyph_width      += glyph_padding_dbl | ||||
| 	glyph_dst_width  += glyph_padding_dbl | ||||
| 	glyph_dst_height += glyph_padding_dbl | ||||
| 	glyph_position := Vec2 {} | ||||
| 	glyph_size     := vec2(glyph_padding_dbl) | ||||
| 	glyph_dst_size := glyph_size + bounds_scaled | ||||
| 	glyph_size     += bounds_scaled * over_sample | ||||
|  | ||||
| 	// Figure out the destination rect. | ||||
| 	bounds_0_scaled := Vec2 { | ||||
| 		cast(f32) i32(bounds_0.x * entry.size_scale - 0.5), | ||||
| 		cast(f32) i32(bounds_0.y * entry.size_scale - 0.5), | ||||
| 	} | ||||
| 	dst        := position + scale * bounds_0_scaled | ||||
| 	dst_width  := scale.x * glyph_dst_width | ||||
| 	dst_height := scale.y * glyph_dst_height | ||||
| 	dst.x      -= scale.x * glyph_padding | ||||
| 	dst.y      -= scale.y * glyph_padding | ||||
| 	dst_size   := Vec2{ dst_width, dst_height } | ||||
|  | ||||
| 	glyph_size := Vec2 { glyph_width, glyph_height } | ||||
| 	textspace_x_form( & glyph_position, & glyph_size, glyph_buffer_width, glyph_buffer_height ) | ||||
| 	dst        := position + scale * bounds_0_scaled - glyph_padding * scale | ||||
| 	dst_size   := glyph_dst_size * scale | ||||
| 	textspace_x_form( & glyph_position, & glyph_size, glyph_buffer_size ) | ||||
|  | ||||
| 	// Add the glyph drawcall. | ||||
| 	call : DrawCall | ||||
| @@ -438,8 +421,12 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, | ||||
| 		pass        = .Target_Uncached | ||||
| 		colour      = ctx.colour | ||||
| 		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(len(ctx.draw_list.indices)) | ||||
|  | ||||
| 		blit_quad( & ctx.draw_list, | ||||
| 				dst,            dst            + dst_size, | ||||
| 				glyph_position, glyph_position + glyph_size ) | ||||
|  | ||||
| 		end_index = u32(len(ctx.draw_list.indices)) | ||||
| 		append( & ctx.draw_list.calls, call ) | ||||
| 	} | ||||
|  | ||||
| @@ -464,13 +451,15 @@ draw_cached_glyph :: proc( ctx : ^Context, | ||||
| ) -> b32 | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	bounds_width  := f32(bounds_1.x - bounds_0.x) | ||||
| 	bounds_height := f32(bounds_1.y - bounds_0.y) | ||||
| 	bounds_size := Vec2 { | ||||
| 		f32(bounds_1.x - bounds_0.x), | ||||
| 		f32(bounds_1.y - bounds_0.y), | ||||
| 	} | ||||
|  | ||||
| 	// E region is special case and not cached to atlas | ||||
| 	if region_kind == .E | ||||
| 	{ | ||||
| 		directly_draw_massive_glyph( ctx, entry, glyph_index, bounds_0, bounds_1, bounds_width, bounds_height, over_sample, position, scale ) | ||||
| 		directly_draw_massive_glyph( ctx, entry, glyph_index, bounds_0, bounds_1, bounds_size, over_sample, position, scale ) | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| @@ -480,30 +469,22 @@ draw_cached_glyph :: proc( ctx : ^Context, | ||||
| 	} | ||||
|  | ||||
| 	atlas := & ctx.atlas | ||||
| 	atlas_width   := f32(atlas.width) | ||||
| 	atlas_height  := f32(atlas.height) | ||||
| 	atlas_size    := Vec2 { f32(atlas.width), f32(atlas.height) } | ||||
| 	glyph_padding := f32(atlas.glyph_padding) | ||||
|  | ||||
| 	// Figure out the source bounding box in the atlas texture | ||||
| 	glyph_atlas_position, glyph_atlas_size := atlas_bbox( atlas, region_kind, atlas_index ) | ||||
| 	slot_position, _ := atlas_bbox( atlas, region_kind, atlas_index ) | ||||
|  | ||||
| 	glyph_width  := bounds_width  * entry.size_scale | ||||
| 	glyph_height := bounds_height * entry.size_scale | ||||
| 	glyph_scale := bounds_size * entry.size_scale + glyph_padding | ||||
|  | ||||
| 	glyph_width  += glyph_padding | ||||
| 	glyph_height += glyph_padding | ||||
| 	glyph_scale  := Vec2 { glyph_width, glyph_height } | ||||
|  | ||||
| 	bounds_0_scaled := Vec2{ f32(bounds_0.x), f32(bounds_0.y) } * entry.size_scale //- { 0.5, 0.5 } | ||||
| 	bounds_0_scaled := bounds_0 * entry.size_scale //- { 0.5, 0.5 } | ||||
| 	bounds_0_scaled  = ceil(bounds_0_scaled) | ||||
|  | ||||
| 	dst        := position + bounds_0_scaled * scale | ||||
| 	dst        -= scale   * glyph_padding | ||||
| 	dst_width  := scale.x * glyph_width | ||||
| 	dst_height := scale.y * glyph_height | ||||
| 	dst_scale  := Vec2 { dst_width, dst_height } | ||||
| 	dst       := position + bounds_0_scaled * scale | ||||
| 	dst       -= glyph_padding * scale | ||||
| 	dst_scale := glyph_scale   * scale | ||||
|  | ||||
| 	textspace_x_form( & glyph_atlas_position, & glyph_scale, atlas_width, atlas_height ) | ||||
| 	textspace_x_form( & slot_position, & glyph_scale, atlas_size ) | ||||
|  | ||||
| 	// Add the glyph drawcall | ||||
| 	call := DrawCall_Default | ||||
| @@ -513,7 +494,9 @@ draw_cached_glyph :: proc( ctx : ^Context, | ||||
| 		colour      = ctx.colour | ||||
| 		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 ) | ||||
| 		blit_quad( & ctx.draw_list, | ||||
| 			dst,           dst           + dst_scale, | ||||
| 			slot_position, slot_position + glyph_scale ) | ||||
| 		end_index   = cast(u32) len(ctx.draw_list.indices) | ||||
| 	} | ||||
| 	append( & ctx.draw_list.calls, call ) | ||||
|   | ||||
| @@ -74,6 +74,10 @@ vec2 :: proc { | ||||
| 	vec2_from_vec2i, | ||||
| } | ||||
|  | ||||
| vec2i :: proc { | ||||
| 	vec2i_from_vec2, | ||||
| } | ||||
|  | ||||
| vec2_64 :: proc { | ||||
| 	vec2_64_from_vec2, | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,6 @@ | ||||
| package VEFontCache | ||||
|  | ||||
| font_glyph_lru_code :: #force_inline proc "contextless" ( font : FontID, glyph_index : Glyph ) -> (lru_code : u64) | ||||
| { | ||||
| 	// font        := font | ||||
| 	// glyph_index := glyph_index | ||||
|  | ||||
| 	// font_bytes  := slice_ptr( transmute(^byte) & font,        size_of(FontID) ) | ||||
| 	// glyph_bytes := slice_ptr( transmute(^byte) & glyph_index, size_of(Glyph) ) | ||||
|  | ||||
| 	// buffer : [32]byte | ||||
| 	// copy( buffer[:], font_bytes ) | ||||
| 	// copy( buffer[ len(font_bytes) :], glyph_bytes ) | ||||
| 	// hash := fnv64a( transmute([]byte) buffer[: size_of(FontID) + size_of(Glyph) ] ) | ||||
| 	// lru_code = hash | ||||
| font_glyph_lru_code :: #force_inline proc "contextless" ( font : FontID, glyph_index : Glyph ) -> (lru_code : u64) { | ||||
| 	lru_code = u64(glyph_index) + ( ( 0x100000000 * u64(font) ) & 0xFFFFFFFF00000000 ) | ||||
| 	return | ||||
| } | ||||
| @@ -79,8 +67,7 @@ is_empty :: #force_inline proc ( ctx : ^Context, entry : ^Entry, glyph_index : G | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| mark_batch_codepoint_seen :: #force_inline proc ( ctx : ^Context, lru_code : u64 ) | ||||
| { | ||||
| mark_batch_codepoint_seen :: #force_inline proc ( ctx : ^Context, lru_code : u64 ) { | ||||
| 	ctx.temp_codepoint_seen[lru_code] = true | ||||
| 	ctx.temp_codepoint_seen_num += 1 | ||||
| } | ||||
| @@ -90,15 +77,13 @@ reset_batch_codepoint_state :: #force_inline proc( ctx : ^Context ) { | ||||
| 	ctx.temp_codepoint_seen_num = 0 | ||||
| } | ||||
|  | ||||
| screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, width, height : f32 ) { | ||||
| screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 ) { | ||||
| 	when true | ||||
| 	{ | ||||
| 		pos_64   := vec2_64_from_vec2(position^) | ||||
| 		scale_64 := vec2_64_from_vec2(scale^) | ||||
| 		width    := f64(width) | ||||
| 		height   := f64(height) | ||||
|  | ||||
| 		quotient : Vec2_64 = 1.0 / { width, height } | ||||
| 		quotient : Vec2_64 = 1.0 / vec2_64(size) | ||||
| 		pos_64      = pos_64   * quotient * 2.0 - 1.0 | ||||
| 		scale_64    = scale_64 * quotient * 2.0 | ||||
|  | ||||
| @@ -107,21 +92,19 @@ screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2 | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		quotient : Vec2 = 1.0 / { width, height } | ||||
| 		quotient : Vec2 = 1.0 / size | ||||
| 		(position^) *= quotient * 2.0 - 1.0 | ||||
| 		(scale^)    *= quotient * 2.0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, width, height : f32 ) { | ||||
| textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 ) { | ||||
| 	when true | ||||
| 	{ | ||||
| 		pos_64   := vec2_64_from_vec2(position^) | ||||
| 		scale_64 := vec2_64_from_vec2(scale^) | ||||
| 		width    := f64(width) | ||||
| 		height   := f64(height) | ||||
|  | ||||
| 		quotient : Vec2_64 = 1.0 / { width, height } | ||||
| 		quotient : Vec2_64 = 1.0 / vec2_64(size) | ||||
| 		pos_64   *= quotient | ||||
| 		scale_64 *= quotient | ||||
|  | ||||
| @@ -130,7 +113,7 @@ textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		quotient    : Vec2 = 1.0 / { width, height } | ||||
| 		quotient    : Vec2 = 1.0 / size | ||||
| 		(position^) *= quotient | ||||
| 		(scale^)    *= quotient | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user