diff --git a/4coder_API/types.h b/4coder_API/types.h index 3c8dc882..c5940832 100644 --- a/4coder_API/types.h +++ b/4coder_API/types.h @@ -709,7 +709,7 @@ STRUCT Theme_Color{ }; /* -DOC(Theme lists ever color that makes up a standard color scheme.) +DOC(Theme lists every color that makes up a standard color scheme.) DOC_SEE(int_color) */ STRUCT Theme{ @@ -717,6 +717,44 @@ STRUCT Theme{ 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]; + bool32 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 uint32_t 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; + + /* 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.) */ + int32_t pt_size; + + /* DOC(Indicates whether the face tries to use a bold style.) */ + bool32 bold; + + /* DOC(Indicates whether the face tries to use an italic style.) */ + bool32 italic; + + /* DOC(Indicates whether the face tries to underline text.) */ + bool32 underline; + + /* DOC(Indicates whether the face tries to apply hinting.) */ + bool32 hinting; +}; + /* DOC(A Buffer_Batch_Edit_Type is a type of batch operation.) */ ENUM(int32_t, Buffer_Batch_Edit_Type){ /* DOC(The BatchEdit_Normal operation is always correct but does the most work if there are tokens to correct.) */ diff --git a/4coder_default_framework.h b/4coder_default_framework.h index 2cbfb3a8..e0baf19c 100644 --- a/4coder_default_framework.h +++ b/4coder_default_framework.h @@ -1114,6 +1114,149 @@ load_themes_folder(Application_Links *app){ } } +// +// Font Helpers +// + +static bool32 +descriptions_match(Face_Description *a, Face_Description *b){ + bool32 result = false; + if (match(a->font.name, 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; + } + } + return(result); +} + +static Face_ID +get_existing_face_id_matching_name(Application_Links *app, char *name, int32_t len){ + String name_str = make_string(name, len); + 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 (match(compare.font.name, name_str)){ + result = id; + break; + } + } + return(result); +} + +static Face_ID +get_existing_face_id_matching_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 (descriptions_match(&compare, description)){ + result = id; + break; + } + } + return(result); +} + +static Face_ID +get_face_id_by_name(Application_Links *app, char *name, int32_t len, Face_Description *base_description){ + Face_ID new_id = 0; + + String str = make_string(name, len); + if (!match(str, base_description->font.name)){ + new_id = get_existing_face_id_matching_name(app, name, len); + if (new_id == 0){ + Face_Description description = *base_description; + copy_fast_unsafe_cs(description.font.name, str); + description.font.name[str.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); + } + } + } + + return(new_id); +} + +static void +change_font(Application_Links *app, char *name, int32_t len, bool32 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, len, &description); + if (new_id != 0){ + set_global_face(app, new_id, apply_to_all_buffers); + } +} + +static void +buffer_set_font(Application_Links *app, Buffer_Summary *buffer, char *name, int32_t len){ + 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, len, &description); + if (new_id != 0){ + buffer_set_face(app, buffer, new_id); + } + } +} + +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 +change_face_description(Application_Links *app, Face_Description *new_description, bool32 apply_to_all_buffers){ + Face_ID global_face_id = get_face_id(app, 0); + Face_Description old_description = get_face_description(app, global_face_id); + Face_ID new_id = get_face_id_by_description(app, new_description, &old_description); + if (new_id != 0){ + set_global_face(app, new_id, apply_to_all_buffers); + } +} + +static void +buffer_set_face_description(Application_Links *app, Buffer_Summary *buffer, Face_Description *new_description){ + Face_ID current_id = get_face_id(app, buffer); + if (current_id != 0){ + Face_Description old_description = get_face_description(app, current_id); + Face_ID new_id = get_face_id_by_description(app, new_description, &old_description); + if (new_id != 0){ + buffer_set_face(app, buffer, new_id); + } + } +} + +static Face_Description +get_buffer_face_description(Application_Links *app, Buffer_Summary *buffer){ + Face_ID current_id = get_face_id(app, buffer); + Face_Description description = {0}; + if (current_id != 0){ + description = get_face_description(app, current_id); + } + return(description); +} + +static 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); +} + // // Framework Init Functions // @@ -1140,7 +1283,7 @@ default_4coder_initialize(Application_Links *app, bool32 use_scrollbars, bool32 String font = get_default_font_name(); change_theme(app, theme.str, theme.size); - change_font(app, font.str, font.size, 1); + change_font(app, font.str, font.size, true); default_use_scrollbars = use_scrollbars; default_use_file_bars = use_file_bars; diff --git a/4coder_default_hooks.cpp b/4coder_default_hooks.cpp index c46ba932..a565d7e1 100644 --- a/4coder_default_hooks.cpp +++ b/4coder_default_hooks.cpp @@ -204,7 +204,7 @@ OPEN_FILE_HOOK_SIG(default_file_settings){ buffer_set_setting(app, &buffer, BufferSetting_LexWithoutStrings, true); buffer_set_setting(app, &buffer, BufferSetting_VirtualWhitespace, true); } - else if (treat_as_code && enable_code_wrapping && buffer.size < (1 << 18)){ + else if (treat_as_code && enable_code_wrapping && buffer.size < (512 << 10)){ // NOTE(allen|a4.0.12): There is a little bit of grossness going on here. // If we set BufferSetting_Lex to true, it will launch a lexing job. // If a lexing job is active when we set BufferSetting_VirtualWhitespace, the call can fail. diff --git a/4coder_generated/app_functions.h b/4coder_generated/app_functions.h index 7231feb3..6d5e43a4 100644 --- a/4coder_generated/app_functions.h +++ b/4coder_generated/app_functions.h @@ -56,9 +56,16 @@ struct Application_Links; #define PRINT_MESSAGE_SIG(n) void n(Application_Links *app, char *str, int32_t len) #define CREATE_THEME_SIG(n) void n(Application_Links *app, Theme *theme, char *name, int32_t len) #define CHANGE_THEME_SIG(n) void n(Application_Links *app, char *name, int32_t len) -#define CHANGE_FONT_SIG(n) void n(Application_Links *app, char *name, int32_t len, bool32 apply_to_all_files) -#define BUFFER_SET_FONT_SIG(n) void n(Application_Links *app, Buffer_Summary *buffer, char *name, int32_t len) -#define BUFFER_GET_FONT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, char *name_out, int32_t name_max) +#define GET_LARGEST_FACE_ID_SIG(n) Face_ID n(Application_Links *app) +#define SET_GLOBAL_FACE_SIG(n) bool32 n(Application_Links *app, Face_ID id, bool32 apply_to_all_buffers) +#define BUFFER_SET_FACE_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Face_ID id) +#define GET_FACE_DESCRIPTION_SIG(n) Face_Description n(Application_Links *app, Face_ID id) +#define GET_FACE_ID_SIG(n) Face_ID n(Application_Links *app, Buffer_Summary *buffer) +#define TRY_CREATE_NEW_FACE_SIG(n) Face_ID n(Application_Links *app, Face_Description *description) +#define TRY_MODIFY_FACE_SIG(n) bool32 n(Application_Links *app, Face_ID id, Face_Description *description) +#define TRY_RELEASE_FACE_SIG(n) bool32 n(Application_Links *app, Face_ID id, Face_ID replacement_id) +#define GET_AVAILABLE_FONT_COUNT_SIG(n) int32_t n(Application_Links *app) +#define GET_AVAILABLE_FONT_SIG(n) Available_Font n(Application_Links *app, int32_t index) #define SET_THEME_COLORS_SIG(n) void n(Application_Links *app, Theme_Color *colors, int32_t count) #define GET_THEME_COLORS_SIG(n) void n(Application_Links *app, Theme_Color *colors, int32_t count) #define DIRECTORY_GET_HOT_SIG(n) int32_t n(Application_Links *app, char *out, int32_t capacity) @@ -133,9 +140,16 @@ typedef END_QUERY_BAR_SIG(End_Query_Bar_Function); typedef PRINT_MESSAGE_SIG(Print_Message_Function); typedef CREATE_THEME_SIG(Create_Theme_Function); typedef CHANGE_THEME_SIG(Change_Theme_Function); -typedef CHANGE_FONT_SIG(Change_Font_Function); -typedef BUFFER_SET_FONT_SIG(Buffer_Set_Font_Function); -typedef BUFFER_GET_FONT_SIG(Buffer_Get_Font_Function); +typedef GET_LARGEST_FACE_ID_SIG(Get_Largest_Face_ID_Function); +typedef SET_GLOBAL_FACE_SIG(Set_Global_Face_Function); +typedef BUFFER_SET_FACE_SIG(Buffer_Set_Face_Function); +typedef GET_FACE_DESCRIPTION_SIG(Get_Face_Description_Function); +typedef GET_FACE_ID_SIG(Get_Face_ID_Function); +typedef TRY_CREATE_NEW_FACE_SIG(Try_Create_New_Face_Function); +typedef TRY_MODIFY_FACE_SIG(Try_Modify_Face_Function); +typedef TRY_RELEASE_FACE_SIG(Try_Release_Face_Function); +typedef GET_AVAILABLE_FONT_COUNT_SIG(Get_Available_Font_Count_Function); +typedef GET_AVAILABLE_FONT_SIG(Get_Available_Font_Function); typedef SET_THEME_COLORS_SIG(Set_Theme_Colors_Function); typedef GET_THEME_COLORS_SIG(Get_Theme_Colors_Function); typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot_Function); @@ -212,9 +226,16 @@ End_Query_Bar_Function *end_query_bar; Print_Message_Function *print_message; Create_Theme_Function *create_theme; Change_Theme_Function *change_theme; -Change_Font_Function *change_font; -Buffer_Set_Font_Function *buffer_set_font; -Buffer_Get_Font_Function *buffer_get_font; +Get_Largest_Face_ID_Function *get_largest_face_id; +Set_Global_Face_Function *set_global_face; +Buffer_Set_Face_Function *buffer_set_face; +Get_Face_Description_Function *get_face_description; +Get_Face_ID_Function *get_face_id; +Try_Create_New_Face_Function *try_create_new_face; +Try_Modify_Face_Function *try_modify_face; +Try_Release_Face_Function *try_release_face; +Get_Available_Font_Count_Function *get_available_font_count; +Get_Available_Font_Function *get_available_font; Set_Theme_Colors_Function *set_theme_colors; Get_Theme_Colors_Function *get_theme_colors; Directory_Get_Hot_Function *directory_get_hot; @@ -290,9 +311,16 @@ End_Query_Bar_Function *end_query_bar_; Print_Message_Function *print_message_; Create_Theme_Function *create_theme_; Change_Theme_Function *change_theme_; -Change_Font_Function *change_font_; -Buffer_Set_Font_Function *buffer_set_font_; -Buffer_Get_Font_Function *buffer_get_font_; +Get_Largest_Face_ID_Function *get_largest_face_id_; +Set_Global_Face_Function *set_global_face_; +Buffer_Set_Face_Function *buffer_set_face_; +Get_Face_Description_Function *get_face_description_; +Get_Face_ID_Function *get_face_id_; +Try_Create_New_Face_Function *try_create_new_face_; +Try_Modify_Face_Function *try_modify_face_; +Try_Release_Face_Function *try_release_face_; +Get_Available_Font_Count_Function *get_available_font_count_; +Get_Available_Font_Function *get_available_font_; Set_Theme_Colors_Function *set_theme_colors_; Get_Theme_Colors_Function *get_theme_colors_; Directory_Get_Hot_Function *directory_get_hot_; @@ -376,9 +404,16 @@ app_links->end_query_bar_ = End_Query_Bar;\ app_links->print_message_ = Print_Message;\ app_links->create_theme_ = Create_Theme;\ app_links->change_theme_ = Change_Theme;\ -app_links->change_font_ = Change_Font;\ -app_links->buffer_set_font_ = Buffer_Set_Font;\ -app_links->buffer_get_font_ = Buffer_Get_Font;\ +app_links->get_largest_face_id_ = Get_Largest_Face_ID;\ +app_links->set_global_face_ = Set_Global_Face;\ +app_links->buffer_set_face_ = Buffer_Set_Face;\ +app_links->get_face_description_ = Get_Face_Description;\ +app_links->get_face_id_ = Get_Face_ID;\ +app_links->try_create_new_face_ = Try_Create_New_Face;\ +app_links->try_modify_face_ = Try_Modify_Face;\ +app_links->try_release_face_ = Try_Release_Face;\ +app_links->get_available_font_count_ = Get_Available_Font_Count;\ +app_links->get_available_font_ = Get_Available_Font;\ app_links->set_theme_colors_ = Set_Theme_Colors;\ app_links->get_theme_colors_ = Get_Theme_Colors;\ app_links->directory_get_hot_ = Directory_Get_Hot;\ @@ -454,9 +489,16 @@ static inline void end_query_bar(Application_Links *app, Query_Bar *bar, uint32_ static inline void print_message(Application_Links *app, char *str, int32_t len){(app->print_message(app, str, len));} static inline void create_theme(Application_Links *app, Theme *theme, char *name, int32_t len){(app->create_theme(app, theme, name, len));} static inline void change_theme(Application_Links *app, char *name, int32_t len){(app->change_theme(app, name, len));} -static inline void change_font(Application_Links *app, char *name, int32_t len, bool32 apply_to_all_files){(app->change_font(app, name, len, apply_to_all_files));} -static inline void buffer_set_font(Application_Links *app, Buffer_Summary *buffer, char *name, int32_t len){(app->buffer_set_font(app, buffer, name, len));} -static inline bool32 buffer_get_font(Application_Links *app, Buffer_Summary *buffer, char *name_out, int32_t name_max){return(app->buffer_get_font(app, buffer, name_out, name_max));} +static inline Face_ID get_largest_face_id(Application_Links *app){return(app->get_largest_face_id(app));} +static inline bool32 set_global_face(Application_Links *app, Face_ID id, bool32 apply_to_all_buffers){return(app->set_global_face(app, id, apply_to_all_buffers));} +static inline bool32 buffer_set_face(Application_Links *app, Buffer_Summary *buffer, Face_ID id){return(app->buffer_set_face(app, buffer, id));} +static inline Face_Description get_face_description(Application_Links *app, Face_ID id){return(app->get_face_description(app, id));} +static inline Face_ID get_face_id(Application_Links *app, Buffer_Summary *buffer){return(app->get_face_id(app, buffer));} +static inline Face_ID try_create_new_face(Application_Links *app, Face_Description *description){return(app->try_create_new_face(app, description));} +static inline bool32 try_modify_face(Application_Links *app, Face_ID id, Face_Description *description){return(app->try_modify_face(app, id, description));} +static inline bool32 try_release_face(Application_Links *app, Face_ID id, Face_ID replacement_id){return(app->try_release_face(app, id, replacement_id));} +static inline int32_t get_available_font_count(Application_Links *app){return(app->get_available_font_count(app));} +static inline Available_Font get_available_font(Application_Links *app, int32_t index){return(app->get_available_font(app, index));} static inline void set_theme_colors(Application_Links *app, Theme_Color *colors, int32_t count){(app->set_theme_colors(app, colors, count));} static inline void get_theme_colors(Application_Links *app, Theme_Color *colors, int32_t count){(app->get_theme_colors(app, colors, count));} static inline int32_t directory_get_hot(Application_Links *app, char *out, int32_t capacity){return(app->directory_get_hot(app, out, capacity));} @@ -532,9 +574,16 @@ static inline void end_query_bar(Application_Links *app, Query_Bar *bar, uint32_ static inline void print_message(Application_Links *app, char *str, int32_t len){(app->print_message_(app, str, len));} static inline void create_theme(Application_Links *app, Theme *theme, char *name, int32_t len){(app->create_theme_(app, theme, name, len));} static inline void change_theme(Application_Links *app, char *name, int32_t len){(app->change_theme_(app, name, len));} -static inline void change_font(Application_Links *app, char *name, int32_t len, bool32 apply_to_all_files){(app->change_font_(app, name, len, apply_to_all_files));} -static inline void buffer_set_font(Application_Links *app, Buffer_Summary *buffer, char *name, int32_t len){(app->buffer_set_font_(app, buffer, name, len));} -static inline bool32 buffer_get_font(Application_Links *app, Buffer_Summary *buffer, char *name_out, int32_t name_max){return(app->buffer_get_font_(app, buffer, name_out, name_max));} +static inline Face_ID get_largest_face_id(Application_Links *app){return(app->get_largest_face_id_(app));} +static inline bool32 set_global_face(Application_Links *app, Face_ID id, bool32 apply_to_all_buffers){return(app->set_global_face_(app, id, apply_to_all_buffers));} +static inline bool32 buffer_set_face(Application_Links *app, Buffer_Summary *buffer, Face_ID id){return(app->buffer_set_face_(app, buffer, id));} +static inline Face_Description get_face_description(Application_Links *app, Face_ID id){return(app->get_face_description_(app, id));} +static inline Face_ID get_face_id(Application_Links *app, Buffer_Summary *buffer){return(app->get_face_id_(app, buffer));} +static inline Face_ID try_create_new_face(Application_Links *app, Face_Description *description){return(app->try_create_new_face_(app, description));} +static inline bool32 try_modify_face(Application_Links *app, Face_ID id, Face_Description *description){return(app->try_modify_face_(app, id, description));} +static inline bool32 try_release_face(Application_Links *app, Face_ID id, Face_ID replacement_id){return(app->try_release_face_(app, id, replacement_id));} +static inline int32_t get_available_font_count(Application_Links *app){return(app->get_available_font_count_(app));} +static inline Available_Font get_available_font(Application_Links *app, int32_t index){return(app->get_available_font_(app, index));} static inline void set_theme_colors(Application_Links *app, Theme_Color *colors, int32_t count){(app->set_theme_colors_(app, colors, count));} static inline void get_theme_colors(Application_Links *app, Theme_Color *colors, int32_t count){(app->get_theme_colors_(app, colors, count));} static inline int32_t directory_get_hot(Application_Links *app, char *out, int32_t capacity){return(app->directory_get_hot_(app, out, capacity));} diff --git a/4ed.cpp b/4ed.cpp index cbce31c1..fc115369 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -1223,7 +1223,7 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, { if (i < argc){ plat_settings->font_size = str_to_int_c(argv[i]); - plat_settings->font_size = plat_settings->font_size; + settings->font_size = plat_settings->font_size; } action = CLAct_Nothing; }break; @@ -1231,6 +1231,7 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, case CLAct_FontUseHinting: { plat_settings->use_hinting = true; + settings->use_hinting = plat_settings->use_hinting; action = CLAct_Nothing; }break; diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 3a7bddd2..45cacfcd 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -2239,78 +2239,234 @@ DOC(This call changes 4coder's color pallet to one of the built in themes.) } } -API_EXPORT void -Change_Font(Application_Links *app, char *name, int32_t len, bool32 apply_to_all_files) -/* -DOC_PARAM(name, The name parameter specifies the name of the font to begin using; it need not be null terminated.) -DOC_PARAM(len, The len parameter specifies the length of the name string.) -DOC_PARAM(apply_to_all_files, If this is set all open files change to this font. Usually this should be true durring the start hook because several files already exist at that time.) -DOC(This call changes 4coder's default font to one of the built in fonts.) -*/{ +API_EXPORT Face_ID +Get_Largest_Face_ID(Application_Links *app) +{ Command_Data *cmd = (Command_Data*)app->cmd_context; - Models *models = cmd->models; System_Functions *system = cmd->system; - - String font_name = make_string(name, len); - Font_ID font_id = font_get_id_by_name(system, font_name); - - if (font_id != 0){ - if (apply_to_all_files){ - global_set_font(system, models, font_id); - } - else{ - models->global_font_id = font_id; - } - } -} - -API_EXPORT void -Buffer_Set_Font(Application_Links *app, Buffer_Summary *buffer, char *name, int32_t len) -/* -DOC_PARAM(buffer, This parameter the buffer that shall have it's font changed) -DOC_PARAM(name, The name parameter specifies the name of the font to begin using; it need not be null terminated.) -DOC_PARAM(len, The len parameter specifies the length of the name string.) -DOC(This call sets the display font of a particular buffer.) -*/{ - - Command_Data *cmd = (Command_Data*)app->cmd_context; - Models *models = cmd->models; - System_Functions *system = cmd->system; - Editing_File *file = imp_get_file(cmd, buffer); - - if (file != 0){ - String font_name = make_string(name, len); - Font_ID font_id = font_get_id_by_name(system, font_name); - if (font_id != 0){ - file_set_font(system, models, file, font_id); - } - } + Face_ID result = system->font.get_largest_id(); + return(result); } API_EXPORT bool32 -Buffer_Get_Font(Application_Links *app, Buffer_Summary *buffer, char *name_out, int32_t name_max) -/* -DOC_PARAM(buffer, the buffer from which to get the font name) -DOC_PARAM(name_out, a character array in which to write the name of the font) -DOC_PARAM(name_max, the capacity of name_out) -DOC_RETURN(returns non-zero on success) -*/{ +Set_Global_Face(Application_Links *app, Face_ID id, bool32 apply_to_all_buffers) +{ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; - Editing_File *file = imp_get_file(cmd, buffer); - bool32 result = false; + bool32 did_change = false; - if (file != 0){ - String name = make_string_cap(name_out, 0, name_max); - Font_ID font_id = file->settings.font_id; - name.size = system->font.get_name_by_id(font_id, name_out, name_max); - if (name.size > 0){ - result = true; + Font_Pointers font = system->font.get_pointers_by_id(id); + if (font.valid){ + did_change = true; + + Models *models = cmd->models; + if (apply_to_all_buffers){ + global_set_font(system, models, id); + } + else{ + models->global_font_id = id; } } - return(result); + return(did_change); +} + +API_EXPORT bool32 +Buffer_Set_Face(Application_Links *app, Buffer_Summary *buffer, Face_ID id) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + Editing_File *file = imp_get_file(cmd, buffer); + + bool32 did_change = false; + + if (file != 0){ + System_Functions *system = cmd->system; + Font_Pointers font = system->font.get_pointers_by_id(id); + if (font.valid){ + did_change = true; + + Models *models = cmd->models; + file_set_font(system, models, file, id); + } + } + + return(did_change); +} + +internal void +font_pointers_to_face_description(Font_Pointers font, Face_Description *description){ + Font_Metrics *metrics = font.metrics; + i32 len = str_size(metrics->name); + memcpy(description->font.name, metrics->name, len); + + Font_Settings *settings = font.settings; + description->font.in_local_font_folder = settings->stub.in_font_folder; + description->pt_size = settings->parameters.pt_size; + description->bold = settings->parameters.bold; + description->italic = settings->parameters.italics; + description->underline = settings->parameters.underline; + description->hinting = settings->parameters.use_hinting; +} + +internal b32 +face_description_to_settings(System_Functions *system, Face_Description description, Font_Settings *settings){ + b32 success = false; + + if (description.font.in_local_font_folder){ + i32 count = system->font.get_loadable_count(); + for (i32 i = 0; i < count; ++i){ + Font_Loadable_Description loadable = {0}; + system->font.get_loadable(i, &loadable); + + if (loadable.valid){ + if (!loadable.stub.in_font_folder){ + break; + } + + if (match(make_string(loadable.display_name, loadable.display_len), description.font.name)){ + success = true; + memcpy(&settings->stub, &loadable.stub, sizeof(settings->stub)); + break; + } + } + } + } + else{ + success = true; + + settings->stub.load_from_path = false; + settings->stub.in_font_folder = false; + settings->stub.len = str_size(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 Face_Description +Get_Face_Description(Application_Links *app, Face_ID id) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + System_Functions *system = cmd->system; + + Face_Description description = {0}; + if (id != 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); + } + } + else{ + Models *models = cmd->models; + description.pt_size = models->settings.font_size; + description.hinting = models->settings.use_hinting; + } + + return(description); +} + +API_EXPORT Face_ID +Get_Face_ID(Application_Links *app, Buffer_Summary *buffer) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + + Face_ID id = 0; + if (buffer != 0){ + Editing_File *file = imp_get_file(cmd, buffer); + if (file != 0){ + id = file->settings.font_id; + } + } + else{ + Models *models = cmd->models; + id = models->global_font_id; + } + + return(id); +} + +API_EXPORT Face_ID +Try_Create_New_Face(Application_Links *app, Face_Description *description) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + System_Functions *system = cmd->system; + + Face_ID id = 0; + Font_Settings settings; + if (face_description_to_settings(system, *description, &settings)){ + id = system->font.face_allocate_and_init(&settings); + } + + return(id); +} + +API_EXPORT bool32 +Try_Modify_Face(Application_Links *app, Face_ID id, Face_Description *description) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + System_Functions *system = cmd->system; + + bool32 success = false; + Font_Settings settings; + if (face_description_to_settings(system, *description, &settings)){ + Models *models = cmd->models; + if (alter_font(system, models, id, &settings)){ + success = true; + } + } + + return(success); +} + +API_EXPORT bool32 +Try_Release_Face(Application_Links *app, Face_ID id, Face_ID replacement_id) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + System_Functions *system = cmd->system; + Models *models = cmd->models; + + bool32 success = false; + if (release_font(system, models, id, replacement_id)){ + success = true; + } + + return(success); +} + +API_EXPORT int32_t +Get_Available_Font_Count(Application_Links *app) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + System_Functions *system = cmd->system; + i32 count = system->font.get_loadable_count(); + return(count); +} + +API_EXPORT Available_Font +Get_Available_Font(Application_Links *app, int32_t index) +{ + Command_Data *cmd = (Command_Data*)app->cmd_context; + System_Functions *system = cmd->system; + + Available_Font available = {0}; + Font_Loadable_Description description = {0}; + system->font.get_loadable(index, &description); + if (description.valid){ + memcpy(available.name, description.display_name, description.display_len); + available.in_local_font_folder = description.stub.in_font_folder; + } + + return(available); } API_EXPORT void diff --git a/4ed_app_models.h b/4ed_app_models.h index 78c2dba2..3d188186 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -20,9 +20,8 @@ struct App_Settings{ i32 initial_line; b32 lctrl_lalt_is_altgr; - char *custom_font_file; - char *custom_font_name; - i32 custom_font_size; + i32 font_size; + b32 use_hinting; }; global_const App_Settings null_app_settings = {0}; @@ -46,7 +45,7 @@ struct Models{ Mem_Options mem; App_Settings settings; - Font_ID global_font_id; + Face_ID global_font_id; Mapping mapping; diff --git a/4ed_file.cpp b/4ed_file.cpp index 2e406bfd..fc4506a5 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -96,7 +96,7 @@ struct Editing_File_Settings{ Parse_Context_ID parse_context_id; b32 dos_write_mode; b32 virtual_white; - Font_ID font_id; + Face_ID font_id; b8 unwrapped_lines; b8 tokens_exist; b8 tokens_without_strings; diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index dc3feaee..2a057961 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1783,7 +1783,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File * } file_synchronize_times(system, file); - Font_ID font_id = models->global_font_id; + Face_ID font_id = models->global_font_id; file->settings.font_id = font_id; Font_Pointers font = system->font.get_pointers_by_id(font_id); Assert(font.valid); @@ -2657,7 +2657,7 @@ file_view_nullify_file(View *view){ } internal void -update_view_line_height(System_Functions *system, Models *models, View *view, Font_ID font_id){ +update_view_line_height(System_Functions *system, Models *models, View *view, Face_ID font_id){ Font_Pointers font = system->font.get_pointers_by_id(font_id); Assert(font.valid); view->line_height = font.metrics->height; @@ -3538,7 +3538,7 @@ style_get_color(Style *style, Cpp_Token token){ internal void file_full_remeasure(System_Functions *system, Models *models, Editing_File *file){ - Font_ID font_id = file->settings.font_id; + Face_ID font_id = file->settings.font_id; Font_Pointers font = system->font.get_pointers_by_id(font_id); file_measure_wraps_and_fix_cursor(system, models, file, font); @@ -3551,13 +3551,13 @@ file_full_remeasure(System_Functions *system, Models *models, Editing_File *file } internal void -file_set_font(System_Functions *system, Models *models, Editing_File *file, Font_ID font_id){ +file_set_font(System_Functions *system, Models *models, Editing_File *file, Face_ID font_id){ file->settings.font_id = font_id; file_full_remeasure(system, models, file); } internal void -global_set_font(System_Functions *system, Models *models, Font_ID font_id){ +global_set_font(System_Functions *system, Models *models, Face_ID font_id){ File_Node *node = 0; File_Node *sentinel = &models->working_set.used_sentinel; for (dll_items(node, sentinel)){ @@ -3567,9 +3567,13 @@ global_set_font(System_Functions *system, Models *models, Font_ID font_id){ models->global_font_id = font_id; } -internal void -alter_font(System_Functions *system, Models *models, Font_ID font_id, Font_Settings *new_settings){ +internal b32 +alter_font(System_Functions *system, Models *models, Face_ID font_id, Font_Settings *new_settings){ + b32 success = false; + if (system->font.face_change_settings(font_id, new_settings)){ + success = true; + File_Node *node = 0; File_Node *sentinel = &models->working_set.used_sentinel; for (dll_items(node, sentinel)){ @@ -3579,6 +3583,39 @@ alter_font(System_Functions *system, Models *models, Font_ID font_id, Font_Setti } } } + + return(success); +} + +internal b32 +release_font(System_Functions *system, Models *models, Face_ID font_id, Face_ID replacement_id){ + b32 success = false; + + 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_Pointers font = system->font.get_pointers_by_id(replacement_id); + if (font.valid){ + break; + } + } + Assert(replacement_id <= largest_id && replacement_id > 0); + } + + success = true; + File_Node *node = 0; + File_Node *sentinel = &models->working_set.used_sentinel; + for (dll_items(node, sentinel)){ + Editing_File *file = (Editing_File*)node; + if (file->settings.font_id == font_id){ + file_set_font(system, models, file, replacement_id); + } + } + } + + return(success); } inline void @@ -3945,7 +3982,7 @@ struct File_Bar{ f32 pos_x, pos_y; f32 text_shift_x, text_shift_y; i32_Rect rect; - Font_ID font_id; + Face_ID font_id; }; internal void @@ -4538,11 +4575,11 @@ step_file_view(System_Functions *system, View *view, Models *models, View *activ gui_begin_scrollable(target, scroll_context, view->gui_scroll, 9*view->line_height, show_scrollbar); - Font_ID font_id = file->settings.font_id; - Font_ID new_font_id = 0; + Face_ID font_id = file->settings.font_id; + Face_ID new_font_id = 0; - Font_ID largest_id = system->font.get_largest_id(); - for (Font_ID i = 1; i <= largest_id; ++i){ + Face_ID largest_id = system->font.get_largest_id(); + for (Face_ID i = 1; i <= largest_id; ++i){ Font_Pointers font = system->font.get_pointers_by_id(i); if (font.valid){ Font_Settings *settings = font.settings; @@ -4629,7 +4666,7 @@ step_file_view(System_Functions *system, View *view, Models *models, View *activ gui_begin_scrollable(target, scroll_context, view->gui_scroll, 9*view->line_height, show_scrollbar); - Font_ID font_edit_id = view->font_edit_id; + Face_ID font_edit_id = view->font_edit_id; Font_Pointers font = system->font.get_pointers_by_id(font_edit_id); Font_Settings *settings = font.settings; Font_Metrics *metrics = font.metrics; @@ -5872,7 +5909,7 @@ draw_file_loaded(System_Functions *system, View *view, Models *models, i32_Rect i32 max = partition_remaining(part) / sizeof(Buffer_Render_Item); Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max); - Font_ID font_id = file->settings.font_id; + Face_ID font_id = file->settings.font_id; Font_Pointers font = system->font.get_pointers_by_id(font_id); f32 scroll_x = view->edit_pos->scroll.scroll_x; @@ -6079,7 +6116,7 @@ draw_file_loaded(System_Functions *system, View *view, Models *models, i32_Rect } internal void -draw_text_field(System_Functions *system, Render_Target *target, View *view, Models *models, Font_ID font_id, i32_Rect rect, String p, String t){ +draw_text_field(System_Functions *system, Render_Target *target, View *view, Models *models, Face_ID font_id, i32_Rect rect, String p, String t){ Style *style = main_style(models); u32 back_color = style->main.margin_color; @@ -6097,7 +6134,7 @@ draw_text_field(System_Functions *system, Render_Target *target, View *view, Mod } internal void -draw_text_with_cursor(System_Functions *system, Render_Target *target, View *view, Models *models, Font_ID font_id, i32_Rect rect, String s, i32 pos){ +draw_text_with_cursor(System_Functions *system, Render_Target *target, View *view, Models *models, Face_ID font_id, i32_Rect rect, String s, i32 pos){ Style *style = main_style(models); u32 back_color = style->main.margin_color; @@ -6232,7 +6269,7 @@ get_margin_color(i32 active_level, Style *style){ } internal void -draw_color_button(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Font_ID font_id, i32_Rect rect, GUI_id id, u32 fore, u32 back, String text){ +draw_color_button(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Face_ID font_id, i32_Rect rect, GUI_id id, u32 fore, u32 back, String text){ i32 active_level = gui_active_level(gui_target, id); if (active_level > 0){ @@ -6244,7 +6281,7 @@ draw_color_button(System_Functions *system, GUI_Target *gui_target, Render_Targe } internal void -draw_font_button(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, i32_Rect rect, GUI_id id, Font_ID font_id, String text){ +draw_font_button(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, i32_Rect rect, GUI_id id, Face_ID font_id, String text){ Style *style = main_style(models); i32 active_level = gui_active_level(gui_target, id); @@ -6259,7 +6296,7 @@ draw_font_button(System_Functions *system, GUI_Target *gui_target, Render_Target } internal void -draw_fat_option_block(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, Font_ID font_id, i32_Rect rect, GUI_id id, String text, String pop, i8 checkbox = -1){ +draw_fat_option_block(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, Face_ID font_id, i32_Rect rect, GUI_id id, String text, String pop, i8 checkbox = -1){ Style *style = main_style(models); i32 active_level = gui_active_level(gui_target, id); @@ -6298,7 +6335,7 @@ draw_fat_option_block(System_Functions *system, GUI_Target *gui_target, Render_T } internal void -draw_button(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, Font_ID font_id, i32_Rect rect, GUI_id id, String text){ +draw_button(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, Face_ID font_id, i32_Rect rect, GUI_id id, String text){ Style *style = main_style(models); i32 active_level = gui_active_level(gui_target, id); @@ -6322,7 +6359,7 @@ draw_button(System_Functions *system, GUI_Target *gui_target, Render_Target *tar } internal void -draw_style_preview(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, Font_ID font_id, i32_Rect rect, GUI_id id, Style *style){ +draw_style_preview(System_Functions *system, GUI_Target *gui_target, Render_Target *target, View *view, Models *models, Face_ID font_id, i32_Rect rect, GUI_id id, Style *style){ i32 active_level = gui_active_level(gui_target, id); char font_name_space[256]; String font_name = make_fixed_width_string(font_name_space); @@ -6381,7 +6418,7 @@ do_render_file_view(System_Functions *system, View *view, Models *models, GUI_Sc Assert(file != 0); - Font_ID font_id = file->settings.font_id; + Face_ID font_id = file->settings.font_id; if (gui_target->push.pos > 0){ gui_session_init(&gui_session, gui_target, rect, view->line_height); @@ -6447,7 +6484,7 @@ do_render_file_view(System_Functions *system, View *view, Models *models, GUI_Sc { GUI_Interactive *b = (GUI_Interactive*)h; void *ptr = (b + 1); - Font_ID this_font_id = (Font_ID)gui_read_integer(&ptr); + Face_ID this_font_id = (Face_ID)gui_read_integer(&ptr); String t = gui_read_string(&ptr); draw_font_button(system, gui_target, target, view, models, gui_session.rect, b->id, this_font_id, t); diff --git a/4ed_font.cpp b/4ed_font.cpp index 8ff81664..efe3c4aa 100644 --- a/4ed_font.cpp +++ b/4ed_font.cpp @@ -9,11 +9,11 @@ // TOP -internal Font_ID +internal Face_ID font_get_id_by_name(System_Functions *system, String name){ - Font_ID id = 0; + Face_ID id = 0; u32 count = system->font.get_count(); - for (Font_ID id_it = 1; id_it <= count; ++id_it){ + 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){ diff --git a/4ed_font.h b/4ed_font.h index cc52d08c..ec1f863e 100644 --- a/4ed_font.h +++ b/4ed_font.h @@ -52,6 +52,9 @@ struct Font_Metrics{ i32 line_skip; i32 advance; + f32 underline_yoff1; + f32 underline_yoff2; + f32 byte_advance; f32 sub_advances[3]; }; @@ -105,8 +108,6 @@ struct Font_Pointers{ Font_Page_Storage *pages; }; -typedef u32 Font_ID; - // NOTE(allen): Platform layer calls - implemented in a "font provider" #define Sys_Font_Get_Loadable_Count_Sig(n) i32 (n)(void) typedef Sys_Font_Get_Loadable_Count_Sig(Font_Get_Loadable_Count_Function); @@ -114,25 +115,25 @@ typedef Sys_Font_Get_Loadable_Count_Sig(Font_Get_Loadable_Count_Function); #define Sys_Font_Get_Loadable_Sig(n,i,o) void (n)(i32 i, Font_Loadable_Description *o) typedef Sys_Font_Get_Loadable_Sig(Font_Get_Loadable_Function, index, out); -#define Sys_Font_Face_Allocate_And_Init_Sig(n,s) Font_ID (n)(Font_Settings *s) +#define Sys_Font_Face_Allocate_And_Init_Sig(n,s) Face_ID (n)(Font_Settings *s) typedef Sys_Font_Face_Allocate_And_Init_Sig(Font_Face_Allocate_And_Init_Function, settings); -#define Sys_Font_Face_Change_Settings_Sig(n,id,s) b32 (n)(Font_ID id, Font_Settings *s) +#define Sys_Font_Face_Change_Settings_Sig(n,id,s) b32 (n)(Face_ID id, Font_Settings *s) typedef Sys_Font_Face_Change_Settings_Sig(Font_Face_Change_Settings_Function, font_id, new_settings); -#define Sys_Font_Face_Release_Sig(n,id) b32 (n)(Font_ID id) +#define Sys_Font_Face_Release_Sig(n,id) b32 (n)(Face_ID id) typedef Sys_Font_Face_Release_Sig(Font_Face_Release_Function, font_id); -#define Sys_Font_Get_Largest_ID_Sig(n) Font_ID (n)(void) +#define Sys_Font_Get_Largest_ID_Sig(n) Face_ID (n)(void) typedef Sys_Font_Get_Largest_ID_Sig(Font_Get_Largest_ID_Function); #define Sys_Font_Get_Count_Sig(n) i32 (n)(void) typedef Sys_Font_Get_Count_Sig(Font_Get_Count_Function); -#define Sys_Font_Get_Name_By_ID_Sig(n, font_id, out, cap) i32 (n)(Font_ID font_id, char *out, u32 cap) +#define Sys_Font_Get_Name_By_ID_Sig(n, font_id, out, cap) i32 (n)(Face_ID font_id, char *out, u32 cap) typedef Sys_Font_Get_Name_By_ID_Sig(Font_Get_Name_By_ID_Function, font_id, out, cap); -#define Sys_Font_Get_Pointers_By_ID_Sig(n, font_id) Font_Pointers (n)(Font_ID font_id) +#define Sys_Font_Get_Pointers_By_ID_Sig(n, font_id) Font_Pointers (n)(Face_ID font_id) typedef Sys_Font_Get_Pointers_By_ID_Sig(Font_Get_Pointers_By_ID_Function, font_id); #define Sys_Font_Load_Page_Sig(n,s,m,p,pn) void (n)(Font_Settings *s, Font_Metrics *m, Glyph_Page *p, u32 pn) diff --git a/4ed_font_provider_freetype.cpp b/4ed_font_provider_freetype.cpp index a930c0b2..03f4e2f9 100644 --- a/4ed_font_provider_freetype.cpp +++ b/4ed_font_provider_freetype.cpp @@ -64,7 +64,10 @@ font_ft_get_face(FT_Library ft, Font_Loadable_Stub *stub, Font_Parameters *param if (data.size > 0){ FT_Error error = FT_New_Memory_Face(ft, data.data, data.size, 0, face); success = (error == 0); - do_transform = (success && data.used_base_file); + if (success){ + success = match((*face)->family_name, stub->name); + do_transform = (success && data.used_base_file); + } } else{ success = false; @@ -117,15 +120,8 @@ font_load_page_layout(Font_Settings *settings, Font_Metrics *metrics, Glyph_Page page->has_layout = true; u32 pt_size = settings->parameters.pt_size; - b32 italics = settings->parameters.italics; - b32 bold = settings->parameters.bold; - b32 underline = settings->parameters.underline; b32 use_hinting = settings->parameters.use_hinting; - AllowLocal(italics); - AllowLocal(bold); - AllowLocal(underline); - // TODO(allen): Stop redoing all this init for each call. FT_Library ft; FT_Init_FreeType(&ft); @@ -188,7 +184,7 @@ font_load_page_layout(Font_Settings *settings, Font_Metrics *metrics, Glyph_Page 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); + *advance_out = (f32)ceil32(face->glyph->advance.x/64.0f); pen_x = ceil32(glyph_out->x1 + 1); } @@ -217,15 +213,8 @@ font_load_page_pixels(Partition *part, Font_Settings *settings, Glyph_Page *page Assert(page->page_number == page_number); u32 pt_size = settings->parameters.pt_size; - b32 italics = settings->parameters.italics; - b32 bold = settings->parameters.bold; - b32 underline = settings->parameters.underline; b32 use_hinting = settings->parameters.use_hinting; - AllowLocal(italics); - AllowLocal(bold); - AllowLocal(underline); - // TODO(allen): Stop redoing all this init for each call. FT_Library ft; FT_Init_FreeType(&ft); @@ -363,14 +352,31 @@ font_load(System_Functions *system, Font_Settings *settings, Font_Metrics *metri } } - metrics->ascent = ceil32 (face->size->metrics.ascender / 64.0f); - metrics->descent = floor32 (face->size->metrics.descender / 64.0f); - metrics->advance = ceil32 (face->size->metrics.max_advance / 64.0f); - metrics->height = ceil32 (face->size->metrics.height / 64.0f); + 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 (metrics->height > pt_size*4){ + + 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_bottom(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{ @@ -558,7 +564,7 @@ Sys_Font_Face_Allocate_And_Init_Sig(system_font_face_allocate_and_init, new_sett 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]; - Font_ID new_id = page_with_slot->first_id + index; + Face_ID new_id = page_with_slot->first_id + index; Assert(((*is_active_flags) & is_active_mask) == 0); @@ -602,7 +608,7 @@ Sys_Font_Get_Count_Sig(system_font_get_count){ } internal Font_Slot_Page_And_Index -system_font_get_active_location(Font_ID font_id){ +system_font_get_active_location(Face_ID font_id){ Font_Slot_Page_And_Index result = {0}; for (Font_Slot_Page *page = fontvars.slot_pages_sentinel.next; @@ -658,6 +664,10 @@ Sys_Font_Face_Change_Settings_Sig(system_font_face_change_settings, font_id, new 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); } diff --git a/4ed_font_provider_freetype.h b/4ed_font_provider_freetype.h index f1a944ce..ade6617b 100644 --- a/4ed_font_provider_freetype.h +++ b/4ed_font_provider_freetype.h @@ -31,7 +31,7 @@ struct Font_Slot_Page{ i32 used_count; i32 fill_count; i32 max; - Font_ID first_id; + Face_ID first_id; }; struct Font_Slot_Page_And_Index{ @@ -48,7 +48,7 @@ struct Font_Vars{ Font_Slot_Page slot_pages_sentinel; i32 used_slot_count; i32 max_slot_count; - Font_ID largest_font_id; + Face_ID largest_font_id; // HACK(allen): // HACK(allen): // HACK(allen): // TODO(allen): Upgrade this to have "unlimited" resizable memory. diff --git a/4ed_render_fill.cpp b/4ed_render_fill.cpp index 4c86881b..776d95b3 100644 --- a/4ed_render_fill.cpp +++ b/4ed_render_fill.cpp @@ -89,7 +89,7 @@ draw_margin(Render_Target *target, i32_Rect outer, i32 width, u32 color){ } internal void -draw_font_glyph(Render_Target *target, Font_ID font_id, u32 codepoint, f32 x, f32 y, u32 color){ +draw_font_glyph(Render_Target *target, Face_ID font_id, u32 codepoint, f32 x, f32 y, u32 color){ Render_Command_Glyph cmd; CmdHeader(RenCom_Glyph); cmd.pos.x = x; @@ -102,7 +102,7 @@ draw_font_glyph(Render_Target *target, Font_ID font_id, u32 codepoint, f32 x, f3 } internal f32 -draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_id, String str_, i32 x_, i32 y_, u32 color){ +draw_string_base(System_Functions *system, Render_Target *target, Face_ID font_id, String str_, i32 x_, i32 y_, u32 color){ f32 x = 0; Font_Pointers font = system->font.get_pointers_by_id(font_id); @@ -155,26 +155,26 @@ draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_i } internal f32 -draw_string(System_Functions *system, Render_Target *target, Font_ID font_id, String str, i32 x, i32 y, u32 color){ +draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, String str, i32 x, i32 y, u32 color){ f32 w = draw_string_base(system, target, font_id, str, x, y, color); return(w); } internal f32 -draw_string(System_Functions *system, Render_Target *target, Font_ID font_id, char *str, i32 x, i32 y, u32 color){ +draw_string(System_Functions *system, Render_Target *target, Face_ID font_id, char *str, i32 x, i32 y, u32 color){ String string = make_string_slowly(str); f32 w = draw_string_base(system, target, font_id, string, x, y, color); return(w); } internal f32 -font_string_width(System_Functions *system, Render_Target *target, Font_ID font_id, String str){ +font_string_width(System_Functions *system, Render_Target *target, Face_ID font_id, String str){ f32 w = draw_string_base(system, target, font_id, str, 0, 0, 0); return(w); } internal f32 -font_string_width(System_Functions *system, Render_Target *target, Font_ID font_id, char *str){ +font_string_width(System_Functions *system, Render_Target *target, Face_ID font_id, char *str){ String string = make_string_slowly(str); f32 w = draw_string_base(system, target, font_id, string, 0, 0, 0); return(w); diff --git a/4ed_render_format.h b/4ed_render_format.h index 4615c4ca..e7beb0f1 100644 --- a/4ed_render_format.h +++ b/4ed_render_format.h @@ -43,7 +43,7 @@ struct Render_Command_Glyph{ Render_Command_Header header; Vec2 pos; u32 color; - Font_ID font_id; + Face_ID font_id; u32 codepoint; }; diff --git a/4ed_style.cpp b/4ed_style.cpp index c73dea32..4b798eaa 100644 --- a/4ed_style.cpp +++ b/4ed_style.cpp @@ -10,7 +10,7 @@ // TOP struct Style_Font{ - Font_ID font_id; + Face_ID font_id; }; struct Style{ diff --git a/4ed_view.cpp b/4ed_view.cpp index a14f2272..6ce82002 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -134,7 +134,7 @@ struct View{ View *hot_file_view; u32 *palette; Color_View_Mode color_mode; - Font_ID font_edit_id; + Face_ID font_edit_id; Super_Color color; b32 p4c_only; Style_Library inspecting_styles; diff --git a/opengl/4ed_opengl_render.cpp b/opengl/4ed_opengl_render.cpp index 765161c2..8c0094a1 100644 --- a/opengl/4ed_opengl_render.cpp +++ b/opengl/4ed_opengl_render.cpp @@ -218,6 +218,26 @@ interpret_render_buffer(Render_Target *t){ glTexCoord2f(uv.x0, uv.y0); glVertex2f(xy.x0, xy.y0); } glEnd(); + + if (codepoint != ' ' && font.settings->parameters.underline){ + glDisable(GL_TEXTURE_2D); + + f32 x0 = x; + f32 x1 = x + page->advance[glyph_index]; + f32 yoff1 = y + font.metrics->underline_yoff1; + f32 yoff2 = y + font.metrics->underline_yoff2; + + glBegin(GL_QUADS); + { + glVertex2f(x0, yoff1); + glVertex2f(x1, yoff1); + glVertex2f(x1, yoff2); + glVertex2f(x0, yoff2); + } + glEnd(); + + glEnable(GL_TEXTURE_2D); + } }break; case RenCom_ChangeClip: