mirror of
https://github.com/Ed94/VEFontCache-Odin.git
synced 2025-08-05 14:42:42 -07:00
Fixed shaper bug, removed shaper_shape_text_uncached_advanced (intergrated into harfbuzz)
This commit is contained in:
@@ -592,12 +592,12 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
colour.g = 1.0
|
||||
colour.b = 0.0
|
||||
}
|
||||
for pack_id, index in oversized {
|
||||
error : Allocator_Error
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
||||
assert(error == .None)
|
||||
assert(glyph_pack[pack_id].shape != nil)
|
||||
}
|
||||
// for pack_id, index in oversized {
|
||||
// error : Allocator_Error
|
||||
// glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
||||
// assert(error == .None)
|
||||
// assert(glyph_pack[pack_id].shape != nil)
|
||||
// }
|
||||
for id, index in oversized
|
||||
{
|
||||
glyph := & glyph_pack[id]
|
||||
@@ -607,6 +607,11 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
& glyph_buffer.clear_draw_list,
|
||||
& glyph_buffer.allocated_x
|
||||
)
|
||||
|
||||
error : Allocator_Error
|
||||
glyph.shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[id])
|
||||
assert(error == .None)
|
||||
assert(glyph.shape != nil)
|
||||
|
||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||
glyph_pack[id].shape,
|
||||
@@ -616,6 +621,9 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
glyph_pack[id].draw_transform.scale
|
||||
)
|
||||
|
||||
assert(glyph.shape != nil)
|
||||
parser_free_shape(entry.parser_info, glyph.shape)
|
||||
|
||||
target_quad := & glyph_pack[id].draw_quad
|
||||
|
||||
draw_to_target : Draw_Call
|
||||
@@ -634,10 +642,10 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
}
|
||||
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.allocated_x)
|
||||
for pack_id, index in oversized {
|
||||
assert(glyph_pack[pack_id].shape != nil)
|
||||
parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
||||
}
|
||||
// for pack_id, index in oversized {
|
||||
// assert(glyph_pack[pack_id].shape != nil)
|
||||
// parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
||||
// }
|
||||
}
|
||||
profile_end()
|
||||
|
||||
@@ -666,12 +674,12 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
profile_begin("to_cache: caching to atlas")
|
||||
if len(to_cache) > 0
|
||||
{
|
||||
for pack_id, index in to_cache {
|
||||
error : Allocator_Error
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
||||
assert(error == .None)
|
||||
assert(glyph_pack[pack_id].shape != nil)
|
||||
}
|
||||
// for pack_id, index in to_cache {
|
||||
// error : Allocator_Error
|
||||
// glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
||||
// assert(error == .None)
|
||||
// assert(glyph_pack[pack_id].shape != nil)
|
||||
// }
|
||||
|
||||
for id, index in to_cache
|
||||
{
|
||||
@@ -724,6 +732,11 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
|
||||
append( & glyph_buffer.clear_draw_list.calls, clear_target_region )
|
||||
append( & glyph_buffer.draw_list.calls, blit_to_atlas )
|
||||
|
||||
error : Allocator_Error
|
||||
glyph.shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[id])
|
||||
assert(error == .None)
|
||||
assert(glyph.shape != nil)
|
||||
|
||||
// Render glyph to glyph render target (FBO)
|
||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||
@@ -733,13 +746,16 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
glyph.draw_transform.pos,
|
||||
glyph.draw_transform.scale
|
||||
)
|
||||
|
||||
assert(glyph.shape != nil)
|
||||
parser_free_shape(entry.parser_info, glyph.shape)
|
||||
}
|
||||
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.allocated_x)
|
||||
for pack_id, index in to_cache {
|
||||
assert(glyph_pack[pack_id].shape != nil)
|
||||
parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
||||
}
|
||||
// for pack_id, index in to_cache {
|
||||
// assert(glyph_pack[pack_id].shape != nil)
|
||||
// parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
||||
// }
|
||||
|
||||
profile_begin("gen_cached_draw_list: to_cache")
|
||||
when ENABLE_DRAW_TYPE_VISUALIZATION {
|
||||
|
@@ -107,9 +107,22 @@ shaper_unload_font :: #force_inline proc( info : ^Shaper_Info )
|
||||
// Recommended shaper. Very performant.
|
||||
// TODO(Ed): Would be nice to properly support vertical shaping, right now its strictly just horizontal...
|
||||
@(optimization_mode="favor_size")
|
||||
shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry : Entry, font_px_Size, font_scale : f32, output :^Shaped_Text )
|
||||
shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context,
|
||||
atlas : Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
entry : Entry,
|
||||
font_px_size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
|
||||
clear( & output.glyph )
|
||||
clear( & output.position )
|
||||
|
||||
current_script := harfbuzz.Script.UNKNOWN
|
||||
hb_ucfunc := harfbuzz.unicode_funcs_get_default()
|
||||
harfbuzz.buffer_clear_contents( ctx.hb_buffer )
|
||||
@@ -142,8 +155,6 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
// Set script and direction. We use the system's default langauge.
|
||||
// script = HB_SCRIPT_LATIN
|
||||
harfbuzz.buffer_set_script ( buffer, script )
|
||||
harfbuzz.buffer_set_direction( buffer, harfbuzz.script_get_horizontal_direction( script ))
|
||||
harfbuzz.buffer_set_language ( buffer, harfbuzz.language_get_default() )
|
||||
@@ -159,11 +170,12 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
|
||||
line_height := (entry.ascent - entry.descent + entry.line_gap) * font_scale
|
||||
|
||||
last_cluster := u32(0)
|
||||
for index : i32; index < i32(glyph_count); index += 1
|
||||
{
|
||||
hb_glyph := glyph_infos[ index ]
|
||||
hb_glyph := glyph_infos [ index ]
|
||||
hb_gposition := glyph_positions[ index ]
|
||||
glyph := cast(Glyph) hb_glyph.codepoint
|
||||
glyph := cast(Glyph) hb_glyph.codepoint
|
||||
|
||||
if hb_glyph.cluster > 0
|
||||
{
|
||||
@@ -172,6 +184,8 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
position.y -= line_height
|
||||
position.y = floor(position.y)
|
||||
(line_count^) += 1
|
||||
|
||||
last_cluster = hb_glyph.cluster
|
||||
continue
|
||||
}
|
||||
if abs( font_px_size ) <= adv_snap_small_font_threshold {
|
||||
@@ -194,7 +208,7 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
(max_line_width^) = max(max_line_width^, position.x)
|
||||
|
||||
is_empty := parser_is_glyph_empty(entry.parser_info, glyph)
|
||||
if ! is_empty {
|
||||
if ! is_empty && glyph != 0 {
|
||||
append( & output.glyph, glyph )
|
||||
append( & output.position, glyph_pos)
|
||||
}
|
||||
@@ -235,7 +249,7 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
& position,
|
||||
& max_line_width,
|
||||
& line_count,
|
||||
font_px_Size,
|
||||
font_px_size,
|
||||
font_scale,
|
||||
ctx.snap_glyph_position,
|
||||
ctx.adv_snap_small_font_threshold
|
||||
@@ -252,7 +266,7 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
& position,
|
||||
& max_line_width,
|
||||
& line_count,
|
||||
font_px_Size,
|
||||
font_px_size,
|
||||
font_scale,
|
||||
ctx.snap_glyph_position,
|
||||
ctx.adv_snap_small_font_threshold
|
||||
@@ -261,27 +275,7 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
// Set the final size
|
||||
output.size.x = max_line_width
|
||||
output.size.y = f32(line_count) * line_height
|
||||
return
|
||||
}
|
||||
|
||||
shaper_shape_text_uncached_advanced :: #force_inline proc( ctx : ^Shaper_Context,
|
||||
atlas : Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
entry : Entry,
|
||||
font_px_size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
|
||||
clear( & output.glyph )
|
||||
clear( & output.position )
|
||||
|
||||
shaper_shape_harfbuzz( ctx, text_utf8, entry, font_px_size, font_scale, output )
|
||||
|
||||
// Resolve each glyphs: bounds, atlas lru, and the atlas region as we have everything we need now.
|
||||
|
||||
resize( & output.atlas_lru_code, len(output.glyph) )
|
||||
@@ -302,6 +296,7 @@ shaper_shape_text_uncached_advanced :: #force_inline proc( ctx : ^Shaper_Context
|
||||
output.region_kind[index] = atlas_decide_region( atlas, glyph_buffer_size, bounds_size_scaled )
|
||||
}
|
||||
profile_end()
|
||||
return
|
||||
}
|
||||
|
||||
// Basic western alphabet based shaping. Not that much faster than harfbuzz if at all.
|
||||
|
@@ -428,9 +428,18 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator )
|
||||
reload_array( & draw_list.indices, allocator)
|
||||
reload_array( & draw_list.calls, allocator)
|
||||
|
||||
parser_reload(& ctx.parser_ctx, allocator)
|
||||
|
||||
// Scope Stack
|
||||
{
|
||||
|
||||
stack := & ctx.stack
|
||||
reload_array(& stack.font, allocator)
|
||||
reload_array(& stack.font_size, allocator)
|
||||
reload_array(& stack.colour, allocator)
|
||||
reload_array(& stack.view, allocator)
|
||||
reload_array(& stack.position, allocator)
|
||||
reload_array(& stack.scale, allocator)
|
||||
reload_array(& stack.zoom, allocator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +506,14 @@ shutdown :: proc( ctx : ^Context )
|
||||
|
||||
// Scope Stack
|
||||
{
|
||||
|
||||
stack := & ctx.stack
|
||||
delete(stack.font)
|
||||
delete(stack.font_size)
|
||||
delete(stack.colour)
|
||||
delete(stack.view)
|
||||
delete(stack.position)
|
||||
delete(stack.scale)
|
||||
delete(stack.zoom)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,7 +849,7 @@ draw_text_normalized_space :: proc( ctx : ^Context,
|
||||
position : Vec2,
|
||||
scale : Vec2,
|
||||
text_utf8 : string,
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_text_uncached_advanced
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_harfbuzz
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
@@ -970,7 +986,7 @@ draw_text_view_space :: proc(ctx : ^Context,
|
||||
scale : Vec2,
|
||||
zoom : f32,
|
||||
text_utf8 : string,
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_text_uncached_advanced
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_harfbuzz
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
@@ -1111,7 +1127,7 @@ absolute_scale := peek(stack.scale ) * scale
|
||||
*/
|
||||
// @(optimization_mode = "favor_size")
|
||||
draw_text :: proc( ctx : ^Context, position, scale : Vec2, text_utf8 : string,
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_text_uncached_advanced
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_harfbuzz
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
@@ -1216,7 +1232,9 @@ measure_shape_size :: #force_inline proc( ctx : ^Context, shape : Shaped_Text )
|
||||
}
|
||||
|
||||
// Don't use this if you already have the shape instead use measure_shape_size
|
||||
measure_text_size :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, text_utf8 : string ) -> (measured : Vec2)
|
||||
measure_text_size :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, text_utf8 : string,
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_harfbuzz
|
||||
) -> (measured : Vec2)
|
||||
{
|
||||
// profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
@@ -1237,7 +1255,7 @@ measure_text_size :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
shaper_proc
|
||||
)
|
||||
return shaped.size * target_scale
|
||||
}
|
||||
@@ -1261,7 +1279,9 @@ get_font_vertical_metrics :: #force_inline proc ( ctx : ^Context, font : Font_ID
|
||||
|
||||
//#region("shaping")
|
||||
|
||||
shape_text_latin :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, text_utf8 : string ) -> Shaped_Text
|
||||
shape_text :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, text_utf8 : string,
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_harfbuzz
|
||||
) -> Shaped_Text
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( len(text_utf8) > 0 )
|
||||
@@ -1279,34 +1299,15 @@ shape_text_latin :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_latin
|
||||
shaper_proc
|
||||
)
|
||||
}
|
||||
|
||||
shape_text_advanced :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size : f32, text_utf8 : string ) -> Shaped_Text
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( len(text_utf8) > 0 )
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
return shaper_shape_text_cached( text_utf8,
|
||||
& ctx.shaper_ctx,
|
||||
& ctx.shape_cache,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
}
|
||||
|
||||
// User handled shaped text. Will not be cached
|
||||
shape_text_latin_uncached :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size: f32, text_utf8 : string, shape : ^Shaped_Text )
|
||||
shape_text_uncached :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size: f32, text_utf8 : string, shape : ^Shaped_Text,
|
||||
shaper_proc : $Shaper_Shape_Text_Uncached_Proc = shaper_shape_harfbuzz
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( len(text_utf8) > 0 )
|
||||
@@ -1315,29 +1316,7 @@ shape_text_latin_uncached :: #force_inline proc( ctx : ^Context, font : Font_ID,
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
shaper_shape_text_latin(& ctx.shaper_ctx,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
text_utf8,
|
||||
shape
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// User handled shaped text. Will not be cached
|
||||
shape_text_advanced_uncached :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size: f32, text_utf8 : string, shape : ^Shaped_Text )
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( len(text_utf8) > 0 )
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
shaper_shape_text_uncached_advanced(& ctx.shaper_ctx,
|
||||
shaper_proc(& ctx.shaper_ctx,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
entry,
|
||||
|
Reference in New Issue
Block a user