From 6b3d61c0357da834aa25fa2bf08ab8f6d5003790 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 24 Jul 2019 00:41:40 -0700 Subject: [PATCH] Font handling and rendering basically working. --- 4coder_API/4coder_types.h | 34 +- 4coder_api_transition_30_31_helpers.cpp | 22 - 4coder_base_commands.cpp | 4 +- 4coder_build_commands.cpp | 3 +- 4coder_config.cpp | 18 +- 4coder_default_framework.cpp | 4 +- 4coder_font_helper.cpp | 135 ++- 4coder_generated/app_functions.h | 6 +- 4coder_generated/command_metadata.h | 6 +- 4ed.cpp | 119 +-- 4ed_api_implementation.cpp | 200 +---- 4ed_app_models.h | 3 +- 4ed_app_target.cpp | 7 +- 4ed_buffer.cpp | 18 +- 4ed_code_wrap.cpp | 24 +- 4ed_edit.cpp | 21 +- 4ed_file.cpp | 23 +- 4ed_font.cpp | 230 ----- 4ed_font.h | 87 -- 4ed_font_face.cpp | 70 ++ 4ed_font_interface.h | 84 ++ 4ed_font_provider_freetype.cpp | 947 ++------------------ 4ed_font_provider_freetype.h | 101 --- 4ed_font_set.cpp | 167 ++++ 4ed_font_set.h | 43 + 4ed_render_format.cpp | 36 +- 4ed_render_target.h | 2 + 4ed_system.h | 6 +- 4ed_translation.cpp | 6 +- 4ed_view.cpp | 88 +- opengl/4ed_opengl_defines.h | 2 + opengl/4ed_opengl_render.cpp | 119 +-- platform_all/4ed_shared_init_logic.cpp | 14 +- platform_all/4ed_shared_library_constants.h | 14 +- platform_win32/win32_4ed.cpp | 27 +- platform_win32/win32_4ed_functions.cpp | 10 +- platform_win32/win32_utf8.cpp | 30 +- things_ive_broken.txt | 5 + 38 files changed, 801 insertions(+), 1934 deletions(-) delete mode 100644 4ed_font.cpp delete mode 100644 4ed_font.h create mode 100644 4ed_font_face.cpp create mode 100644 4ed_font_interface.h create mode 100644 4ed_font_set.cpp create mode 100644 4ed_font_set.h diff --git a/4coder_API/4coder_types.h b/4coder_API/4coder_types.h index 63d51183..5f408ed0 100644 --- a/4coder_API/4coder_types.h +++ b/4coder_API/4coder_types.h @@ -815,30 +815,22 @@ DOC_SEE(int_color) //int_color colors[Stag_COUNT]; //}; -/* -DOC(Available_Font contains a name for a font was detected at startup either in the local 4coder font folder, or by the system. An available font is not necessarily loaded yet, and may fail to load for various reasons even though it appearsin the available font list.) -DOC_SEE(get_available_font) -*/ -STRUCT Available_Font{ - char name[64]; - b32 in_local_font_folder; -}; - /* DOC(Every face is assigned a unique and consistent Face_ID for it's life time. This represents a slot in which a face can exist. The face in the slot is always valid once it exists, but the face might be changed or released durring it's lifetime. A Face_ID value of zero is reserved for the meaning "not a valid face".) */ TYPEDEF u32 Face_ID; -/* -DOC(Face_Description contains all the information unique to a single font face, including the font name, the size, and style of the face.) -DOC_SEE(get_available_font) -*/ -STRUCT Face_Description{ - /* DOC(Indicates a face's association with an available font. This should be an exact copy of an Available_Font returned by get_available_fonts.) DOC_SEE(get_available_font) */ - Available_Font font; - +// TODO(allen): redocument +STRUCT Font_Load_Location{ + String_Const_u8 file_name; + b32 in_4coder_font_folder; +}; + + +// TODO(allen): redocument +STRUCT Face_Load_Parameters{ /* DOC(Indicates the size for the face. Valid values must be greater than 0. Different fonts with the same pt_size do not necessarily have the same line height.) */ - i32 pt_size; + u32 pt_size; /* DOC(Indicates whether the face tries to use a bold style.) */ b32 bold; @@ -853,6 +845,12 @@ STRUCT Face_Description{ b32 hinting; }; +// TODO(allen): redocument +STRUCT Face_Description{ + Font_Load_Location font; + Face_Load_Parameters parameters; +}; + STRUCT Face_Metrics{ f32 line_height; f32 typical_character_width; diff --git a/4coder_api_transition_30_31_helpers.cpp b/4coder_api_transition_30_31_helpers.cpp index 305e993c..a4966c57 100644 --- a/4coder_api_transition_30_31_helpers.cpp +++ b/4coder_api_transition_30_31_helpers.cpp @@ -759,13 +759,6 @@ get_buffer_face_description(Application_Links *app, Buffer_Summary *buffer){ return(result); } -static void -set_buffer_face_by_name(Application_Links *app, Buffer_Summary *buffer, char *name, i32 len){ - if (buffer != 0){ - set_buffer_face_by_name(app, buffer->buffer_id, SCu8(name, len)); - } -} - static void execute_standard_build(Application_Links *app, View_Summary *view, Buffer_ID active_buffer){ standard_search_and_build(app, view==0?0:view->view_id, active_buffer); @@ -990,21 +983,6 @@ condense_whitespace(String *a){ } } -static Face_ID -get_existing_face_id_matching_name(Application_Links *app, char *name, i32 len){ - return(get_existing_face_id_matching_name(app, SCu8(name, len))); -} - -static Face_ID -get_face_id_by_name(Application_Links *app, char *name, i32 len, Face_Description *base_description){ - return(get_face_id_by_name(app, SCu8(name, len), base_description)); -} - -static void -set_global_face_by_name(Application_Links *app, char *name, i32 len, b32 apply_to_all_buffers){ - set_global_face_by_name(app, SCu8(name, len), apply_to_all_buffers); -} - static void insert_string__no_buffering(Buffer_Insertion *insertion, String string){ insert_string__no_buffering(insertion, string_new_u8_from_old(string)); diff --git a/4coder_base_commands.cpp b/4coder_base_commands.cpp index c6f4d447..5667eeb4 100644 --- a/4coder_base_commands.cpp +++ b/4coder_base_commands.cpp @@ -772,7 +772,7 @@ CUSTOM_DOC("Increase the size of the face used by the current buffer.") Buffer_ID buffer = view_get_buffer(app, view, AccessAll); Face_ID face_id = get_face_id(app, buffer); Face_Description description = get_face_description(app, face_id); - ++description.pt_size; + ++description.parameters.pt_size; try_modify_face(app, face_id, &description); } @@ -783,7 +783,7 @@ CUSTOM_DOC("Decrease the size of the face used by the current buffer.") Buffer_ID buffer = view_get_buffer(app, view, AccessAll); Face_ID face_id = get_face_id(app, buffer); Face_Description description = get_face_description(app, face_id); - --description.pt_size; + --description.parameters.pt_size; try_modify_face(app, face_id, &description); } diff --git a/4coder_build_commands.cpp b/4coder_build_commands.cpp index a02f47d3..50325fde 100644 --- a/4coder_build_commands.cpp +++ b/4coder_build_commands.cpp @@ -156,7 +156,8 @@ get_or_open_build_panel(Application_Links *app){ static void set_fancy_compilation_buffer_font(Application_Links *app){ Buffer_ID buffer = get_comp_buffer(app); - set_buffer_face_by_name(app, buffer, string_u8_litexpr("Inconsolata")); + Font_Load_Location font = { string_u8_litexpr("Inconsolata-Regular.ttf"), true, }; + set_buffer_face_by_font_load_location(app, buffer, &font); } CUSTOM_COMMAND_SIG(build_in_build_panel) diff --git a/4coder_config.cpp b/4coder_config.cpp index c3d41073..7b0332c6 100644 --- a/4coder_config.cpp +++ b/4coder_config.cpp @@ -1525,19 +1525,19 @@ load_config_and_apply(Application_Links *app, Arena *out_arena, Config_Data *con highlight_line_at_cursor = config->highlight_line_at_cursor; Face_Description description = {}; - umem len = config->default_font_name.size; - len = clamp_top(len, sizeof(description.font.name) - 1); - u8 *name_ptr = config->default_font_name.str; - memcpy(description.font.name, name_ptr, len); - description.font.name[len] = 0; + description.font.file_name = config->default_font_name; + description.font.in_4coder_font_folder = true; if (override_font_size != 0){ - description.pt_size = override_font_size; + description.parameters.pt_size = override_font_size; } else{ - description.pt_size = config->default_font_size; + description.parameters.pt_size = config->default_font_size; + } + description.parameters.hinting = config->default_font_hinting || override_hinting; + if (!modify_global_face_by_description(app, description)){ + description.font.in_4coder_font_folder = !description.font.in_4coder_font_folder; + modify_global_face_by_description(app, description); } - description.hinting = config->default_font_hinting || override_hinting; - change_global_face_by_description(app, description, true); } end_temp(temp); diff --git a/4coder_default_framework.cpp b/4coder_default_framework.cpp index 12fba46d..8573a890 100644 --- a/4coder_default_framework.cpp +++ b/4coder_default_framework.cpp @@ -410,13 +410,13 @@ default_4coder_initialize(Application_Links *app, i32 override_font_size, b32 ov static void default_4coder_initialize(Application_Links *app, char **command_line_files, i32 file_count){ Face_Description command_line_description = get_face_description(app, 0); - default_4coder_initialize(app, command_line_files, file_count, command_line_description.pt_size, command_line_description.hinting); + default_4coder_initialize(app, command_line_files, file_count, command_line_description.parameters.pt_size, command_line_description.parameters.hinting); } static void default_4coder_initialize(Application_Links *app){ Face_Description command_line_description = get_face_description(app, 0); - default_4coder_initialize(app, 0, 0, command_line_description.pt_size, command_line_description.hinting); + default_4coder_initialize(app, 0, 0, command_line_description.parameters.pt_size, command_line_description.parameters.hinting); } static void diff --git a/4coder_font_helper.cpp b/4coder_font_helper.cpp index c4cecf5b..16033078 100644 --- a/4coder_font_helper.cpp +++ b/4coder_font_helper.cpp @@ -4,8 +4,7 @@ // TOP -// TODO(allen): transition wrappers -static Face_Description +internal Face_Description get_buffer_face_description(Application_Links *app, Buffer_ID buffer){ Face_ID current_id = get_face_id(app, buffer); Face_Description description = {}; @@ -15,31 +14,42 @@ get_buffer_face_description(Application_Links *app, Buffer_ID buffer){ return(description); } -static Face_Description +internal Face_Description get_global_face_description(Application_Links *app){ - Face_ID current_id = get_face_id(app, 0); - Face_Description description = get_face_description(app, current_id); - return(description); + return(get_buffer_face_description(app, 0)); } -static b32 -descriptions_match(Face_Description *a, Face_Description *b){ +internal b32 +font_load_location_match(Font_Load_Location *a, Font_Load_Location *b){ b32 result = false; - if (string_match(SCchar(a->font.name), SCchar(b->font.name)) && a->font.in_local_font_folder == b->font.in_local_font_folder){ - if (memcmp((&a->pt_size), (&b->pt_size), sizeof(*a) - sizeof(a->font)) == 0){ - result = true; - } + if (string_match(a->file_name, b->file_name) && a->in_4coder_font_folder == b->in_4coder_font_folder){ + result = true; } return(result); } -static Face_ID -get_existing_face_id_matching_name(Application_Links *app, String_Const_u8 name){ +internal b32 +face_load_parameters_match(Face_Load_Parameters *a, Face_Load_Parameters *b){ + return(block_compare(a, b, sizeof(*a)) == 0); +} + +internal b32 +face_description_match(Face_Description *a, Face_Description *b){ + b32 result = false; + if (font_load_location_match(&a->font, &b->font) && + face_load_parameters_match(&a->parameters, &b->parameters)){ + result = true; + } + return(result); +} + +internal Face_ID +face_id_from_font_load_target(Application_Links *app, Font_Load_Location *font){ Face_ID largest_id = get_largest_face_id(app); Face_ID result = 0; for (Face_ID id = 1; id <= largest_id; ++id){ Face_Description compare = get_face_description(app, id); - if (string_match(SCu8(compare.font.name), name)){ + if (font_load_location_match(&compare.font, font)){ result = id; break; } @@ -47,13 +57,13 @@ get_existing_face_id_matching_name(Application_Links *app, String_Const_u8 name) return(result); } -static Face_ID -get_existing_face_id_matching_description(Application_Links *app, Face_Description *description){ +internal Face_ID +face_id_from_face_load_parameters(Application_Links *app, Face_Load_Parameters *parameters){ Face_ID largest_id = get_largest_face_id(app); Face_ID result = 0; for (Face_ID id = 1; id <= largest_id; ++id){ Face_Description compare = get_face_description(app, id); - if (descriptions_match(&compare, description)){ + if (face_load_parameters_match(&compare.parameters, parameters)){ result = id; break; } @@ -61,68 +71,49 @@ get_existing_face_id_matching_description(Application_Links *app, Face_Descripti return(result); } -static Face_ID -get_face_id_by_name(Application_Links *app, String_Const_u8 name, Face_Description *base_description){ - Face_ID new_id = 0; - name.size = clamp_top(name.size, sizeof(base_description->font.name) - 1); - if (!string_match(name, SCu8(base_description->font.name))){ - new_id = get_existing_face_id_matching_name(app, name); - if (new_id == 0){ - Face_Description description = *base_description; - block_copy(description.font.name, name.str, name.size); - description.font.name[name.size] = 0; - description.font.in_local_font_folder = false; - new_id = try_create_new_face(app, &description); - if (new_id == 0){ - description.font.in_local_font_folder = true; - new_id = try_create_new_face(app, &description); - } +internal Face_ID +face_id_from_description(Application_Links *app, Face_Description *description){ + Face_ID largest_id = get_largest_face_id(app); + Face_ID result = 0; + for (Face_ID id = 1; id <= largest_id; ++id){ + Face_Description compare = get_face_description(app, id); + if (face_description_match(&compare, description)){ + result = id; + break; } } - return(new_id); + return(result); } -static Face_ID -get_face_id_by_description(Application_Links *app, Face_Description *description, Face_Description *base_description){ - Face_ID new_id = 0; - if (!descriptions_match(description, base_description)){ - new_id = get_existing_face_id_matching_description(app, description); - if (new_id == 0){ - new_id = try_create_new_face(app, description); - } - } - return(new_id); -} - -static void -set_global_face_by_name(Application_Links *app, String_Const_u8 name, b32 apply_to_all_buffers){ - Face_ID global_face_id = get_face_id(app, 0); - Face_Description description = get_face_description(app, global_face_id); - Face_ID new_id = get_face_id_by_name(app, name, &description); - if (new_id != 0){ - set_global_face(app, new_id, apply_to_all_buffers); - } -} - -static void -change_global_face_by_description(Application_Links *app, Face_Description description, b32 apply_to_all_buffers){ +internal b32 +modify_global_face_by_description(Application_Links *app, Face_Description description){ Face_ID face_id = get_face_id(app, 0); - if (!try_modify_face(app, face_id, &description)){ - description.font.in_local_font_folder = !description.font.in_local_font_folder; - try_modify_face(app, face_id, &description); + return(try_modify_face(app, face_id, &description)); +} + +internal void +set_buffer_face_by_description(Application_Links *app, Buffer_ID buffer, Face_Description *description){ + Face_ID id = face_id_from_description(app, description); + if (id == 0){ + id = try_create_new_face(app, description); + } + if (id != 0){ + buffer_set_face(app, buffer, id); } } -static void -set_buffer_face_by_name(Application_Links *app, Buffer_ID buffer, String_Const_u8 name){ - Face_ID current_id = get_face_id(app, buffer); - if (current_id != 0){ - Face_Description description = get_face_description(app, current_id); - Face_ID new_id = get_face_id_by_name(app, name, &description); - if (new_id != 0){ - buffer_set_face(app, buffer, new_id); - } - } +internal void +set_buffer_face_by_font_load_location(Application_Links *app, Buffer_ID buffer, Font_Load_Location *font){ + Face_Description description = get_buffer_face_description(app, buffer); + description.font = *font; + set_buffer_face_by_description(app, buffer, &description); +} + +internal void +set_buffer_face_by_face_load_parameters(Application_Links *app, Buffer_ID buffer, Face_Load_Parameters *parameters){ + Face_Description description = get_buffer_face_description(app, buffer); + description.parameters = *parameters; + set_buffer_face_by_description(app, buffer, &description); } // BOTTOM diff --git a/4coder_generated/app_functions.h b/4coder_generated/app_functions.h index 2791bd76..a5bb2145 100644 --- a/4coder_generated/app_functions.h +++ b/4coder_generated/app_functions.h @@ -133,7 +133,7 @@ struct Application_Links; #define GLOBAL_HISTORY_EDIT_GROUP_BEGIN_SIG(n) void n(Application_Links *app) #define GLOBAL_HISTORY_EDIT_GROUP_END_SIG(n) void n(Application_Links *app) #define BUFFER_SET_FACE_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id, Face_ID id) -#define GET_FACE_DESCRIPTION_SIG(n) Face_Description n(Application_Links *app, Face_ID id) +#define GET_FACE_DESCRIPTION_SIG(n) Face_Description n(Application_Links *app, Face_ID face_id) #define GET_FACE_METRICS_SIG(n) Face_Metrics n(Application_Links *app, Face_ID face_id) #define GET_FACE_ID_SIG(n) Face_ID n(Application_Links *app, Buffer_ID buffer_id) #define TRY_CREATE_NEW_FACE_SIG(n) Face_ID n(Application_Links *app, Face_Description *description) @@ -1041,7 +1041,7 @@ static b32 buffer_history_clear_after_current_state(Application_Links *app, Buff static void global_history_edit_group_begin(Application_Links *app){(app->global_history_edit_group_begin(app));} static void global_history_edit_group_end(Application_Links *app){(app->global_history_edit_group_end(app));} static b32 buffer_set_face(Application_Links *app, Buffer_ID buffer_id, Face_ID id){return(app->buffer_set_face(app, buffer_id, id));} -static Face_Description get_face_description(Application_Links *app, Face_ID id){return(app->get_face_description(app, id));} +static Face_Description get_face_description(Application_Links *app, Face_ID face_id){return(app->get_face_description(app, face_id));} static Face_Metrics get_face_metrics(Application_Links *app, Face_ID face_id){return(app->get_face_metrics(app, face_id));} static Face_ID get_face_id(Application_Links *app, Buffer_ID buffer_id){return(app->get_face_id(app, buffer_id));} static Face_ID try_create_new_face(Application_Links *app, Face_Description *description){return(app->try_create_new_face(app, description));} @@ -1221,7 +1221,7 @@ static b32 buffer_history_clear_after_current_state(Application_Links *app, Buff static void global_history_edit_group_begin(Application_Links *app){(app->global_history_edit_group_begin_(app));} static void global_history_edit_group_end(Application_Links *app){(app->global_history_edit_group_end_(app));} static b32 buffer_set_face(Application_Links *app, Buffer_ID buffer_id, Face_ID id){return(app->buffer_set_face_(app, buffer_id, id));} -static Face_Description get_face_description(Application_Links *app, Face_ID id){return(app->get_face_description_(app, id));} +static Face_Description get_face_description(Application_Links *app, Face_ID face_id){return(app->get_face_description_(app, face_id));} static Face_Metrics get_face_metrics(Application_Links *app, Face_ID face_id){return(app->get_face_metrics_(app, face_id));} static Face_ID get_face_id(Application_Links *app, Buffer_ID buffer_id){return(app->get_face_id_(app, buffer_id));} static Face_ID try_create_new_face(Application_Links *app, Face_Description *description){return(app->try_create_new_face_(app, description));} diff --git a/4coder_generated/command_metadata.h b/4coder_generated/command_metadata.h index d68660da..fd055278 100644 --- a/4coder_generated/command_metadata.h +++ b/4coder_generated/command_metadata.h @@ -445,9 +445,9 @@ static Command_Metadata fcoder_metacmd_table[237] = { { PROC_LINKS(execute_previous_cli, 0), "execute_previous_cli", 20, "If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.", 126, "w:\\4ed\\code\\4coder_system_command.cpp", 37, 7 }, { PROC_LINKS(execute_any_cli, 0), "execute_any_cli", 15, "Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer.", 133, "w:\\4ed\\code\\4coder_system_command.cpp", 37, 22 }, { PROC_LINKS(build_search, 0), "build_search", 12, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*.", 153, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 128 }, -{ PROC_LINKS(build_in_build_panel, 0), "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 162 }, -{ PROC_LINKS(close_build_panel, 0), "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 177 }, -{ PROC_LINKS(change_to_build_panel, 0), "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 183 }, +{ PROC_LINKS(build_in_build_panel, 0), "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 163 }, +{ PROC_LINKS(close_build_panel, 0), "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 178 }, +{ PROC_LINKS(change_to_build_panel, 0), "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "w:\\4ed\\code\\4coder_build_commands.cpp", 37, 184 }, { PROC_LINKS(close_all_code, 0), "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 928 }, { PROC_LINKS(open_all_code, 0), "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 934 }, { PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\4coder_project_commands.cpp", 39, 940 }, diff --git a/4ed.cpp b/4ed.cpp index 5e45e60f..4727326e 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -71,7 +71,7 @@ file_cursor_to_end(System_Functions *system, Models *models, Editing_File *file) if (view->file != file){ continue; } - Full_Cursor cursor = file_compute_cursor(system, file, seek_pos(pos)); + Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(pos)); view_set_cursor(system, models, view, cursor, true); view->mark = cursor.pos; } @@ -702,47 +702,19 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, //////////////////////////////// -internal void* -base_reserve__system(void *user_data, umem size, umem *size_out){ - System_Functions *system = (System_Functions*)user_data; - umem extra_size = 128; - umem increased_size = size + extra_size; - size = round_up_umem(increased_size, KB(4)); - *size_out = size - extra_size; - void *ptr = system->memory_allocate(size); - *(umem*)ptr = size; - ptr = (u8*)ptr + extra_size; - return(ptr); -} - -internal void -base_free__system(void *user_data, void *ptr){ - System_Functions *system = (System_Functions*)user_data; - umem extra_size = 128; - ptr = (u8*)ptr - extra_size; - umem size = *(umem*)ptr; - system->memory_free(ptr, size); -} - -internal Base_Allocator -make_base_allocator_system(System_Functions *system){ - return(make_base_allocator(base_reserve__system, 0, 0, - base_free__system, 0, system)); -} - internal Arena make_arena_models(Models *models, umem chunk_size, umem align){ - return(make_arena(&models->allocator, chunk_size, align)); + return(make_arena(models->base_allocator, chunk_size, align)); } internal Arena make_arena_models(Models *models, umem chunk_size){ - return(make_arena(&models->allocator, chunk_size, 8)); + return(make_arena(models->base_allocator, chunk_size, 8)); } internal Arena make_arena_models(Models *models){ - return(make_arena(&models->allocator, KB(16), 8)); + return(make_arena(models->base_allocator, KB(16), 8)); } //////////////////////////////// @@ -751,8 +723,8 @@ internal App_Vars* app_setup_memory(System_Functions *system, Application_Memory *memory){ Cursor cursor = make_cursor(memory->vars_memory, memory->vars_memory_size); App_Vars *vars = push_array_zero(&cursor, App_Vars, 1); - vars->models.allocator = make_base_allocator_system(system); - vars->models.mem.arena = make_arena(&vars->models.allocator); + vars->models.mem.arena = make_arena_system(system); + vars->models.base_allocator = vars->models.mem.arena.base_allocator; heap_init(&vars->models.mem.heap); heap_extend(&vars->models.mem.heap, memory->target_memory, memory->target_memory_size); return(vars); @@ -862,6 +834,9 @@ App_Init_Sig(app_init){ Arena *arena = &models->mem.arena; + // NOTE(allen): font set + font_set_init(system, &models->font_set); + // NOTE(allen): live set { models->live_set.count = 0; @@ -923,7 +898,13 @@ App_Init_Sig(app_init){ } // NOTE(allen): style setup - models->global_font_id = 1; + { + Face_Description description = {}; + description.font.file_name = string_u8_litexpr("liberation-mono.ttf"); + description.font.in_4coder_font_folder = true; + description.parameters.pt_size = 12; + models->global_font_id = font_set_new_face(&models->font_set, &description); + } app_hardcode_default_style(models); // NOTE(allen): title space @@ -986,7 +967,7 @@ App_Step_Sig(app_step){ models->animate_next_frame = false; // NOTE(allen): per-frame update of models state - begin_frame(target); + begin_frame(target, &models->font_set); models->target = target; models->input = input; @@ -1190,30 +1171,6 @@ App_Step_Sig(app_step){ models->hook_start(&models->app_links, files, files_count, flags, flags_count); } - -#if 0 - // Open command line files. - char space[512]; - String cl_file_name = make_fixed_width_string(space); - copy_ss(&cl_file_name, models->hot_directory.string); - i32 cl_file_name_len = cl_file_name.size; - for (i32 i = 0; i < models->settings.init_files_count; ++i){ - cl_file_name.size = cl_file_name_len; - - String file_name = {}; - Editing_File_Name canon_name = {}; - if (get_canon_name(system, make_string_slowly(models->settings.init_files[i]), &canon_name)){ - file_name = canon_name.name; - } - else{ - append_sc(&cl_file_name, models->settings.init_files[i]); - file_name = cl_file_name; - } - - Buffer_ID id = 0; - create_buffer(&models->app_links, file_name, 0, &id); - } -#endif } // NOTE(allen): consume event stream @@ -1507,48 +1464,6 @@ App_Step_Sig(app_step){ models->render_caller(&models->app_links, frame); } -#if 0 - Panel *active_panel = layout_get_active_panel(layout); - View *active_view = active_panel->view; - - // NOTE(allen): render the panels - for (Panel *panel = layout_get_first_open_panel(layout); - panel != 0; - panel = layout_get_next_open_panel(layout, panel)){ - i32_Rect full = panel->rect_full; - i32_Rect inner = panel->rect_inner; - - View *view = panel->view; - //Style *style = &models->styles.styles[0]; - Color_Table color_table = models->color_table; - - draw_rectangle(target, full, color_table.vals[Stag_Back]); - - File_Edit_Positions edit_pos = view_get_edit_pos(view); - GUI_Scroll_Vars *scroll_vars = &edit_pos.scroll; - - b32 active = (panel == active_panel); - do_render_file_view(system, view, models, scroll_vars, active_view, inner, active, target); - - view_set_edit_pos(view, edit_pos); - - u32 margin_color = 0; - if (active){ - margin_color = color_table.vals[Stag_Margin_Active]; - } - else if (panel == mouse_panel){ - margin_color = color_table.vals[Stag_Margin_Hover]; - } - else{ - margin_color = color_table.vals[Stag_Margin]; - } - draw_rectangle(target, i32R( full.x0, full.y0, full.x1, inner.y0), margin_color); - draw_rectangle(target, i32R( full.x0, inner.y1, full.x1, full.y1), margin_color); - draw_rectangle(target, i32R( full.x0, inner.y0, inner.x0, inner.y1), margin_color); - draw_rectangle(target, i32R(inner.x1, inner.y0, full.x1, inner.y1), margin_color); - } -#endif - models->in_render_mode = false; end_render_section(target, system); } diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index e679e88d..f9c4a3c8 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -98,7 +98,7 @@ Context_Get_Arena(Application_Links *app){ API_EXPORT Base_Allocator* Context_Get_Base_Allocator(Application_Links *app){ Models *models = (Models*)app->cmd_context; - return(&models->allocator); + return(models->base_allocator); } API_EXPORT b32 @@ -775,10 +775,7 @@ DOC_SEE(Buffer_Setting_ID) new_value = 48; } if (new_value != file->settings.display_width){ -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id); -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); file->settings.display_width = new_value; file_measure_wraps(system, &models->mem, file, face); adjust_views_looking_at_file_to_new_cursor(system, models, file); @@ -792,10 +789,7 @@ DOC_SEE(Buffer_Setting_ID) new_value = 0; } if (new_value != file->settings.minimum_base_display_width){ -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id); -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); file->settings.minimum_base_display_width = new_value; file_measure_wraps(system, &models->mem, file, face); adjust_views_looking_at_file_to_new_cursor(system, models, file); @@ -873,11 +867,7 @@ DOC_SEE(Buffer_Setting_ID) } if (full_remeasure){ -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id); -#endif - Face *face = 0; - + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); file_allocate_character_starts_as_needed(&models->mem.heap, file); buffer_measure_character_starts(system, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white); file_measure_wraps(system, &models->mem, file, face); @@ -1132,7 +1122,7 @@ Buffer_Reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reopen_Flag fl if (view_it->file == file){ vptrs[vptr_count] = view_it; File_Edit_Positions edit_pos = view_get_edit_pos(view_it); - Full_Cursor cursor = file_compute_cursor(system, view_it->file, seek_pos(edit_pos.cursor_pos)); + Full_Cursor cursor = file_compute_cursor(models, view_it->file, seek_pos(edit_pos.cursor_pos)); line_numbers[vptr_count] = (i32)cursor.line; column_numbers[vptr_count] = (i32)cursor.character; view_it->file = models->scratch_buffer; @@ -1149,7 +1139,7 @@ Buffer_Reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reopen_Flag fl view_set_file(system, models, vptrs[i], file); vptrs[i]->file = file; - Full_Cursor cursor = file_compute_cursor(system, file, seek_line_char(line_numbers[i], column_numbers[i])); + Full_Cursor cursor = file_compute_cursor(models, file, seek_line_char(line_numbers[i], column_numbers[i])); view_set_cursor(system, models, vptrs[i], cursor, true); } @@ -1778,7 +1768,7 @@ DOC_SEE(Full_Cursor) if (file->settings.unwrapped_lines && seek.type == buffer_seek_wrapped_xy){ seek.type = buffer_seek_unwrapped_xy; } - result = file_compute_cursor(models->system, file, seek); + result = file_compute_cursor(models, file, seek); if (file->settings.unwrapped_lines){ result.wrapped_x = result.unwrapped_x; result.wrapped_y = result.unwrapped_y; @@ -1809,7 +1799,7 @@ DOC_SEE(Buffer_Seek) if (file->settings.unwrapped_lines && seek.type == buffer_seek_wrapped_xy){ seek.type = buffer_seek_unwrapped_xy; } - Full_Cursor cursor = file_compute_cursor(models->system, file, seek); + Full_Cursor cursor = file_compute_cursor(models, file, seek); view_set_cursor(models->system, models, view, cursor, set_preferred_x); result = true; } @@ -1864,7 +1854,7 @@ DOC_SEE(Buffer_Seek) Assert(file != 0); if (api_check_buffer(file)){ if (seek.type != buffer_seek_pos){ - Full_Cursor cursor = file_compute_cursor(models->system, file, seek); + Full_Cursor cursor = file_compute_cursor(models, file, seek); view->mark = cursor.pos; } else{ @@ -2937,12 +2927,7 @@ DOC_RETURN(Returns the largest face ID that could be valid. There is no guarant */ { Models *models = (Models*)app->cmd_context; - Face_ID result = 0; -#if 0 - Face_ID result = models->system->font.get_largest_id(); -#endif - NotImplemented; - return(result); + return(font_set_get_largest_id(&models->font_set)); } API_EXPORT b32 @@ -2958,21 +2943,16 @@ DOC_RETURN(Returns true if the given id was a valid face and the change was made System_Functions *system = models->system; b32 did_change = false; - - NotImplemented; -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(id); - if (font.valid){ - did_change = true; - + Face *face = font_set_face_from_id(&models->font_set, id); + if (face != 0){ if (apply_to_all_buffers){ global_set_font_and_update_files(system, models, id); } else{ models->global_font_id = id; } + did_change = true; } -#endif return(did_change); } @@ -3147,67 +3127,6 @@ Global_History_Edit_Group_End(Application_Links *app){ global_history_adjust_edit_grouping_counter(&models->global_history, -1); } -internal void -face_to_face_description(Face *face, Face_Description *description){ - umem size = clamp_top(face->name.size, sizeof(description->font.name) - 1); - block_copy(description->font.name, face->name.str, size); - description->font.name[size] = 0; - description->font.in_local_font_folder = face->settings.stub.in_font_folder; - - description->pt_size = face->settings.parameters.pt_size; - description->bold = face->settings.parameters.bold; - description->italic = face->settings.parameters.italics; - description->underline = face->settings.parameters.underline; - description->hinting = face->settings.parameters.use_hinting; -} - -internal b32 -face_description_to_settings(System_Functions *system, Face_Description description, Face_Settings *settings){ - b32 success = false; - - String_Const_u8 desc_name = SCu8(description.font.name); - if (description.font.in_local_font_folder){ -#if 0 - i32 count = system->font.get_loadable_count(); - for (i32 i = 0; i < count; ++i){ - Font_Loadable_Description loadable = {}; - system->font.get_loadable(i, &loadable); - - if (loadable.valid){ - if (!loadable.stub.in_font_folder){ - break; - } - - String_Const_u8 loadable_name = SCu8(loadable.display_name, loadable.display_len); - if (string_match(loadable_name, desc_name)){ - success = true; - block_copy_struct(&settings->stub, &loadable.stub); - break; - } - } - } -#endif - } - else{ - success = true; - - settings->stub.load_from_path = false; - settings->stub.in_font_folder = false; - settings->stub.len = (i32)cstring_length(description.font.name); - memcpy(settings->stub.name, description.font.name, settings->stub.len + 1); - } - - if (success){ - settings->parameters.pt_size = description.pt_size; - settings->parameters.italics = description.italic; - settings->parameters.bold = description.bold; - settings->parameters.underline = description.underline; - settings->parameters.use_hinting = description.hinting; - } - - return(success); -} - API_EXPORT b32 Buffer_Set_Face(Application_Links *app, Buffer_ID buffer_id, Face_ID id) /* @@ -3222,25 +3141,16 @@ DOC_RETURN(Returns true if the given id was a valid face and the change was made b32 did_change = false; if (api_check_buffer(file)){ - System_Functions *system = models->system; -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(id); - if (font.valid){ + if (font_set_face_from_id(&models->font_set, id) != 0){ did_change = true; - file_set_font(system, models, file, id); - } -#endif - Face *face = 0; - if (face != 0){ - did_change = true; - file_set_font(system, models, file, id); + file_set_font(models->system, models, file, id); } } return(did_change); } API_EXPORT Face_Description -Get_Face_Description(Application_Links *app, Face_ID id) +Get_Face_Description(Application_Links *app, Face_ID face_id) /* DOC_PARAM(id, The face slot from which to read a description. If zero gets default values.) DOC(Fills out the values of a Face_Description struct, which includes all the information that determines the appearance of the face. If the id does not specify a valid face the description will be invalid. An invalid description has a zero length string in it's font.name field (i.e. description.font.name[0] == 0), and a valid description always contains a non-zero length string in the font.name field (i.e. description.font.name[0] != 0) @@ -3253,25 +3163,16 @@ DOC_SEE(Face_Description) */ { Models *models = (Models*)app->cmd_context; - System_Functions *system = models->system; Face_Description description = {}; - if (id != 0){ -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(id); - if (font.valid){ - font_pointers_to_face_description(font, &description); - Assert(description.font.name[0] != 0); - } -#endif - Face *face = 0; + if (face_id != 0){ + Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - face_to_face_description(face, &description); - Assert(description.font.name[0] != 0); + description = face->description; } } else{ - description.pt_size = models->settings.font_size; - description.hinting = models->settings.use_hinting; + description.parameters.pt_size = models->settings.font_size; + description.parameters.hinting = models->settings.use_hinting; } return(description); } @@ -3282,17 +3183,10 @@ Get_Face_Metrics(Application_Links *app, Face_ID face_id){ System_Functions *system = models->system; Face_Metrics result = {}; if (face_id != 0){ -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(face_id); - if (font.valid){ - result.line_height = (f32)font.metrics->height; - result.typical_character_width = font.metrics->sub_advances[1]; - } -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ result.line_height = (f32)face->height; - result.typical_character_width = face->sub_advances[1]; + result.typical_character_width = face->byte_sub_advances[1]; } } return(result); @@ -3339,16 +3233,7 @@ DOC_SEE(Face_Description) */ { Models *models = (Models*)app->cmd_context; - System_Functions *system = models->system; - Face_ID id = 0; - Face_Settings settings = {}; - if (face_description_to_settings(system, *description, &settings)){ -#if 0 - id = system->font.face_allocate_and_init(&settings); -#endif - NotImplemented; - } - return(id); + return(font_set_new_face(&models->font_set, description)); } API_EXPORT b32 @@ -3366,15 +3251,7 @@ DOC_SEE(try_create_new_face) */ { Models *models = (Models*)app->cmd_context; - System_Functions *system = models->system; - b32 success = false; - Face_Settings settings = {}; - if (face_description_to_settings(system, *description, &settings)){ - if (alter_font_and_update_files(system, models, id, &settings)){ - success = true; - } - } - return(success); + return(alter_font_and_update_files(models->system, models, id, description)); } API_EXPORT b32 @@ -3586,11 +3463,7 @@ DOC_RETURN(This call returns non-zero on success.) */{ Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; - // TODO(allen): rewrite this with a better OS layer API - i32 required_size = system->get_4ed_path(0, 0); - char *memory = push_array(arena, char, required_size + 1); - required_size = system->get_4ed_path(memory, required_size); - return(SCu8(memory, required_size)); + return(system->get_4ed_path(arena)); } // TODO(allen): do(add a "shown but auto-hides on timer" setting for cursor show type) @@ -3749,14 +3622,14 @@ Draw_String(Application_Links *app, Face_ID font_id, String_Const_u8 str, Vec2 p Vec2 result = point; Models *models = (Models*)app->cmd_context; if (models->target == 0){ - f32 width = font_string_width(models->system, models->target, font_id, str); + f32 width = font_string_width(models->target, font_id, str); result += delta*width; } else{ Color_Table color_table = models->color_table; point = draw_helper__models_space_to_screen_space(models, point); u32 actual_color = finalize_color(color_table, color); - f32 width = draw_string(models->system, models->target, font_id, str, point, actual_color, flags, delta); + f32 width = draw_string(models->target, font_id, str, point, actual_color, flags, delta); result += delta*width; } return(result); @@ -3766,7 +3639,7 @@ API_EXPORT f32 Get_String_Advance(Application_Links *app, Face_ID font_id, String_Const_u8 str) { Models *models = (Models*)app->cmd_context; - return(font_string_width(models->system, models->target, font_id, str)); + return(font_string_width(models->target, font_id, str)); } API_EXPORT void @@ -3849,7 +3722,7 @@ Text_Layout_Buffer_Point_To_Layout_Point(Application_Links *app, Text_Layout_ID if (api_check_buffer(file)){ System_Functions *system = models->system; // TODO(allen): this could be computed and stored _once_ right? - Full_Cursor top = file_compute_cursor(system, file, seek_line_char(layout.point.line_number, 1)); + Full_Cursor top = file_compute_cursor(models, file, seek_line_char(layout.point.line_number, 1)); f32 top_y = top.wrapped_y; if (file->settings.unwrapped_lines){ top_y = top.unwrapped_y; @@ -3873,7 +3746,7 @@ Text_Layout_Layout_Point_To_Buffer_Point(Application_Links *app, Text_Layout_ID if (api_check_buffer(file)){ System_Functions *system = models->system; // TODO(allen): this could be computed and stored _once_ right? - Full_Cursor top = file_compute_cursor(system, file, seek_line_char(layout.point.line_number, 1)); + Full_Cursor top = file_compute_cursor(models, file, seek_line_char(layout.point.line_number, 1)); f32 top_y = top.wrapped_y; if (file->settings.unwrapped_lines){ top_y = top.unwrapped_y; @@ -3943,19 +3816,16 @@ Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_ b32 wrapped = !file->settings.unwrapped_lines; Face_ID font_id = file->settings.font_id; -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(font_id); -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, font_id); - Full_Cursor intermediate_cursor = file_compute_cursor(system, file, seek_line_char(buffer_point.line_number, 1)); + Full_Cursor intermediate_cursor = file_compute_cursor(models, file, seek_line_char(buffer_point.line_number, 1)); f32 scroll_x = buffer_point.pixel_shift.x; f32 scroll_y = intermediate_cursor.wrapped_y; if (file->settings.unwrapped_lines){ scroll_y = intermediate_cursor.unwrapped_y; } scroll_y += buffer_point.pixel_shift.y; - Full_Cursor render_cursor = file_get_render_cursor(system, file, scroll_y); + Full_Cursor render_cursor = file_get_render_cursor(models, file, scroll_y); i32 item_count = 0; i32 end_pos = 0; @@ -4119,7 +3989,7 @@ Get_View_Visible_Range(Application_Links *app, View_ID view_id){ if (api_check_view(view)){ i32 view_height = rect_height(view->panel->rect_inner); i32 line_height = view->line_height; - Full_Cursor min_cursor = view_get_render_cursor(models->system, view); + Full_Cursor min_cursor = view_get_render_cursor(models, view); Buffer_Seek seek = seek_unwrapped_xy(0.f, min_cursor.wrapped_y + view_height + line_height, false); Full_Cursor max_cursor = view_compute_cursor(app, view_id, seek); result = Ii32((i32)min_cursor.pos, (i32)max_cursor.pos); diff --git a/4ed_app_models.h b/4ed_app_models.h index 42bb88ef..ca76b185 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -28,7 +28,7 @@ struct App_Settings{ }; struct Models{ - Base_Allocator allocator; + Base_Allocator *base_allocator; Mem_Options mem; App_Settings settings; @@ -72,6 +72,7 @@ struct Models{ Parse_Context_Memory parse_context_memory; Global_History global_history; Text_Layout_Container text_layouts; + Font_Set font_set; Dynamic_Variable_Layout variable_layout; Dynamic_Workspace dynamic_workspace; diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index c99165de..bbf26c2d 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -18,13 +18,14 @@ #include "4coder_base_types.h" #include "4coder_table.h" -#include "4ed_font.h" +#include "4ed_font_interface.h" #include "4ed_system.h" #include "4coder_base_types.cpp" #include "4coder_string_match.cpp" #include "4coder_stringf.cpp" #include "4coder_app_links_allocator.cpp" +#include "4ed_system_allocator.cpp" #include "4coder_hash_functions.cpp" #include "4coder_table.cpp" @@ -68,6 +69,7 @@ struct Mem_Options{ #include "4ed_view.h" #include "4ed_edit.h" #include "4ed_text_layout.h" +#include "4ed_font_set.h" #include "4ed_app_models.h" #include "4ed_mem.cpp" @@ -75,7 +77,8 @@ struct Mem_Options{ #include "4ed_memory_bank.cpp" #include "4ed_dynamic_variables.cpp" #include "4ed_parse_context.cpp" -#include "4ed_font.cpp" +#include "4ed_font_face.cpp" +#include "4ed_font_set.cpp" #include "4ed_translation.cpp" #include "4ed_render_target.cpp" #include "4ed_render_format.cpp" diff --git a/4ed_buffer.cpp b/4ed_buffer.cpp index 192e4cde..766826a1 100644 --- a/4ed_buffer.cpp +++ b/4ed_buffer.cpp @@ -705,7 +705,7 @@ buffer_measure_character_starts(System_Functions *system, Gap_Buffer *buffer, i3 for (; i < stream.end; ++i){ u8 ch = (u8)stream.data[i]; - translating_fully_process_byte(system, &tran, ch, i, size, &emits); + translating_fully_process_byte(&tran, ch, i, size, &emits); for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ TRANSLATION_DECL_GET_STEP(step, behavior, J, emits); @@ -781,7 +781,7 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para S.skipping_whitespace = false; } - translating_fully_process_byte(params.system, &S.tran, ch, S.i, S.size, &S.emits); + translating_fully_process_byte(&S.tran, ch, S.i, S.size, &S.emits); } for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){ @@ -809,7 +809,7 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){ if (!S.skipping_whitespace){ if (S.behavior.do_codepoint_advance){ - S.current_adv = font_get_glyph_advance(params.system, params.face, S.step.value); + S.current_adv = font_get_glyph_advance(params.face, S.step.value); } else{ S.current_adv = params.face->byte_advance; @@ -990,7 +990,7 @@ buffer_remeasure_character_starts(System_Functions *system, Gap_Buffer *buffer, do{ for (; char_i < stream.end; ++char_i){ u8 ch = (u8)stream.data[char_i]; - translating_fully_process_byte(system, &tran, ch, char_i, size, &emits); + translating_fully_process_byte(&tran, ch, char_i, size, &emits); for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ TRANSLATION_DECL_GET_STEP(step, behavior, J, emits); @@ -1417,7 +1417,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa for (; S.i < S.stream.end; ++S.i){ { u8 ch = (u8)S.stream.data[S.i]; - translating_fully_process_byte(params.system, &S.tran, ch, S.i, S.size, &S.emits); + translating_fully_process_byte(&S.tran, ch, S.i, S.size, &S.emits); } for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){ @@ -1448,7 +1448,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){ if (S.behavior.do_codepoint_advance){ - S.ch_width = font_get_glyph_advance(params.system, params.face, S.step.value); + S.ch_width = font_get_glyph_advance(params.face, S.step.value); } else{ S.ch_width = params.face->byte_advance; @@ -1628,7 +1628,7 @@ internal Render_Item_Write write_render_item(Render_Item_Write write, i32 index, u32 codepoint, u32 flags, Render_Item_Flag render_flags){ if (write.item < write.item_end){ - f32 ch_width = font_get_glyph_advance(write.system, write.face, codepoint); + f32 ch_width = font_get_glyph_advance(write.face, codepoint); b32 visible_on_layout = (write.x_min <= write.x + ch_width && write.x <= write.x_max); @@ -1714,7 +1714,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 for (; S.i < S.stream.end; ++S.i){ { u8 ch = (u8)S.stream.data[S.i]; - translating_fully_process_byte(params.system, &S.tran, ch, S.i, S.size, &S.emits); + translating_fully_process_byte(&S.tran, ch, S.i, S.size, &S.emits); } for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){ @@ -1814,7 +1814,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 case '\t': { - S.ch_width = font_get_glyph_advance(params.system, params.face, '\t'); + S.ch_width = font_get_glyph_advance(params.face, '\t'); f32 new_x = S.write.x + S.ch_width; S.write = write_render_item(S.write, I, ' ', 0, flags); diff --git a/4ed_code_wrap.cpp b/4ed_code_wrap.cpp index 885b573a..f8eb6574 100644 --- a/4ed_code_wrap.cpp +++ b/4ed_code_wrap.cpp @@ -10,7 +10,7 @@ // TOP internal void -wrap_state_init(System_Functions *system, Code_Wrap_State *state, Editing_File *file, Face *face){ +wrap_state_init(Code_Wrap_State *state, Editing_File *file, Face *face){ state->token_array = file->state.token_array; state->token_ptr = state->token_array.tokens; state->end_token = state->token_ptr + state->token_array.count; @@ -27,7 +27,7 @@ wrap_state_init(System_Functions *system, Code_Wrap_State *state, Editing_File * state->face = face; - state->tab_indent_amount = font_get_glyph_advance(system, face, '\t'); + state->tab_indent_amount = font_get_glyph_advance(face, '\t'); state->byte_advance = face->byte_advance; state->tran = null_buffer_translating_state; @@ -123,7 +123,7 @@ wrap_state_consume_token(System_Functions *system, Face *face, Code_Wrap_State * } u8 ch = (u8)state->stream.data[i]; - translating_fully_process_byte(system, &state->tran, ch, i, state->size, &state->emits); + translating_fully_process_byte(&state->tran, ch, i, state->size, &state->emits); for (TRANSLATION_EMIT_LOOP(state->J, state->emits)){ TRANSLATION_GET_STEP(state->step, state->behavior, state->J, state->emits); @@ -136,7 +136,7 @@ wrap_state_consume_token(System_Functions *system, Face *face, Code_Wrap_State * u32 n = state->step.value; f32 adv = 0; if (state->behavior.do_codepoint_advance){ - adv = font_get_glyph_advance(system, state->face, n); + adv = font_get_glyph_advance(state->face, n); if (n != ' ' && n != '\t'){ skipping_whitespace = false; @@ -484,7 +484,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil i32 max_wrap_indent_mark = Million(1); if (params.virtual_white && file->state.tokens_complete && !file->state.still_lexing){ - wrap_state_init(system, &wrap_state, file, face); + wrap_state_init(&wrap_state, file, face); use_tokens = true; potential_marks = push_array(scratch, Potential_Wrap_Indent_Pair, floor32(width)); @@ -531,7 +531,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil for (; i < stream.end; ++i){ { u8 ch = stream.data[i]; - translating_fully_process_byte(system, &tran, ch, i, size, &emits); + translating_fully_process_byte(&tran, ch, i, size, &emits); } for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ @@ -545,7 +545,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil word_stage = 1; } else{ - f32 adv = font_get_glyph_advance(params.system, params.face, codepoint); + f32 adv = font_get_glyph_advance(params.face, codepoint); x += adv; self_x += adv; @@ -659,7 +659,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil for (; i < stream.end; ++i){ { u8 ch = stream.data[i]; - translating_fully_process_byte(system, &tran, ch, i, end_i, &emits); + translating_fully_process_byte(&tran, ch, i, end_i, &emits); } for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ @@ -680,7 +680,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil for (; i < stream.end; ++i){ { u8 ch = stream.data[i]; - translating_fully_process_byte(system, &tran, ch, i, end_i, &emits); + translating_fully_process_byte(&tran, ch, i, end_i, &emits); } for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ @@ -690,7 +690,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil goto doublebreak_stage1; } - f32 adv = font_get_glyph_advance(params.system, params.face, buffer_step.value); + f32 adv = font_get_glyph_advance(params.face, buffer_step.value); x += adv; if (!first_word && x > current_width){ @@ -715,7 +715,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil for (; i < stream.end; ++i){ { u8 ch = stream.data[i]; - translating_fully_process_byte(system, &tran, ch, i, end_i, &emits); + translating_fully_process_byte(&tran, ch, i, end_i, &emits); } for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ @@ -726,7 +726,7 @@ file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *fil goto doublebreak_stage2; } - f32 adv = font_get_glyph_advance(params.system, params.face, buffer_step.value); + f32 adv = font_get_glyph_advance(params.face, buffer_step.value); x += adv; } } diff --git a/4ed_edit.cpp b/4ed_edit.cpp index 4784408a..0ef8b3de 100644 --- a/4ed_edit.cpp +++ b/4ed_edit.cpp @@ -10,7 +10,8 @@ // TOP internal void -edit_pre_state_change(System_Functions *system, Heap *heap, Models *models, Editing_File *file){ +edit_pre_state_change(Models *models, Heap *heap, Editing_File *file){ + System_Functions *system = models->system; if (file->state.still_lexing){ system->cancel_job(BACKGROUND_THREADS, file->state.lex_job); if (file->state.swap_array.tokens){ @@ -27,8 +28,8 @@ edit_pre_state_change(System_Functions *system, Heap *heap, Models *models, Edit panel = layout_get_next_open_panel(layout, panel)){ View *view = panel->view; if (view->file == file){ - Full_Cursor render_cursor = view_get_render_cursor(system, view); - Full_Cursor target_cursor = view_get_render_cursor_target(system, view); + Full_Cursor render_cursor = view_get_render_cursor(models, view); + Full_Cursor target_cursor = view_get_render_cursor_target(models, view); view->temp_view_top_left_pos = (i32)render_cursor.pos; view->temp_view_top_left_target_pos = (i32)target_cursor.pos; } @@ -172,7 +173,7 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E View *view = panel->view; if (view->file == file){ i32 cursor_pos = cursors[cursor_count++].pos; - Full_Cursor new_cursor = file_compute_cursor(system, file, seek_pos(cursor_pos)); + Full_Cursor new_cursor = file_compute_cursor(models, file, seek_pos(cursor_pos)); File_Edit_Positions edit_pos = view_get_edit_pos(view); GUI_Scroll_Vars scroll = edit_pos.scroll; @@ -183,7 +184,7 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E i32 top_left_target_pos = cursors[cursor_count++].pos; f32 new_y_val_aligned = 0; if (view->temp_view_top_left_pos != top_left_pos){ - Full_Cursor new_position_cursor = file_compute_cursor(system, file, seek_pos(top_left_pos)); + Full_Cursor new_position_cursor = file_compute_cursor(models, file, seek_pos(top_left_pos)); if (file->settings.unwrapped_lines){ new_y_val_aligned = new_position_cursor.unwrapped_y; } @@ -194,7 +195,7 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E } if (view->temp_view_top_left_target_pos != top_left_target_pos){ if (top_left_target_pos != top_left_pos){ - Full_Cursor new_position_cursor = file_compute_cursor(system, file, seek_pos(top_left_target_pos)); + Full_Cursor new_position_cursor = file_compute_cursor(models, file, seek_pos(top_left_target_pos)); if (file->settings.unwrapped_lines){ new_y_val_aligned = new_position_cursor.unwrapped_y; } @@ -252,7 +253,7 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Range } // NOTE(allen): fixing stuff beforewards???? - edit_pre_state_change(system, heap, models, file); + edit_pre_state_change(models, heap, file); // NOTE(allen): edit range hook if (models->hook_file_edit_range != 0){ @@ -294,11 +295,7 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Range } // NOTE(allen): wrap meta data -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id); - Assert(font.valid); -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); Assert(face != 0); file_measure_wraps(system, &models->mem, file, face); diff --git a/4ed_file.cpp b/4ed_file.cpp index 706dfef8..c4d662f0 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -237,12 +237,9 @@ file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek){ } internal Full_Cursor -file_compute_cursor__inner(System_Functions *system, Editing_File *file, Buffer_Seek seek, b32 return_hint){ -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id); - Assert(font.valid); -#endif - Face *face = 0; +file_compute_cursor__inner(Models *models, Editing_File *file, Buffer_Seek seek, b32 return_hint){ + System_Functions *system = models->system; + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); Assert(face != 0); Full_Cursor result = {}; @@ -314,13 +311,13 @@ file_compute_cursor__inner(System_Functions *system, Editing_File *file, Buffer_ } internal Full_Cursor -file_compute_cursor(System_Functions *system, Editing_File *file, Buffer_Seek seek){ - return(file_compute_cursor__inner(system, file, seek, false)); +file_compute_cursor(Models *models, Editing_File *file, Buffer_Seek seek){ + return(file_compute_cursor__inner(models, file, seek, false)); } internal Full_Cursor -file_compute_cursor_hint(System_Functions *system, Editing_File *file, Buffer_Seek seek){ - return(file_compute_cursor__inner(system, file, seek, true)); +file_compute_cursor_hint(Models *models, Editing_File *file, Buffer_Seek seek){ + return(file_compute_cursor__inner(models, file, seek, true)); } //////////////////////////////// @@ -450,11 +447,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File * Face_ID font_id = models->global_font_id; file->settings.font_id = font_id; -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(font_id); - Assert(font.valid); -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, font_id); Assert(face != 0); file_measure_starts(heap, &file->state.buffer); diff --git a/4ed_font.cpp b/4ed_font.cpp deleted file mode 100644 index a4b80e79..00000000 --- a/4ed_font.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 11.03.2017 - * - * Implements some basic getters for fonts set up to make the font type opaque. - * - */ - -// TOP - -// TODO(allen): This is really "renderer font helpers or something like that" - -#if 0 -internal Face_ID -font_get_id_by_name(System_Functions *system, String_Const_u8 name){ - Face_ID id = 0; - u32 count = system->font.get_count(); - for (Face_ID id_it = 1; id_it <= count; ++id_it){ - char str[256]; - i32 str_len = system->font.get_name_by_id(id_it, str, sizeof(str)); - if (str_len > 0){ - String_Const_u8 font_name = SCu8(str, str_len); - if (string_match(font_name, name)){ - id = id_it; - break; - } - } - } - return(id); -} - -internal Glyph_Page** -font_page_lookup(Font_Page_Storage *page_storage, u32 page_number, b32 get_empty_slot){ - Glyph_Page **result = 0; - - if (page_storage->page_max > 0){ - u32 first_index = page_number % page_storage->page_max; - - u32 range_count = 0; - u32 ranges[4]; - if (first_index == 0){ - ranges[0] = 0; - ranges[1] = page_storage->page_max; - range_count = 2; - } - else{ - ranges[0] = first_index; - ranges[1] = page_storage->page_max; - ranges[2] = 0; - ranges[3] = first_index; - range_count = 4; - } - - Glyph_Page **pages = page_storage->pages; - if (get_empty_slot){ - for (u32 j = 0; j < range_count; j += 2){ - u32 stop = ranges[j+1]; - for (u32 i = ranges[j]; i < stop; ++i){ - if (pages[i] == FONT_PAGE_EMPTY || pages[i] == FONT_PAGE_DELETED){ - result = &pages[i]; - goto break2; - } - if (pages[i]->page_number == page_number){ - goto break2; - } - } - } - } - else{ - for (u32 j = 0; j < range_count; j += 2){ - u32 stop = ranges[j+1]; - for (u32 i = ranges[j]; i < stop; ++i){ - if (pages[i] == FONT_PAGE_EMPTY){ - goto break2; - } - if (pages[i] != FONT_PAGE_DELETED && pages[i]->page_number == page_number){ - result = &pages[i]; - goto break2; - } - } - } - } - - break2:; - } - - return(result); -} - -internal Glyph_Page* -font_get_page(Font_Page_Storage *pages, u32 page_number){ - Glyph_Page *result = 0; - if (page_number <= 0x10FF){ - Glyph_Page **page_get_result = font_page_lookup(pages, page_number, false); - if (page_get_result != 0){ - result = *page_get_result; - } - } - return(result); -} - -internal Glyph_Page* -font_allocate_and_hash_new_page(System_Functions *system, Font_Page_Storage *storage, u32 page_number){ - Glyph_Page *new_page = 0; - if (page_number <= 0x10FF){ - b32 has_space = true; - - // Grow and rehash the table if we need to now. - u32 new_page_count = 1; - u32 new_max = (storage->page_count + new_page_count)*3; - if (storage->page_max < FONT_PAGE_MAX && new_max > storage->page_max*2){ - Glyph_Page **pages = (Glyph_Page**)system->font.allocate(sizeof(Glyph_Page*)*new_max); - if (pages != 0){ - u32 old_max = storage->page_max; - Glyph_Page **old_pages = storage->pages; - storage->pages = pages; - storage->page_max = new_max; - memset(pages, 0, sizeof(*pages)*new_max); - if (old_pages != 0){ - for (u32 i = 0; i < old_max; ++i){ - Glyph_Page *this_page = old_pages[i]; - if (this_page != FONT_PAGE_EMPTY && this_page != FONT_PAGE_DELETED){ - u32 this_page_number = this_page->page_number; - Glyph_Page **dest = font_page_lookup(storage, this_page_number, true); - Assert(dest != 0); - *dest = this_page; - } - } - system->font.free(old_pages); - } - } - else{ - has_space = false; - } - } - - // Allocate and hash a new page if there is room in the table. - if (has_space){ - new_page = (Glyph_Page*)system->font.allocate(sizeof(Glyph_Page)); - if (new_page != 0){ - Glyph_Page **dest = font_page_lookup(storage, page_number, true); - Assert(dest != 0); - *dest = new_page; - storage->page_count += new_page_count; - } - } - } - return(new_page); -} - -internal Glyph_Page* -font_make_page(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages, u32 page_number){ - Glyph_Page *new_page = font_allocate_and_hash_new_page(system, pages, page_number); - if (new_page != 0){ - system->font.load_page(settings, metrics, new_page, page_number); - } - return(new_page); -} - -/////// -// HACK(allen): Hack optimizations -struct Font_Cached_Lookup_Result{ - Glyph_Page *page; - u32 index; -}; - -internal Font_Cached_Lookup_Result -font_cached_lookup(Font_Page_Storage *pages, u32 page_number){ - Font_Cached_Lookup_Result result = {}; - - result.index = page_number % ArrayCount(pages->cache); - if (pages->cache[result.index].page_number == page_number){ - result.page = pages->cache[result.index].page; - } - - if (result.page == 0){ - result.page = font_get_page(pages, page_number); - } - - return(result); -} - -internal Glyph_Page* -font_cached_get_page(Font_Page_Storage *pages, u32 page_number){ - Font_Cached_Lookup_Result result = font_cached_lookup(pages, page_number); - if (result.page != 0){ - pages->cache[result.index].page = result.page; - pages->cache[result.index].page_number = page_number; - } - return(result.page); -} - -internal Glyph_Page* -font_cached_get_or_make_page(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages, u32 page_number){ - Font_Cached_Lookup_Result result = font_cached_lookup(pages, page_number); - if (result.page == 0){ - result.page = font_make_page(system, settings, metrics, pages, page_number); - } - if (result.page != 0){ - pages->cache[result.index].page = result.page; - pages->cache[result.index].page_number = page_number; - } - return(result.page); -} -/////// - -internal f32 -font_get_glyph_advance(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages, u32 codepoint){ - f32 result = 0.f; - u32 page_number = (codepoint >> 8); - Glyph_Page *page = font_cached_get_or_make_page(system, settings, metrics, pages, page_number); - - u32 glyph_index = codepoint & 0xFF; - if (page != 0 && page->advance[glyph_index] > 0.f){ - result = page->advance[glyph_index]; - } - return(result); -} -#endif - -internal f32 -font_get_glyph_advance(System_Functions *system, Face *face, u32 codepoint){ - f32 result = 0.f; - NotImplemented; - return(result); -} - -// BOTTOM - diff --git a/4ed_font.h b/4ed_font.h deleted file mode 100644 index fe82049b..00000000 --- a/4ed_font.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 11.03.2017 - * - * Font system interface. - * - */ - -// TOP - -#if !defined(FCODER_FONT_H) -#define FCODER_FONT_H - -struct Font_Loadable_Stub{ - b32 load_from_path; - b32 in_font_folder; - i32 len; - char name[256]; -}; - -struct Face_Parameters{ - i32 pt_size; - b32 italics; - b32 bold; - b32 underline; - b32 use_hinting; -}; - -struct Face_Settings{ - Font_Loadable_Stub stub; - Face_Parameters parameters; -}; - -struct Glyph_Bounds{ - Rect_f32 uv; - f32 w; - Rect_f32 xy_off; -}; - -typedef i32 Texture_Kind; - -struct Face{ - Face_Settings settings; - - // NOTE(allen): Metrics - String_Const_u8 name; - - f32 height; - f32 ascent; - f32 descent; - f32 line_skip; - f32 advance; - - f32 underline_yoff1; - f32 underline_yoff2; - - f32 byte_advance; - f32 sub_advances[3]; - - // NOTE(allen): Glyph data - Table_u32_u16 codepoint_to_index_table; - i32 index_count; - Glyph_Bounds *bounds; - Glyph_Bounds white; - - Texture_Kind gpu_texture_kind; - u32 gpu_texture; - Vec3_f32 gpu_texture_dim; -}; - -//////////////////////////////// - -typedef u32 Get_GPU_Texture_Function(Vec3_i32 dim, Texture_Kind texture_kind); -typedef b32 Fill_GPU_Texture_Function(Texture_Kind texture_kind, u32 gpu_texture, - Vec3_i32 p, Vec3_i32 dim, void *data); - -// NOTE(allen): Platform layer calls - implemented in a "font provider" -typedef Face Font_Make_Face_Function(Arena *arena, Face_Settings *settings, - Get_GPU_Texture_Function *get_gpu_texture, - Fill_GPU_Texture_Function *fill_gpu_texture); - -#endif - -// BOTTOM - - diff --git a/4ed_font_face.cpp b/4ed_font_face.cpp new file mode 100644 index 00000000..bdcdc598 --- /dev/null +++ b/4ed_font_face.cpp @@ -0,0 +1,70 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 23.07.2019 + * + * Face basic operations. + * + */ + +// TOP + +internal b32 +codepoint_index_map_read(Codepoint_Index_Map *map, u32 codepoint, u16 *index_out){ + b32 success = true; + if (codepoint == 0 && map->has_zero_index){ + *index_out = map->zero_index; + } + else if (table_read(&map->table, codepoint, index_out)){ + // NOTE(allen): do nothing + } + else{ + success = false; + } + return(success); +} + +internal u16 +codepoint_index_map_count(Codepoint_Index_Map *map){ + return(map->max_index + 1); +} + +internal f32 +font_get_glyph_advance(Face *face, u32 codepoint){ + f32 result = 0.f; + if (codepoint == '\t'){ + result = face->space_advance*4.f; + } + else{ + u16 index = 0; + if (codepoint_index_map_read(&face->codepoint_to_index_map, codepoint, &index)){ + if (index < face->index_count){ + result = face->advance[index]; + } + } + } + return(result); +} + +internal f32 +font_get_max_glyph_advance_range(Face *face, u32 codepoint_first, u32 codepoint_last){ + f32 result = font_get_glyph_advance(face, codepoint_first); + for (u32 i = codepoint_first + 1; i <= codepoint_last; i += 1){ + f32 a = font_get_glyph_advance(face, i); + result = Max(a, result); + } + return(result); +} + +internal f32 +font_get_average_glyph_advance_range(Face *face, u32 codepoint_first, u32 codepoint_last){ + f32 result = 0.f; + for (u32 i = codepoint_first; i <= codepoint_last; i += 1){ + result += font_get_glyph_advance(face, i); + } + result /= (f32)(codepoint_last - codepoint_first + 1); + return(result); +} + +// BOTTOM + diff --git a/4ed_font_interface.h b/4ed_font_interface.h new file mode 100644 index 00000000..f273d0b2 --- /dev/null +++ b/4ed_font_interface.h @@ -0,0 +1,84 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 11.03.2017 + * + * Font system interface. + * + */ + +// TOP + +#if !defined(FCODER_FONT_INTERFACE_H) +#define FCODER_FONT_INTERFACE_H + +typedef i32 Texture_Kind; +enum{ + TextureKind_Error, + TextureKind_Mono, +}; + +typedef u32 Graphics_Get_Texture_Function(Vec3_i32 dim, Texture_Kind texture_kind); +typedef b32 Graphics_Fill_Texture_Function(Texture_Kind texture_kind, u32 texture, + Vec3_i32 p, Vec3_i32 dim, void *data); + +//////////////////////////////// + +struct Glyph_Bounds{ + Rect_f32 uv; + f32 w; + Rect_f32 xy_off; +}; + +struct Codepoint_Index_Map{ + b32 has_zero_index; + u16 zero_index; + u16 max_index; + Table_u32_u16 table; +}; + +struct Face{ + Face_Description description; + + // NOTE(allen): Metrics + + f32 height; + f32 ascent; + f32 descent; + f32 line_skip; + f32 max_advance; + + f32 underline_yoff1; + f32 underline_yoff2; + + f32 space_advance; + f32 digit_advance; + f32 hex_advance; + f32 byte_advance; + f32 byte_sub_advances[3]; + f32 typical_lowercase_advance; + f32 typical_uppercase_advance; + f32 typical_advance; + + // NOTE(allen): Glyph data + Codepoint_Index_Map codepoint_to_index_map; + u16 index_count; + Glyph_Bounds *bounds; + f32 *advance; + Glyph_Bounds white; + + Texture_Kind texture_kind; + u32 texture; + Vec3_f32 texture_dim; +}; + +//////////////////////////////// + +// NOTE(allen): Platform layer calls - implemented in a "font provider" +typedef Face *Font_Make_Face_Function(Arena *arena, Face_Description *description); + +#endif + +// BOTTOM + + diff --git a/4ed_font_provider_freetype.cpp b/4ed_font_provider_freetype.cpp index d5209a81..fbbe30b3 100644 --- a/4ed_font_provider_freetype.cpp +++ b/4ed_font_provider_freetype.cpp @@ -63,23 +63,31 @@ ft__get_codepoint_index_pairs(Arena *arena, FT_Face face, u16 *maximum_index_out return(array); } -internal Table_u32_u16 -ft__get_codepoint_index_table(Base_Allocator *base_allocator, FT_Face face, u16 *maximum_index_out){ +internal Codepoint_Index_Map +ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){ FT_Long glyph_count = face->num_glyphs; - Table_u32_u16 table = make_table_u32_u16(base_allocator, glyph_count*4); + 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); - table_insert(&table, (u32)codepoint, (u16)index); + table_insert(&map.table, (u32)codepoint, (u16)index); maximum_index = Max(maximum_index, (u16)index); counter += 1; for (;;){ codepoint = FT_Get_Next_Char(face, codepoint, &index); - table_insert(&table, (u32)codepoint, (u16)index); + if (codepoint == 0){ + map.has_zero_index = true; + map.zero_index = (u16)(index); + } + else{ + table_insert(&map.table, (u32)codepoint, (u16)index); + } maximum_index = Max(maximum_index, (u16)index); counter += 1; if (counter == glyph_count){ @@ -87,9 +95,9 @@ ft__get_codepoint_index_table(Base_Allocator *base_allocator, FT_Face face, u16 } } - *maximum_index_out = maximum_index; + map.max_index = maximum_index; - return(table); + return(map); } struct FT_Bad_Rect_Pack{ @@ -102,7 +110,7 @@ struct FT_Bad_Rect_Pack{ internal void ft__bad_rect_pack_init(FT_Bad_Rect_Pack *pack, Vec2_i32 max_dim){ pack->max_dim = max_dim; - pack->dim = V3i32(0, 0, 0); + pack->dim = V3i32(0, 0, 1); pack->p = V3i32(0, 0, 0); pack->current_line_h = 0; } @@ -135,6 +143,7 @@ ft__bad_rect_pack_next(FT_Bad_Rect_Pack *pack, Vec2_i32 dim){ result = pack->p; pack->p.x += dim.x; pack->current_line_h = Max(pack->current_line_h, dim.y); + pack->dim.x = clamp_bot(pack->dim.x, pack->p.x); } } return(result); @@ -146,14 +155,18 @@ ft__glyph_bounds_store_uv_raw(Vec3_i32 p, Vec2_i32 dim, Glyph_Bounds *bounds){ bounds->w = (f32)p.z; } -enum{ - TextureKind_Error, - TextureKind_Mono, -}; - internal Face* -ft__font_make_face(Arena *arena, Face_Settings *settings, Get_GPU_Texture_Function *get_gpu_texture, Fill_GPU_Texture_Function *fill_gpu_texture){ - String_Const_u8 file_name = SCu8(settings->stub.name, settings->stub.len); +ft__font_make_face(Arena *arena, Face_Description *description){ + String_Const_u8 file_name = {}; + if (description->font.in_4coder_font_folder){ + String_Const_u8 binary_path = sysfunc.get_4ed_path(arena); + binary_path = string_mod_replace_character(binary_path, '\\', '/'); + file_name = push_u8_stringf(arena, "%.*sfonts/%.*s", string_expand(binary_path), + string_expand(description->font.file_name)); + } + else{ + file_name = push_string_copy(arena, description->font.file_name); + } FT_Library ft; FT_Init_FreeType(&ft); @@ -161,24 +174,27 @@ ft__font_make_face(Arena *arena, Face_Settings *settings, Get_GPU_Texture_Functi FT_Face ft_face; FT_Error error = FT_New_Face(ft, (char*)file_name.str, 0, &ft_face); - Face *face = push_array_zero(arena, Face, 1);; + Face *face = 0; if (error == 0){ - u32 pt_size = settings->parameters.pt_size; - b32 use_hinting = settings->parameters.use_hinting; + face = push_array_zero(arena, Face, 1); + + u32 pt_size = description->parameters.pt_size; + 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->name = push_string_copy(arena, file_name); + face->description = *description; + face->description.font.file_name = file_name; - face->ascent = f32_ceil32(ft_face->size->metrics.ascender/64.f); - face->descent = f32_floor32(ft_face->size->metrics.descender/64.f); - face->advance = f32_ceil32(ft_face->size->metrics.max_advance/64.f); - face->height = f32_ceil32(ft_face->size->metrics.height/64.f); - face->line_skip = face->height - (face->ascent - face->descent); - face->height -= face->line_skip; + face->ascent = f32_ceil32(ft_face->size->metrics.ascender/64.f); + face->descent = f32_floor32(ft_face->size->metrics.descender/64.f); + face->max_advance = f32_ceil32(ft_face->size->metrics.max_advance/64.f); + face->height = f32_ceil32(ft_face->size->metrics.height/64.f); + face->line_skip = face->height - (face->ascent - face->descent); + face->height -= face->line_skip; { f32 real_over_notional = (f32)face->height/(f32)ft_face->height; @@ -192,9 +208,11 @@ ft__font_make_face(Arena *arena, Face_Settings *settings, Get_GPU_Texture_Functi face->underline_yoff2 = center + thickness*0.5f; } - u16 index_count = 0; - face->codepoint_to_index_table = ft__get_codepoint_index_table(arena->base_allocator, ft_face, &index_count); + face->codepoint_to_index_map = ft__get_codepoint_index_map(arena->base_allocator, ft_face); + u16 index_count = codepoint_index_map_count(&face->codepoint_to_index_map); + face->index_count = index_count; face->bounds = push_array(arena, Glyph_Bounds, index_count); + face->advance = push_array_zero(arena, f32, index_count); struct FT_Bitmap{ Vec2_i32 dim; @@ -202,9 +220,8 @@ ft__font_make_face(Arena *arena, Face_Settings *settings, Get_GPU_Texture_Functi }; FT_Bitmap *glyph_bitmaps = push_array(arena, FT_Bitmap, index_count); - u32 load_flags = ft__load_flags(use_hinting); + u32 load_flags = ft__load_flags(hinting); for (u16 i = 0; i < index_count; i += 1){ - FT_Bitmap *bitmap = &glyph_bitmaps[i]; error = FT_Load_Glyph(ft_face, i, load_flags); @@ -248,6 +265,8 @@ ft__font_make_face(Arena *arena, Face_Settings *settings, Get_GPU_Texture_Functi NotImplemented; }break; } + + face->advance[i] = (f32)ceil32(ft_glyph->advance.x/64.0f); } } @@ -271,25 +290,49 @@ ft__font_make_face(Arena *arena, Face_Settings *settings, Get_GPU_Texture_Functi } Texture_Kind texture_kind = TextureKind_Mono; - u32 gpu_texture = get_gpu_texture(pack.dim, texture_kind); - face->gpu_texture_kind = texture_kind; - face->gpu_texture = gpu_texture; + u32 texture = sysfunc.get_texture(pack.dim, texture_kind); + 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); + sysfunc.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; + } - Vec3_f32 gpu_texture_dim = V3f32(pack.dim); - face->gpu_texture_dim = gpu_texture_dim; 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); - fill_gpu_texture(texture_kind, gpu_texture, p, dim, glyph_bitmaps[i].data); - - face->bounds[i].uv.x1 = (face->bounds[i].uv.x0 + face->bounds[i].uv.x1)/gpu_texture_dim.x; - face->bounds[i].uv.y1 = (face->bounds[i].uv.y0 + face->bounds[i].uv.y1)/gpu_texture_dim.y; - face->bounds[i].uv.x0 = face->bounds[i].uv.x0/gpu_texture_dim.x; - face->bounds[i].uv.y0 = face->bounds[i].uv.y0/gpu_texture_dim.y; - face->bounds[i].w /= gpu_texture_dim.z; + sysfunc.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->settings = *settings; + { + face->space_advance = font_get_glyph_advance(face, ' '); + face->digit_advance = font_get_max_glyph_advance_range(face, '0', '9'); + face->hex_advance = font_get_max_glyph_advance_range(face, 'A', 'F'); + face->hex_advance = Max(face->hex_advance, face->digit_advance); + face->byte_sub_advances[0] = font_get_glyph_advance(face, '\\'); + face->byte_sub_advances[1] = face->hex_advance; + face->byte_sub_advances[2] = face->hex_advance; + face->typical_lowercase_advance = font_get_average_glyph_advance_range(face, 'a', 'z'); + face->typical_uppercase_advance = font_get_average_glyph_advance_range(face, 'A', 'Z'); + face->typical_advance = (26*face->typical_lowercase_advance + + 26*face->typical_uppercase_advance + + 10*face->digit_advance)/62.f; + } } FT_Done_FreeType(ft); @@ -297,825 +340,5 @@ ft__font_make_face(Arena *arena, Face_Settings *settings, Get_GPU_Texture_Functi return(face); } -#if 0 -internal b32 -font_ft_get_face(FT_Library ft, Font_Loadable_Stub *stub, Font_Parameters *parameters, FT_Face *face){ - b32 success = true; - b32 do_transform = false; - if (stub->load_from_path){ - // TODO(allen): Look for italics/bold stuff? - FT_Error error = FT_New_Face(ft, stub->name, 0, face); - success = (error == 0); - do_transform = success; - } - else{ - switch (system_font_method){ - case SystemFontMethod_FilePath: - { - Font_Path path = system_font_path(stub->name, parameters); - if (path.len > 0){ - FT_Error error = FT_New_Face(ft, path.name, 0, face); - success = (error == 0); - if (success){ - success = match((*face)->family_name, stub->name); - do_transform = (success && path.used_base_file); - } - } - else{ - success = false; - } - }break; - - case SystemFontMethod_RawData: - { - Font_Raw_Data data = system_font_data(stub->name, parameters); - if (data.size > 0){ - FT_Error error = FT_New_Memory_Face(ft, data.data, data.size, 0, face); - success = (error == 0); - if (success){ - success = match((*face)->family_name, stub->name); - do_transform = (success && data.used_base_file); - } - } - else{ - success = false; - } - }break; - } - } - - return(success); -} - -internal b32 -font_load_name(Font_Loadable_Stub *stub, char *buffer, i32 capacity){ - b32 success = false; - - // TODO(allen): Stop redoing all this init for each call. - FT_Library ft; - FT_Init_FreeType(&ft); - - FT_Face face; - if (font_ft_get_face(ft, stub, 0, &face)){ - char *name = face->family_name; - i32 name_len = str_size(name); - if (name_len < capacity){ - memcpy(buffer, name, name_len + 1); - success = true; - } - } - - FT_Done_FreeType(ft); - - return(success); -} - -internal b32 -font_load_page_layout(Font_Settings *settings, Font_Metrics *metrics, Glyph_Page *page, u32 page_number){ - Assert(page != 0); - memset(page, 0, sizeof(*page)); - page->page_number = page_number; - page->has_layout = true; - - u32 pt_size = settings->parameters.pt_size; - b32 use_hinting = settings->parameters.use_hinting; - - Temp_Memory temp = begin_temp(&shared_vars.font_scratch); - - // TODO(allen): Stop redoing all this init for each call. - FT_Library ft; - FT_Init_FreeType(&ft); - - FT_Face face; - b32 has_a_good_face = font_ft_get_face(ft, &settings->stub, &settings->parameters, &face); - - if (has_a_good_face){ - FT_Size_RequestRec_ size = {}; - size.type = FT_SIZE_REQUEST_TYPE_NOMINAL; - size.height = pt_size << 6; - FT_Request_Size(face, &size); - - // NOTE(allen): Determine glyph layout dimensions - i32 max_glyph_w = face->size->metrics.x_ppem; - i32 max_glyph_h = metrics->height; - i32 pen_y_descent = max_glyph_h + 2; - i32 tex_width = 64; - i32 tex_height = 0; - - do { - tex_width *= 2; - f32 glyphs_per_row = ceilf(tex_width/(f32)max_glyph_w); - f32 rows = ceilf(GLYPHS_PER_PAGE/glyphs_per_row); - tex_height = ceil32(rows*pen_y_descent); - } - while(tex_height > tex_width); - tex_height = round_up_pot_u32(tex_height); - - i32 pen_x = 0; - i32 pen_y = 0; - - // NOTE(allen): Fill the glyph bounds array - u32 ft_flags = font_ft_flags(use_hinting); - - u32 codepoint = (page_number << 8); - Glyph_Bounds *glyph_out = &page->glyphs[0]; - f32 *advance_out = &page->advance[0]; - for (u32 i = 0; i < GLYPHS_PER_PAGE; ++i, ++codepoint, ++glyph_out, ++advance_out){ - if (FT_Load_Char(face, codepoint, ft_flags) == 0){ - i32 w = face->glyph->bitmap.width; - i32 h = face->glyph->bitmap.rows; - i32 ascent = metrics->ascent; - - // NOTE(allen): Move to next line if necessary - if (pen_x + w >= tex_width){ - pen_x = 0; - pen_y += pen_y_descent; - } - - // NOTE(allen): Set all this stuff the renderer needs - glyph_out->x0 = (f32)(pen_x); - glyph_out->y0 = (f32)(pen_y); - glyph_out->x1 = (f32)(pen_x + w); - glyph_out->y1 = (f32)(pen_y + h + 1); - - glyph_out->xoff = (f32)(face->glyph->bitmap_left); - glyph_out->yoff = (f32)(ascent - face->glyph->bitmap_top); - glyph_out->xoff2 = glyph_out->xoff + w; - glyph_out->yoff2 = glyph_out->yoff + h + 1; - - // TODO(allen): maybe advance data should be integers? - *advance_out = (f32)ceil32(face->glyph->advance.x/64.0f); - - pen_x = ceil32(glyph_out->x1 + 1); - } - } - - // TODO(allen): Not sure setting tex_height here is right... double check. - tex_height = round_up_pot_u32(pen_y + pen_y_descent); - - page->tex_width = tex_width; - page->tex_height = tex_height; - } - else{ - page->tex_width = 1; - page->tex_height = 1; - } - - FT_Done_FreeType(ft); - - end_temp(temp); - - return(has_a_good_face); -} - -internal u32* -font_load_page_pixels(Arena *arena, Font_Settings *settings, Glyph_Page *page, u32 page_number, i32 *tex_width_out, i32 *tex_height_out){ - Assert(page != 0); - Assert(page->has_layout); - Assert(page->page_number == page_number); - - u32 pt_size = settings->parameters.pt_size; - b32 use_hinting = settings->parameters.use_hinting; - - // TODO(allen): Stop redoing all this init for each call. - FT_Library ft; - FT_Init_FreeType(&ft); - - u32 *pixels = 0; - - FT_Face face; - b32 has_a_good_face = font_ft_get_face(ft, &settings->stub, &settings->parameters, &face); - if (has_a_good_face){ - FT_Size_RequestRec_ size = {}; - size.type = FT_SIZE_REQUEST_TYPE_NOMINAL; - size.height = pt_size << 6; - FT_Request_Size(face, &size); - - page->page_number = page_number; - - // NOTE(allen): Prepare a pixel buffer. - i32 tex_width = page->tex_width; - i32 tex_height = page->tex_height; - - pixels = push_array(arena, u32, tex_width*tex_height); - - if (pixels != 0){ - memset(pixels, 0, tex_width*tex_height*sizeof(u32)); - - // NOTE(allen): Fill the texture - u32 ft_flags = font_ft_flags(use_hinting); - - u32 codepoint = (page_number << 8); - Glyph_Bounds *glyph_ptr = &page->glyphs[0]; - for (i32 i = 0; i < GLYPHS_PER_PAGE; ++i, ++codepoint, ++glyph_ptr){ - if (FT_Load_Char(face, codepoint, ft_flags) == 0){ - // NOTE(allen): Extract this glyph's dimensions. - i32 x = (i32)glyph_ptr->x0; - i32 y = (i32)glyph_ptr->y0; - i32 w = (i32)(glyph_ptr->x1 - glyph_ptr->x0); - i32 h = (i32)(glyph_ptr->y1 - glyph_ptr->y0 - 1); - - // NOTE(allen): Write to the pixels. - u8 *src = face->glyph->bitmap.buffer; - i32 end_x = x + w; - i32 end_y = y + h; - if (src != 0){ - i32 pitch = face->glyph->bitmap.pitch; - for (i32 Y = y, YY = 0; Y < end_y; ++Y, ++YY){ - for (i32 X = x, XX = 0; X < end_x; ++X, ++XX){ - //pixels[Y*tex_width + X] = (0x01010101*src[YY*pitch + XX]); - pixels[Y*tex_width + X] = 0x00FFFFFF + (0x01000000*src[YY*pitch + XX]); - } - } - } - else{ - for (i32 Y = y, YY = 0; Y < end_y; ++Y, ++YY){ - for (i32 X = x, XX = 0; X < end_x; ++X, ++XX){ - pixels[Y*tex_width + X] = 0xFFFFFFFF; - } - } - } - } - } - - *tex_width_out = tex_width; - *tex_height_out = tex_height; - } - else{ - pixels = 0; - *tex_width_out = 1; - *tex_height_out = 1; - } - } - else{ - // TODO(allen): Fill in white boxes here. - pixels = 0; - *tex_width_out = 1; - *tex_height_out = 1; - } - - FT_Done_FreeType(ft); - - return(pixels); -} - -internal void -font_release_pages(System_Functions *system, Font_Page_Storage *storage){ - u32 old_max = storage->page_max; - Glyph_Page **old_pages = storage->pages; - - for (u32 i = 0; i < old_max; ++i){ - Glyph_Page *this_page = old_pages[i]; - if (this_page != FONT_PAGE_EMPTY && this_page != FONT_PAGE_DELETED){ - if (this_page->has_gpu_setup){ - Assert(sizeof(Render_Pseudo_Command_Free_Texture)%8 == 0); - Render_Pseudo_Command_Free_Texture *c = push_array(&target.buffer, Render_Pseudo_Command_Free_Texture, 1); - c->header.size = sizeof(*c); - c->free_texture_node.tex_id = this_page->gpu_tex; - sll_queue_push(target.free_texture_first, target.free_texture_last, &c->free_texture_node); - } - system->font.free(this_page); - } - } - - system->font.free(old_pages); -} - -internal b32 -font_load(System_Functions *system, Font_Settings *settings, Font_Metrics *metrics, Font_Page_Storage *pages){ - i32 pt_size = settings->parameters.pt_size; - - // TODO(allen): Stop redoing all this init for each call. - FT_Library ft; - FT_Init_FreeType(&ft); - - FT_Face face; - b32 success = font_ft_get_face(ft, &settings->stub, &settings->parameters, &face); - - if (success){ - FT_Size_RequestRec_ size = {}; - size.type = FT_SIZE_REQUEST_TYPE_NOMINAL; - size.height = (pt_size << 6); - FT_Request_Size(face, &size); - - // NOTE(allen): Set size and metrics - char *name = face->family_name; - if (name != 0){ - i32 name_len = str_size(name); - name_len = clamp_top(name_len, sizeof(metrics->name)-1); - memcpy(metrics->name, name, name_len + 1); - metrics->name_len = name_len; - } - else{ - if (!settings->stub.load_from_path){ - i32 name_len = settings->stub.len; - memcpy(metrics->name, settings->stub.name, name_len + 1); - metrics->name_len = name_len; - } - } - - metrics->ascent = ceil32(face->size->metrics.ascender /64.f); - metrics->descent = floor32(face->size->metrics.descender /64.f); - metrics->advance = ceil32(face->size->metrics.max_advance/64.f); - metrics->height = ceil32(face->size->metrics.height /64.f); - metrics->line_skip = metrics->height - (metrics->ascent - metrics->descent); - metrics->height -= metrics->line_skip; - metrics->line_skip = 0; - - if (settings->parameters.underline){ - f32 notional_to_real_ratio = (f32)metrics->height/(f32)face->height; - f32 relative_center = -1.f*notional_to_real_ratio*face->underline_position; - f32 relative_thickness = notional_to_real_ratio*face->underline_thickness; - - f32 center = (f32)floor32(metrics->ascent + relative_center); - f32 thickness = clamp_bot(1.f, relative_thickness); - - metrics->underline_yoff1 = center - thickness*0.5f; - metrics->underline_yoff2 = center + thickness*0.5f; - } - else{ - metrics->underline_yoff1 = 0.f; - metrics->underline_yoff2 = 0.f; - } - - if (metrics->height > pt_size*4 || metrics->height < 6){ - success = false; - } - else{ - // NOTE(allen): Set texture and glyph data. - Assert(font_get_page(pages, 0) == 0); - Glyph_Page *page = font_allocate_and_hash_new_page(system, pages, 0); - font_load_page_layout(settings, metrics, page, 0); - - // NOTE(allen): Whitespace spacing stuff - i32 tab_width = 4; - - f32 space_adv = page->advance[' ']; - f32 backslash_adv = page->advance['\\']; - f32 r_adv = page->advance['r']; - - page->advance['\n'] = space_adv; - page->advance['\r'] = backslash_adv + r_adv; - page->advance['\t'] = space_adv*tab_width; - - // NOTE(allen): The rest of the metrics. - f32 max_hex_advance = 0.f; - for (u32 i = '0'; i <= '9'; ++i){ - f32 adv = page->advance[i]; - max_hex_advance = Max(max_hex_advance, adv); - } - for (u32 i = 'a'; i <= 'f'; ++i){ - f32 adv = page->advance[i]; - max_hex_advance = Max(max_hex_advance, adv); - } - for (u32 i = 'A'; i <= 'F'; ++i){ - f32 adv = page->advance[i]; - max_hex_advance = Max(max_hex_advance, adv); - } - - metrics->byte_advance = backslash_adv + max_hex_advance*2; - metrics->sub_advances[0] = backslash_adv; - metrics->sub_advances[1] = max_hex_advance; - metrics->sub_advances[2] = max_hex_advance; - } - } - - FT_Done_FreeType(ft); - - return(success); -} - -//////////////////////////////// - -internal -Sys_Font_Allocate_Sig(system_font_allocate, size){ - umem *size_ptr = 0; - void *result = system_memory_allocate(size + sizeof(*size_ptr)); - size_ptr = (umem*)result; - *size_ptr = size + 4; - return(size_ptr + 1); -} - -internal -Sys_Font_Free_Sig(system_font_free, ptr){ - if (ptr != 0){ - umem *size_ptr = ((umem*)ptr) - 1; - system_memory_free(size_ptr, *size_ptr); - } -} - -internal -Sys_Font_Get_Loadable_Count_Sig(system_font_get_loadable_count){ - return(fontvars.loadable_count); -} - -internal -Sys_Font_Get_Loadable_Sig(system_font_get_loadable, i, out){ - if (0 <= i && i < fontvars.loadable_count){ - memcpy(out, &fontvars.loadables[i], sizeof(*out)); - } - else{ - memset(out, 0, sizeof(*out)); - } -} - -internal -Sys_Font_Face_Allocate_And_Init_Sig(system_font_face_allocate_and_init, new_settings){ - i32 slot_max = fontvars.max_slot_count; - Font_Slot_Page *page_with_slot = 0; - - Assert(fontvars.used_slot_count <= slot_max); - if (fontvars.used_slot_count == slot_max){ - i32 memsize = round_up_i32(SLOT_PAGE_SIZE, KB(4)); - i32 page_count = memsize/SLOT_PAGE_SIZE; - void *ptr = system_font_allocate(memsize); - memset(ptr, 0, memsize); - - page_with_slot = (Font_Slot_Page*)ptr; - - for (i32 i = 0; i < page_count; ++i){ - i32 page_slot_count = SLOT_PER_PAGE; - - Font_Slot_Page *page = (Font_Slot_Page*)ptr; - page->is_active = (u64*)(page + 1); - page->settings = (Font_Settings*)(page->is_active + (page_slot_count + 63)/64); - page->metrics = (Font_Metrics*)(page->settings + page_slot_count); - page->pages = (Font_Page_Storage*)(page->metrics + page_slot_count); - ptr = page->pages + page_slot_count; - - page->used_count = 0; - page->fill_count = 0; - page->max = page_slot_count; - - dll_insert_back(&fontvars.slot_pages_sentinel, page); - if (page->prev == &fontvars.slot_pages_sentinel){ - page->first_id = 1; - } - else{ - page->first_id = page->prev->first_id + page->prev->max; - } - - // NOTE(allen): Some of the last 64 bits of the is_active array may not line up with actual slots. - // Set such bits to 1 to simulate the "slot" being filled for allocation purposes. - // TODO(allen): This could be O(log n) instead of O(n) if I end up making bit manipulation helpers someday. - u64 last_mask_fill = 0; - if (page_slot_count%64 != 0){ - last_mask_fill = (1ULL << 63); - for (i32 spread_step = (page_slot_count%64) - 1; - spread_step > 0; - --spread_step){ - last_mask_fill |= (last_mask_fill >> 1); - } - } - - i32 is_active_max = (page_with_slot->max + 63)/64; - page->is_active[is_active_max - 1] = last_mask_fill; - } - - fontvars.max_slot_count += page_count*SLOT_PER_PAGE; - } - else{ - for (Font_Slot_Page *page = fontvars.slot_pages_sentinel.next; - page != &fontvars.slot_pages_sentinel; - page = page->next){ - if (page->used_count < page->max){ - page_with_slot = page; - break; - } - } - } - - if (page_with_slot == 0){ - //LOG("Could not get a font slot while loading a font\n"); - return(0); - } - - Assert(page_with_slot->used_count < page_with_slot->max); - - // Get a fillable index - i32 index = -1; - if (page_with_slot->fill_count < page_with_slot->max){ - index = page_with_slot->fill_count; - } - else{ - i32 is_active_max = (page_with_slot->max + 63)/64; - u64 *is_active_ptr = page_with_slot->is_active; - for (i32 i = 0; i < is_active_max; ++i){ - u64 is_active_v = is_active_ptr[i]; - if (is_active_v != (~0)){ - i32 j_stop = 64; - if (i + 1 == is_active_max){ - j_stop = SLOT_PER_PAGE%64; - } - for (i32 j = 0; j < j_stop; ++j){ - if ((is_active_v & (1ULL << j)) == 0){ - index = i*64 + j; - break; - } - } - break; - } - } - } - - // Get the slot pointers. - Assert(index != -1); - - u64 *is_active_flags = &page_with_slot->is_active[index/64]; - u64 is_active_mask = (1ULL << (index % 64)); - Font_Settings *settings = &page_with_slot->settings[index]; - Font_Metrics *metrics = &page_with_slot->metrics[index]; - Font_Page_Storage *pages = &page_with_slot->pages[index]; - Face_ID new_id = page_with_slot->first_id + index; - - Assert(((*is_active_flags) & is_active_mask) == 0); - - char *filename = new_settings->stub.name; - i32 filename_len = 0; - for (;filename[filename_len];++filename_len); - - // Initialize font settings. - memcpy(settings, new_settings, sizeof(*new_settings)); - - memset(metrics, 0, sizeof(*metrics)); - memset(pages, 0, sizeof(*pages)); - b32 success = font_load(&sysfunc, settings, metrics, pages); - if (success){ - *is_active_flags |= is_active_mask; - ++fontvars.used_slot_count; - ++page_with_slot->used_count; - if (index >= page_with_slot->fill_count){ - page_with_slot->fill_count = index + 1; - } - } - else{ - new_id = 0; - } - - if (new_id > fontvars.largest_font_id){ - fontvars.largest_font_id = new_id; - } - - return(new_id); -} - -internal -Sys_Font_Get_Largest_ID_Sig(system_font_get_largest_id){ - return(fontvars.largest_font_id); -} - -internal -Sys_Font_Get_Count_Sig(system_font_get_count){ - return(fontvars.used_slot_count); -} - -internal Font_Slot_Page_And_Index -system_font_get_active_location(Face_ID font_id){ - Font_Slot_Page_And_Index result = {}; - - for (Font_Slot_Page *page = fontvars.slot_pages_sentinel.next; - page != &fontvars.slot_pages_sentinel; - page = page->next){ - if (page->first_id <= font_id && font_id < page->first_id + SLOT_PER_PAGE){ - i32 index = (i32)(font_id - page->first_id); - u64 is_active_v = page->is_active[index/64]; - if ((is_active_v & (1ULL << (index%64))) != 0){ - result.page = page; - result.index = index; - } - break; - } - } - - return(result); -} - -internal -Sys_Font_Face_Change_Settings_Sig(system_font_face_change_settings, font_id, new_settings){ - if (font_id == 0){ - return(false); - } - - Font_Slot_Page_And_Index page_and_index = system_font_get_active_location(font_id); - if (page_and_index.page == 0){ - return(false); - } - - Font_Settings *old_settings = &page_and_index.page->settings[page_and_index.index]; - if (memcmp(new_settings, old_settings, sizeof(*new_settings)) == 0){ - return(false); - } - - b32 made_change = false; - - Font_Metrics temp_metrics = {}; - Font_Page_Storage temp_pages = {}; - - if (font_load(&sysfunc, new_settings, &temp_metrics, &temp_pages)){ - Font_Metrics *metrics_ptr = &page_and_index.page->metrics[page_and_index.index]; - Font_Page_Storage *pages_ptr = &page_and_index.page->pages[page_and_index.index]; - font_release_pages(&sysfunc, pages_ptr); - memcpy(old_settings, new_settings, sizeof(*old_settings)); - memcpy(metrics_ptr, &temp_metrics, sizeof(*metrics_ptr)); - memcpy(pages_ptr, &temp_pages, sizeof(*pages_ptr)); - made_change = true; - } - - return(made_change); -} - -internal -Sys_Font_Face_Release_Sig(system_font_face_release, font_id){ - if (fontvars.used_slot_count == 1){ - return(false); - } - - if (font_id == 0){ - return(false); - } - - Font_Slot_Page_And_Index page_and_index = system_font_get_active_location(font_id); - if (page_and_index.page == 0){ - return(false); - } - - Font_Page_Storage *pages_ptr = &page_and_index.page->pages[page_and_index.index]; - font_release_pages(&sysfunc, pages_ptr); - - u64 *is_active_ptr = &page_and_index.page->is_active[page_and_index.index/64]; - (*is_active_ptr) &= (~(1 << (page_and_index.index%64))); - - return(true); -} - -internal -Sys_Font_Get_Name_By_ID_Sig(system_font_get_name_by_id, font_id, str_out, capacity){ - i32 length = 0; - if (font_id == 0){ - return(length); - } - - Font_Slot_Page_And_Index page_and_index = system_font_get_active_location(font_id); - if (page_and_index.page != 0){ - Font_Metrics *metrics = &page_and_index.page->metrics[page_and_index.index]; - length = metrics->name_len; - copy_partial_cs(str_out, capacity, make_string(metrics->name, length)); - } - - return(length); -} - -internal -Sys_Font_Get_Pointers_By_ID_Sig(system_font_get_pointers_by_id, font_id){ - Font_Pointers font = {}; - if (font_id == 0){ - return(font); - } - - Font_Slot_Page_And_Index page_and_index = system_font_get_active_location(font_id); - if (page_and_index.page != 0){ - font.valid = true; - font.settings = &page_and_index.page->settings[page_and_index.index]; - font.metrics = &page_and_index.page->metrics[page_and_index.index]; - font.pages = &page_and_index.page->pages[page_and_index.index]; - } - - return(font); -} - -internal -Sys_Font_Load_Page_Sig(system_font_load_page, settings, metrics, page, page_number){ - Assert(page_number != 0); - font_load_page_layout(settings, metrics, page, page_number); -} - -//////////////////////////////// - -internal Font_Setup_List -system_font_get_local_stubs(Arena *arena){ - Font_Setup_List list = {}; - - u32 dir_max = KB(32); - u8 *directory = push_array(arena, u8, dir_max); - String dir_str = make_string_cap(directory, 0, dir_max); - u32 dir_len = dir_str.size = system_get_4ed_path(dir_str.str, dir_str.memory_size); - Assert(dir_len < dir_max); - - set_last_folder_sc(&dir_str, "fonts", SLASH); - terminate_with_null(&dir_str); - dir_len = dir_str.size; - - pop_array(arena, u8, dir_max - dir_len - 1); - - File_List file_list = {}; - system_set_file_list(&file_list, (char*)directory, 0, 0, 0); - - for (u32 i = 0; i < file_list.count; ++i){ - File_Info *info = &file_list.infos[i]; - - char *filename = info->filename; - u32 len = 0; - for (;filename[len];++len); - - if (dir_len + len + 1 <= sizeof(list.first->stub.name)){ - Font_Setup *setup = push_array_zero(arena, Font_Setup, 1); - sll_queue_push(list.first, list.last, setup); - setup->stub.load_from_path = true; - setup->stub.in_font_folder = true; - memcpy(&setup->stub.name[0], directory, dir_len); - memcpy(&setup->stub.name[dir_len], filename, len + 1); - setup->stub.len = dir_len + len; - } - } - - system_set_file_list(&file_list, 0, 0, 0, 0); - - return(list); -} - -internal void -system_font_init(Font_Functions *font_links, u32 pt_size, b32 use_hinting, Font_Setup_List list){ - // Linking - font_links->get_loadable_count = system_font_get_loadable_count; - font_links->get_loadable = system_font_get_loadable; - font_links->face_allocate_and_init = system_font_face_allocate_and_init; - font_links->face_change_settings = system_font_face_change_settings; - font_links->get_largest_id = system_font_get_largest_id; - font_links->get_count = system_font_get_count; - font_links->get_name_by_id = system_font_get_name_by_id; - font_links->get_pointers_by_id = system_font_get_pointers_by_id; - font_links->load_page = system_font_load_page; - font_links->allocate = system_font_allocate; - font_links->free = system_font_free; - - // Initialize fontvars - memset(&fontvars, 0, sizeof(fontvars)); - dll_init_sentinel(&fontvars.slot_pages_sentinel); - - // TODO(allen): Eliminate from fontvars. - fontvars.pt_size = pt_size; - fontvars.use_hinting = use_hinting; - - // Filling loadable font descriptions - for (Font_Setup *ptr = list.first; - ptr != 0; - ptr = ptr->next){ - Font_Loadable_Stub *stub = &ptr->stub; - - if (fontvars.loadable_count < ArrayCount(fontvars.loadables)){ - Font_Loadable_Description *loadable = &fontvars.loadables[fontvars.loadable_count]; - - b32 name_good = false; - i32 capacity = (i32)(sizeof(loadable->display_name)); - - if (stub->load_from_path){ - if (ptr->has_display_name){ - name_good = true; - memcpy(loadable->display_name, ptr->name, ptr->len); - } - else{ - name_good = font_load_name(stub, loadable->display_name, capacity); - } - if (name_good){ - loadable->display_len = str_size(loadable->display_name); - } - } - else{ - i32 len = str_size(stub->name); - if (len < capacity){ - name_good = true; - memcpy(loadable->display_name, stub->name, len + 1); - loadable->display_len = len; - } - } - - if (name_good){ - if (stub->in_font_folder){ - memcpy(&loadable->stub, stub, sizeof(*stub)); - } - else{ - stub->load_from_path = false; - stub->in_font_folder = false; - stub->len = loadable->display_len; - memset(loadable->stub.name, 0, sizeof(stub->name)); - memcpy(loadable->stub.name, loadable->display_name, stub->len); - } - - loadable->valid = true; - ++fontvars.loadable_count; - } - } - } - - // Force load one font. - Font_Setup *first_setup = list.first; - Font_Settings first_settings = {}; - memcpy(&first_settings.stub, &first_setup->stub, sizeof(first_setup->stub)); - first_settings.parameters.pt_size = pt_size; - first_settings.parameters.use_hinting = use_hinting; - system_font_face_allocate_and_init(&first_settings); -} -#endif - // BOTTOM diff --git a/4ed_font_provider_freetype.h b/4ed_font_provider_freetype.h index 66124dd4..be7678c3 100644 --- a/4ed_font_provider_freetype.h +++ b/4ed_font_provider_freetype.h @@ -22,107 +22,6 @@ struct FT_Codepoint_Index_Pair_Array{ i32 count; }; -#if 0 -struct Font_Slot{ - b32 is_active; - Font_Settings settings; - Font_Metrics metrics; - Font_Data data; -#if 0 - Font_Page_Storage pages; -#endif -}; - -struct Font_Slot_Page{ - Font_Slot_Page *next; - Font_Slot_Page *prev; - - u64 *is_active; - Font_Settings *settings; - Font_Metrics *metrics; - Font_Page_Storage *pages; - - i32 used_count; - i32 fill_count; - i32 max; - Face_ID first_id; -}; - -struct Font_Slot_Page_And_Index{ - Font_Slot_Page *page; - i32 index; -}; - -// NOTE(allen): SLOT_PER_PAGE must be >= 1 -global i32 SLOT_PER_PAGE = 32; -global i32 SLOT_SIZE = sizeof(Font_Settings) + sizeof(Font_Metrics) + sizeof(Font_Page_Storage); -global i32 SLOT_PAGE_SIZE = sizeof(Font_Slot_Page) + ((SLOT_PER_PAGE + 63)/64)*8 + SLOT_PER_PAGE*SLOT_SIZE; - -struct Font_Vars{ - Font_Slot_Page slot_pages_sentinel; - i32 used_slot_count; - i32 max_slot_count; - Face_ID largest_font_id; - - // HACK(allen): // HACK(allen): // HACK(allen): - // TODO(allen): Upgrade this to have "unlimited" resizable memory. - Font_Loadable_Description loadables[4096]; - i32 loadable_count; - - u32 pt_size; - b32 use_hinting; -}; - -global Font_Vars fontvars = {}; - -struct Font_Setup{ - Font_Setup *next; - Font_Loadable_Stub stub; - - b32 has_display_name; - i32 len; - char name[64]; -}; - -struct _Setup_List{ - Font_Setup *first; - Font_Setup *last; -}; - -// NOTE(allen): Procedures to be implemented per-OS for the freetype font provider. -struct Font_Path{ - char *name; - i32 len; - b32 used_base_file; -}; - -struct Font_Raw_Data{ - u8 *data; - i32 size; - b32 used_base_file; -}; - -enum{ - SystemFontMethod_FilePath, - SystemFontMethod_RawData, -}; - -#define Sys_Font_Path(name, parameters) Font_Path system_font_path(char *name, Font_Parameters *parameters) -internal Sys_Font_Path(name, parameters); - -#define Sys_Font_Path_Not_Used \ -internal Sys_Font_Path(n,p){ \ - Font_Path path = {}; LOG("there is no font path retrieval procedure available\n"); return(path);} - -#define Sys_Font_Data(name, parameters) Font_Raw_Data system_font_data(char *name, Font_Parameters *parameters) -internal Sys_Font_Data(name, parameters); - -#define Sys_Font_Data_Not_Used \ -internal Sys_Font_Data(n,p){ \ - Font_Raw_Data data = {}; LOG("there is no font data retrieval procedure available\n"); return(data);} -#endif - - #endif // BOTTOM diff --git a/4ed_font_set.cpp b/4ed_font_set.cpp new file mode 100644 index 00000000..53cf39ca --- /dev/null +++ b/4ed_font_set.cpp @@ -0,0 +1,167 @@ +/* +* Mr. 4th Dimention - Allen Webster +* +* 23.07.2019 +* +* Type for organizating the set of all loaded font faces. +* +*/ + +// TOP + +internal Face_ID +font_set__alloc_face_id(Font_Set *set){ + Face_ID result = 0; + if (set->free_ids != 0){ + Font_Face_ID_Node *node = set->free_ids; + result = node->id; + sll_stack_pop(set->free_ids); + sll_stack_push(set->free_id_nodes, node); + } + else{ + result = set->next_id_counter; + set->next_id_counter += 1; + } + return(result); +} + +internal void +font_set__free_face_id(Font_Set *set, Face_ID id){ + if (id + 1 == set->next_id_counter){ + set->next_id_counter -= 1; + } + else{ + Font_Face_ID_Node *node = 0; + if (set->free_id_nodes == 0){ + node = push_array(&set->arena, Font_Face_ID_Node, 1); + } + else{ + node = set->free_id_nodes; + sll_stack_pop(set->free_id_nodes); + } + sll_stack_push(set->free_ids, node); + node->id = id; + } +} + +internal Font_Face_Slot* +font_set__alloc_face_slot(Font_Set *set){ + Font_Face_Slot *result = 0; + if (set->free_face_slots == 0){ + result = push_array(&set->arena, Font_Face_Slot, 1); + } + else{ + result = set->free_face_slots; + sll_stack_pop(set->free_face_slots); + } + return(result); +} + +internal void +font_set__free_face_slot(Font_Set *set, Font_Face_Slot *slot){ + if (slot->arena.base_allocator != 0){ + linalloc_clear(&slot->arena); + } + block_zero_struct(slot); + sll_stack_push(set->free_face_slots, slot); +} + +internal void +font_set_init(System_Functions *system, Font_Set *set){ + block_zero_struct(set); + set->system = system; + set->arena = make_arena_system(system); + set->next_id_counter = 1; + set->id_to_slot_table = make_table_u64_u64(set->arena.base_allocator, 40); +} + +internal Face_ID +font_set_new_face(Font_Set *set, Face_Description *description){ + Face_ID result = 0; + Arena arena = make_arena_system(set->system); + Face *face = set->system->font_make_face(&arena, description); + if (face != 0){ + Font_Face_Slot *slot = font_set__alloc_face_slot(set); + slot->arena = arena; + slot->face = face; + result = font_set__alloc_face_id(set); + table_insert(&set->id_to_slot_table, result, (u64)slot); + } + else{ + linalloc_clear(&arena); + } + return(result); +} + +internal Font_Face_Slot* +font_set__get_face_slot(Font_Set *set, Face_ID id){ + Font_Face_Slot *result = 0; + u64 slot_ptr_u64 = 0; + if (table_read(&set->id_to_slot_table, id, &slot_ptr_u64)){ + result = (Font_Face_Slot*)slot_ptr_u64; + } + return(result); +} + +internal b32 +font_set_release_face(Font_Set *set, Face_ID id){ + b32 result = false; + Font_Face_Slot *slot = font_set__get_face_slot(set, id); + if (slot != 0){ + table_erase(&set->id_to_slot_table, id); + font_set__free_face_slot(set, slot); + font_set__free_face_id(set, id); + result = true; + } + return(result); +} + +internal Face* +font_set_face_from_id(Font_Set *set, Face_ID id){ + Face *result = 0; + Font_Face_Slot *slot = font_set__get_face_slot(set, id); + if (slot != 0){ + result = slot->face; + } + return(result); +} + +internal Face_ID +font_set_get_fallback_face(Font_Set *set){ + Face_ID result = 0; + for (Face_ID i = 1; i < set->next_id_counter; i += 1){ + if (font_set__get_face_slot(set, i) != 0){ + result = i; + break; + } + } + return(result); +} + +internal Face_ID +font_set_get_largest_id(Font_Set *set){ + return(set->next_id_counter - 1); +} + +internal b32 +font_set_modify_face(Font_Set *set, Face_ID id, Face_Description *description){ + b32 result = false; + Font_Face_Slot *slot = font_set__get_face_slot(set, id); + if (slot != 0){ + Arena arena = make_arena_system(set->system); + Face *face = set->system->font_make_face(&arena, description); + if (face != 0){ + linalloc_clear(&slot->arena); + slot->arena = arena; + slot->face = face; + result = true; + } + else{ + linalloc_clear(&arena); + } + } + return(result); +} + +// BOTTOM + diff --git a/4ed_font_set.h b/4ed_font_set.h new file mode 100644 index 00000000..16dc8976 --- /dev/null +++ b/4ed_font_set.h @@ -0,0 +1,43 @@ +/* +* Mr. 4th Dimention - Allen Webster +* +* 23.07.2019 +* +* Type for organizating the set of all loaded font faces. +* +*/ + +// TOP + +#if !defined(FRED_FONT_SET_H) +#define FRED_FONT_SET_H + +struct Font_Face_ID_Node{ + Font_Face_ID_Node *next; + Face_ID id; +}; + +union Font_Face_Slot{ + struct{ + Font_Face_Slot *next; + }; + struct{ + Arena arena; + Face *face; + }; +}; + +struct Font_Set{ + struct System_Functions *system; + Arena arena; + Face_ID next_id_counter; + Font_Face_ID_Node *free_ids; + Font_Face_ID_Node *free_id_nodes; + Font_Face_Slot *free_face_slots; + Table_u64_u64 id_to_slot_table; +}; + +#endif + +// BOTTOM + diff --git a/4ed_render_format.cpp b/4ed_render_format.cpp index 7f140aad..6814b029 100644 --- a/4ed_render_format.cpp +++ b/4ed_render_format.cpp @@ -26,8 +26,9 @@ draw_change_clip(Render_Target *target, i32_Rect clip_box){ } internal void -begin_frame(Render_Target *target){ +begin_frame(Render_Target *target, void *font_set){ target->buffer.pos = 0; + target->font_set = font_set; } internal void @@ -139,19 +140,16 @@ snap_point_to_boundary(Vec2 point){ } internal f32 -draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, String_Const_u8 string, Vec2 point, u32 color, u32 flags, Vec2 delta){ +draw_string(Render_Target *target, Face_ID font_id, String_Const_u8 string, Vec2 point, u32 color, u32 flags, Vec2 delta){ f32 total_delta = 0.f; -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(font_id); -#endif Face *face = 0; if (face != 0){ point = snap_point_to_boundary(point); f32 byte_advance = face->byte_advance; - f32 *sub_advances = face->sub_advances; + f32 *byte_sub_advances = face->byte_sub_advances; u8 *str = (u8*)string.str; u8 *str_end = str + string.size; @@ -160,7 +158,7 @@ draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, St Translation_Emits emits = {}; for (u32 i = 0; str < str_end; ++str, ++i){ - translating_fully_process_byte(system, &tran, *str, i, (i32)string.size, &emits); + translating_fully_process_byte(&tran, *str, i, (i32)string.size, &emits); for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ TRANSLATION_DECL_GET_STEP(step, behavior, J, emits); @@ -170,7 +168,7 @@ draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, St if (color != 0){ draw_font_glyph(target, font_id, codepoint, point.x, point.y, color, flags); } - f32 d = font_get_glyph_advance(system, face, codepoint); + f32 d = font_get_glyph_advance(face, codepoint); point += d*delta; total_delta += d; } @@ -183,7 +181,7 @@ draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, St Vec2 pp = point; for (u32 j = 0; j < 3; ++j){ draw_font_glyph(target, font_id, cs[j], pp.x, pp.y, color, flags); - pp += delta*sub_advances[j]; + pp += delta*byte_sub_advances[j]; } } point += byte_advance*delta; @@ -197,30 +195,30 @@ draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, St } internal f32 -draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, String_Const_u8 string, Vec2 point, u32 color){ - return(draw_string(system, target, font_id, string, point, color, 0, V2(1.f, 0.f))); +draw_string(Render_Target *target, Face_ID font_id, String_Const_u8 string, Vec2 point, u32 color){ + return(draw_string(target, font_id, string, point, color, 0, V2(1.f, 0.f))); } internal f32 -draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, u8 *str, Vec2 point, +draw_string(Render_Target *target, Face_ID font_id, u8 *str, Vec2 point, u32 color, u32 flags, Vec2 delta){ - return(draw_string(system, target, font_id, SCu8(str), point, color, flags, delta)); + return(draw_string(target, font_id, SCu8(str), point, color, flags, delta)); } internal f32 -draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, u8 *str, Vec2 point, +draw_string(Render_Target *target, Face_ID font_id, u8 *str, Vec2 point, u32 color){ - return(draw_string(system, target, font_id, SCu8(str), point, color, 0, V2(1.f, 0.f))); + return(draw_string(target, font_id, SCu8(str), point, color, 0, V2(1.f, 0.f))); } internal f32 -font_string_width(System_Functions *system, Render_Target *target, Face_ID font_id, String_Const_u8 str){ - return(draw_string(system, target, font_id, str, V2(0, 0), 0, 0, V2(0, 0))); +font_string_width(Render_Target *target, Face_ID font_id, String_Const_u8 str){ + return(draw_string(target, font_id, str, V2(0, 0), 0, 0, V2(0, 0))); } internal f32 -font_string_width(System_Functions *system, Render_Target *target, Face_ID font_id, u8 *str){ - return(draw_string(system, target, font_id, SCu8(str), V2(0, 0), 0, 0, V2(0, 0))); +font_string_width(Render_Target *target, Face_ID font_id, u8 *str){ + return(draw_string(target, font_id, SCu8(str), V2(0, 0), 0, 0, V2(0, 0))); } // BOTTOM diff --git a/4ed_render_target.h b/4ed_render_target.h index b5a41375..f80d84e2 100644 --- a/4ed_render_target.h +++ b/4ed_render_target.h @@ -36,6 +36,8 @@ struct Render_Target{ // TODO(allen): rewrite render system to work on an arena Cursor buffer; + + void *font_set; }; #endif diff --git a/4ed_system.h b/4ed_system.h index 9c079e76..b713f5fd 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -208,10 +208,10 @@ typedef Sys_Memory_Set_Protection_Sig(System_Memory_Set_Protection); typedef Sys_Memory_Free_Sig(System_Memory_Free); // file system -#define Sys_Get_Current_Path_Sig(name) i32 name(char *out, i32 capacity) +#define Sys_Get_Current_Path_Sig(name) String_Const_u8 name(Arena *arena) typedef Sys_Get_Current_Path_Sig(System_Get_Current_Path); -#define Sys_Get_4ed_Path_Sig(name) i32 name(char *out, i32 capacity) +#define Sys_Get_4ed_Path_Sig(name) String_Const_u8 name(Arena *arena) typedef Sys_Get_4ed_Path_Sig(System_Get_4ed_Path); // behavior and appearance options @@ -226,6 +226,8 @@ typedef Sys_Is_Fullscreen_Sig(System_Is_Fullscreen); struct System_Functions{ Font_Make_Face_Function *font_make_face; + Graphics_Get_Texture_Function *get_texture; + Graphics_Fill_Texture_Function *fill_texture; // files (tracked api): 11 System_Set_File_List *set_file_list; diff --git a/4ed_translation.cpp b/4ed_translation.cpp index a9e66c60..b5b10565 100644 --- a/4ed_translation.cpp +++ b/4ed_translation.cpp @@ -98,7 +98,7 @@ translating_select_emit_rule_ASCII(Translation_State *tran, Translation_Byte_Des } internal void -translating_select_emit_rule_UTF8(System_Functions *system, Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){ +translating_select_emit_rule_UTF8(Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){ type_out->byte_class = desc.byte_class; type_out->last_byte_handler = desc.last_byte_handler; type_out->emit_type = desc.prelim_emit_type; @@ -178,11 +178,11 @@ translating_generate_emits(Translation_State *tran, Translation_Emit_Rule emit_r } internal void -translating_fully_process_byte(System_Functions *system, Translation_State *tran, u8 ch, u32 i, u32 size, Translation_Emits *emits_out){ +translating_fully_process_byte(Translation_State *tran, u8 ch, u32 i, u32 size, Translation_Emits *emits_out){ Translation_Byte_Description description = {}; translating_consume_byte(tran, ch, i, size, &description); Translation_Emit_Rule emit_rule = {}; - translating_select_emit_rule_UTF8(system, tran, description, &emit_rule); + translating_select_emit_rule_UTF8(tran, description, &emit_rule); translating_generate_emits(tran, emit_rule, ch, i, emits_out); } diff --git a/4ed_view.cpp b/4ed_view.cpp index 23151f31..ccd52a2f 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -117,9 +117,9 @@ view_height(Models *models, View *view){ } internal Vec2_i32 -view_get_cursor_xy(System_Functions *system, View *view){ +view_get_cursor_xy(Models *models, View *view){ File_Edit_Positions edit_pos = view_get_edit_pos(view); - Full_Cursor cursor = file_compute_cursor(system, view->file, seek_pos(edit_pos.cursor_pos)); + Full_Cursor cursor = file_compute_cursor(models, view->file, seek_pos(edit_pos.cursor_pos)); Vec2_i32 result = {}; if (view->file->settings.unwrapped_lines){ result = V2i32((i32)cursor.unwrapped_x, (i32)cursor.unwrapped_y); @@ -175,12 +175,13 @@ view_compute_max_target_y(Models *models, View *view){ //////////////////////////////// internal b32 -view_move_view_to_cursor(System_Functions *system, Models *models, View *view, GUI_Scroll_Vars *scroll){ +view_move_view_to_cursor(Models *models, View *view, GUI_Scroll_Vars *scroll){ + System_Functions *system = models->system; b32 result = false; i32 max_x = (i32)view_width(models, view); i32 max_y = view_compute_max_target_y(models, view); - Vec2_i32 cursor = view_get_cursor_xy(system, view); + Vec2_i32 cursor = view_get_cursor_xy(models, view); GUI_Scroll_Vars scroll_vars = *scroll; i32 target_x = scroll_vars.target_x; @@ -213,9 +214,10 @@ view_move_view_to_cursor(System_Functions *system, Models *models, View *view, G } internal b32 -view_move_cursor_to_view(System_Functions *system, Models *models, View *view, GUI_Scroll_Vars scroll, i32 *pos_in_out, f32 preferred_x){ +view_move_cursor_to_view(Models *models, View *view, GUI_Scroll_Vars scroll, i32 *pos_in_out, f32 preferred_x){ + System_Functions *system = models->system; Editing_File *file = view->file; - Full_Cursor cursor = file_compute_cursor(system, file, seek_pos(*pos_in_out)); + Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(*pos_in_out)); i32 line_height = view->line_height; f32 old_cursor_y = 0.f; @@ -246,7 +248,7 @@ view_move_cursor_to_view(System_Functions *system, Models *models, View *view, G cursor_y -= line_height; } Buffer_Seek seek = seek_xy(preferred_x, cursor_y, false, file->settings.unwrapped_lines); - cursor = file_compute_cursor(system, file, seek); + cursor = file_compute_cursor(models, file, seek); *pos_in_out = (i32)cursor.pos; result = true; } @@ -270,9 +272,9 @@ view_set_preferred_x(View *view, Full_Cursor cursor){ } internal void -view_set_preferred_x_to_current_position(System_Functions *system, View *view){ +view_set_preferred_x_to_current_position(Models *models, View *view){ File_Edit_Positions edit_pos = view_get_edit_pos(view); - Full_Cursor cursor = file_compute_cursor(system, view->file, seek_pos(edit_pos.cursor_pos)); + Full_Cursor cursor = file_compute_cursor(models, view->file, seek_pos(edit_pos.cursor_pos)); view_set_preferred_x(view, cursor); } @@ -285,7 +287,7 @@ view_set_cursor(System_Functions *system, Models *models, View *view, Full_Curso } view_set_edit_pos(view, edit_pos); GUI_Scroll_Vars scroll = edit_pos.scroll; - if (view_move_view_to_cursor(system, models, view, &scroll)){ + if (view_move_view_to_cursor(models, view, &scroll)){ edit_pos.scroll = scroll; view_set_edit_pos(view, edit_pos); } @@ -297,8 +299,8 @@ view_set_scroll(System_Functions *system, Models *models, View *view, GUI_Scroll file_edit_positions_set_scroll(&edit_pos, scroll, view_compute_max_target_y(models, view)); view_set_edit_pos(view, edit_pos); i32 pos = (i32)edit_pos.cursor_pos; - if (view_move_cursor_to_view(system, models, view, edit_pos.scroll, &pos, view->preferred_x)){ - Full_Cursor cursor = file_compute_cursor(system, view->file, seek_pos(pos)); + if (view_move_cursor_to_view(models, view, edit_pos.scroll, &pos, view->preferred_x)){ + Full_Cursor cursor = file_compute_cursor(models, view->file, seek_pos(pos)); edit_pos.cursor_pos = cursor.pos; view_set_edit_pos(view, edit_pos); } @@ -343,12 +345,9 @@ view_set_file(System_Functions *system, Models *models, View *view, Editing_File File_Edit_Positions edit_pos = file_edit_positions_pop(file); view_set_edit_pos(view, edit_pos); view->mark = edit_pos.cursor_pos; - view_set_preferred_x_to_current_position(system, view); + view_set_preferred_x_to_current_position(models, view); -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id); -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); Assert(face != 0); view->line_height = (i32)face->height; @@ -382,7 +381,7 @@ adjust_views_looking_at_file_to_new_cursor(System_Functions *system, Models *mod View *view = panel->view; if (view->file == file){ File_Edit_Positions edit_pos = view_get_edit_pos(view); - Full_Cursor cursor = file_compute_cursor(system, file, seek_pos(edit_pos.cursor_pos)); + Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(edit_pos.cursor_pos)); view_set_cursor(system, models, view, cursor, true); } } @@ -391,10 +390,7 @@ adjust_views_looking_at_file_to_new_cursor(System_Functions *system, Models *mod internal void file_full_remeasure(System_Functions *system, Models *models, Editing_File *file){ Face_ID font_id = file->settings.font_id; -#if 0 - Font_Pointers font = system->font.get_pointers_by_id(font_id); -#endif - Face *face = 0; + Face *face = font_set_face_from_id(&models->font_set, font_id); file_measure_wraps(system, &models->mem, file, face); adjust_views_looking_at_file_to_new_cursor(system, models, file); @@ -427,43 +423,31 @@ global_set_font_and_update_files(System_Functions *system, Models *models, Face_ } internal b32 -alter_font_and_update_files(System_Functions *system, Models *models, Face_ID font_id, Face_Settings *new_settings){ +alter_font_and_update_files(System_Functions *system, Models *models, Face_ID face_id, Face_Description *new_description){ b32 success = false; - NotImplemented; -#if 0 - if (system->font.face_change_settings(font_id, new_settings)){ + if (font_set_modify_face(&models->font_set, face_id, new_description)){ success = true; for (Node *node = models->working_set.used_sentinel.next; node != &models->working_set.used_sentinel; node = node->next){ Editing_File *file = CastFromMember(Editing_File, main_chain_node, node); - if (file->settings.font_id == font_id){ + if (file->settings.font_id == face_id){ file_full_remeasure(system, models, file); } } } -#endif return(success); } internal b32 release_font_and_update_files(System_Functions *system, Models *models, Face_ID font_id, Face_ID replacement_id){ b32 success = false; - NotImplemented; -#if 0 - if (system->font.face_release(font_id)){ - Font_Pointers font = system->font.get_pointers_by_id(replacement_id); - if (!font.valid){ - Face_ID largest_id = system->font.get_largest_id(); - for (replacement_id = 1; replacement_id <= largest_id && replacement_id > 0; ++replacement_id){ - font = system->font.get_pointers_by_id(replacement_id); - if (font.valid){ - break; - } - } - Assert(replacement_id <= largest_id && replacement_id > 0); + if (font_set_release_face(&models->font_set, font_id)){ + Face *face = font_set_face_from_id(&models->font_set, replacement_id); + if (face == 0){ + replacement_id = font_set_get_fallback_face(&models->font_set); + Assert(font_set_face_from_id(&models->font_set, replacement_id) != 0); } - success = true; for (Node *node = models->working_set.used_sentinel.next; node != &models->working_set.used_sentinel; node = node->next){ @@ -472,8 +456,8 @@ release_font_and_update_files(System_Functions *system, Models *models, Face_ID file_set_font(system, models, file, replacement_id); } } + success = true; } -#endif return(success); } @@ -1230,36 +1214,36 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v } internal Full_Cursor -file_get_render_cursor(System_Functions *system, Editing_File *file, f32 scroll_y){ +file_get_render_cursor(Models *models, Editing_File *file, f32 scroll_y){ Full_Cursor result = {}; if (file->settings.unwrapped_lines){ - result = file_compute_cursor_hint(system, file, seek_unwrapped_xy(0, scroll_y, false)); + result = file_compute_cursor_hint(models, file, seek_unwrapped_xy(0, scroll_y, false)); } else{ - result = file_compute_cursor(system, file, seek_wrapped_xy(0, scroll_y, false)); + result = file_compute_cursor(models, file, seek_wrapped_xy(0, scroll_y, false)); } return(result); } internal Full_Cursor -view_get_render_cursor(System_Functions *system, View *view, f32 scroll_y){ - return(file_get_render_cursor(system, view->file, scroll_y)); +view_get_render_cursor(Models *models, View *view, f32 scroll_y){ + return(file_get_render_cursor(models, view->file, scroll_y)); } internal Full_Cursor -view_get_render_cursor(System_Functions *system, View *view){ +view_get_render_cursor(Models *models, View *view){ File_Edit_Positions edit_pos = view_get_edit_pos(view); f32 scroll_y = edit_pos.scroll.scroll_y; //scroll_y += view->widget_height; - return(view_get_render_cursor(system, view, scroll_y)); + return(view_get_render_cursor(models, view, scroll_y)); } internal Full_Cursor -view_get_render_cursor_target(System_Functions *system, View *view){ +view_get_render_cursor_target(Models *models, View *view){ File_Edit_Positions edit_pos = view_get_edit_pos(view); f32 scroll_y = (f32)edit_pos.scroll.target_y; //scroll_y += view->widget_height; - return(view_get_render_cursor(system, view, scroll_y)); + return(view_get_render_cursor(models, view, scroll_y)); } internal void diff --git a/opengl/4ed_opengl_defines.h b/opengl/4ed_opengl_defines.h index db76550f..528187d9 100644 --- a/opengl/4ed_opengl_defines.h +++ b/opengl/4ed_opengl_defines.h @@ -190,6 +190,8 @@ #define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEBUG_OUTPUT 0x92E0 + //////////////////////////////// #define GL_FRAMEBUFFER_UNDEFINED 0x8219 diff --git a/opengl/4ed_opengl_render.cpp b/opengl/4ed_opengl_render.cpp index 301be6d3..fea30a6a 100644 --- a/opengl/4ed_opengl_render.cpp +++ b/opengl/4ed_opengl_render.cpp @@ -13,49 +13,39 @@ //#include "4ed_opengl_funcs.h" #include "4ed_opengl_defines.h" -#if 0 -internal GLuint -gl__texture_initialize(GLint tex_width, GLint tex_height, u32 *pixels){ - GLuint tex; - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, tex_width, tex_height, 0, GL_RED, GL_UNSIGNED_INT, pixels); - return(tex); +internal void +gl__bind_texture(Render_Target *t, i32 texid){ + if (t->bound_texture != texid){ + glBindTexture(GL_TEXTURE_2D_ARRAY, texid); + t->bound_texture = texid; + } } -#endif internal u32 -gl__get_gpu_texture(Vec3_i32 dim, Texture_Kind texture_kind){ +gl__get_texture(Vec3_i32 dim, Texture_Kind texture_kind){ u32 tex = 0; glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); + glBindTexture(GL_TEXTURE_2D_ARRAY, tex); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R8, dim.x, dim.y, dim.z, 0, GL_RED, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0); - glTexStorage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R8, dim.x, dim.y, 0, GL_RED, GL_UNSIGNED_INT, 0); return(tex); } internal b32 -gl__fill_gpu_texture(Texture_Kind texture_kind, u32 gpu_texture, Vec3_i32 p, Vec3_i32 dim, void *data){ +gl__fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void *data){ b32 result = false; - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, p.x, p.y, p.z, dim.x, dim.y, dim.z, GL_RED, GL_UNSIGNED_INT, data); - return(result); -} - -internal void -gl__draw_bind_texture(Render_Target *t, i32 texid){ - if (t->bound_texture != texid){ - glBindTexture(GL_TEXTURE_2D, texid); - t->bound_texture = texid; + if (texture != 0){ + glBindTexture(GL_TEXTURE_2D_ARRAY, texture); } + if (dim.x > 0 && dim.y > 0 && dim.z > 0){ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, p.x, p.y, p.z, dim.x, dim.y, dim.z, GL_RED, GL_UNSIGNED_BYTE, data); + } + return(result); } internal void CALL_CONVENTION @@ -71,26 +61,26 @@ uniform vec2 view_t; uniform mat2x2 view_m; uniform vec4 color; in vec2 vertex_p; -in vec2 vertex_t; +in vec3 vertex_t; smooth out vec4 fragment_color; -smooth out vec2 uv; +smooth out vec3 uvw; void main(void) { gl_Position = vec4(view_m*(vertex_p - view_t), 0.f, 1.f); fragment_color = color; -uv = vertex_t; +uvw = vertex_t; } )foo"; char *gl__fragment = R"foo( smooth in vec4 fragment_color; -smooth in vec2 uv; -uniform sampler2D sampler; +smooth in vec3 uvw; +uniform sampler2DArray sampler; uniform float texture_override; out vec4 out_color; void main(void) { -out_color = fragment_color*(texture(sampler, uv).r + texture_override); +out_color = fragment_color*(texture(sampler, uvw).r + texture_override); } )foo"; @@ -171,6 +161,8 @@ gl__make_program(char *header, char *vertex, char *fragment){ internal void gl_render(Render_Target *t, Arena *scratch){ + Font_Set *font_set = (Font_Set*)t->font_set; + local_persist b32 first_opengl_call = true; local_persist u32 attribute_buffer = 0; local_persist GL_Program gpu_program = {}; @@ -179,6 +171,7 @@ gl_render(Render_Target *t, Arena *scratch){ first_opengl_call = false; #if !SHIP_MODE + glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, 0, true); glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0, 0, true); @@ -202,7 +195,7 @@ gl_render(Render_Target *t, Arena *scratch){ glEnable(GL_SCISSOR_TEST); glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); //////////////////////////////// @@ -229,6 +222,8 @@ gl_render(Render_Target *t, Arena *scratch){ t->free_texture_first = 0; t->free_texture_last = 0; + i32 glyph_counter = 0; + u8 *start = (u8*)t->buffer.base; u8 *end = (u8*)t->buffer.base + t->buffer.pos; Render_Command_Header *header = 0; @@ -240,7 +235,7 @@ gl_render(Render_Target *t, Arena *scratch){ case RenCom_Rectangle: { Render_Command_Rectangle *rectangle = (Render_Command_Rectangle*)header; - gl__draw_bind_texture(t, 0); + gl__bind_texture(t, 0); Vec4 c = unpack_color4(rectangle->color); @@ -255,7 +250,7 @@ gl_render(Render_Target *t, Arena *scratch){ 0.f, -2.f/height, }; glUniformMatrix2fv(gpu_program.view_m, 1, GL_FALSE, m); - glUniform4f(gpu_program.color, c.r, c.g, c.b, c.a); + glUniform4f(gpu_program.color, c.r*c.a, c.g*c.a, c.b*c.a, c.a); glUniform1f(gpu_program.texture_override, 1.f); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count); @@ -264,59 +259,27 @@ gl_render(Render_Target *t, Arena *scratch){ case RenCom_Glyph: { - Render_Command_Glyph *glyph = (Render_Command_Glyph*)header; -#if 0 - Font_Pointers font = system_font_get_pointers_by_id(glyph->font_id); - if (!font.valid){ +#if 1 + if ((glyph_counter += 1) > 10){ break; } #endif - Face *face = 0; + + Render_Command_Glyph *glyph = (Render_Command_Glyph*)header; + Face *face = font_set_face_from_id(font_set, glyph->font_id); if (face == 0){ break; } u32 codepoint = glyph->codepoint; -#if 0 - u32 page_number = codepoint/GLYPHS_PER_PAGE; - Glyph_Page *page = font_cached_get_page(font.pages, page_number); - if (page == 0){ - break; - } - - if (!page->has_gpu_setup){ - Temp_Memory temp = begin_temp(scratch); - i32 tex_width = 0; - i32 tex_height = 0; - u32 *pixels = font_load_page_pixels(scratch, font.settings, page, page_number, &tex_width, &tex_height); - page->has_gpu_setup = true; - page->gpu_tex = gl__texture_initialize(tex_width, tex_height, pixels); - end_temp(temp); - } - if (page->gpu_tex == 0){ - break; - } - - u32 glyph_index = codepoint%GLYPHS_PER_PAGE; - Glyph_Bounds bounds = page->glyphs[glyph_index]; - GLuint tex = page->gpu_tex; - i32 tex_width = page->tex_width; - i32 tex_height = page->tex_height; - - // TODO(allen): do(think about baking unit_u/unit_v into font data) - f32 unit_u = 1.f/tex_width; - f32 unit_v = 1.f/tex_height; -#else - u16 glyph_index = 0; - if (!table_read(&face->codepoint_to_index_table, codepoint, &glyph_index)){ + if (!codepoint_index_map_read(&face->codepoint_to_index_map, codepoint, &glyph_index)){ glyph_index = 0; } Glyph_Bounds bounds = face->bounds[glyph_index]; - GLuint tex = face->gpu_texture; - Vec3_f32 gpu_texture_dim = face->gpu_texture_dim; -#endif + GLuint tex = face->texture; + Vec3_f32 texture_dim = face->texture_dim; f32 x = glyph->pos.x; f32 y = glyph->pos.y; @@ -345,7 +308,7 @@ gl_render(Render_Target *t, Arena *scratch){ vertices[3].xy = V2(xy.x1, xy.y0); vertices[3].uv = V2(uv.x0, uv.y0); } - gl__draw_bind_texture(t, tex); + gl__bind_texture(t, tex); Vec4 c = unpack_color4(glyph->color); @@ -362,7 +325,7 @@ gl_render(Render_Target *t, Arena *scratch){ 0.f, -2.f/height, }; glUniformMatrix2fv(gpu_program.view_m, 1, GL_FALSE, m); - glUniform4f(gpu_program.color, c.r, c.g, c.b, c.a); + glUniform4f(gpu_program.color, c.r*c.a, c.g*c.a, c.b*c.a, c.a); glUniform1i(gpu_program.sampler, 0); glUniform1f(gpu_program.texture_override, 0.f); diff --git a/platform_all/4ed_shared_init_logic.cpp b/platform_all/4ed_shared_init_logic.cpp index a0577d4c..1e245a16 100644 --- a/platform_all/4ed_shared_init_logic.cpp +++ b/platform_all/4ed_shared_init_logic.cpp @@ -124,22 +124,16 @@ load_custom_code(){ } internal void -read_command_line(i32 argc, char **argv){ - //LOG("Reading command line\n"); - char cwd[4096]; - u32 size = sysfunc.get_current_path(cwd, sizeof(cwd)); - if (size == 0 || size >= sizeof(cwd)){ - system_error_box("Could not get current directory at launch."); - } - - String_Const_u8 curdir = SCu8(cwd, size); +read_command_line(Arena *scratch, i32 argc, char **argv){ + Temp_Memory temp = begin_temp(scratch); + String_Const_u8 curdir = sysfunc.get_current_path(scratch); curdir = string_mod_replace_character(curdir, '\\', '/'); char **files = 0; i32 *file_count = 0; app.read_command_line(&sysfunc, &memory_vars, curdir, &plat_settings, &files, &file_count, argc, argv); sysshared_filter_real_files(files, file_count); - //LOG("Read command line.\n"); + end_temp(temp); } internal void diff --git a/platform_all/4ed_shared_library_constants.h b/platform_all/4ed_shared_library_constants.h index 4a5dea1c..d236f9d7 100644 --- a/platform_all/4ed_shared_library_constants.h +++ b/platform_all/4ed_shared_library_constants.h @@ -46,18 +46,16 @@ system_load_library(Arena *scratch, Library *library, char *name_cstr, Load_Libr name_cstr = full_name.str; } - umem memory_size = KB(4); - String_Const_char path = {}; - path.str = push_array(scratch, char, memory_size); + String_Const_u8 path = {}; switch (location){ case LoadLibrary_CurrentDirectory: { - path.size = (umem)sysfunc.get_current_path(path.str, (i32)memory_size); + path = sysfunc.get_current_path(scratch); }break; case LoadLibrary_BinaryDirectory: { - path.size = (umem)sysfunc.get_4ed_path(path.str, (i32)memory_size); + path = sysfunc.get_4ed_path(scratch); }break; //default: LOG("Invalid library location passed.\n"); break; @@ -66,12 +64,12 @@ system_load_library(Arena *scratch, Library *library, char *name_cstr, Load_Libr b32 success = false; if (path.size > 0){ if (path.str[path.size - 1] != SLASH){ - path = push_stringf(scratch, "%.*s%c%.*s", string_expand(path), SLASH, string_expand(name)); + path = push_u8_stringf(scratch, "%.*s%c%.*s", string_expand(path), SLASH, string_expand(name)); } else{ - path = push_stringf(scratch, "%.*s%.*s", string_expand(path), string_expand(name)); + path = push_u8_stringf(scratch, "%.*s%.*s", string_expand(path), string_expand(name)); } - success = system_load_library_direct(library, path.str); + success = system_load_library_direct(library, (char*)path.str); if (success && full_file_out != 0 && full_file_out > 0){ u32 fill_size = clamp_top((u32)(path.size), (u32)(full_file_max - 1)); block_copy(full_file_out, path.str, fill_size); diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index 6b5dd219..df1087d8 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -42,7 +42,8 @@ # include "4coder_default_bindings.cpp" #endif -#include "4ed_font.h" +#include "4ed_font_interface.h" +#include "4ed_font_set.h" #include "4ed_system.h" #include "4ed_render_target.h" #include "4ed_render_format.h" @@ -120,12 +121,13 @@ global System_Functions sysfunc; #include "4ed_standard_libraries.cpp" #include "4ed_coroutine.cpp" -#include "4ed_font.cpp" +#include "4ed_font_face.cpp" #include "4ed_mem.cpp" #include "4coder_hash_functions.cpp" #include "4ed_system_allocator.cpp" +#include "4ed_font_set.cpp" //////////////////////////////// @@ -2039,6 +2041,9 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS // System Linkage // + sysfunc.font_make_face = ft__font_make_face; + sysfunc.get_texture = gl__get_texture; + sysfunc.fill_texture = gl__fill_texture; link_system_code(); // @@ -2082,7 +2087,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS // // Read Command Line // - read_command_line(argc, argv); + read_command_line(&shared_vars.scratch, argc, argv); // // Load Custom Code @@ -2236,16 +2241,14 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS // App init // - char cwd[4096]; - u32 size = sysfunc.get_current_path(cwd, sizeof(cwd)); - if (size == 0 || size >= sizeof(cwd)){ - system_error_box("Could not get current directory at launch."); - } - String_Const_u8 curdir = SCu8(cwd, size); - curdir = string_mod_replace_character(curdir, '\\', '/'); - //LOG("Initializing application variables\n"); - app.init(&sysfunc, &target, &memory_vars, win32vars.clipboard_contents, curdir, custom_api); + { + Temp_Memory temp = begin_temp(&shared_vars.scratch); + String_Const_u8 curdir = sysfunc.get_current_path(&shared_vars.scratch); + curdir = string_mod_replace_character(curdir, '\\', '/'); + app.init(&sysfunc, &target, &memory_vars, win32vars.clipboard_contents, curdir, custom_api); + end_temp(temp); + } // // Main loop diff --git a/platform_win32/win32_4ed_functions.cpp b/platform_win32/win32_4ed_functions.cpp index 0aea4f5a..949a2b3b 100644 --- a/platform_win32/win32_4ed_functions.cpp +++ b/platform_win32/win32_4ed_functions.cpp @@ -71,8 +71,10 @@ Sys_Memory_Free_Sig(system_memory_free){ internal Sys_Get_Current_Path_Sig(system_get_current_path){ - i32 result = GetCurrentDirectory_utf8(&shared_vars.scratch, capacity, (u8*)out); - return(result); + DWORD size = GetCurrentDirectory_utf8(&shared_vars.scratch, 0, 0); + u8 *out = push_array(arena, u8, size); + GetCurrentDirectory_utf8(&shared_vars.scratch, size, out); + return(SCu8(out, size - 1)); } internal @@ -88,9 +90,7 @@ Sys_Get_4ed_Path_Sig(system_get_4ed_path){ win32vars.binary_path = string_remove_last_folder(win32vars.binary_path); win32vars.binary_path.str[win32vars.binary_path.size] = 0; } - i32 copy_size = Min((i32)(win32vars.binary_path.size), capacity); - block_copy(out, win32vars.binary_path.str, copy_size); - return((i32)(win32vars.binary_path.size)); + return(push_string_copy(arena, win32vars.binary_path)); } // diff --git a/platform_win32/win32_utf8.cpp b/platform_win32/win32_utf8.cpp index e0cc6841..46924c5e 100644 --- a/platform_win32/win32_utf8.cpp +++ b/platform_win32/win32_utf8.cpp @@ -166,22 +166,22 @@ internal DWORD GetCurrentDirectory_utf8(Arena *scratch, DWORD max, u8 *buffer){ DWORD result = 0; - Temp_Memory temp = begin_temp(scratch); - - u32 buffer_16_max = KB(40); - u16 *buffer_16 = push_array(scratch, u16, buffer_16_max); - - DWORD buffer_16_len = GetCurrentDirectoryW(buffer_16_max, (LPWSTR)buffer_16); - - b32 error = false; - u32 buffer_8_len = (u32)utf16_to_utf8_minimal_checking(buffer, max-1, buffer_16, buffer_16_len, &error); - - if (buffer_8_len < max && !error){ - buffer[buffer_8_len] = 0; - result = buffer_8_len; + if (buffer != 0){ + Temp_Memory temp = begin_temp(scratch); + u32 buffer_16_max = KB(40); + u16 *buffer_16 = push_array(scratch, u16, buffer_16_max); + DWORD buffer_16_len = GetCurrentDirectoryW(buffer_16_max, (LPWSTR)buffer_16); + b32 error = false; + u32 buffer_8_len = (u32)utf16_to_utf8_minimal_checking(buffer, max-1, buffer_16, buffer_16_len, &error); + if (buffer_8_len < max && !error){ + buffer[buffer_8_len] = 0; + result = buffer_8_len; + } + end_temp(temp); + } + else{ + result = GetCurrentDirectoryW(0, 0); } - - end_temp(temp); return(result); } diff --git a/things_ive_broken.txt b/things_ive_broken.txt index 4866d41b..32333998 100644 --- a/things_ive_broken.txt +++ b/things_ive_broken.txt @@ -39,3 +39,8 @@ list__parameters list_query__parameters list_identifier__parameters list_type_definition__parameters + +set_buffer_face_by_name -> set_buffer_face_by_font_load_location +get_existing_face_id_matching_name -> face_id_from_font_load_target +get_face_id_by_name +set_global_face_by_name -> set_buffer_face_by_font_load_location (with id = 0)