diff --git a/code/4ed_font_provider_freetype.cpp b/code/4ed_font_provider_freetype.cpp index be4e10eb..8450eaf9 100644 --- a/code/4ed_font_provider_freetype.cpp +++ b/code/4ed_font_provider_freetype.cpp @@ -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); } diff --git a/code/platform_win32/4ed_dx11_render.cpp b/code/platform_win32/4ed_dx11_render.cpp index e1fcbfc9..8eb6763b 100644 --- a/code/platform_win32/4ed_dx11_render.cpp +++ b/code/platform_win32/4ed_dx11_render.cpp @@ -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";