diff --git a/4coder_API/version.h b/4coder_API/version.h index 71ac8835..496d6f8e 100644 --- a/4coder_API/version.h +++ b/4coder_API/version.h @@ -1,6 +1,6 @@ #define MAJOR 4 #define MINOR 0 -#define PATCH 17 +#define PATCH 18 #define VN__(a,b,c) #a"."#b"."#c #define VN_(a,b,c) VN__(a,b,c) diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index 6ec7cd69..45a9aaa7 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -487,10 +487,12 @@ CUSTOM_COMMAND_SIG(execute_arbitrary_command){ else if (match_ss(bar.string, make_lit_string("open menu"))){ exec_command(app, cmdid_open_menu); } - else if (match_ss(bar.string, make_lit_string("dos lines"))){ + else if (match_ss(bar.string, make_lit_string("dos lines")) || + match_ss(bar.string, make_lit_string("dosify"))){ exec_command(app, eol_dosify); } - else if (match_ss(bar.string, make_lit_string("nix lines"))){ + else if (match_ss(bar.string, make_lit_string("nix lines")) || + match_ss(bar.string, make_lit_string("nixify"))){ exec_command(app, eol_nixify); } else{ diff --git a/4ed.cpp b/4ed.cpp index 954bc805..73cf3efb 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -1507,7 +1507,7 @@ App_Init_Sig(app_init){ String file_name = make_string(font_setup[i].c_file_name, font_setup[i].file_name_len); String name = make_string(font_setup[i].c_name, font_setup[i].name_len); i32 pt_size = font_setup[i].pt_size; - font_set_add(partition, models->font_set, file_name, name, pt_size); + font_set_add(models->font_set, file_name, name, pt_size); } } diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 8e8a82d6..0c92f83b 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -878,8 +878,9 @@ DOC_SEE(Buffer_Setting_ID) } if (new_value != file->settings.display_width){ i16 font_id = file->settings.font_id; - Render_Font *font = get_font_info(models->font_set, font_id)->font; - file_set_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance); + Font_Info *font_info = get_font_info(models->font_set, font_id); + Render_Font *font = font_info->font; + file_set_width(models, file, new_value, font); } }break; @@ -892,7 +893,7 @@ DOC_SEE(Buffer_Setting_ID) if (new_value != file->settings.minimum_base_display_width){ i16 font_id = file->settings.font_id; Render_Font *font = get_font_info(models->font_set, font_id)->font; - file_set_min_base_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance); + file_set_min_base_width(models, file, new_value, font); } }break; @@ -981,7 +982,7 @@ DOC_SEE(Buffer_Setting_ID) file_allocate_character_starts_as_needed(&models->mem.general, file); buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white); - file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance); + file_measure_wraps(models, file, font); file_update_cursor_positions(models, file); } }break; diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 637180a0..e1fbaae0 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -395,9 +395,7 @@ view_compute_cursor(View *view, Buffer_Seek seek, b32 return_hint){ Buffer_Cursor_Seek_Params params; params.buffer = &file->state.buffer; params.seek = seek; - params.font_height = (f32)font->height; - params.cp_adv = font->codepoint_advance_data; - params.byte_adv = font->byte_advance; + params.font = font; params.wrap_line_index = file->state.wrap_line_index; params.character_starts = file->state.character_starts; params.virtual_white = file->settings.virtual_white; @@ -1011,15 +1009,14 @@ struct Code_Wrap_State{ i32 size; i32 i; - f32 *cp_adv; - f32 byte_adv; + Render_Font *font; f32 tab_indent_amount; Buffer_Translating_State tran; }; internal void -wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *cp_adv, f32 byte_adv){ +wrap_state_init(Code_Wrap_State *state, Editing_File *file, Render_Font *font){ state->token_array = file->state.token_array; state->token_ptr = state->token_array.tokens; state->end_token = state->token_ptr + state->token_array.count; @@ -1033,9 +1030,8 @@ wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *cp_adv, f32 byt state->size = size; state->i = 0; - state->cp_adv = cp_adv; - state->byte_adv = byte_adv; - state->tab_indent_amount = cp_adv['\t']; + state->font = font; + state->tab_indent_amount = get_codepoint_advance(font, '\t'); state->tran = null_buffer_translating_state; } @@ -1147,13 +1143,13 @@ wrap_state_consume_token(Code_Wrap_State *state, i32 fixed_end_point){ u32 n = state->tran.step_current.value; f32 adv = 0; if (state->tran.do_codepoint_advance){ - adv = state->cp_adv[n]; + adv = get_codepoint_advance(state->font, n); if (n != ' ' && n != '\t'){ skipping_whitespace = false; } } else{ - adv = state->byte_adv; + adv = state->font->byte_advance; skipping_whitespace = false; } @@ -1450,7 +1446,7 @@ get_current_shift(Code_Wrap_State *wrap_state, i32 next_line_start, b32 *adjust_ } internal void -file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_adv, f32 byte_adv){ +file_measure_wraps(Models *models, Editing_File *file, Render_Font *font){ General_Memory *general = &models->mem.general; Partition *part = &models->mem.part; @@ -1463,8 +1459,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_ Buffer_Measure_Wrap_Params params; params.buffer = &file->state.buffer; params.wrap_line_index = file->state.wrap_line_index; - params.cp_adv = cp_adv; - params.byte_adv = byte_adv; + params.font = font; params.virtual_white = file->settings.virtual_white; f32 width = (f32)file->settings.display_width; @@ -1496,7 +1491,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_ i32 max_wrap_indent_mark = 0; if (params.virtual_white && file->state.tokens_complete && !file->state.still_lexing){ - wrap_state_init(&wrap_state, file, cp_adv, byte_adv); + wrap_state_init(&wrap_state, file, font); use_tokens = 1; potential_marks = push_array(part, Potential_Wrap_Indent_Pair, floor32(width)); @@ -1548,7 +1543,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_ word_stage = 1; } else{ - f32 adv = params.cp_adv[ch]; + f32 adv = get_codepoint_advance(params.font, ch); x += adv; self_x += adv; if (self_x > width){ @@ -1675,7 +1670,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_ goto doublebreak_stage1; } - f32 adv = params.cp_adv[ch]; + f32 adv = get_codepoint_advance(params.font, ch); x += adv; if (!first_word && x > current_width){ emit_comment_position = 1; @@ -1701,7 +1696,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_ goto doublebreak_stage2; } - f32 adv = params.cp_adv[ch]; + f32 adv = get_codepoint_advance(params.font, ch); x += adv; } still_looping = buffer_stringify_next(&stream); @@ -1908,21 +1903,21 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_ } internal void -file_measure_wraps_and_fix_cursor(Models *models, Editing_File *file, f32 font_height, f32 *cp_adv, f32 byte_adv){ - file_measure_wraps(models, file, font_height, cp_adv, byte_adv); +file_measure_wraps_and_fix_cursor(Models *models, Editing_File *file, Render_Font *font){ + file_measure_wraps(models, file, font); file_update_cursor_positions(models, file); } internal void -file_set_width(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *cp_adv, f32 byte_adv){ +file_set_width(Models *models, Editing_File *file, i32 display_width, Render_Font *font){ file->settings.display_width = display_width; - file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv); + file_measure_wraps_and_fix_cursor(models, file, font); } internal void -file_set_min_base_width(Models *models, Editing_File *file, i32 minimum_base_display_width, f32 font_height, f32 *cp_adv, f32 byte_adv){ +file_set_min_base_width(Models *models, Editing_File *file, i32 minimum_base_display_width, Render_Font *font){ file->settings.minimum_base_display_width = minimum_base_display_width; - file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv); + file_measure_wraps_and_fix_cursor(models, file, font); } // @@ -1971,7 +1966,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File * file->settings.font_id = font_id; Render_Font *font = get_font_info(font_set, font_id)->font; - file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance); + file_measure_wraps(models, file, font); file->settings.read_only = read_only; if (!read_only){ @@ -3269,12 +3264,10 @@ file_do_single_edit(System_Functions *system, Models *models, Editing_File *file // TODO(allen): Redo this as some sort of dialogical API #if 0 file_allocate_wraps_as_needed(general, file); - buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift, - file->state.wraps, (f32)font->height, font->advance_data, - (f32)file->settings.display_width); + buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift, file->state.wraps, (f32)font->height, font->advance_data, (f32)file->settings.display_width); #endif - file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance); + file_measure_wraps(models, file, font); // NOTE(allen): cursor fixing Cursor_Fix_Descriptor desc = {0}; @@ -3388,7 +3381,7 @@ file_do_batch_edit(System_Functions *system, Models *models, Editing_File *file, buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white); Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font; - file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance); + file_measure_wraps(models, file, font); // NOTE(allen): cursor fixing Cursor_Fix_Descriptor desc = {0}; @@ -3667,8 +3660,9 @@ style_get_color(Style *style, Cpp_Token token){ internal void file_set_font(Models *models, Editing_File *file, i16 font_id){ file->settings.font_id = font_id; - Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font; - file_measure_wraps_and_fix_cursor(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance); + Font_Info *font_info = get_font_info(models->font_set, file->settings.font_id); + Render_Font *font = font_info->font; + file_measure_wraps_and_fix_cursor(models, file, font); Editing_Layout *layout = &models->layout; for (View_Iter iter = file_view_iter_init(layout, file, 0); @@ -5959,9 +5953,7 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target params.height = (f32)max_y; params.start_cursor = render_cursor; params.wrapped = wrapped; - params.font_height = (f32)line_height; - params.cp_adv = font->codepoint_advance_data; - params.byte_adv = font->byte_advance; + params.font = font; params.virtual_white = file->settings.virtual_white; params.wrap_slashes = file->settings.wrap_indicator; @@ -6173,12 +6165,10 @@ draw_text_with_cursor(Render_Target *target, View *view, i16 font_id, i32_Rect r part2 = substr(s, pos, 1); part3 = substr(s, pos+1, s.size-pos-1); - x = draw_string(target, font_id, part1, floor32(x), y, text_color); - // TODO(allen): WHAT TO DO NOW? cursor_rect.x0 = floor32(x); - cursor_rect.x1 = floor32(x) + ceil32(font->codepoint_advance_data[s.str[pos]]); + cursor_rect.x1 = floor32(x) + ceil32(get_codepoint_advance(font, s.str[pos])); cursor_rect.y0 = y; cursor_rect.y1 = y + view->line_height; draw_rectangle(target, cursor_rect, cursor_color); @@ -6385,8 +6375,7 @@ draw_button(GUI_Target *gui_target, Render_Target *target, View *view, i16 font_ } internal void -draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view, - i16 font_id, i32_Rect rect, GUI_id id, Style *style){ +draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view, i16 font_id, i32_Rect rect, GUI_id id, Style *style){ Models *models = view->persistent.models; i32 active_level = gui_active_level(gui_target, id); @@ -6412,8 +6401,9 @@ draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view, draw_string(target, font_id, info->name.str, font_x, y, text_color); } + i32 height = info->font->height; x = inner.x0; - y += info->height; + y += height; x = ceil32(draw_string(target, font_id, "if", x, y, keyword_color)); x = ceil32(draw_string(target, font_id, "(x < ", x, y, text_color)); x = ceil32(draw_string(target, font_id, "0", x, y, int_constant_color)); @@ -6423,7 +6413,7 @@ draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view, x = ceil32(draw_string(target, font_id, "// comment", x, y, comment_color)); x = inner.x0; - y += info->height; + y += height; draw_string(target, font_id, "[] () {}; * -> +-/ <>= ! && || % ^", x, y, text_color); } diff --git a/4ed_font_set.cpp b/4ed_font_set.cpp index 9c4a47f3..a4439e71 100644 --- a/4ed_font_set.cpp +++ b/4ed_font_set.cpp @@ -111,7 +111,7 @@ font_set_can_load(Font_Set *set){ } internal void -font_set_load(Partition *partition, Font_Set *set, i16 font_id){ +font_set_load(Font_Set *set, i16 font_id){ Font_Info *info = get_font_info(set, font_id); Font_Slot *slot = set->free_slots.next; Assert(slot != &set->free_slots); @@ -119,10 +119,7 @@ font_set_load(Partition *partition, Font_Set *set, i16 font_id){ font__insert(&set->used_slots, slot); Render_Font *font = (Render_Font*)(slot + 1); - set->font_load(font, - info->filename.str, - info->name.str, - info->pt_size, 4, true); + set->font_load(font, info->filename.str, info->name.str, info->pt_size, 4, true); info->font = font; slot->font_id = font_id; } @@ -145,7 +142,7 @@ font_set_evict_lru(Font_Set *set){ } internal void -font_set_use(Partition *partition, Font_Set *set, i16 font_id){ +font_set_use(Font_Set *set, i16 font_id){ b8 already_used = set->font_used_flags[font_id-1]; if (!already_used){ @@ -164,7 +161,7 @@ font_set_use(Partition *partition, Font_Set *set, i16 font_id){ if (!font_set_can_load(set)){ font_set_evict_lru(set); } - font_set_load(partition, set, font_id); + font_set_load(set, font_id); } slot = ((Font_Slot*)info->font) - 1; @@ -174,7 +171,7 @@ font_set_use(Partition *partition, Font_Set *set, i16 font_id){ } internal b32 -font_set_add(Partition *partition, Font_Set *set, String filename, String name, i32 pt_size){ +font_set_add(Font_Set *set, String filename, String name, i32 pt_size){ b32 result = 0; if (font_set_can_add(set)){ Render_Font dummy_font = {0}; @@ -184,13 +181,13 @@ font_set_add(Partition *partition, Font_Set *set, String filename, String name, info->name = name; info->pt_size = pt_size; set->font_load(&dummy_font, info->filename.str, info->name.str, info->pt_size, 4, false); - info->height = dummy_font.height; - info->advance = dummy_font.advance; + //info->height = dummy_font.height; + //info->advance = dummy_font.advance; font_set_add_hash(set, name, font_id); if (font_set_can_load(set)){ - font_set_load(partition, set, font_id); + font_set_load(set, font_id); } result = 1; diff --git a/4ed_rendering.h b/4ed_rendering.h index 2e5a2ca8..a85a4d6f 100644 --- a/4ed_rendering.h +++ b/4ed_rendering.h @@ -12,30 +12,58 @@ #ifndef FRED_RENDERING_H #define FRED_RENDERING_H -struct Glyph_Data{ - b32 exists; - - f32 x0, x1; - f32 y0, y1; - - f32 xoff, yoff; - f32 xoff2, yoff2; +// +// Fonts +// + +#include "file/4coder_font_data.h" + +struct Font_Table_Entry{ + u32 hash; + String name; + i16 font_id; }; -struct Render_Font{ - char name_[24]; +struct Font_Info{ + Render_Font *font; + String filename; String name; - b32 loaded; - - Glyph_Data glyphs[256]; - f32 byte_advance; - f32 codepoint_advance_data[256]; - i32 height, ascent, descent, line_skip; - i32 advance; - u32 tex; - i32 tex_width, tex_height; + i32 pt_size; }; +struct Font_Slot{ + Font_Slot *next, *prev; + i16 font_id; + u8 padding[6]; +}; + +#define Font_Load_Sig(name) i32 name(Render_Font *font_out, char *filename, char *fontname, i32 pt_size, i32 tab_width, b32 store_texture) +typedef Font_Load_Sig(Font_Load); + +#define Release_Font_Sig(name) void name(Render_Font *font) +typedef Release_Font_Sig(Release_Font); + +struct Font_Set{ + Font_Info *info; + Font_Table_Entry *entries; + u32 count, max; + + void *font_block; + Font_Slot free_slots; + Font_Slot used_slots; + + Font_Load *font_load; + Release_Font *release_font; + + b8 *font_used_flags; + i16 used_this_frame; + i16 live_max; +}; + +// +// Render Commands +// + enum Render_Piece_Type{ piece_type_rectangle, piece_type_outline, @@ -101,49 +129,9 @@ typedef Draw_Pop_Clip_Sig(Draw_Pop_Clip); #define Draw_Push_Piece_Sig(name) void name(Render_Target *target, Render_Piece_Combined piece) typedef Draw_Push_Piece_Sig(Draw_Push_Piece); -#define Font_Load_Sig(name) i32 name(Render_Font *font_out, char *filename, char *fontname, i32 pt_size, i32 tab_width, b32 store_texture) -typedef Font_Load_Sig(Font_Load); - -#define Release_Font_Sig(name) void name(Render_Font *font) -typedef Release_Font_Sig(Release_Font); - -struct Font_Table_Entry{ - u32 hash; - String name; - i16 font_id; -}; - -struct Font_Info{ - Render_Font *font; - String filename; - String name; - i32 height, advance; - i32 pt_size; -}; - -struct Font_Slot{ - Font_Slot *next, *prev; - i16 font_id; - u8 padding[14]; -}; - -struct Font_Set{ - Font_Info *info; - Font_Table_Entry *entries; - u32 count, max; - - void *font_block; - Font_Slot free_slots; - Font_Slot used_slots; - - //Font_Info_Load *font_info_load; - Font_Load *font_load; - Release_Font *release_font; - - b8 *font_used_flags; - i16 used_this_frame; - i16 live_max; -}; +// +// Render target stuff +// struct Render_Target{ void *handle; @@ -159,13 +147,13 @@ struct Render_Target{ char *push_buffer; i32 size, max; - // TODO(allen): rename this to font_partition - Font_Set font_set; - Partition *partition; - Draw_Push_Clip *push_clip; Draw_Pop_Clip *pop_clip; Draw_Push_Piece *push_piece; + + // TODO(allen): Does the font set really belong here? Actually, do we still want it at all? + Font_Set font_set; + Partition *partition; }; #define DpiMultiplier(n,dpi) ((n) * (dpi) / 96) diff --git a/4ed_rendering_helper.cpp b/4ed_rendering_helper.cpp index f84069a6..078af7ff 100644 --- a/4ed_rendering_helper.cpp +++ b/4ed_rendering_helper.cpp @@ -125,7 +125,7 @@ font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32 piece.glyph.font_id = font_id; piece.glyph.character = character; target->push_piece(target, piece); - font_set_use(target->partition, &target->font_set, font_id); + font_set_use(&target->font_set, font_id); } internal void @@ -135,7 +135,8 @@ font_draw_glyph(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y, internal f32 draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 x_, i32 y_, u32 color){ - Render_Font *font = get_font_info(&target->font_set, font_id)->font; + Font_Info *font_info = get_font_info(&target->font_set, font_id); + Render_Font *font = font_info->font; f32 x = 0; if (font){ @@ -143,7 +144,6 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 x = (f32)x_; f32 byte_advance = font->byte_advance; - f32 *codepoint_advance_data = font->codepoint_advance_data; u8 *str = (u8*)str_.str; u8 *str_end = str + str_.size; @@ -170,7 +170,7 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 if (color != 0){ font_draw_glyph(target, font_id, type, (u8)codepoint, x, y, color); } - x += codepoint_advance_data[codepoint]; + x += get_codepoint_advance(font, codepoint); } else if (do_numbers){ for (;byte < str; ++byte){ diff --git a/4ed_system_shared.cpp b/4ed_system_shared.cpp index 3f40fcf9..1261feee 100644 --- a/4ed_system_shared.cpp +++ b/4ed_system_shared.cpp @@ -225,13 +225,9 @@ sysshared_to_binary_path(String *out_filename, char *filename){ // Rendering // - inline void draw_set_clip(Render_Target *target, i32_Rect clip_box){ - glScissor(clip_box.x0, - target->height - clip_box.y1, - clip_box.x1 - clip_box.x0, - clip_box.y1 - clip_box.y0); + glScissor(clip_box.x0, target->height - clip_box.y1, clip_box.x1 - clip_box.x0, clip_box.y1 - clip_box.y0); } inline void @@ -267,23 +263,25 @@ draw_push_piece(Render_Target *target, Render_Piece_Combined piece){ PutStruct(Render_Piece_Header, piece.header); switch (piece.header.type){ - case piece_type_rectangle: - case piece_type_outline: - PutStruct(Render_Piece_Rectangle, piece.rectangle); - break; + case piece_type_rectangle: case piece_type_outline: + { + PutStruct(Render_Piece_Rectangle, piece.rectangle); + }break; case piece_type_gradient: - PutStruct(Render_Piece_Gradient, piece.gradient); - break; + { + PutStruct(Render_Piece_Gradient, piece.gradient); + }break; - case piece_type_glyph: - case piece_type_mono_glyph: - PutStruct(Render_Piece_Glyph, piece.glyph); - break; + case piece_type_glyph: case piece_type_mono_glyph: + { + PutStruct(Render_Piece_Glyph, piece.glyph); + }break; case piece_type_mono_glyph_advance: - PutStruct(Render_Piece_Glyph_Advance, piece.glyph_advance); - break; + { + PutStruct(Render_Piece_Glyph_Advance, piece.glyph_advance); + }break; } Assert(target->size <= target->max); @@ -385,7 +383,7 @@ struct Render_Quad{ }; inline Render_Quad -get_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){ +get_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){ Render_Quad q; float ipw = 1.0f / pw, iph = 1.0f / ph; @@ -404,7 +402,7 @@ get_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){ } inline Render_Quad -get_exact_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){ +get_exact_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){ Render_Quad q; float ipw = 1.0f / pw, iph = 1.0f / ph; @@ -423,47 +421,48 @@ get_exact_render_quad(Glyph_Data *b, i32 pw, i32 ph, float xpos, float ypos){ } inline void -private_draw_glyph(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, u32 color){ - Render_Quad q = get_render_quad(font->glyphs + character, font->tex_width, font->tex_height, x, y); - - draw_set_color(target, color); - draw_bind_texture(target, font->tex); - glBegin(GL_QUADS); - { - glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1); - glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1); - glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0); - glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0); +private_draw_glyph(Render_Target *target, Render_Font *font, u32 character, f32 x, f32 y, u32 color){ + Glyph_Data glyph = {0}; + if (get_codepoint_glyph_data(font, character, &glyph)){ + Render_Quad q = get_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y); + + draw_set_color(target, color); + draw_bind_texture(target, glyph.tex); + glBegin(GL_QUADS); + { + glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1); + glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1); + glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0); + glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0); + } + glEnd(); } - glEnd(); } inline void -private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, - f32 x, f32 y, f32 advance, u32 color){ - - f32 left = font->glyphs[character].x0; - f32 right = font->glyphs[character].x1; - f32 width = (right - left); - f32 x_shift = (advance - width) * .5f; - - x += x_shift; - - Render_Quad q = get_exact_render_quad( - font->glyphs + character, - font->tex_width, font->tex_height, x, y - ); - - draw_set_color(target, color); - draw_bind_texture(target, font->tex); - glBegin(GL_QUADS); - { - glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1); - glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1); - glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0); - glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0); +private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, f32 advance, u32 color){ + Glyph_Data glyph = {0}; + if (get_codepoint_glyph_data(font, character, &glyph)){ + f32 left = glyph.bounds.x0; + f32 right = glyph.bounds.x1; + f32 width = (right - left); + f32 x_shift = (advance - width) * .5f; + + x += x_shift; + + Render_Quad q = get_exact_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y); + + draw_set_color(target, color); + draw_bind_texture(target, glyph.tex); + glBegin(GL_QUADS); + { + glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1); + glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1); + glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0); + glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0); + } + glEnd(); } - glEnd(); } inline void @@ -541,149 +540,6 @@ launch_rendering(Render_Target *target){ #undef ExtractStruct -#if 0 -internal void* -part_alloc(i32 size, void *context){ - Partition *part = (Partition*)context; - void *result = push_block(part, size); - return(result); -} - -internal void -part_free(void *ptr, void *context){} - -#define STBTT_malloc part_alloc -#define STBTT_free part_free - -#define STB_TRUETYPE_IMPLEMENTATION -#include "stb_truetype.h" - -internal b32 -stb_font_load(Partition *part, Render_Font *font_out, char *filename_untranslated, i32 pt_size, i32 tab_width, i32 oversample, b32 store_texture){ - - char space_[1024]; - String filename = make_fixed_width_string(space_); - b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated); - if (!translate_success) return 0; - - b32 result = true; - - stbtt_packedchar chardata[256]; - - File_Data file = sysshared_load_file(filename.str); - - if (!file.data){ - result = false; - } - - else{ - stbtt_fontinfo font; - if (!stbtt_InitFont(&font, (u8*)file.data, 0)){ - result = false; - } - else{ - memset(font_out, 0, sizeof(*font_out)); - - i32 ascent, descent, line_gap; - stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap); - - f32 scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size); - - f32 scaled_ascent = scale*ascent; - f32 scaled_descent = scale*descent; - f32 scaled_line_gap = scale*line_gap; - - font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap); - font_out->ascent = (i32)(scaled_ascent); - font_out->descent = (i32)(scaled_descent); - font_out->line_skip = (i32)(scaled_line_gap); - - if (store_texture){ - Temp_Memory temp = begin_temp_memory(part); - - i32 tex_width = pt_size*16*oversample; - i32 tex_height = pt_size*16*oversample; - void *block = sysshared_push_block(part, tex_width * tex_height); - - font_out->tex_width = tex_width; - font_out->tex_height = tex_height; - - ///////////////////////////////////////////////////////////////// - stbtt_pack_context spc; - - if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, part)){ - stbtt_PackSetOversampling(&spc, oversample, oversample); - if (!stbtt_PackFontRange(&spc, (u8*)file.data, 0, STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){ - result = false; - } - - stbtt_PackEnd(&spc); - } - else{ - result = false; - } - ///////////////////////////////////////////////////////////////// - - if (result){ - GLuint font_tex; - glGenTextures(1, &font_tex); - glBindTexture(GL_TEXTURE_2D, font_tex); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block); - - font_out->tex = font_tex; - glBindTexture(GL_TEXTURE_2D, 0); - - f32 *advance_data = font_out->advance_data; - Glyph_Data *glyphs = font_out->glyphs; - for (u8 code_point = 0; code_point < 128; ++code_point){ - advance_data[code_point] = (f32)(ceil32(chardata[code_point].xadvance)); - glyphs[code_point].x0 = chardata[code_point].x0; - glyphs[code_point].y0 = chardata[code_point].y0; - glyphs[code_point].x1 = chardata[code_point].x1; - glyphs[code_point].y1 = chardata[code_point].y1; - glyphs[code_point].xoff = chardata[code_point].xoff; - glyphs[code_point].yoff = chardata[code_point].yoff + font_out->ascent; - glyphs[code_point].xoff2 = chardata[code_point].xoff2; - glyphs[code_point].yoff2 = chardata[code_point].yoff2 + font_out->ascent; - } - - glyphs['\r'] = glyphs[' ']; - advance_data['\r'] = advance_data[' ']; - - glyphs['\n'] = glyphs[' ']; - advance_data['\n'] = advance_data[' ']; - - glyphs['\t'] = glyphs[' ']; - advance_data['\t'] = advance_data[' ']*tab_width; - - i32 max_advance = 0; - for (u8 code_point = 0; code_point < 128; ++code_point){ - if (stbtt_FindGlyphIndex(&font, code_point) != 0){ - font_out->glyphs[code_point].exists = 1; - i32 advance = ceil32(advance_data[code_point]); - if (max_advance < advance){ - max_advance = advance; - } - } - } - font_out->advance = max_advance - 1; - } - - end_temp_memory(temp); - } - } - system_free_memory(file.data); - } - - return(result); -} -#endif - // NOTE(allen): Thanks to insofaras. This is copy-pasted from some work he originally did to get free type working on Linux. #undef internal @@ -800,88 +656,99 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size } // set all this stuff the renderer needs - Glyph_Data* c = rf->glyphs + i; - - c->x0 = (f32)(pen_x); - c->y0 = (f32)(pen_y); - c->x1 = (f32)(pen_x + w); - c->y1 = (f32)(pen_y + h + 1); - - c->xoff = (f32)(face->glyph->bitmap_left); - c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top); - - c->xoff2 = w + c->xoff; - c->yoff2 = h + c->yoff + 1; - - // TODO(allen): maybe advance data should be integers for a while... - // I require the actual values to be integers anyway... hmm... - f32 advance = (f32)ceil32(face->glyph->advance.x / 64.0f); - rf->codepoint_advance_data[i] = advance; - - rf->glyphs[i].exists = 1; - - i32 pitch = face->glyph->bitmap.pitch; - - // write to texture atlas - for(i32 j = 0; j < h; ++j){ - for(i32 i = 0; i < w; ++i){ - i32 x = pen_x + i; - i32 y = pen_y + j; - - if(use_lcd_filter){ + Glyph_Bounds* c = 0; + f32 *advance_ptr = 0; + get_codepoint_memory(rf, i, &c, &advance_ptr); + if (c != 0 && advance_ptr != 0){ + c->exists = true; + + c->x0 = (f32)(pen_x); + c->y0 = (f32)(pen_y); + c->x1 = (f32)(pen_x + w); + c->y1 = (f32)(pen_y + h + 1); + + c->xoff = (f32)(face->glyph->bitmap_left); + c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top); + + c->xoff2 = w + c->xoff; + c->yoff2 = h + c->yoff + 1; + + // TODO(allen): maybe advance data should be integers for a while... + // I require the actual values to be integers anyway... hmm... + f32 advance = (f32)ceil32(face->glyph->advance.x / 64.0f); + *advance_ptr = advance; + + // write to texture atlas + i32 pitch = face->glyph->bitmap.pitch; + for(i32 j = 0; j < h; ++j){ + for(i32 i = 0; i < w; ++i){ + i32 x = pen_x + i; + i32 y = pen_y + j; + + if(use_lcd_filter){ #if 1 - u8 a = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1]; - u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3 + 0]; - u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2]; - - pixels[y * tex_width + x] = (a << 24) | (b << 16) | (a << 8) | r; - + u8 a = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1]; + u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3 + 0]; + u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2]; + + pixels[y * tex_width + x] = (a << 24) | (b << 16) | (a << 8) | r; + #else - - u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3]; - u8 g = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1]; - u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2]; - u8 a = (u8)ROUND32((r + g + b) / 3.0f); - - pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b; + + u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3]; + u8 g = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1]; + u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2]; + u8 a = (u8)ROUND32((r + g + b) / 3.0f); + + pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b; #endif - } else { - pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101; + } else { + pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101; + } } } + + pen_x = ceil32(c->x1 + 1); } - - pen_x = ceil32(c->x1 + 1); } - f32 *cp_adv = rf->codepoint_advance_data; - cp_adv['\n'] = cp_adv[' ']; - cp_adv['\r'] = cp_adv['\\'] + cp_adv['r']; - cp_adv['\t'] = cp_adv[' ']*tab_width; + // NOTE(allen): Setup some basic spacing stuff. + f32 space_adv = get_codepoint_advance(rf, ' '); + f32 backslash_adv = get_codepoint_advance(rf, '\\'); + f32 r_adv = get_codepoint_advance(rf, 'r'); - f32 max_hex_advance = cp_adv['0']; - for (u32 i = '1'; i <= '9'; ++i){ - max_hex_advance = Max(max_hex_advance, cp_adv[i]); + set_codepoint_advance(rf, '\n', space_adv); + set_codepoint_advance(rf, '\r', backslash_adv + r_adv); + set_codepoint_advance(rf, '\t', space_adv*tab_width); + + f32 max_hex_advance = 0.f; + for (u32 i = '0'; i <= '9'; ++i){ + f32 adv = get_codepoint_advance(rf, i); + max_hex_advance = Max(max_hex_advance, adv); } for (u32 i = 'a'; i <= 'f'; ++i){ - max_hex_advance = Max(max_hex_advance, cp_adv[i]); + f32 adv = get_codepoint_advance(rf, i); + max_hex_advance = Max(max_hex_advance, adv); } for (u32 i = 'A'; i <= 'F'; ++i){ - max_hex_advance = Max(max_hex_advance, cp_adv[i]); + f32 adv = get_codepoint_advance(rf, i); + max_hex_advance = Max(max_hex_advance, adv); } - rf->byte_advance = cp_adv['\\'] + max_hex_advance*2; + rf->byte_advance = backslash_adv + max_hex_advance*2; FT_Done_FreeType(ft); tex_height = next_pow_of_2(pen_y + max_glyph_h + 2); - rf->tex_width = tex_width; - rf->tex_height = tex_height; + u32 page_index = 0; + rf->glyph_pages[page_index].tex_width = tex_width; + rf->glyph_pages[page_index].tex_height = tex_height; // upload texture - glGenTextures(1, &rf->tex); - glBindTexture(GL_TEXTURE_2D, rf->tex); + u32 tex; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); @@ -896,14 +763,22 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size } glBindTexture(GL_TEXTURE_2D, 0); + rf->glyph_pages[page_index].tex = tex; - return 1; + rf->glyph_pages[page_index].exists = true; + + return(true); } internal Release_Font_Sig(draw_release_font){ - glDeleteTextures(1, &font->tex); - font->tex = 0; + for (u32 i = 0; i < ArrayCount(font->glyph_pages); ++i){ + Glyph_Page *page = &font->glyph_pages[i]; + if (page->exists){ + glDeleteTextures(1, &page->tex); + } + page->tex = 0; + } } // BOTTOM diff --git a/file/4coder_buffer.cpp b/file/4coder_buffer.cpp index f4705dc2..b2d93e6b 100644 --- a/file/4coder_buffer.cpp +++ b/file/4coder_buffer.cpp @@ -13,6 +13,7 @@ // Buffer low level operations // +#include "../file/4coder_font_data.h" #include "../4coder_helper/4coder_seek_types.h" typedef struct Cursor_With_Index{ @@ -992,8 +993,7 @@ struct Buffer_Layout_Stop{ struct Buffer_Measure_Wrap_Params{ Gap_Buffer *buffer; i32 *wrap_line_index; - f32 *cp_adv; - f32 byte_adv; + Render_Font *font; b32 virtual_white; }; @@ -1094,10 +1094,10 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para if (!S.skipping_whitespace){ if (S.tran.do_codepoint_advance){ - S.current_adv = params.cp_adv[S.tran.step_current.value]; + S.current_adv = get_codepoint_advance(params.font, S.tran.step_current.value); } else{ - S.current_adv = params.byte_adv; + S.current_adv = params.font->byte_advance; } S.did_wrap = false; @@ -1461,7 +1461,7 @@ buffer_get_line_index_from_character_pos(i32 *character_starts, i32 pos, i32 l_b } inline i32 -buffer_get_line_index_from_wrapped_y(i32 *wrap_line_index, f32 y, f32 line_height, i32 l_bound, i32 u_bound){ +buffer_get_line_index_from_wrapped_y(i32 *wrap_line_index, f32 y, i32 line_height, i32 l_bound, i32 u_bound){ i32 wrap_index = floor32(y/line_height); i32 i = binary_search(wrap_line_index, wrap_index, l_bound, u_bound); return(i); @@ -1539,9 +1539,7 @@ buffer_partial_from_line_character(Gap_Buffer *buffer, i32 line, i32 character){ struct Buffer_Cursor_Seek_Params{ Gap_Buffer *buffer; Buffer_Seek seek; - f32 font_height; - f32 *cp_adv; - f32 byte_adv; + Render_Font *font; i32 *wrap_line_index; i32 *character_starts; b32 virtual_white; @@ -1628,7 +1626,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa case buffer_seek_unwrapped_xy: { - line_index = (i32)(params.seek.y / params.font_height); + line_index = (i32)(params.seek.y / params.font->height); if (line_index >= params.buffer->line_count){ line_index = params.buffer->line_count - 1; } @@ -1639,8 +1637,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa case buffer_seek_wrapped_xy: { - line_index = buffer_get_line_index_from_wrapped_y(params.wrap_line_index, params.seek.y, params.font_height, - 0, params.buffer->line_count); + line_index = buffer_get_line_index_from_wrapped_y(params.wrap_line_index, params.seek.y, params.font->height, 0, params.buffer->line_count); }break; default: InvalidCodePath; @@ -1652,9 +1649,9 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa S.next_cursor.line = line_index + 1; S.next_cursor.character = 1; S.next_cursor.wrap_line = params.wrap_line_index[line_index] + 1; - S.next_cursor.unwrapped_y = (f32)(line_index * params.font_height); + S.next_cursor.unwrapped_y = (f32)(line_index * params.font->height); S.next_cursor.unwrapped_x = 0; - S.next_cursor.wrapped_y = (f32)(params.wrap_line_index[line_index] * params.font_height); + S.next_cursor.wrapped_y = (f32)(params.wrap_line_index[line_index] * params.font->height); S.next_cursor.wrapped_x = 0; } @@ -1765,8 +1762,8 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa ++S.next_cursor.character_pos; ++S.next_cursor.line; ++S.next_cursor.wrap_line; - S.next_cursor.unwrapped_y += params.font_height; - S.next_cursor.wrapped_y += params.font_height; + S.next_cursor.unwrapped_y += params.font->height; + S.next_cursor.wrapped_y += params.font->height; S.next_cursor.character = 1; S.next_cursor.unwrapped_x = 0; @@ -1783,10 +1780,10 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){ if (S.tran.do_codepoint_advance){ - S.ch_width = params.cp_adv[S.tran.step_current.value]; + S.ch_width = get_codepoint_advance(params.font, S.tran.step_current.value); } else{ - S.ch_width = params.byte_adv; + S.ch_width = params.font->byte_advance; } if (S.tran.step_current.i >= S.wrap_unit_end){ @@ -1800,7 +1797,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa S.wrap_unit_end = wrap_unit_end; if (do_wrap && !S.first_of_the_line){ - S.next_cursor.wrapped_y += params.font_height; + S.next_cursor.wrapped_y += params.font->height; ++S.next_cursor.wrap_line; if (params.virtual_white){ @@ -1869,7 +1866,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa goto buffer_cursor_seek_end; } - if (y > params.seek.y - params.font_height && x >= params.seek.x){ + if (y > params.seek.y - params.font->height && x >= params.seek.x){ if (!params.seek.round_down){ if (py >= y && S.ch != '\n' && (params.seek.x - px) < (x - params.seek.x)){ S.this_cursor = S.prev_cursor; @@ -1975,15 +1972,14 @@ typedef struct Buffer_Render_Item{ typedef struct Render_Item_Write{ Buffer_Render_Item *item; f32 x, y; - f32 *adv; - f32 font_height; + Render_Font *font; f32 x_min; f32 x_max; } Render_Item_Write; inline Render_Item_Write write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){ - f32 ch_width = write.adv[(u8)glyphid]; + f32 ch_width = get_codepoint_advance(write.font, glyphid); if (write.x <= write.x_max && write.x + ch_width >= write.x_min){ write.item->index = index; @@ -1992,7 +1988,7 @@ write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){ write.item->x0 = write.x; write.item->y0 = write.y; write.item->x1 = write.x + ch_width; - write.item->y1 = write.y + write.font_height; + write.item->y1 = write.y + write.font->height; ++write.item; } @@ -2017,9 +2013,7 @@ struct Buffer_Render_Params{ f32 height; Full_Cursor start_cursor; i32 wrapped; - f32 font_height; - f32 *cp_adv; - f32 byte_adv; + Render_Font *font; b32 virtual_white; i32 wrap_slashes; }; @@ -2092,8 +2086,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 S.write.item = params.items; S.write.x = S.shift_x + line_shift; S.write.y = S.shift_y; - S.write.adv = params.cp_adv; - S.write.font_height = params.font_height; + S.write.font = params.font; S.write.x_min = params.port_x; S.write.x_max = params.port_x + params.clip_w; @@ -2149,7 +2142,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 } S.write.x = S.shift_x + line_shift; - S.write.y += params.font_height; + S.write.y += params.font->height; } } } @@ -2175,7 +2168,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 ++S.wrap_line; S.write.x = S.shift_x + line_shift; - S.write.y += params.font_height; + S.write.y += params.font->height; S.first_of_the_line = true; } @@ -2198,7 +2191,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 case '\t': { - S.ch_width = params.cp_adv['\t']; + S.ch_width = get_codepoint_advance(params.font, '\t'); f32 new_x = S.write.x + S.ch_width; S.write = write_render_item(S.write, I, ' ', 0); S.write.x = new_x; @@ -2216,7 +2209,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 u32 I = S.tran.step_current.i; S.skipping_whitespace = false; - S.ch_width = params.byte_adv; + S.ch_width = params.font->byte_advance; f32 new_x = S.write.x + S.ch_width; u8 cs[3]; diff --git a/file/4coder_font_data.h b/file/4coder_font_data.h new file mode 100644 index 00000000..ab0afd5b --- /dev/null +++ b/file/4coder_font_data.h @@ -0,0 +1,137 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 03.03.2017 + * + * Font data type definitions. + * + */ + +// TOP + +#if !defined(FCODER_FONT_DATA_H) +#define FCODER_FONT_DATA_H + +#define FONT_PAGE_ITEMS 256 + +struct Glyph_Bounds{ + b32 exists; + + f32 x0, x1; + f32 y0, y1; + + f32 xoff, yoff; + f32 xoff2, yoff2; +}; + +struct Glyph_Page{ + Glyph_Bounds glyphs[256]; + u32 tex; + i32 tex_width, tex_height; + b32 exists; +}; + +struct Glyph_Data{ + Glyph_Bounds bounds; + u32 tex; + i32 tex_width, tex_height; +}; + +struct Advance_Page{ + f32 advance[256]; +}; + +struct Render_Font{ + char name_[24]; + String name; + b32 loaded; + + Glyph_Page glyph_pages[1]; + Advance_Page advance_pages[1]; + + f32 byte_advance; + i32 height, ascent, descent, line_skip; + i32 advance; +}; + +internal b32 +get_codepoint_can_render(Render_Font *font, u32 codepoint){ + b32 exists = false; + if (codepoint < FONT_PAGE_ITEMS){ + exists = true; + } + return(exists); +} + +internal u32 +get_codepoint_page_index(Render_Font *font, u32 codepoint, u32 *page_base_codepoint){ + *page_base_codepoint = 0; + return(0); +} + +internal void +get_codepoint_memory(Render_Font *font, u32 codepoint, Glyph_Bounds **bounds_mem_out, f32 **advance_mem_out){ + Glyph_Bounds *bounds = 0; + f32 *advance = 0; + + if (get_codepoint_can_render(font, codepoint)){ + u32 base_codepoint = 0; + u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); + Glyph_Page *bounds_page = &font->glyph_pages[page_index]; + Advance_Page *advance_page = &font->advance_pages[page_index]; + u32 glyph_index = codepoint - base_codepoint; + + bounds = &bounds_page->glyphs[glyph_index]; + advance = &advance_page->advance[glyph_index]; + } + + *bounds_mem_out = bounds; + *advance_mem_out = advance; +} + +internal b32 +get_codepoint_glyph_data(Render_Font *font, u32 codepoint, Glyph_Data *data_out){ + b32 success = false; + if (get_codepoint_can_render(font, codepoint)){ + u32 base_codepoint = 0; + u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); + Glyph_Page *page = &font->glyph_pages[page_index]; + data_out->bounds = page->glyphs[codepoint - base_codepoint]; + data_out->tex = page->tex; + data_out->tex_width = page->tex_width; + data_out->tex_height = page->tex_height; + success = true; + } + return(success); +} + +internal f32 +get_codepoint_advance(Render_Font *font, u32 codepoint){ + f32 advance = (f32)font->advance; + if (get_codepoint_can_render(font, codepoint)){ + u32 base_codepoint = 0; + u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); + Advance_Page *page = &font->advance_pages[page_index]; + advance = page->advance[codepoint - base_codepoint]; + } + return(advance); +} + +internal b32 +set_codepoint_advance(Render_Font *font, u32 codepoint, f32 value){ + b32 success = false; + if (get_codepoint_can_render(font, codepoint)){ + u32 base_codepoint = 0; + u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint); + Advance_Page *page = &font->advance_pages[page_index]; + page->advance[codepoint - base_codepoint] = value; + success = true; + } + return(success); +} + +#endif + +// BOTTOM + +