mirror of
https://github.com/Ed94/VEFontCache-Odin.git
synced 2025-08-06 06:52:44 -07:00
Realized while writing the docs that I need to preseve non-visible glyphs in the shape. (Fixed some crashing as well)
So the shaper has been adjusted along with downstream codepaths in drawlist gen pass.
This commit is contained in:
@@ -28,6 +28,7 @@ Glyph_Draw_Quad :: struct {
|
|||||||
// This is used by generate_shape_draw_list & batch_generate_glyphs_draw_list
|
// This is used by generate_shape_draw_list & batch_generate_glyphs_draw_list
|
||||||
// to track relevant glyph data in soa format for pipelined processing
|
// to track relevant glyph data in soa format for pipelined processing
|
||||||
Glyph_Pack_Entry :: struct #packed {
|
Glyph_Pack_Entry :: struct #packed {
|
||||||
|
vis_index : i16,
|
||||||
position : Vec2,
|
position : Vec2,
|
||||||
|
|
||||||
atlas_index : i32,
|
atlas_index : i32,
|
||||||
@@ -320,7 +321,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
|||||||
oversized := & glyph_buffer.oversized
|
oversized := & glyph_buffer.oversized
|
||||||
to_cache := & glyph_buffer.to_cache
|
to_cache := & glyph_buffer.to_cache
|
||||||
cached := & glyph_buffer.cached
|
cached := & glyph_buffer.cached
|
||||||
resize_soa_non_zero(glyph_pack, len(shape.glyph))
|
resize_soa_non_zero(glyph_pack, len(shape.visible))
|
||||||
|
|
||||||
append_sub_pack :: #force_inline proc ( pack : ^[dynamic]i32, entry : i32 )
|
append_sub_pack :: #force_inline proc ( pack : ^[dynamic]i32, entry : i32 )
|
||||||
{
|
{
|
||||||
@@ -332,11 +333,18 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
|||||||
|
|
||||||
profile_begin("translate")
|
profile_begin("translate")
|
||||||
for & glyph, index in glyph_pack {
|
for & glyph, index in glyph_pack {
|
||||||
glyph.position = target_position + (shape.position[index]) * target_scale
|
// Throughout the draw list generation vis_id will need to be used over index as
|
||||||
|
// not all glyphs or positions for the shape are visibly rendered.
|
||||||
|
vis_id := shape.visible[index]
|
||||||
|
glyph.position = target_position + (shape.position[vis_id]) * target_scale
|
||||||
}
|
}
|
||||||
profile_end()
|
profile_end()
|
||||||
|
|
||||||
profile_begin("batching & segregating glyphs")
|
profile_begin("batching & segregating glyphs")
|
||||||
|
// We do any reservation up front as appending to the array's will not check.
|
||||||
|
reserve(oversized, len(shape.visible))
|
||||||
|
reserve(to_cache, len(shape.visible))
|
||||||
|
reserve(cached, len(shape.visible))
|
||||||
clear(oversized)
|
clear(oversized)
|
||||||
clear(to_cache)
|
clear(to_cache)
|
||||||
clear(cached)
|
clear(cached)
|
||||||
@@ -344,15 +352,13 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
|||||||
|
|
||||||
for & glyph, index in glyph_pack
|
for & glyph, index in glyph_pack
|
||||||
{
|
{
|
||||||
|
// atlas_lru_code, region_kind, and bounds are all 1:1 with shape.visible
|
||||||
atlas_key := shape.atlas_lru_code[index]
|
atlas_key := shape.atlas_lru_code[index]
|
||||||
region_kind := shape.region_kind[index]
|
region_kind := shape.region_kind[index]
|
||||||
bounds := shape.bounds[index]
|
bounds := shape.bounds[index]
|
||||||
bounds_size_scaled := size(bounds) * font_scale
|
bounds_size_scaled := size(bounds) * font_scale
|
||||||
|
|
||||||
if region_kind == .None {
|
assert(region_kind != .None, "FAILED TO ASSGIN REGION")
|
||||||
assert(false, "FAILED TO ASSGIN REGION")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
when ENABLE_OVERSIZED_GLYPHS
|
when ENABLE_OVERSIZED_GLYPHS
|
||||||
{
|
{
|
||||||
if region_kind == .E
|
if region_kind == .E
|
||||||
@@ -454,7 +460,11 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
|||||||
The transform and draw quads are computed first (getting the math done in one spot as possible)
|
The transform and draw quads are computed first (getting the math done in one spot as possible)
|
||||||
Some of the math from to_cache pass for glyph generation was not moved over (it could be but I'm not sure its worth it)
|
Some of the math from to_cache pass for glyph generation was not moved over (it could be but I'm not sure its worth it)
|
||||||
|
|
||||||
Order: Oversized first, then to_cache, then cached.
|
Order : Oversized first, then to_cache, then cached.
|
||||||
|
Important: These slices store ids for glyph_pack which matches shape.visible in index.
|
||||||
|
shape.position and shape.glyph DO NOT.
|
||||||
|
|
||||||
|
There are only two places this matters for: getting glyph shapes when doing glyph pass generation for oversized and to_cache iterations.
|
||||||
|
|
||||||
Oversized and to_cache will both enqueue operations for rendering glyphs to the glyph buffer render target.
|
Oversized and to_cache will both enqueue operations for rendering glyphs to the glyph buffer render target.
|
||||||
The compute section will have operations regarding how many glyphs they may alloate before a flush must occur.
|
The compute section will have operations regarding how many glyphs they may alloate before a flush must occur.
|
||||||
@@ -589,12 +599,13 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
|||||||
colour.g = 1.0
|
colour.g = 1.0
|
||||||
colour.b = 0.0
|
colour.b = 0.0
|
||||||
}
|
}
|
||||||
// for pack_id, index in oversized {
|
for pack_id, index in oversized {
|
||||||
// error : Allocator_Error
|
vis_id := shape.visible[pack_id]
|
||||||
// glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
error : Allocator_Error
|
||||||
// assert(error == .None)
|
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[vis_id])
|
||||||
// assert(glyph_pack[pack_id].shape != nil)
|
assert(error == .None)
|
||||||
// }
|
assert(glyph_pack[pack_id].shape != nil)
|
||||||
|
}
|
||||||
for id, index in oversized
|
for id, index in oversized
|
||||||
{
|
{
|
||||||
glyph := & glyph_pack[id]
|
glyph := & glyph_pack[id]
|
||||||
@@ -605,10 +616,11 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
|||||||
& glyph_buffer.allocated_x
|
& glyph_buffer.allocated_x
|
||||||
)
|
)
|
||||||
|
|
||||||
error : Allocator_Error
|
// vis_id := shape.visible[id]
|
||||||
glyph.shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[id])
|
// error : Allocator_Error
|
||||||
assert(error == .None)
|
// glyph.shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[vis_id])
|
||||||
assert(len(glyph.shape) > 0)
|
// assert(error == .None)
|
||||||
|
// assert(len(glyph.shape) > 0)
|
||||||
|
|
||||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||||
glyph_pack[id].shape,
|
glyph_pack[id].shape,
|
||||||
@@ -618,8 +630,8 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
|||||||
glyph_pack[id].draw_transform.scale
|
glyph_pack[id].draw_transform.scale
|
||||||
)
|
)
|
||||||
|
|
||||||
assert(len(glyph.shape) > 0)
|
// assert(len(glyph.shape) > 0)
|
||||||
parser_free_shape(entry.parser_info, glyph.shape)
|
// parser_free_shape(entry.parser_info, glyph.shape)
|
||||||
|
|
||||||
target_quad := & glyph_pack[id].draw_quad
|
target_quad := & glyph_pack[id].draw_quad
|
||||||
|
|
||||||
@@ -639,10 +651,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)
|
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 {
|
for pack_id, index in oversized {
|
||||||
// assert(glyph_pack[pack_id].shape != nil)
|
assert(glyph_pack[pack_id].shape != nil)
|
||||||
// parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
profile_end()
|
profile_end()
|
||||||
|
|
||||||
@@ -671,12 +683,13 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
|||||||
profile_begin("to_cache: caching to atlas")
|
profile_begin("to_cache: caching to atlas")
|
||||||
if len(to_cache) > 0
|
if len(to_cache) > 0
|
||||||
{
|
{
|
||||||
// for pack_id, index in to_cache {
|
for pack_id, index in to_cache {
|
||||||
// error : Allocator_Error
|
vis_id := shape.visible[pack_id]
|
||||||
// glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
error : Allocator_Error
|
||||||
// assert(error == .None)
|
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[vis_id])
|
||||||
// assert(glyph_pack[pack_id].shape != nil)
|
assert(error == .None)
|
||||||
// }
|
assert(glyph_pack[pack_id].shape != nil)
|
||||||
|
}
|
||||||
|
|
||||||
for id, index in to_cache
|
for id, index in to_cache
|
||||||
{
|
{
|
||||||
@@ -730,10 +743,11 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
|||||||
append( & glyph_buffer.clear_draw_list.calls, clear_target_region )
|
append( & glyph_buffer.clear_draw_list.calls, clear_target_region )
|
||||||
append( & glyph_buffer.draw_list.calls, blit_to_atlas )
|
append( & glyph_buffer.draw_list.calls, blit_to_atlas )
|
||||||
|
|
||||||
error : Allocator_Error
|
// vis_id := shape.visible[id]
|
||||||
glyph.shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[id])
|
// error : Allocator_Error
|
||||||
assert(error == .None)
|
// glyph.shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[vis_id])
|
||||||
assert(len(glyph.shape) > 0)
|
// assert(error == .None)
|
||||||
|
// assert(len(glyph.shape) > 0)
|
||||||
|
|
||||||
// Render glyph to glyph render target (FBO)
|
// Render glyph to glyph render target (FBO)
|
||||||
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
generate_glyph_pass_draw_list( draw_list, & glyph_buffer.shape_gen_scratch,
|
||||||
@@ -744,15 +758,15 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
|||||||
glyph.draw_transform.scale
|
glyph.draw_transform.scale
|
||||||
)
|
)
|
||||||
|
|
||||||
assert(len(glyph.shape) > 0)
|
// assert(len(glyph.shape) > 0)
|
||||||
parser_free_shape(entry.parser_info, glyph.shape)
|
// 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)
|
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 {
|
for pack_id, index in to_cache {
|
||||||
// assert(glyph_pack[pack_id].shape != nil)
|
assert(glyph_pack[pack_id].shape != nil)
|
||||||
// parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
parser_free_shape(entry.parser_info, glyph_pack[pack_id].shape)
|
||||||
// }
|
}
|
||||||
|
|
||||||
profile_begin("gen_cached_draw_list: to_cache")
|
profile_begin("gen_cached_draw_list: to_cache")
|
||||||
when ENABLE_DRAW_TYPE_VISUALIZATION {
|
when ENABLE_DRAW_TYPE_VISUALIZATION {
|
||||||
|
@@ -74,7 +74,9 @@ parser_stbtt_allocator_proc :: proc(
|
|||||||
assert(error == .None)
|
assert(error == .None)
|
||||||
|
|
||||||
if type == .Alloc || type == .Resize {
|
if type == .Alloc || type == .Resize {
|
||||||
return transmute(rawptr) & result[0]
|
raw := transmute(Raw_Slice) result
|
||||||
|
// assert(raw.len > 0, "Allocation is 0 bytes?")
|
||||||
|
return transmute(rawptr) raw.data
|
||||||
}
|
}
|
||||||
else do return nil
|
else do return nil
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import "base:builtin"
|
|||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array
|
Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array
|
||||||
Raw_Map :: runtime.Raw_Map
|
Raw_Map :: runtime.Raw_Map
|
||||||
|
Raw_Slice :: runtime.Raw_Slice
|
||||||
raw_soa_footer :: runtime.raw_soa_footer
|
raw_soa_footer :: runtime.raw_soa_footer
|
||||||
nil_allocator :: runtime.nil_allocator
|
nil_allocator :: runtime.nil_allocator
|
||||||
import "core:hash"
|
import "core:hash"
|
||||||
|
@@ -27,6 +27,7 @@ Shape_Key :: u32
|
|||||||
Shaped_Text :: struct #packed {
|
Shaped_Text :: struct #packed {
|
||||||
glyph : [dynamic]Glyph,
|
glyph : [dynamic]Glyph,
|
||||||
position : [dynamic]Vec2,
|
position : [dynamic]Vec2,
|
||||||
|
visible : [dynamic]i32,
|
||||||
atlas_lru_code : [dynamic]Atlas_Key,
|
atlas_lru_code : [dynamic]Atlas_Key,
|
||||||
region_kind : [dynamic]Atlas_Region_Kind,
|
region_kind : [dynamic]Atlas_Region_Kind,
|
||||||
bounds : [dynamic]Range2,
|
bounds : [dynamic]Range2,
|
||||||
@@ -100,7 +101,7 @@ shaper_load_font :: #force_inline proc( ctx : ^Shaper_Context, label : string, d
|
|||||||
|
|
||||||
shaper_unload_font :: #force_inline proc( info : ^Shaper_Info )
|
shaper_unload_font :: #force_inline proc( info : ^Shaper_Info )
|
||||||
{
|
{
|
||||||
if info.blob != nil do harfbuzz.font_destroy( info.font )
|
if info.font != nil do harfbuzz.font_destroy( info.font )
|
||||||
if info.face != nil do harfbuzz.face_destroy( info.face )
|
if info.face != nil do harfbuzz.face_destroy( info.face )
|
||||||
if info.blob != nil do harfbuzz.blob_destroy( info.blob )
|
if info.blob != nil do harfbuzz.blob_destroy( info.blob )
|
||||||
}
|
}
|
||||||
@@ -125,6 +126,7 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context,
|
|||||||
|
|
||||||
clear( & output.glyph )
|
clear( & output.glyph )
|
||||||
clear( & output.position )
|
clear( & output.position )
|
||||||
|
clear( & output.visible )
|
||||||
|
|
||||||
current_script := harfbuzz.Script.UNKNOWN
|
current_script := harfbuzz.Script.UNKNOWN
|
||||||
hb_ucfunc := harfbuzz.unicode_funcs_get_default()
|
hb_ucfunc := harfbuzz.unicode_funcs_get_default()
|
||||||
@@ -210,10 +212,15 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context,
|
|||||||
(position^) += advance
|
(position^) += advance
|
||||||
(max_line_width^) = max(max_line_width^, position.x)
|
(max_line_width^) = max(max_line_width^, position.x)
|
||||||
|
|
||||||
is_empty := parser_is_glyph_empty(entry.parser_info, glyph)
|
// We track all glyphs so that user can use the shape for navigation purposes.
|
||||||
if ! is_empty && glyph != 0 {
|
|
||||||
append( & output.glyph, glyph )
|
append( & output.glyph, glyph )
|
||||||
append( & output.position, glyph_pos)
|
append( & output.position, glyph_pos)
|
||||||
|
|
||||||
|
// We don't accept all glyphs for rendering, harfbuzz preserves positions of non-visible codepoints (as .notdef glyphs)
|
||||||
|
// We also double check to make sure the glyph isn't detected for drawing by the parser.
|
||||||
|
visible_glyph := glyph != 0 && ! parser_is_glyph_empty(entry.parser_info, glyph)
|
||||||
|
if visible_glyph {
|
||||||
|
append( & output.visible, cast(i32) len(output.glyph) - 1 )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,17 +241,23 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context,
|
|||||||
// Can we continue the current run?
|
// Can we continue the current run?
|
||||||
ScriptKind :: harfbuzz.Script
|
ScriptKind :: harfbuzz.Script
|
||||||
|
|
||||||
special_script : b32 = script == ScriptKind.UNKNOWN || script == ScriptKind.INHERITED || script == ScriptKind.COMMON
|
// These scripts don't break runs because they don't represent script transitions - they adapt to their context.
|
||||||
if special_script \
|
// Maintaining the current shaping run for these scripts ensures correct processing of marks, numbers,
|
||||||
|
// and punctuation within the primary text flow.
|
||||||
|
is_neutral_script := script == ScriptKind.UNKNOWN || script == ScriptKind.INHERITED || script == ScriptKind.COMMON
|
||||||
|
|
||||||
|
// Essentially if the script is neutral, or the same as current,
|
||||||
|
// or this is the first codepoint: add it to the buffer and continue the loop.
|
||||||
|
if is_neutral_script \
|
||||||
|| script == current_script \
|
|| script == current_script \
|
||||||
|| byte_offset == 0
|
|| byte_offset == 0
|
||||||
{
|
{
|
||||||
harfbuzz.buffer_add( ctx.hb_buffer, hb_codepoint, codepoint == '\n' ? 1 : 0 )
|
harfbuzz.buffer_add( ctx.hb_buffer, hb_codepoint, codepoint == '\n' ? 1 : 0 )
|
||||||
current_script = special_script ? current_script : script
|
current_script = is_neutral_script ? current_script : script
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// End current run since we've encountered a script change.
|
// End current run since we've encountred a significant script change.
|
||||||
shape_run( output,
|
shape_run( output,
|
||||||
entry,
|
entry,
|
||||||
ctx.hb_buffer,
|
ctx.hb_buffer,
|
||||||
@@ -281,22 +294,26 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context,
|
|||||||
|
|
||||||
// Resolve each glyphs: bounds, atlas lru, and the atlas region as we have everything we need now.
|
// 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) )
|
resize( & output.atlas_lru_code, len(output.visible) )
|
||||||
resize( & output.region_kind, len(output.glyph) )
|
resize( & output.region_kind, len(output.visible) )
|
||||||
resize( & output.bounds, len(output.glyph) )
|
resize( & output.bounds, len(output.visible) )
|
||||||
|
|
||||||
profile_begin("atlas_lru_code")
|
profile_begin("atlas_lru_code")
|
||||||
for id, index in output.glyph {
|
for vis_id, index in output.visible {
|
||||||
output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, font_px_size, id)
|
glyph_id := output.glyph[vis_id]
|
||||||
|
output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, font_px_size, glyph_id)
|
||||||
|
// atlas_lru_code is 1:1 with visible index
|
||||||
}
|
}
|
||||||
profile_end()
|
profile_end()
|
||||||
|
|
||||||
profile_begin("bounds & region")
|
profile_begin("bounds & region")
|
||||||
for id, index in output.glyph {
|
for vis_id, index in output.visible {
|
||||||
|
glyph_id := output.glyph[vis_id]
|
||||||
bounds := & output.bounds[index]
|
bounds := & output.bounds[index]
|
||||||
(bounds ^) = parser_get_bounds( entry.parser_info, id )
|
(bounds ^) = parser_get_bounds( entry.parser_info, glyph_id )
|
||||||
bounds_size_scaled := (bounds.p1 - bounds.p0) * font_scale
|
bounds_size_scaled := (bounds.p1 - bounds.p0) * font_scale
|
||||||
output.region_kind[index] = atlas_decide_region( atlas, glyph_buffer_size, bounds_size_scaled )
|
output.region_kind[index] = atlas_decide_region( atlas, glyph_buffer_size, bounds_size_scaled )
|
||||||
|
// bounds & region_kind are 1:1 with visible index
|
||||||
}
|
}
|
||||||
profile_end()
|
profile_end()
|
||||||
|
|
||||||
@@ -323,6 +340,7 @@ shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
|||||||
|
|
||||||
clear( & output.glyph )
|
clear( & output.glyph )
|
||||||
clear( & output.position )
|
clear( & output.position )
|
||||||
|
clear( & output.visible )
|
||||||
|
|
||||||
line_height := (entry.ascent - entry.descent + entry.line_gap) * font_scale
|
line_height := (entry.ascent - entry.descent + entry.line_gap) * font_scale
|
||||||
|
|
||||||
@@ -353,14 +371,16 @@ shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
|||||||
|
|
||||||
glyph_index := parser_find_glyph_index( entry.parser_info, codepoint )
|
glyph_index := parser_find_glyph_index( entry.parser_info, codepoint )
|
||||||
is_glyph_empty := parser_is_glyph_empty( entry.parser_info, glyph_index )
|
is_glyph_empty := parser_is_glyph_empty( entry.parser_info, glyph_index )
|
||||||
if ! is_glyph_empty
|
|
||||||
{
|
|
||||||
if ctx.snap_glyph_position {
|
if ctx.snap_glyph_position {
|
||||||
position.x = ceil(position.x)
|
position.x = ceil(position.x)
|
||||||
position.y = ceil(position.y)
|
position.y = ceil(position.y)
|
||||||
}
|
}
|
||||||
append( & output.glyph, glyph_index)
|
append( & output.glyph, glyph_index)
|
||||||
append( & output.position, position)
|
append( & output.position, position)
|
||||||
|
|
||||||
|
if ! is_glyph_empty {
|
||||||
|
append( & output.visible, cast(i32) len(output.glyph) - 1 )
|
||||||
}
|
}
|
||||||
|
|
||||||
advance, _ := parser_get_codepoint_horizontal_metrics( entry.parser_info, codepoint )
|
advance, _ := parser_get_codepoint_horizontal_metrics( entry.parser_info, codepoint )
|
||||||
@@ -381,17 +401,21 @@ shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
|||||||
resize( & output.bounds, len(output.glyph) )
|
resize( & output.bounds, len(output.glyph) )
|
||||||
|
|
||||||
profile_begin("atlas_lru_code")
|
profile_begin("atlas_lru_code")
|
||||||
for id, index in output.glyph {
|
for vis_id, index in output.visible {
|
||||||
output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, font_px_size, id)
|
glyph_id := output.glyph[vis_id]
|
||||||
|
output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, font_px_size, glyph_id)
|
||||||
|
// atlas_lru_code is 1:1 with visible index
|
||||||
}
|
}
|
||||||
profile_end()
|
profile_end()
|
||||||
|
|
||||||
profile_begin("bounds & region")
|
profile_begin("bounds & region")
|
||||||
for id, index in output.glyph {
|
for vis_id, index in output.visible {
|
||||||
|
glyph_id := output.glyph[vis_id]
|
||||||
bounds := & output.bounds[index]
|
bounds := & output.bounds[index]
|
||||||
(bounds ^) = parser_get_bounds( entry.parser_info, id )
|
(bounds ^) = parser_get_bounds( entry.parser_info, glyph_id )
|
||||||
bounds_size_scaled := (bounds.p1 - bounds.p0) * font_scale
|
bounds_size_scaled := (bounds.p1 - bounds.p0) * font_scale
|
||||||
output.region_kind[index] = atlas_decide_region( atlas, glyph_buffer_size, bounds_size_scaled )
|
output.region_kind[index] = atlas_decide_region( atlas, glyph_buffer_size, bounds_size_scaled )
|
||||||
|
// bounds & region_kind are 1:1 with visible index
|
||||||
}
|
}
|
||||||
profile_end()
|
profile_end()
|
||||||
|
|
||||||
|
@@ -581,8 +581,8 @@ unload_font :: proc( ctx : ^Context, font : Font_ID )
|
|||||||
entry := & ctx.entries[ font ]
|
entry := & ctx.entries[ font ]
|
||||||
entry.used = false
|
entry.used = false
|
||||||
|
|
||||||
parser_unload_font( & entry.parser_info )
|
|
||||||
shaper_unload_font( & entry.shaper_info )
|
shaper_unload_font( & entry.shaper_info )
|
||||||
|
parser_unload_font( & entry.parser_info )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be used with hot-reload
|
// Can be used with hot-reload
|
||||||
|
Reference in New Issue
Block a user