Set glyph_padding to 4 (when using 8x8 over_sample we need more padding)
This commit is contained in:
		| @@ -6,8 +6,6 @@ Its original purpose was for use in game engines, however its rendeirng quality | ||||
|  | ||||
| TODO (Making it a more idiomatic library): | ||||
|  | ||||
| * Use Odin's builtin dynamic arrays | ||||
| * Use Odin's builtin map type | ||||
| * Setup freetype, harfbuzz, depedency management within the library | ||||
|  | ||||
| TODO Documentation: | ||||
|   | ||||
| @@ -21,8 +21,8 @@ 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 "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) }} | ||||
|  | ||||
| FontID  :: distinct i64 | ||||
| @@ -104,7 +104,7 @@ InitAtlasParams :: struct { | ||||
| InitAtlasParams_Default :: InitAtlasParams { | ||||
| 	width         = 4096, | ||||
| 	height        = 2048, | ||||
| 	glyph_padding = 1, | ||||
| 	glyph_padding = 4, | ||||
|  | ||||
| 	region_a = { | ||||
| 		width  = 32, | ||||
|   | ||||
| @@ -41,7 +41,7 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : i32 ) | ||||
| 	{ | ||||
| 		case .A: | ||||
| 			width  = f32(atlas.region_a.width) | ||||
| 			height = f32(atlas.region_b.height) | ||||
| 			height = f32(atlas.region_a.height) | ||||
|  | ||||
| 			position.x = cast(f32) (( local_idx % atlas.region_a.capacity.x ) * i32(atlas.region_a.width)) | ||||
| 			position.y = cast(f32) (( local_idx / atlas.region_a.capacity.x ) * i32(atlas.region_a.height)) | ||||
| @@ -123,7 +123,7 @@ can_batch_glyph :: #force_inline proc( ctx : ^Context, font : FontID, entry : ^E | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| decide_codepoint_region :: #force_inline proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph | ||||
| decide_codepoint_region :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph | ||||
| ) -> (region_kind : AtlasRegionKind, region : ^AtlasRegion, over_sample : Vec2) | ||||
| { | ||||
| 	if parser_is_glyph_empty( & entry.parser_info, glyph_index ) { | ||||
| @@ -131,14 +131,16 @@ decide_codepoint_region :: #force_inline proc( ctx : ^Context, entry : ^Entry, g | ||||
| 	} | ||||
|  | ||||
| 	bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) | ||||
| 	bounds_width  := bounds_1.x - bounds_0.x | ||||
| 	bounds_height := bounds_1.y - bounds_0.y | ||||
| 	bounds_width  := f32(bounds_1.x - bounds_0.x) | ||||
| 	bounds_height := f32(bounds_1.y - bounds_0.y) | ||||
|  | ||||
| 	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)) | ||||
| 	glyph_padding := f32(atlas.glyph_padding) * 2 | ||||
|  | ||||
| 	bounds_width_scaled  := cast(u32) (bounds_width  * entry.size_scale + glyph_padding) | ||||
| 	bounds_height_scaled := cast(u32) (bounds_height * entry.size_scale + glyph_padding) | ||||
|  | ||||
| 	if bounds_width_scaled <= atlas.region_a.width && bounds_height_scaled <= atlas.region_a.height | ||||
| 	{ | ||||
|   | ||||
| @@ -70,4 +70,6 @@ Will update the draw list layer with the latest offset based on the current leng | ||||
|  | ||||
| Provides a Vec2 the width and height occupied by the provided text string. The y is measured to be the the largest glyph box bounds height of the text. The width is derived from the `end_cursor_pos` field from a `ShapedText` entry. | ||||
|  | ||||
| ## get_font_vertical_metrics | ||||
|  | ||||
| A wrapper for `parser_get_font_vertical_metrics`. Will provide the ascent, descent, and line_gap for a font entry. | ||||
|   | ||||
| @@ -224,7 +224,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, | ||||
| 	region      : ^AtlasRegion, | ||||
| 	over_sample : Vec2 ) | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| 	profile(#procedure) | ||||
|  | ||||
| 	// Get hb_font text metrics. These are unscaled! | ||||
| 	bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) | ||||
| @@ -283,8 +283,8 @@ 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 := i32( bounds_width * glyph_draw_scale.x + 1.0 ) + i32(over_sample.x * glyph_padding) | ||||
|   if i32(glyph_buffer.batch_x + gwidth_scaled_px) >= i32(glyph_buffer.width) { | ||||
| 	gwidth_scaled_px := bounds_width * 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 ) | ||||
| 	} | ||||
|  | ||||
| @@ -311,7 +311,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, | ||||
|  | ||||
| 	// Advance glyph_update_batch_x and calculate final glyph drawing transform | ||||
| 	glyph_draw_translate.x += f32(glyph_buffer.batch_x) | ||||
| 	glyph_buffer.batch_x   += gwidth_scaled_px | ||||
| 	glyph_buffer.batch_x   += i32(gwidth_scaled_px) | ||||
| 	screenspace_x_form( & glyph_draw_translate, & glyph_draw_scale, glyph_buffer_width, glyph_buffer_height ) | ||||
|  | ||||
| 	call : DrawCall | ||||
| @@ -524,7 +524,7 @@ draw_filled_path :: proc( draw_list : ^DrawList, outside_point : Vec2, path : [] | ||||
| 		append( & draw_list.vertices, vertex ) | ||||
| 	} | ||||
|  | ||||
| 	for index : u32 = 1; index < u32(len(path)); index += 1 { | ||||
| 	for index : u32 = 1; index < cast(u32) len(path); index += 1 { | ||||
| 		indices := & draw_list.indices | ||||
| 		append( indices, outside_vertex ) | ||||
| 		append( indices, v_offset + index - 1 ) | ||||
| @@ -577,7 +577,7 @@ draw_text_shape :: proc( ctx : ^Context, | ||||
| 	// position := position //+ ctx.cursor_pos * scale | ||||
| 	// profile(#procedure) | ||||
| 	batch_start_idx : i32 = 0 | ||||
| 	for index : i32 = 0; index < i32(len(shaped.glyphs)); index += 1 | ||||
| 	for index : i32 = 0; index < cast(i32) len(shaped.glyphs); index += 1 | ||||
| 	{ | ||||
| 		glyph_index := shaped.glyphs[ index ] | ||||
| 		if is_empty( ctx, entry, glyph_index ) do continue | ||||
| @@ -602,7 +602,7 @@ draw_text_shape :: proc( ctx : ^Context, | ||||
| 	} | ||||
|  | ||||
| 	// 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 ) | ||||
| 	draw_text_batch( ctx, entry, shaped, batch_start_idx, cast(i32) len(shaped.glyphs), position, scale, snap_width , snap_height ) | ||||
| 	reset_batch_codepoint_state( ctx ) | ||||
| 	cursor_pos = shaped.end_cursor_pos | ||||
| 	return | ||||
|   | ||||
| @@ -30,10 +30,10 @@ shape_lru_hash :: #force_inline proc "contextless" ( label : string ) -> u64 { | ||||
| // ve_fontcache_eval_bezier (quadratic) | ||||
| eval_point_on_bezier3 :: #force_inline proc "contextless" ( p0, p1, p2 : Vec2, alpha : f32 ) -> Vec2 | ||||
| { | ||||
| 	// p0    := vec2_64_from_vec2(p0) | ||||
| 	// p1    := vec2_64_from_vec2(p1) | ||||
| 	// p2    := vec2_64_from_vec2(p2) | ||||
| 	// alpha := f64(alpha) | ||||
| 	p0    := vec2_64(p0) | ||||
| 	p1    := vec2_64(p1) | ||||
| 	p2    := vec2_64(p2) | ||||
| 	alpha := f64(alpha) | ||||
|  | ||||
| 	weight_start   := (1 - alpha) * (1 - alpha) | ||||
| 	weight_control := 2.0 * (1 - alpha) * alpha | ||||
| @@ -52,11 +52,11 @@ eval_point_on_bezier3 :: #force_inline proc "contextless" ( p0, p1, p2 : Vec2, a | ||||
| // ve_fontcache_eval_bezier (cubic) | ||||
| eval_point_on_bezier4 :: #force_inline proc "contextless" ( p0, p1, p2, p3 : Vec2, alpha : f32 ) -> Vec2 | ||||
| { | ||||
| 	// p0    := vec2_64_from_vec2(p0) | ||||
| 	// p1    := vec2_64_from_vec2(p1) | ||||
| 	// p2    := vec2_64_from_vec2(p2) | ||||
| 	// p3    := vec2_64_from_vec2(p3) | ||||
| 	// alpha := f64(alpha) | ||||
| 	p0    := vec2_64(p0) | ||||
| 	p1    := vec2_64(p1) | ||||
| 	p2    := vec2_64(p2) | ||||
| 	p3    := vec2_64(p3) | ||||
| 	alpha := f64(alpha) | ||||
|  | ||||
| 	weight_start := (1 - alpha) * (1 - alpha) * (1 - alpha) | ||||
| 	weight_c_a   := 3 * (1 - alpha) * (1 - alpha) * alpha | ||||
| @@ -91,7 +91,7 @@ reset_batch_codepoint_state :: #force_inline proc( ctx : ^Context ) { | ||||
| } | ||||
|  | ||||
| screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, width, height : f32 ) { | ||||
| 	when false | ||||
| 	when true | ||||
| 	{ | ||||
| 		pos_64   := vec2_64_from_vec2(position^) | ||||
| 		scale_64 := vec2_64_from_vec2(scale^) | ||||
| @@ -108,15 +108,13 @@ screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2 | ||||
| 	else | ||||
| 	{ | ||||
| 		quotient : Vec2 = 1.0 / { width, height } | ||||
| 		pos   := position^  * quotient * 2.0 - 1.0 | ||||
| 		s     := scale^     * quotient * 2.0 | ||||
| 		(position^) = { f32(pos.x), f32(pos.y) } | ||||
| 		(scale^)    = { f32(s.x), f32(s.y) } | ||||
| 		(position^) *= quotient * 2.0 - 1.0 | ||||
| 		(scale^)    *= quotient * 2.0 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, width, height : f32 ) { | ||||
| 	when false | ||||
| 	when true | ||||
| 	{ | ||||
| 		pos_64   := vec2_64_from_vec2(position^) | ||||
| 		scale_64 := vec2_64_from_vec2(scale^) | ||||
| @@ -132,13 +130,8 @@ textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		pos := position^ | ||||
| 		s   := scale^ | ||||
|  | ||||
| 		quotient    : Vec2 = 1.0 / { width, height } | ||||
| 		pos *= quotient | ||||
| 		s   *= quotient | ||||
| 		(position^) = { f32(pos.x), f32(pos.y) } | ||||
| 		(scale^)    = { f32(s.x), f32(s.y) } | ||||
| 		(position^) *= quotient | ||||
| 		(scale^)    *= quotient | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -62,6 +62,7 @@ shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, en | ||||
| 	return & shape_cache.storage[ shape_cache_idx ] | ||||
| } | ||||
|  | ||||
| // TODO(Ed): Make position rounding an option | ||||
| shape_text_uncached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, entry : ^Entry, output : ^ShapedText ) | ||||
| { | ||||
| 	// profile(#procedure) | ||||
| @@ -105,7 +106,7 @@ shape_text_uncached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, | ||||
| 			{ | ||||
| 				position.x  = 0.0 | ||||
| 				position.y -= (ascent - descent + line_gap) * entry.size_scale | ||||
| 				position.y  = cast(f32) i32( position.y + 0.5 ) | ||||
| 				position.y  = ceil(position.y) | ||||
| 				prev_codepoint = rune(0) | ||||
| 				continue | ||||
| 			} | ||||
| @@ -116,11 +117,11 @@ shape_text_uncached :: proc( ctx : ^Context, font : FontID, text_utf8 : string, | ||||
| 			append( & output.glyphs, parser_find_glyph_index( & entry.parser_info, codepoint )) | ||||
| 			advance, to_left_side_glyph = parser_get_codepoint_horizontal_metrics( & entry.parser_info, codepoint ) | ||||
|  | ||||
| 			// append( & output.positions, Vec2 { | ||||
| 			// 	cast(f32) i32(position.x + 0.5), | ||||
| 			// 	position.y | ||||
| 			// }) | ||||
| 			append( & output.positions, position ) | ||||
| 			append( & output.positions, Vec2 { | ||||
| 				ceil(position.x), | ||||
| 				position.y | ||||
| 			}) | ||||
| 			// append( & output.positions, position ) | ||||
|  | ||||
| 			position.x    += f32(advance) * entry.size_scale | ||||
| 			prev_codepoint = codepoint | ||||
|   | ||||
		Reference in New Issue
	
	Block a user