Fixed slice index not being passed correctly. It was normalized instead of pass as an integer value.

This commit is setup for testing the texture array slices, it shouldn't be shipped to users.
This commit is contained in:
Simon Anciaux 2025-03-15 15:12:07 +01:00 committed by Peter Slattery
parent bd7dac90ac
commit 9b927bd410
2 changed files with 110 additions and 122 deletions

View File

@ -33,13 +33,13 @@ ft__load_flags(b32 use_hinting){
internal FT_Codepoint_Index_Pair_Array
ft__get_codepoint_index_pairs(Arena *arena, FT_Face face, u16 *maximum_index_out){
FT_Long glyph_count = face->num_glyphs;
FT_Codepoint_Index_Pair_Array array = {};
array.count = glyph_count;
array.vals = push_array(arena, FT_Codepoint_Index_Pair, glyph_count);
u16 maximum_index = 0;
i32 counter = 0;
FT_UInt index = 0;
FT_ULong codepoint = FT_Get_First_Char(face, &index);
@ -57,22 +57,22 @@ ft__get_codepoint_index_pairs(Arena *arena, FT_Face face, u16 *maximum_index_out
break;
}
}
*maximum_index_out = maximum_index;
return(array);
}
internal Codepoint_Index_Map
ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){
FT_Long glyph_count = face->num_glyphs;
Codepoint_Index_Map map = {};
map.zero_index = max_u16;
map.table = make_table_u32_u16(base_allocator, glyph_count*4);
u16 maximum_index = 0;
i32 counter = 0;
FT_UInt index = 0;
FT_ULong codepoint = FT_Get_First_Char(face, &index);
@ -94,9 +94,9 @@ ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){
break;
}
}
map.max_index = maximum_index;
return(map);
}
@ -125,29 +125,29 @@ ft__bad_rect_pack_end_line(Bad_Rect_Pack *pack){
internal Vec3_i32
ft__bad_rect_pack_next(Bad_Rect_Pack *pack, Vec2_i32 dim){
Vec3_i32 result = { };
// NOTE(simon, 28/02/24): Does this character fit in the texture if it's the only character ?
if ( dim.x <= pack->max_dim.x && dim.y <= pack->max_dim.y ){
b8 end_line = false;
if ( pack->p.x + dim.x > pack->max_dim.x ) {
// NOTE(simon, 28/02/24): Can't fit the character horizontally.
end_line = true;
}
if ( pack->current_line_h < dim.y && pack->p.y + dim.y > pack->max_dim.y ) {
// NOTE(simon, 28/02/24): Character doesn't fit in the current line height, AND we
// can't grow the line height.
end_line = true;
}
if ( end_line ) {
ft__bad_rect_pack_end_line( pack );
}
if ( pack->p.y + dim.y > pack->max_dim.y ) {
Assert( end_line );
// NOTE(simon, 28/02/24): We ended a line. There isn't enough space on a new line to
@ -156,22 +156,19 @@ ft__bad_rect_pack_next(Bad_Rect_Pack *pack, Vec2_i32 dim){
pack->p.y = 0;
pack->dim.z += 1;
pack->p.z += 1;
// NOTE(simon, 28/02/24): There are no checks on the z axis range, but texture arrays
// have a limit. At the moment it's 2048 on both OpenGL and DirectX.
}
// NOTE(simon, 28/02/24): We are now sure that the character will fit.
if ( pack->current_line_h < dim.y ) {
pack->current_line_h = dim.y;
}
pack->current_line_h = Max(pack->current_line_h, dim.y);
result = pack->p;
pack->p.x += dim.x;
pack->dim.x = Max( pack->dim.x, pack->p.x );
}
return(result);
}
@ -189,31 +186,31 @@ ft__glyph_bounds_store_uv_raw(Vec3_i32 p, Vec2_i32 dim, Glyph_Bounds *bounds){
internal Face*
ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor){
String_Const_u8 file_name = push_string_copy(arena, description->font.file_name);
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face ft_face;
FT_Error error = FT_New_Face(ft, (char*)file_name.str, 0, &ft_face);
Face *face = 0;
if (error == 0){
face = push_array_zero(arena, Face, 1);
u32 pt_size_unscaled = Max(description->parameters.pt_size, 8);
u32 pt_size = (u32)(pt_size_unscaled*scale_factor);
b32 hinting = description->parameters.hinting;
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = (pt_size << 6);
FT_Request_Size(ft_face, &size);
face->description.font.file_name = file_name;
face->description.parameters = description->parameters;
Face_Metrics *met = &face->metrics;
met->max_advance = f32_ceil32(ft_face->size->metrics.max_advance/64.f);
met->ascent = f32_ceil32(ft_face->size->metrics.ascender/64.f);
met->descent = f32_floor32(ft_face->size->metrics.descender/64.f);
@ -221,19 +218,19 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
met->line_skip = met->text_height - (met->ascent - met->descent);
met->line_skip = clamp_bot(1.f, met->line_skip);
met->line_height = met->text_height + met->line_skip;
{
f32 real_over_notional = met->line_height/(f32)ft_face->height;
f32 relative_center = -1.f*real_over_notional*ft_face->underline_position;
f32 relative_thickness = real_over_notional*ft_face->underline_thickness;
f32 center = f32_floor32(met->ascent + relative_center);
f32 thickness = clamp_bot(1.f, relative_thickness);
met->underline_yoff1 = center - thickness*0.5f;
met->underline_yoff2 = center + thickness*0.5f;
}
face->advance_map.codepoint_to_index =
ft__get_codepoint_index_map(arena->base_allocator, ft_face);
u16 index_count =
@ -241,40 +238,40 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
face->advance_map.index_count = index_count;
face->advance_map.advance = push_array_zero(arena, f32, index_count);
face->bounds = push_array(arena, Glyph_Bounds, index_count);
Temp_Memory_Block temp_memory(arena);
struct Bitmap{
Vec2_i32 dim;
u8 *data;
};
Bitmap *glyph_bitmaps = push_array(arena, Bitmap, index_count);
u32 load_flags = ft__load_flags(hinting);
for (u16 i = 0; i < index_count; i += 1){
Bitmap *bitmap = &glyph_bitmaps[i];
error = FT_Load_Glyph(ft_face, i, load_flags);
if (error == 0){
FT_GlyphSlot ft_glyph = ft_face->glyph;
Vec2_i32 dim = V2i32(ft_glyph->bitmap.width, ft_glyph->bitmap.rows);
bitmap->dim = dim;
bitmap->data = push_array(arena, u8, dim.x*dim.y);
face->bounds[i].xy_off.x0 = (f32)(ft_face->glyph->bitmap_left);
face->bounds[i].xy_off.y0 = (f32)(met->ascent - ft_face->glyph->bitmap_top);
face->bounds[i].xy_off.x1 = (f32)(face->bounds[i].xy_off.x0 + dim.x);
face->bounds[i].xy_off.y1 = (f32)(face->bounds[i].xy_off.y0 + dim.y);
switch (ft_glyph->bitmap.pixel_mode){
case FT_PIXEL_MODE_MONO:
{
NotImplemented;
}break;
case FT_PIXEL_MODE_GRAY:
{
b32 aa_1bit_mono = (description->parameters.aa_mode == FaceAntialiasingMode_1BitMono);
u8 *src_line = ft_glyph->bitmap.buffer;
if (ft_glyph->bitmap.pitch < 0){
src_line = ft_glyph->bitmap.buffer + (-ft_glyph->bitmap.pitch)*(dim.y - 1);
@ -299,107 +296,98 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
src_line += ft_glyph->bitmap.pitch;
}
}break;
default:
{
NotImplemented;
}break;
}
face->advance_map.advance[i] = f32_ceil32(ft_glyph->advance.x/64.0f);
}
}
u8 white_data[16] = {
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
};
Bitmap white = {};
white.dim = V2i32(4, 4);
white.data = white_data;
Bad_Rect_Pack pack = {};
ft__bad_rect_pack_init(&pack, V2i32(1024, 1024));
// ft__bad_rect_pack_init(&pack, V2i32(1024, 1024));
ft__bad_rect_pack_init(&pack, V2i32(128, 128));
ft__glyph_bounds_store_uv_raw(ft__bad_rect_pack_next(&pack, white.dim), white.dim, &face->white);
for (u16 i = 0; i < index_count; i += 1){
Vec2_i32 dim = glyph_bitmaps[i].dim;
ft__glyph_bounds_store_uv_raw(ft__bad_rect_pack_next(&pack, dim), dim, &face->bounds[i]);
}
ft__bad_rect_store_finish(&pack);
Texture_Kind texture_kind = TextureKind_Mono;
u32 texture = graphics_get_texture(pack.dim, texture_kind);
/* NOTE simon (06/01/25): This assumes that every platforms don't use 0 as a valid texture id.
This is valid for OpenGL and the DX11 implementaion. Someone needs to check the MAC versions. */
if (texture != 0 ){
face->texture_kind = texture_kind;
face->texture = texture;
Vec3_f32 texture_dim = V3f32(pack.dim);
face->texture_dim = texture_dim;
{
Vec3_i32 p = V3i32((i32)face->white.uv.x0, (i32)face->white.uv.y0, (i32)face->white.w);
Vec3_i32 dim = V3i32(white.dim.x, white.dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, white.data);
face->white.uv.x1 = (face->white.uv.x0 + face->white.uv.x1)/texture_dim.x;
face->white.uv.y1 = (face->white.uv.y0 + face->white.uv.y1)/texture_dim.y;
face->white.uv.x0 = face->white.uv.x0/texture_dim.x;
face->white.uv.y0 = face->white.uv.y0/texture_dim.y;
face->white.w /= texture_dim.z;
}
for (u16 i = 0; i < index_count; i += 1){
Vec3_i32 p = V3i32((i32)face->bounds[i].uv.x0, (i32)face->bounds[i].uv.y0, (i32)face->bounds[i].w);
Vec3_i32 dim = V3i32(glyph_bitmaps[i].dim.x, glyph_bitmaps[i].dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, glyph_bitmaps[i].data);
face->bounds[i].uv.x1 = (face->bounds[i].uv.x0 + face->bounds[i].uv.x1)/texture_dim.x;
face->bounds[i].uv.y1 = (face->bounds[i].uv.y0 + face->bounds[i].uv.y1)/texture_dim.y;
face->bounds[i].uv.x0 = face->bounds[i].uv.x0/texture_dim.x;
face->bounds[i].uv.y0 = face->bounds[i].uv.y0/texture_dim.y;
face->bounds[i].w /= texture_dim.z;
}
{
Face_Advance_Map *advance_map = &face->advance_map;
met->space_advance = font_get_glyph_advance(advance_map, met, ' ', 0);
met->decimal_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, '0', '9', 0);
met->hex_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, 'A', 'F', 0);
met->hex_digit_advance =
Max(met->hex_digit_advance, met->decimal_digit_advance);
met->byte_sub_advances[0] =
font_get_glyph_advance(advance_map, met, '\\', 0);
met->byte_sub_advances[1] = met->hex_digit_advance;
met->byte_sub_advances[2] = met->hex_digit_advance;
met->byte_advance =
met->byte_sub_advances[0] +
met->byte_sub_advances[1] +
met->byte_sub_advances[2];
met->normal_lowercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'a', 'z', 0);
met->normal_uppercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'A', 'Z', 0);
met->normal_advance = (26*met->normal_lowercase_advance +
26*met->normal_uppercase_advance +
10*met->decimal_digit_advance)/62.f;
}
} else {
pop_array(arena, Face, 1);
face = 0;
Vec3_f32 texture_dim = V3f32(pack.dim);
face->texture_dim = texture_dim;
{
Vec3_i32 p = V3i32((i32)face->white.uv.x0, (i32)face->white.uv.y0, (i32)face->white.w);
Vec3_i32 dim = V3i32(white.dim.x, white.dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, white.data);
face->white.uv.x1 = (face->white.uv.x0 + face->white.uv.x1)/texture_dim.x;
face->white.uv.y1 = (face->white.uv.y0 + face->white.uv.y1)/texture_dim.y;
face->white.uv.x0 = face->white.uv.x0/texture_dim.x;
face->white.uv.y0 = face->white.uv.y0/texture_dim.y;
face->white.w /= texture_dim.z;
}
for (u16 i = 0; i < index_count; i += 1){
Vec3_i32 p = V3i32((i32)face->bounds[i].uv.x0, (i32)face->bounds[i].uv.y0, (i32)face->bounds[i].w);
Vec3_i32 dim = V3i32(glyph_bitmaps[i].dim.x, glyph_bitmaps[i].dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, glyph_bitmaps[i].data);
face->bounds[i].uv.x1 = (face->bounds[i].uv.x0 + face->bounds[i].uv.x1)/texture_dim.x;
face->bounds[i].uv.y1 = (face->bounds[i].uv.y0 + face->bounds[i].uv.y1)/texture_dim.y;
face->bounds[i].uv.x0 = face->bounds[i].uv.x0/texture_dim.x;
face->bounds[i].uv.y0 = face->bounds[i].uv.y0/texture_dim.y;
#if 0
face->bounds[i].w /= texture_dim.z;
#endif
}
{
Face_Advance_Map *advance_map = &face->advance_map;
met->space_advance = font_get_glyph_advance(advance_map, met, ' ', 0);
met->decimal_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, '0', '9', 0);
met->hex_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, 'A', 'F', 0);
met->hex_digit_advance =
Max(met->hex_digit_advance, met->decimal_digit_advance);
met->byte_sub_advances[0] =
font_get_glyph_advance(advance_map, met, '\\', 0);
met->byte_sub_advances[1] = met->hex_digit_advance;
met->byte_sub_advances[2] = met->hex_digit_advance;
met->byte_advance =
met->byte_sub_advances[0] +
met->byte_sub_advances[1] +
met->byte_sub_advances[2];
met->normal_lowercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'a', 'z', 0);
met->normal_uppercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'A', 'Z', 0);
met->normal_advance = (26*met->normal_lowercase_advance +
26*met->normal_uppercase_advance +
10*met->decimal_digit_advance)/62.f;
}
}
FT_Done_FreeType(ft);
return(face);
}

View File

@ -154,7 +154,7 @@ gl__fill_texture(Texture_Kind texture_kind, u32 texid, Vec3_i32 p, Vec3_i32 dim,
// font rendering code and other platforms. Fortunately the only call that specified 0 for the
// texture handle was for the creation of the fallback texture in gl_render, and we can modify
// that call to pass the fallback texture handle.
Assert( texid != 0 );
Assert( texid != 0 );
if (dim.x > 0 && dim.y > 0 && dim.z > 0){
@ -220,20 +220,20 @@ struct output_t {
};
output_t main(input_t input) {
output_t output;
output.position = float4( mul( view_m, ( input.vertex_p - view_t ) ), 0.0, 1.0 );
// NOTE(simon, 28/02/24): The input colors are BGRA, we need them as RGBA.
output.color = input.vertex_c.zyxw;
output.uvw = input.vertex_t;
output.xy = input.vertex_p;
output.half_thickness = input.vertex_ht;
output.xy = input.vertex_p;
output.half_thickness = input.vertex_ht;
float2 center = input.vertex_t.xy;
float2 half_dim = abs( input.vertex_p - center );
output.adjusted_half_dim = half_dim - input.vertex_t.zz + float2( 0.5, 0.5 );
return output;
}
)foo";