VEFontCache: Lifted the GlyphDrawBuffer member of atlas to the context
This commit is contained in:
		| @@ -175,7 +175,6 @@ LRU_reload :: #force_inline proc( cache : ^LRU_Cache, allocator : Allocator ) | ||||
| LRU_hash_key :: #force_inline proc( key : u64 ) -> ( hash : u64 ) { | ||||
| 	bytes := transmute( [8]byte ) key | ||||
| 	hash   = fnv64a( bytes[:] ) | ||||
| 	// hash = cast(u64) crc64( bytes[:] ) | ||||
| 	return | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,6 @@ Changes: | ||||
| package VEFontCache | ||||
|  | ||||
| import "base:runtime" | ||||
| import "core:mem" | ||||
|  | ||||
| Advance_Snap_Smallfont_Size :: 12 | ||||
|  | ||||
| @@ -22,8 +21,9 @@ Vec2    :: [2]f32 | ||||
| Vec2i   :: [2]i32 | ||||
| Vec2_64 :: [2]f64 | ||||
|  | ||||
| vec2_from_scalar  :: #force_inline proc( scalar : f32  ) -> Vec2    { return { scalar, scalar } } | ||||
| vec2_64_from_vec2 :: #force_inline proc( v2     : Vec2 ) -> Vec2_64 { return { f64(v2.x), f64(v2.y) }} | ||||
| vec2_from_scalar  :: #force_inline proc( scalar : f32   ) -> Vec2    { return { scalar, scalar } } | ||||
| vec2_64_from_vec2 :: #force_inline proc( 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) }} | ||||
|  | ||||
| FontID  :: distinct i64 | ||||
| Glyph   :: distinct i32 | ||||
| @@ -71,9 +71,10 @@ Context :: struct { | ||||
| 		calls_offset    : int, | ||||
| 	}, | ||||
|  | ||||
| 	draw_list   : DrawList, | ||||
| 	atlas       : Atlas, | ||||
| 	shape_cache : ShapedTextCache, | ||||
| 	draw_list    : DrawList, | ||||
| 	atlas        : Atlas, | ||||
| 	glyph_buffer : GlyphDrawBuffer, | ||||
| 	shape_cache  : ShapedTextCache, | ||||
|  | ||||
| 	curve_quality  : u32, | ||||
| 	text_shape_adv : b32, | ||||
| @@ -103,7 +104,7 @@ InitAtlasParams :: struct { | ||||
| InitAtlasParams_Default :: InitAtlasParams { | ||||
| 	width         = 4096, | ||||
| 	height        = 2048, | ||||
| 	glyph_padding = 2, | ||||
| 	glyph_padding = 1, | ||||
|  | ||||
| 	region_a = { | ||||
| 		width  = 32, | ||||
| @@ -151,7 +152,7 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind, | ||||
| 	atlas_params                := InitAtlasParams_Default, | ||||
| 	glyph_draw_params           := InitGlyphDrawParams_Default, | ||||
| 	shape_cache_params          := InitShapeCacheParams_Default, | ||||
| 	curve_quality               : u32 = 6, | ||||
| 	curve_quality               : u32 = 3, | ||||
| 	entires_reserve             : u32 = 512, | ||||
| 	temp_path_reserve           : u32 = 512, | ||||
| 	temp_codepoint_seen_reserve : u32 = 512, | ||||
| @@ -164,7 +165,7 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind, | ||||
| 	context.allocator = ctx.backing | ||||
|  | ||||
| 	if curve_quality == 0 { | ||||
| 		curve_quality = 6 | ||||
| 		curve_quality = 3 | ||||
| 	} | ||||
| 	ctx.curve_quality = curve_quality | ||||
|  | ||||
| @@ -242,11 +243,11 @@ startup :: proc( ctx : ^Context, parser_kind : ParserKind, | ||||
|  | ||||
| 	// Note(From original author): We can actually go over VE_FONTCACHE_GLYPHDRAW_BUFFER_BATCH batches due to smart packing! | ||||
| 	{ | ||||
| 		using atlas | ||||
| 		using glyph_buffer | ||||
| 		over_sample   = glyph_draw_params.over_sample | ||||
| 		buffer_batch  = glyph_draw_params.buffer_batch | ||||
| 		buffer_width  = region_d.width  * u32(over_sample.x) * buffer_batch | ||||
| 		buffer_height = region_d.height * u32(over_sample.y) | ||||
| 		batch         = glyph_draw_params.buffer_batch | ||||
| 		width         = atlas.region_d.width  * u32(over_sample.x) * batch | ||||
| 		height        = atlas.region_d.height * u32(over_sample.y) | ||||
| 		draw_padding  = glyph_draw_params.draw_padding | ||||
|  | ||||
| 		draw_list.calls, error = make( [dynamic]DrawCall, cast(u64) glyph_draw_params.buffer_batch * 2 ) | ||||
| @@ -301,13 +302,13 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator ) | ||||
| 		reload_array( & positions, allocator ) | ||||
| 	} | ||||
|  | ||||
| 	reload_array( & atlas.draw_list.calls, allocator ) | ||||
| 	reload_array( & atlas.draw_list.indices, allocator ) | ||||
| 	reload_array( & atlas.draw_list.vertices, allocator ) | ||||
| 	reload_array( & glyph_buffer.draw_list.calls, allocator ) | ||||
| 	reload_array( & glyph_buffer.draw_list.indices, allocator ) | ||||
| 	reload_array( & glyph_buffer.draw_list.vertices, 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 ) | ||||
| 	reload_array( & glyph_buffer.clear_draw_list.calls, allocator ) | ||||
| 	reload_array( & glyph_buffer.clear_draw_list.indices, allocator ) | ||||
| 	reload_array( & glyph_buffer.clear_draw_list.vertices, allocator ) | ||||
|  | ||||
| 	reload_array( & shape_cache.storage, allocator ) | ||||
| 	LRU_reload( & shape_cache.state, allocator ) | ||||
| @@ -358,7 +359,7 @@ load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32 | ||||
| 		// assert( parser_info != nil, "VEFontCache.load_font: Failed to load font info from parser" ) | ||||
|  | ||||
| 		size = size_px | ||||
| 		size_scale = size_px < 0.0 ?                             \ | ||||
| 		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 | ||||
| @@ -404,10 +405,6 @@ configure_snap :: #force_inline proc( ctx : ^Context, snap_width, snap_height : | ||||
| get_cursor_pos :: #force_inline proc "contextless" ( ctx : ^Context                  ) -> Vec2 { return ctx.cursor_pos } | ||||
| set_colour     :: #force_inline proc "contextless" ( ctx : ^Context, colour : Colour )         { ctx.colour = colour } | ||||
|  | ||||
| // TODO(Ed): Change this to be whitespace aware so that we can optimize the caching of shpaes properly. | ||||
| // Right now the entire text provided to this call is considered a "shape" this is really bad as basically it invalidates caching for large chunks of text | ||||
| // Instead we should be aware of whitespace tokens and the chunks between them (the whitespace lexer could be abused for this).  | ||||
| // From there we should maek a 'draw text shape' that breaks up the batch text draws for each of the shapes. | ||||
| draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : Vec2, scale : Vec2 ) -> b32 | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| @@ -424,8 +421,6 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : | ||||
|  | ||||
| 	entry  := & ctx.entries[ font ] | ||||
|  | ||||
| 	last_shaped : ^ShapedText | ||||
|  | ||||
| 	ChunkType   :: enum u32 { Visible, Formatting } | ||||
| 	chunk_kind  : ChunkType | ||||
| 	chunk_start : int = 0 | ||||
| @@ -434,91 +429,91 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : | ||||
| 	text_utf8_bytes := transmute([]u8) text_utf8 | ||||
| 	text_chunk      : string | ||||
|  | ||||
| 	when true { | ||||
| 	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 ) | ||||
| 		last_shaped = shaped | ||||
| 	} | ||||
| 	} | ||||
| 	else { | ||||
| 	last_byte_offset : int = 0 | ||||
| 	byte_offset      : int = 0 | ||||
| 	for codepoint, offset in text_utf8 | ||||
| 	Text_As_Shape :: true | ||||
| 	when Text_As_Shape | ||||
| 	{ | ||||
| 		Rune_Space           :: ' ' | ||||
| 		Rune_Tab             :: '\t' | ||||
| 		Rune_Carriage_Return :: '\r' | ||||
| 		Rune_Line_Feed       :: '\n' | ||||
| 		// Rune_Tab_Vertical :: '\v' | ||||
|  | ||||
| 		byte_offset = offset | ||||
|  | ||||
| 		switch codepoint | ||||
| 		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 | ||||
| 		{ | ||||
| 			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 ) | ||||
| 						last_shaped = shaped | ||||
| 			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 | ||||
| 						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 ) | ||||
| 				last_shaped = shaped | ||||
| 						last_byte_offset = byte_offset | ||||
| 						continue | ||||
| 					} | ||||
| 			} | ||||
|  | ||||
| 			chunk_start = byte_offset | ||||
| 			chunk_end   = chunk_start | ||||
| 			chunk_kind  = .Visible | ||||
| 			// 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 ) | ||||
| 				} | ||||
|  | ||||
| 			last_byte_offset = byte_offset | ||||
| 				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 | ||||
| 	} | ||||
|  | ||||
| 	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 ) | ||||
| 		last_shaped = shaped | ||||
| 	} | ||||
|  | ||||
| 	chunk_start = byte_offset | ||||
| 	chunk_end   = chunk_start | ||||
| 	chunk_kind  = .Visible | ||||
|  | ||||
| 	last_byte_offset = byte_offset | ||||
| 	} | ||||
| 	 | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| @@ -526,7 +521,6 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : | ||||
| get_draw_list :: proc( ctx : ^Context, optimize_before_returning := true ) -> ^DrawList { | ||||
| 	assert( ctx != nil ) | ||||
| 	if optimize_before_returning do optimize_draw_list( & ctx.draw_list, 0 ) | ||||
|  | ||||
| 	return & ctx.draw_list | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -33,8 +33,6 @@ Atlas :: struct { | ||||
| 	region_b : AtlasRegion, | ||||
| 	region_c : AtlasRegion, | ||||
| 	region_d : AtlasRegion, | ||||
|  | ||||
| 	using glyph_update_batch : GlyphDrawBuffer, | ||||
| } | ||||
|  | ||||
| atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : i32 ) -> (position : Vec2, width, height : f32) | ||||
| @@ -136,7 +134,8 @@ decide_codepoint_region :: #force_inline proc( ctx : ^Context, entry : ^Entry, g | ||||
| 	bounds_width  := bounds_1.x - bounds_0.x | ||||
| 	bounds_height := bounds_1.y - bounds_0.y | ||||
|  | ||||
| 	atlas := & ctx.atlas | ||||
| 	atlas        := & ctx.atlas | ||||
| 	glyph_buffer := & ctx.glyph_buffer | ||||
|  | ||||
| 	bounds_width_scaled  := cast(u32) (f32(bounds_width)  * entry.size_scale + 2.0 * f32(atlas.glyph_padding)) | ||||
| 	bounds_height_scaled := cast(u32) (f32(bounds_height) * entry.size_scale + 2.0 * f32(atlas.glyph_padding)) | ||||
| @@ -165,12 +164,12 @@ decide_codepoint_region :: #force_inline proc( ctx : ^Context, entry : ^Entry, g | ||||
| 		region_kind = .D | ||||
| 		region      = & atlas.region_d | ||||
| 	} | ||||
| 	else if bounds_width_scaled <= atlas.buffer_width && bounds_height_scaled <= atlas.buffer_height | ||||
| 	else if bounds_width_scaled <= glyph_buffer.width && bounds_height_scaled <= glyph_buffer.height | ||||
| 	{ | ||||
| 		// Region 'E' for massive glyphs. These are rendered uncached and un-oversampled. | ||||
| 		region_kind = .E | ||||
| 		region      = nil | ||||
| 		if bounds_width_scaled <= atlas.buffer_width / 2 && bounds_height_scaled <= atlas.buffer_height / 2 { | ||||
| 		if bounds_width_scaled <= glyph_buffer.width / 2 && bounds_height_scaled <= glyph_buffer.height / 2 { | ||||
| 			over_sample = { 2.0, 2.0 } | ||||
| 		} | ||||
| 		else { | ||||
| @@ -183,7 +182,7 @@ decide_codepoint_region :: #force_inline proc( ctx : ^Context, entry : ^Entry, g | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	over_sample = ctx.atlas.over_sample | ||||
| 	over_sample = glyph_buffer.over_sample | ||||
| 	assert(region != nil) | ||||
| 	return | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| package VEFontCache | ||||
|  | ||||
| import "core:math" | ||||
|  | ||||
| Vertex :: struct { | ||||
| 	pos  : Vec2, | ||||
| 	u, v : f32, | ||||
| @@ -41,12 +39,12 @@ FrameBufferPass :: enum u32 { | ||||
|  | ||||
| GlyphDrawBuffer :: struct { | ||||
| 	over_sample   : Vec2, | ||||
| 	buffer_batch  : u32, | ||||
| 	buffer_width  : u32, | ||||
| 	buffer_height : u32, | ||||
| 	batch         : u32, | ||||
| 	width         : u32, | ||||
| 	height        : u32, | ||||
| 	draw_padding  : u32, | ||||
|  | ||||
| 	update_batch_x  : i32, | ||||
| 	batch_x         : i32, | ||||
| 	clear_draw_list : DrawList, | ||||
| 	draw_list       : DrawList, | ||||
| } | ||||
| @@ -94,7 +92,7 @@ blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : ^Entry, bounds_0, bounds_1 : Vec2i, scale, translate : Vec2  ) -> b32 | ||||
| cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : ^Entry, bounds_0, bounds_1 : Vec2, scale, translate : Vec2  ) -> b32 | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	if glyph_index == Glyph(0) { | ||||
| @@ -141,8 +139,8 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : | ||||
| 	Note that this outside point is scaled alongside the glyph in ve_fontcache_draw_filled_path, so we don't need to handle that here. | ||||
| 	*/ | ||||
| 	outside := Vec2 { | ||||
| 		f32(bounds_0.x) - 21, | ||||
| 		f32(bounds_0.y) - 33, | ||||
| 		bounds_0.x - 21, | ||||
| 		bounds_0.y - 33, | ||||
| 	} | ||||
|  | ||||
| 	// Note(Original Author): Figure out scaling so it fits within our box. | ||||
| @@ -165,7 +163,7 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : | ||||
| 			fallthrough | ||||
|  | ||||
| 		case .Line: | ||||
| 			append_elem( & path, Vec2{ f32(edge.x), f32(edge.y) }) | ||||
| 			append( & path, Vec2{ f32(edge.x), f32(edge.y) }) | ||||
|  | ||||
| 		case .Curve: | ||||
| 			assert( len(path) > 0 ) | ||||
| @@ -176,7 +174,7 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : | ||||
| 			step  := 1.0 / f32(ctx.curve_quality) | ||||
| 			alpha := step | ||||
| 			for index := i32(0); index < i32(ctx.curve_quality); index += 1 { | ||||
| 				append_elem( & path, eval_point_on_bezier3( p0, p1, p2, alpha )) | ||||
| 				append( & path, eval_point_on_bezier3( p0, p1, p2, alpha )) | ||||
| 				alpha += step | ||||
| 			} | ||||
|  | ||||
| @@ -190,7 +188,7 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : | ||||
| 			step  := 1.0 / f32(ctx.curve_quality) | ||||
| 			alpha := step | ||||
| 			for index := i32(0); index < i32(ctx.curve_quality); index += 1 { | ||||
| 				append_elem( & path, eval_point_on_bezier4( p0, p1, p2, p3, alpha )) | ||||
| 				append( & path, eval_point_on_bezier4( p0, p1, p2, p3, alpha )) | ||||
| 				alpha += step | ||||
| 			} | ||||
|  | ||||
| @@ -214,9 +212,17 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, entry : | ||||
| /* | ||||
| 	Called by: | ||||
| 	* can_batch_glyph : If it determines that the glyph was not detected and we haven't reached capacity in the atlas | ||||
| 	* draw_text_shape : Glyph  | ||||
| 	* draw_text_shape : Glyph | ||||
| */ | ||||
| cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, lru_code : u64, atlas_index : i32, entry : ^Entry, region_kind : AtlasRegionKind, region : ^AtlasRegion, over_sample : Vec2 ) | ||||
| cache_glyph_to_atlas :: proc( ctx : ^Context, | ||||
| 	font        : FontID, | ||||
| 	glyph_index : Glyph, | ||||
| 	lru_code    : u64, | ||||
| 	atlas_index : i32, | ||||
| 	entry       : ^Entry, | ||||
| 	region_kind : AtlasRegionKind, | ||||
| 	region      : ^AtlasRegion, | ||||
| 	over_sample : Vec2 ) | ||||
| { | ||||
| 	// profile(#procedure) | ||||
|  | ||||
| @@ -257,26 +263,28 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph | ||||
| 	atlas               := & ctx.atlas | ||||
| 	atlas_width         := f32(atlas.width) | ||||
| 	atlas_height        := f32(atlas.height) | ||||
| 	glyph_buffer_width  := f32(atlas.buffer_width) | ||||
| 	glyph_buffer_height := f32(atlas.buffer_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 | ||||
|  | ||||
| 	if ctx.debug_print | ||||
| 	{ | ||||
| 		@static debug_total_cached : i32 = 0 | ||||
| 		logf("glyph %v%v( %v ) caching to atlas region %v at idx %d. %d total glyphs cached.\n", i32(glyph_index), rune(glyph_index), cast(rune) region_kind, atlas_index, debug_total_cached) | ||||
| 		logf("glyph %v%v( %v ) caching to atlas region %v at idx %d. %d total glyphs cached.\n", | ||||
| 			i32(glyph_index), rune(glyph_index), cast(rune) region_kind, atlas_index, debug_total_cached) | ||||
| 		debug_total_cached += 1 | ||||
| 	} | ||||
|  | ||||
| 	// Draw oversized glyph to update FBO | ||||
| 	glyph_draw_scale       := over_sample * entry.size_scale | ||||
| 	glyph_draw_translate   := -1 * Vec2 { f32(bounds_0.x), f32(bounds_0.y) } * glyph_draw_scale + vec2( glyph_padding ) | ||||
| 	glyph_draw_translate   := -1 * vec2(bounds_0) * glyph_draw_scale + vec2( glyph_padding ) | ||||
| 	glyph_draw_translate.x  = cast(f32) (i32(glyph_draw_translate.x + 0.9999999)) | ||||
| 	glyph_draw_translate.y  = cast(f32) (i32(glyph_draw_translate.y + 0.9999999)) | ||||
|  | ||||
| 	// Allocate a glyph_update_FBO region | ||||
| 	gwidth_scaled_px := i32( bounds_width * glyph_draw_scale.x + 1.0 ) + i32(over_sample.x * glyph_padding) | ||||
|   if i32(atlas.update_batch_x + gwidth_scaled_px) >= i32(atlas.buffer_width) { | ||||
|   if i32(glyph_buffer.batch_x + gwidth_scaled_px) >= i32(glyph_buffer.width) { | ||||
| 		flush_glyph_buffer_to_atlas( ctx ) | ||||
| 	} | ||||
|  | ||||
| @@ -293,7 +301,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph | ||||
| 	screenspace_x_form( & dst_glyph_position, & dst_glyph_size, atlas_width, atlas_height ) | ||||
| 	screenspace_x_form( & dst_position,       & dst_size,       atlas_width, atlas_height ) | ||||
|  | ||||
| 	src_position := Vec2 { f32(atlas.update_batch_x), 0 } | ||||
| 	src_position := Vec2 { f32(glyph_buffer.batch_x), 0 } | ||||
| 	src_size     := Vec2 { | ||||
| 		bounds_width  * glyph_draw_scale.x, | ||||
| 		bounds_height * glyph_draw_scale.y, | ||||
| @@ -302,8 +310,8 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph | ||||
| 	textspace_x_form( & src_position, & src_size, glyph_buffer_width, glyph_buffer_height ) | ||||
|  | ||||
| 	// Advance glyph_update_batch_x and calculate final glyph drawing transform | ||||
| 	glyph_draw_translate.x += f32(atlas.update_batch_x) | ||||
| 	atlas.update_batch_x   += gwidth_scaled_px | ||||
| 	glyph_draw_translate.x += f32(glyph_buffer.batch_x) | ||||
| 	glyph_buffer.batch_x   += gwidth_scaled_px | ||||
| 	screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_width, glyph_buffer_height ) | ||||
|  | ||||
| 	call : DrawCall | ||||
| @@ -312,21 +320,21 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph | ||||
| 		using call | ||||
| 		pass        = .Atlas | ||||
| 		region      = .Ignore | ||||
| 		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 = cast(u32) len(atlas.clear_draw_list.indices) | ||||
| 		append( & atlas.clear_draw_list.calls, call ) | ||||
| 		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 } ) | ||||
| 		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(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 = cast(u32) len(atlas.draw_list.indices) | ||||
| 		append( & atlas.draw_list.calls, call ) | ||||
| 		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 ) | ||||
| 		end_index = cast(u32) len(glyph_buffer.draw_list.indices) | ||||
| 		append( & glyph_buffer.draw_list.calls, call ) | ||||
| 	} | ||||
|  | ||||
| 	// Render glyph to glyph_update_FBO | ||||
| 	cache_glyph( ctx, font, glyph_index, entry, bounds_0, bounds_1, glyph_draw_scale, glyph_draw_translate ) | ||||
| 	cache_glyph( ctx, font, glyph_index, entry, vec2(bounds_0), vec2(bounds_1), glyph_draw_scale, glyph_draw_translate ) | ||||
| } | ||||
|  | ||||
| // ve_fontcache_clear_drawlist | ||||
| @@ -336,18 +344,23 @@ clear_draw_list :: #force_inline proc ( draw_list : ^DrawList ) { | ||||
| 	clear( & draw_list.vertices ) | ||||
| } | ||||
|  | ||||
| directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Glyph, bounds_0, bounds_1 : Vec2i, bounds_width, bounds_height : f32, over_sample, position, scale : Vec2 ) | ||||
| directly_draw_massive_glyph :: proc( ctx : ^Context, | ||||
| 	entry : ^Entry, | ||||
| 	glyph : Glyph, | ||||
| 	bounds_0,     bounds_1       : Vec2, | ||||
| 	bounds_width, bounds_height  : f32, | ||||
| 	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.atlas.buffer_width) | ||||
| 	glyph_buffer_height := f32(ctx.atlas.buffer_height) | ||||
| 	glyph_buffer_width  := f32(ctx.glyph_buffer.width) | ||||
| 	glyph_buffer_height := f32(ctx.glyph_buffer.height) | ||||
|  | ||||
| 	// Draw un-antialiased glyph to update FBO. | ||||
| 	glyph_draw_scale     := over_sample * entry.size_scale | ||||
| 	glyph_draw_translate := -1 * Vec2{ f32(bounds_0.x), f32(bounds_0.y) } * glyph_draw_scale + vec2_from_scalar(glyph_padding) | ||||
| 	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 ) | ||||
|  | ||||
| 	cache_glyph( ctx, entry.id, glyph, entry, bounds_0, bounds_1, glyph_draw_scale, glyph_draw_translate ) | ||||
| @@ -368,14 +381,14 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Gly | ||||
|  | ||||
| 	// Figure out the destination rect. | ||||
| 	bounds_0_scaled := Vec2 { | ||||
| 		cast(f32) i32(f32(bounds_0.x) * entry.size_scale - 0.5), | ||||
| 		cast(f32) i32(f32(bounds_0.y) * entry.size_scale - 0.5), | ||||
| 		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 * f32(ctx.atlas.draw_padding) | ||||
| 	dst.y      -= scale.y * f32(ctx.atlas.draw_padding) | ||||
| 	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 } | ||||
| @@ -401,11 +414,16 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Gly | ||||
| 	append( & ctx.draw_list.calls, call ) | ||||
| } | ||||
|  | ||||
| draw_cached_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph, | ||||
| 	lru_code : u64, atlas_index : i32, | ||||
| 	bounds_0, bounds_1 : Vec2i, | ||||
| 	region_kind : AtlasRegionKind, region : ^AtlasRegion, over_sample : Vec2, | ||||
| 	position,	scale : Vec2 | ||||
| draw_cached_glyph :: proc( ctx : ^Context, | ||||
| 	entry              : ^Entry, | ||||
| 	glyph_index        : Glyph, | ||||
| 	lru_code           : u64, | ||||
| 	atlas_index        : i32, | ||||
| 	bounds_0, bounds_1 : Vec2, | ||||
| 	region_kind        : AtlasRegionKind, | ||||
| 	region             : ^AtlasRegion, | ||||
| 	over_sample        : Vec2, | ||||
| 	position,	scale    : Vec2 | ||||
| ) -> b32 | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| @@ -440,10 +458,8 @@ draw_cached_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph, | ||||
| 	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  = { | ||||
| 		math.ceil(bounds_0_scaled.x), | ||||
| 		math.ceil(bounds_0_scaled.y), | ||||
| 	} | ||||
| 	bounds_0_scaled  = ceil(bounds_0_scaled) | ||||
|  | ||||
| 	dst        := position + bounds_0_scaled * scale | ||||
| 	dst        -= scale   * glyph_padding | ||||
| 	dst_width  := scale.x * glyph_width | ||||
| @@ -516,12 +532,14 @@ draw_filled_path :: proc( draw_list : ^DrawList, outside_point : Vec2, path : [] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| draw_text_batch :: proc( ctx : ^Context, entry : ^Entry, shaped : ^ShapedText, batch_start_idx, batch_end_idx : i32, position, scale : Vec2, snap_width, snap_height : f32 ) | ||||
| draw_text_batch :: proc( ctx : ^Context, entry : ^Entry, shaped : ^ShapedText, | ||||
| 	batch_start_idx, batch_end_idx : i32, | ||||
| 	position,        scale         : Vec2, | ||||
| 	snap_width,      snap_height   : f32 ) | ||||
| { | ||||
| 	// flush_glyph_buffer_to_atlas( ctx ) | ||||
| 	flush_glyph_buffer_to_atlas( ctx ) | ||||
| 	for index := batch_start_idx; index < batch_end_idx; index += 1 | ||||
| 	{ | ||||
| 		// profile(#procedure) | ||||
| 		glyph_index := shaped.glyphs[ index ] | ||||
|  | ||||
| 		if glyph_index == 0                                          do continue | ||||
| @@ -537,10 +555,10 @@ draw_text_batch :: proc( ctx : ^Context, entry : ^Entry, shaped : ^ShapedText, b | ||||
| 		shaped_position := shaped.positions[index] | ||||
| 		glyph_translate := position + shaped_position * scale | ||||
|  | ||||
| 		glyph_cached      := draw_cached_glyph( ctx, | ||||
| 			entry, glyph_index, | ||||
| 			lru_code, atlas_index, | ||||
| 			bounds_0, bounds_1, | ||||
| 		glyph_cached := draw_cached_glyph( ctx, | ||||
| 			entry,       glyph_index, | ||||
| 			lru_code,    atlas_index, | ||||
| 			vec2(bounds_0), vec2(bounds_1), | ||||
| 			region_kind, region, over_sample, | ||||
| 			glyph_translate, scale) | ||||
| 		assert( glyph_cached == true ) | ||||
| @@ -548,7 +566,13 @@ draw_text_batch :: proc( ctx : ^Context, entry : ^Entry, shaped : ^ShapedText, b | ||||
| } | ||||
|  | ||||
| // Helper for draw_text, all raw text content should be confirmed to be either formatting or visible shapes before getting cached. | ||||
| draw_text_shape :: proc( ctx : ^Context, font : FontID, entry : ^Entry, shaped : ^ShapedText, position, scale : Vec2, snap_width, snap_height : f32 ) -> (cursor_pos : Vec2) | ||||
| draw_text_shape :: proc( ctx : ^Context, | ||||
| 	font                    : FontID, | ||||
| 	entry                   : ^Entry, | ||||
| 	shaped                  : ^ShapedText, | ||||
| 	position,   scale       : Vec2, | ||||
| 	snap_width, snap_height : f32 | ||||
| ) -> (cursor_pos : Vec2) | ||||
| { | ||||
| 	// position := position //+ ctx.cursor_pos * scale | ||||
| 	// profile(#procedure) | ||||
| @@ -568,7 +592,7 @@ draw_text_shape :: proc( ctx : ^Context, font : FontID, entry : ^Entry, shaped : | ||||
| 		// Glyph has not been catched, needs to be directly drawn. | ||||
|  | ||||
| 		// First batch the other cached glyphs | ||||
| 		flush_glyph_buffer_to_atlas(ctx) | ||||
| 		// flush_glyph_buffer_to_atlas(ctx) | ||||
| 		draw_text_batch( ctx, entry, shaped, batch_start_idx, index, position, scale, snap_width, snap_height ) | ||||
| 		reset_batch_codepoint_state( ctx ) | ||||
|  | ||||
| @@ -577,7 +601,7 @@ draw_text_shape :: proc( ctx : ^Context, font : FontID, entry : ^Entry, shaped : | ||||
| 		batch_start_idx = index | ||||
| 	} | ||||
|  | ||||
| 	flush_glyph_buffer_to_atlas(ctx) | ||||
| 	// flush_glyph_buffer_to_atlas(ctx) | ||||
| 	draw_text_batch( ctx, entry, shaped, batch_start_idx, i32(len(shaped.glyphs)), position, scale, snap_width , snap_height ) | ||||
| 	reset_batch_codepoint_state( ctx ) | ||||
| 	cursor_pos = shaped.end_cursor_pos | ||||
| @@ -588,22 +612,21 @@ flush_glyph_buffer_to_atlas :: proc( ctx : ^Context ) | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	// Flush drawcalls to draw list | ||||
| 	merge_draw_list( & ctx.draw_list, & ctx.atlas.clear_draw_list ) | ||||
| 	merge_draw_list( & ctx.draw_list, & ctx.atlas.draw_list) | ||||
| 	clear_draw_list( & ctx.atlas.draw_list ) | ||||
| 	clear_draw_list( & ctx.atlas.clear_draw_list ) | ||||
| 	merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.clear_draw_list ) | ||||
| 	merge_draw_list( & ctx.draw_list, & ctx.glyph_buffer.draw_list) | ||||
| 	clear_draw_list( & ctx.glyph_buffer.draw_list ) | ||||
| 	clear_draw_list( & ctx.glyph_buffer.clear_draw_list ) | ||||
|  | ||||
| 	// Clear glyph_update_FBO | ||||
| 	if ctx.atlas.update_batch_x != 0 | ||||
| 	if ctx.glyph_buffer.batch_x != 0 | ||||
| 	{ | ||||
| 		call := DrawCall_Default | ||||
| 		call.pass = .Glyph | ||||
| 		call.start_index = 0 | ||||
| 		call.end_index   = 0 | ||||
| 		call.pass              = .Glyph | ||||
| 		call.start_index       = 0 | ||||
| 		call.end_index         = 0 | ||||
| 		call.clear_before_draw = true | ||||
|  | ||||
| 		append( & ctx.draw_list.calls, call ) | ||||
| 		ctx.atlas.update_batch_x = 0 | ||||
| 		ctx.glyph_buffer.batch_x = 0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -614,23 +637,19 @@ merge_draw_list :: proc( dst, src : ^DrawList ) | ||||
| 	error : AllocatorError | ||||
|  | ||||
| 	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 ) | ||||
| 	// } | ||||
| 	num_appended : int | ||||
| 	num_appended, error = append_elems( & dst.vertices, ..src.vertices[:] ) | ||||
| 	num_appended, error = append( & dst.vertices, ..src.vertices[:] ) | ||||
| 	assert( error == .None ) | ||||
|  | ||||
| 	i_offset := cast(u32) len(dst.indices) | ||||
| 	for index : u32 = 0; index < cast(u32) len(src.indices); index += 1 { | ||||
| 	for index : int = 0; index < 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) len(src.calls); index += 1 { | ||||
| 		src_call := src.calls[ index ] | ||||
| 	for index : int = 0; index < 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 ) | ||||
|   | ||||
| @@ -1,36 +1,36 @@ | ||||
| package VEFontCache | ||||
|  | ||||
| import "core:hash" | ||||
| 	crc64  :: hash.crc64_xz | ||||
| 	crc32  :: hash.crc32 | ||||
| 	fnv64a :: hash.fnv64a | ||||
| import "core:math" | ||||
| 	ceil_f16   :: math.ceil_f16 | ||||
| 	ceil_f16le :: math.ceil_f16le | ||||
| 	ceil_f16be :: math.ceil_f16be | ||||
| 	ceil_f32   :: math.ceil_f32 | ||||
| 	ceil_f32le :: math.ceil_f32le | ||||
| 	ceil_f32be :: math.ceil_f32be | ||||
| 	ceil_f64   :: math.ceil_f64 | ||||
| 	ceil_f64le :: math.ceil_f64le | ||||
| 	ceil_f64be :: math.ceil_f64be | ||||
|  | ||||
| import "core:math/linalg" | ||||
| import "core:mem" | ||||
| 	Kilobyte  :: mem.Kilobyte | ||||
| 	slice_ptr :: mem.slice_ptr | ||||
|  | ||||
| Kilobyte :: mem.Kilobyte | ||||
|  | ||||
| slice_ptr :: mem.slice_ptr | ||||
|  | ||||
| Arena :: mem.Arena | ||||
|  | ||||
| arena_allocator :: mem.arena_allocator | ||||
| arena_init      :: mem.arena_init | ||||
|  | ||||
| Allocator      :: mem.Allocator | ||||
| AllocatorError :: mem.Allocator_Error | ||||
| 	Allocator      :: mem.Allocator | ||||
| 	AllocatorError :: mem.Allocator_Error | ||||
|  | ||||
| 	Arena           :: mem.Arena | ||||
| 	arena_allocator :: mem.arena_allocator | ||||
| 	arena_init      :: mem.arena_init | ||||
| import "codebase:grime" | ||||
|  | ||||
| hmap_closest_prime :: grime.hmap_closest_prime | ||||
|  | ||||
| // logging | ||||
| log  :: grime.log | ||||
| logf :: grime.logf | ||||
|  | ||||
| profile :: grime.profile | ||||
|  | ||||
| reload_array :: grime.reload_array | ||||
| reload_map   :: grime.reload_map | ||||
| 	hmap_closest_prime :: grime.hmap_closest_prime | ||||
| 	log                :: grime.log | ||||
| 	logf               :: grime.logf | ||||
| 	profile            :: grime.profile | ||||
| 	reload_array       :: grime.reload_array | ||||
| 	reload_map         :: grime.reload_map | ||||
|  | ||||
| //#region("Proc overload mappings") | ||||
|  | ||||
| @@ -40,6 +40,20 @@ append :: proc { | ||||
| 	append_elem_string, | ||||
| } | ||||
|  | ||||
| ceil :: proc { | ||||
| 	math.ceil_f16, | ||||
| 	math.ceil_f16le, | ||||
| 	math.ceil_f16be, | ||||
| 	math.ceil_f32, | ||||
| 	math.ceil_f32le, | ||||
| 	math.ceil_f32be, | ||||
| 	math.ceil_f64, | ||||
| 	math.ceil_f64le, | ||||
| 	math.ceil_f64be, | ||||
|  | ||||
| 	grime.ceil_vec2, | ||||
| } | ||||
|  | ||||
| clear :: proc { | ||||
| 	clear_dynamic_array, | ||||
| } | ||||
| @@ -51,13 +65,17 @@ make :: proc { | ||||
| 	make_map, | ||||
| } | ||||
|  | ||||
|  | ||||
| resize :: proc { | ||||
| 	resize_dynamic_array, | ||||
| } | ||||
|  | ||||
| vec2 :: proc { | ||||
| 	vec2_from_scalar, | ||||
| 	vec2_from_vec2i, | ||||
| } | ||||
|  | ||||
| vec2_64 :: proc { | ||||
| 	vec2_64_from_vec2, | ||||
| } | ||||
|  | ||||
| //#endregion("Proc overload mappings") | ||||
|   | ||||
| @@ -4,7 +4,6 @@ Note(Ed): The only reason I didn't directly use harfbuzz is because hamza exists | ||||
| */ | ||||
|  | ||||
| import "core:c" | ||||
| import "core:math" | ||||
| import "thirdparty:harfbuzz" | ||||
|  | ||||
| ShaperKind :: enum { | ||||
| @@ -112,9 +111,9 @@ shaper_shape_from_text :: proc( ctx : ^ShaperContext, info : ^ShaperInfo, output | ||||
| 				(vertical_position^)  = cast(f32) i32(vertical_position^ + 0.5) | ||||
| 				continue | ||||
| 			} | ||||
| 			if math.abs( size ) <= Advance_Snap_Smallfont_Size | ||||
| 			if abs( size ) <= Advance_Snap_Smallfont_Size | ||||
| 			{ | ||||
| 				(position^) = math.ceil( position^ ) | ||||
| 				(position^) = ceil( position^ ) | ||||
| 			} | ||||
|  | ||||
| 			append( & output.glyphs, glyph_id ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user