font work

This commit is contained in:
Allen Webster 2016-06-16 23:31:15 -04:00
parent f8c5738dc1
commit da19d21bac
17 changed files with 686 additions and 473 deletions

View File

@ -103,7 +103,7 @@ typedef struct File_List{
int block_size; int block_size;
} File_List; } File_List;
// NOTE(allen|a4.0.7): This is used to identify which buffer // NOTE(allen|a4.0.8): This is used to identify which buffer
// an operation should work on when you might want to // an operation should work on when you might want to
// identify it by id or by name. // identify it by id or by name.
typedef struct Buffer_Identifier{ typedef struct Buffer_Identifier{
@ -117,6 +117,8 @@ enum Command_ID{
cmdid_center_view, cmdid_center_view,
cmdid_left_adjust_view, cmdid_left_adjust_view,
cmdid_page_up,
cmdid_page_down,
cmdid_word_complete, cmdid_word_complete,
@ -125,6 +127,18 @@ enum Command_ID{
cmdid_history_backward, cmdid_history_backward,
cmdid_history_forward, cmdid_history_forward,
cmdid_to_uppercase,
cmdid_to_lowercase,
cmdid_toggle_line_wrap,
cmdid_toggle_show_whitespace,
cmdid_clean_all_lines,
cmdid_eol_dosify,
cmdid_eol_nixify,
cmdid_hide_scrollbar,
cmdid_show_scrollbar,
cmdid_interactive_new, cmdid_interactive_new,
cmdid_interactive_open, cmdid_interactive_open,
cmdid_reopen, cmdid_reopen,
@ -134,31 +148,15 @@ enum Command_ID{
cmdid_interactive_kill_buffer, cmdid_interactive_kill_buffer,
cmdid_kill_buffer, cmdid_kill_buffer,
cmdid_to_uppercase,
cmdid_to_lowercase,
cmdid_toggle_line_wrap,
cmdid_toggle_show_whitespace,
cmdid_clean_all_lines,
cmdid_eol_dosify,
cmdid_eol_nixify,
cmdid_open_panel_vsplit,
cmdid_open_panel_hsplit,
cmdid_close_panel,
cmdid_change_active_panel,
cmdid_page_up,
cmdid_page_down,
cmdid_open_color_tweaker, cmdid_open_color_tweaker,
cmdid_open_config, cmdid_open_config,
cmdid_open_menu, cmdid_open_menu,
cmdid_open_debug, cmdid_open_debug,
cmdid_hide_scrollbar, cmdid_open_panel_vsplit,
cmdid_show_scrollbar, cmdid_open_panel_hsplit,
cmdid_close_panel,
cmdid_change_active_panel,
// //
cmdid_count cmdid_count

View File

@ -19,7 +19,9 @@
#define BUFFER_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len) #define BUFFER_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len)
#define BUFFER_SEEK_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags) #define BUFFER_SEEK_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags)
#define BUFFER_SET_SETTING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int setting, int value) #define BUFFER_SET_SETTING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int setting, int value)
#define BUFFER_SAVE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len) #define CREATE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int filename_len, int do_in_background)
#define SAVE_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len)
#define KILL_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Identifier buffer, int always_kill, int view_id)
#define GET_VIEW_FIRST_SIG(n) View_Summary n(Application_Links *app) #define GET_VIEW_FIRST_SIG(n) View_Summary n(Application_Links *app)
#define GET_VIEW_NEXT_SIG(n) void n(Application_Links *app, View_Summary *view) #define GET_VIEW_NEXT_SIG(n) void n(Application_Links *app, View_Summary *view)
#define GET_VIEW_SIG(n) View_Summary n(Application_Links *app, int index) #define GET_VIEW_SIG(n) View_Summary n(Application_Links *app, int index)
@ -34,8 +36,6 @@
#define VIEW_POST_FADE_SIG(n) int n(Application_Links *app, View_Summary *view, int ticks, int start, int end, unsigned int color) #define VIEW_POST_FADE_SIG(n) int n(Application_Links *app, View_Summary *view, int ticks, int start, int end, unsigned int color)
#define VIEW_SET_PASTE_REWRITE__SIG(n) void n(Application_Links *app, View_Summary *view) #define VIEW_SET_PASTE_REWRITE__SIG(n) void n(Application_Links *app, View_Summary *view)
#define VIEW_GET_PASTE_REWRITE__SIG(n) int n(Application_Links *app, View_Summary *view) #define VIEW_GET_PASTE_REWRITE__SIG(n) int n(Application_Links *app, View_Summary *view)
#define VIEW_OPEN_FILE_SIG(n) int n(Application_Links *app, View_Summary *view, char *filename, int filename_len, int do_in_background)
#define VIEW_KILL_BUFFER_SIG(n) int n(Application_Links *app, View_Summary *view, Buffer_Identifier buffer)
#define GET_USER_INPUT_SIG(n) User_Input n(Application_Links *app, unsigned int get_type, unsigned int abort_type) #define GET_USER_INPUT_SIG(n) User_Input n(Application_Links *app, unsigned int get_type, unsigned int abort_type)
#define GET_COMMAND_INPUT_SIG(n) User_Input n(Application_Links *app) #define GET_COMMAND_INPUT_SIG(n) User_Input n(Application_Links *app)
#define GET_EVENT_MESSAGE_SIG(n) Event_Message n(Application_Links *app) #define GET_EVENT_MESSAGE_SIG(n) Event_Message n(Application_Links *app)
@ -69,7 +69,9 @@ extern "C"{
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function); typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
typedef BUFFER_SEEK_SIG(Buffer_Seek_Function); typedef BUFFER_SEEK_SIG(Buffer_Seek_Function);
typedef BUFFER_SET_SETTING_SIG(Buffer_Set_Setting_Function); typedef BUFFER_SET_SETTING_SIG(Buffer_Set_Setting_Function);
typedef BUFFER_SAVE_SIG(Buffer_Save_Function); typedef CREATE_BUFFER_SIG(Create_Buffer_Function);
typedef SAVE_BUFFER_SIG(Save_Buffer_Function);
typedef KILL_BUFFER_SIG(Kill_Buffer_Function);
typedef GET_VIEW_FIRST_SIG(Get_View_First_Function); typedef GET_VIEW_FIRST_SIG(Get_View_First_Function);
typedef GET_VIEW_NEXT_SIG(Get_View_Next_Function); typedef GET_VIEW_NEXT_SIG(Get_View_Next_Function);
typedef GET_VIEW_SIG(Get_View_Function); typedef GET_VIEW_SIG(Get_View_Function);
@ -84,8 +86,6 @@ extern "C"{
typedef VIEW_POST_FADE_SIG(View_Post_Fade_Function); typedef VIEW_POST_FADE_SIG(View_Post_Fade_Function);
typedef VIEW_SET_PASTE_REWRITE__SIG(View_Set_Paste_Rewrite__Function); typedef VIEW_SET_PASTE_REWRITE__SIG(View_Set_Paste_Rewrite__Function);
typedef VIEW_GET_PASTE_REWRITE__SIG(View_Get_Paste_Rewrite__Function); typedef VIEW_GET_PASTE_REWRITE__SIG(View_Get_Paste_Rewrite__Function);
typedef VIEW_OPEN_FILE_SIG(View_Open_File_Function);
typedef VIEW_KILL_BUFFER_SIG(View_Kill_Buffer_Function);
typedef GET_USER_INPUT_SIG(Get_User_Input_Function); typedef GET_USER_INPUT_SIG(Get_User_Input_Function);
typedef GET_COMMAND_INPUT_SIG(Get_Command_Input_Function); typedef GET_COMMAND_INPUT_SIG(Get_Command_Input_Function);
typedef GET_EVENT_MESSAGE_SIG(Get_Event_Message_Function); typedef GET_EVENT_MESSAGE_SIG(Get_Event_Message_Function);
@ -122,7 +122,9 @@ struct Application_Links{
Buffer_Replace_Range_Function *buffer_replace_range; Buffer_Replace_Range_Function *buffer_replace_range;
Buffer_Seek_Function *buffer_seek; Buffer_Seek_Function *buffer_seek;
Buffer_Set_Setting_Function *buffer_set_setting; Buffer_Set_Setting_Function *buffer_set_setting;
Buffer_Save_Function *buffer_save; Create_Buffer_Function *create_buffer;
Save_Buffer_Function *save_buffer;
Kill_Buffer_Function *kill_buffer;
Get_View_First_Function *get_view_first; Get_View_First_Function *get_view_first;
Get_View_Next_Function *get_view_next; Get_View_Next_Function *get_view_next;
Get_View_Function *get_view; Get_View_Function *get_view;
@ -137,8 +139,6 @@ struct Application_Links{
View_Post_Fade_Function *view_post_fade; View_Post_Fade_Function *view_post_fade;
View_Set_Paste_Rewrite__Function *view_set_paste_rewrite_; View_Set_Paste_Rewrite__Function *view_set_paste_rewrite_;
View_Get_Paste_Rewrite__Function *view_get_paste_rewrite_; View_Get_Paste_Rewrite__Function *view_get_paste_rewrite_;
View_Open_File_Function *view_open_file;
View_Kill_Buffer_Function *view_kill_buffer;
Get_User_Input_Function *get_user_input; Get_User_Input_Function *get_user_input;
Get_Command_Input_Function *get_command_input; Get_Command_Input_Function *get_command_input;
Get_Event_Message_Function *get_event_message; Get_Event_Message_Function *get_event_message;
@ -177,7 +177,9 @@ app_links->buffer_read_range = external_buffer_read_range;\
app_links->buffer_replace_range = external_buffer_replace_range;\ app_links->buffer_replace_range = external_buffer_replace_range;\
app_links->buffer_seek = external_buffer_seek;\ app_links->buffer_seek = external_buffer_seek;\
app_links->buffer_set_setting = external_buffer_set_setting;\ app_links->buffer_set_setting = external_buffer_set_setting;\
app_links->buffer_save = external_buffer_save;\ app_links->create_buffer = external_create_buffer;\
app_links->save_buffer = external_save_buffer;\
app_links->kill_buffer = external_kill_buffer;\
app_links->get_view_first = external_get_view_first;\ app_links->get_view_first = external_get_view_first;\
app_links->get_view_next = external_get_view_next;\ app_links->get_view_next = external_get_view_next;\
app_links->get_view = external_get_view;\ app_links->get_view = external_get_view;\
@ -192,8 +194,6 @@ app_links->view_set_buffer = external_view_set_buffer;\
app_links->view_post_fade = external_view_post_fade;\ app_links->view_post_fade = external_view_post_fade;\
app_links->view_set_paste_rewrite_ = external_view_set_paste_rewrite_;\ app_links->view_set_paste_rewrite_ = external_view_set_paste_rewrite_;\
app_links->view_get_paste_rewrite_ = external_view_get_paste_rewrite_;\ app_links->view_get_paste_rewrite_ = external_view_get_paste_rewrite_;\
app_links->view_open_file = external_view_open_file;\
app_links->view_kill_buffer = external_view_kill_buffer;\
app_links->get_user_input = external_get_user_input;\ app_links->get_user_input = external_get_user_input;\
app_links->get_command_input = external_get_command_input;\ app_links->get_command_input = external_get_command_input;\
app_links->get_event_message = external_get_event_message;\ app_links->get_event_message = external_get_event_message;\

View File

@ -96,7 +96,7 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
CUSTOM_COMMAND_SIG(open_my_files){ CUSTOM_COMMAND_SIG(open_my_files){
// TODO(allen|a4.0.8): comment // TODO(allen|a4.0.8): comment
View_Summary view = app->get_active_view(app); View_Summary view = app->get_active_view(app);
app->view_open_file(app, &view, literal("w:/4ed/data/test/basic.cpp"), false); view_open_file(app, &view, literal("w:/4ed/data/test/basic.cpp"), false);
} }
CUSTOM_COMMAND_SIG(build_at_launch_location){ CUSTOM_COMMAND_SIG(build_at_launch_location){

View File

@ -784,7 +784,7 @@ CUSTOM_COMMAND_SIG(open_file_in_quotes){
append(&file_name, make_string(short_file_name, size)); append(&file_name, make_string(short_file_name, size));
exec_command(app, cmdid_change_active_panel); exec_command(app, cmdid_change_active_panel);
app->view_open_file(app, &view, expand_str(file_name), false); view_open_file(app, &view, expand_str(file_name), false);
} }
} }
@ -1065,10 +1065,8 @@ CUSTOM_COMMAND_SIG(close_all_code){
} }
} }
View_Summary view = app->get_active_view(app);
for (int i = 0; i < buffers_to_close_count; ++i){ for (int i = 0; i < buffers_to_close_count; ++i){
app->view_kill_buffer(app, &view, buffer_identifier(buffers_to_close[i])); app->kill_buffer(app, buffer_identifier(buffers_to_close[i]), true, 0);
} }
} }

View File

@ -725,4 +725,25 @@ buffer_identifier(int id){
return(identifier); return(identifier);
} }
static int
view_open_file(Application_Links *app, View_Summary *view,
char *filename, int filename_len, int do_in_background){
int result = false;
Buffer_Summary buffer = app->get_buffer_by_name(app, filename, filename_len);
if (buffer.exists){
app->view_set_buffer(app, view, buffer.buffer_id);
result = true;
}
else{
buffer = app->create_buffer(app, filename, filename_len, do_in_background);
if (!do_in_background){
if (buffer.exists){
app->view_set_buffer(app, view, buffer.buffer_id);
result = true;
}
}
}
return(result);
}

View File

@ -31,7 +31,7 @@ i32R(int32_t l, int32_t t, int32_t r, int32_t b){
i32_Rect rect; i32_Rect rect;
rect.x0 = l; rect.y0 = t; rect.x0 = l; rect.y0 = t;
rect.x1 = r; rect.y1 = b; rect.x1 = r; rect.y1 = b;
return rect; return(rect);
} }
inline i32_Rect inline i32_Rect
@ -41,7 +41,7 @@ i32R(f32_Rect r){
rect.y0 = (int32_t)r.y0; rect.y0 = (int32_t)r.y0;
rect.x1 = (int32_t)r.x1; rect.x1 = (int32_t)r.x1;
rect.y1 = (int32_t)r.y1; rect.y1 = (int32_t)r.y1;
return rect; return(rect);
} }
inline i32_Rect inline i32_Rect
@ -49,7 +49,7 @@ i32XYWH(int32_t x, int32_t y, int32_t w, int32_t h){
i32_Rect rect; i32_Rect rect;
rect.x0 = x; rect.y0 = y; rect.x0 = x; rect.y0 = y;
rect.x1 = x+w; rect.y1 = y+h; rect.x1 = x+w; rect.y1 = y+h;
return rect; return(rect);
} }
inline f32_Rect inline f32_Rect
@ -57,7 +57,7 @@ f32R(float l, float t, float r, float b){
f32_Rect rect; f32_Rect rect;
rect.x0 = l; rect.y0 = t; rect.x0 = l; rect.y0 = t;
rect.x1 = r; rect.y1 = b; rect.x1 = r; rect.y1 = b;
return rect; return(rect);
} }
inline f32_Rect inline f32_Rect
@ -67,7 +67,7 @@ f32R(i32_Rect r){
rect.y0 = (float)r.y0; rect.y0 = (float)r.y0;
rect.x1 = (float)r.x1; rect.x1 = (float)r.x1;
rect.y1 = (float)r.y1; rect.y1 = (float)r.y1;
return rect; return(rect);
} }
inline f32_Rect inline f32_Rect
@ -75,7 +75,7 @@ f32XYWH(float x, float y, float w, float h){
f32_Rect rect; f32_Rect rect;
rect.x0 = x; rect.y0 = y; rect.x0 = x; rect.y0 = y;
rect.x1 = x+w; rect.y1 = y+h; rect.x1 = x+w; rect.y1 = y+h;
return rect; return(rect);
} }
inline int inline int

12
4ed.cpp
View File

@ -1793,23 +1793,23 @@ App_Init_Sig(app_init){
Font_Setup font_setup[] = { Font_Setup font_setup[] = {
{literal("LiberationSans-Regular.ttf"), {literal("LiberationSans-Regular.ttf"),
literal("liberation sans"), literal("Liberation Sans"),
font_size}, font_size},
{literal("liberation-mono.ttf"), {literal("liberation-mono.ttf"),
literal("liberation mono"), literal("Liberation Mono"),
font_size}, font_size},
{literal("Hack-Regular.ttf"), {literal("Hack-Regular.ttf"),
literal("hack"), literal("Hack"),
font_size}, font_size},
{literal("CutiveMono-Regular.ttf"), {literal("CutiveMono-Regular.ttf"),
literal("cutive mono"), literal("Cutive Mono"),
font_size}, font_size},
{literal("Inconsolata-Regular.ttf"), {literal("Inconsolata-Regular.ttf"),
literal("inconsolata"), literal("Inconsolata"),
font_size}, font_size},
}; };
i32 font_count = ArrayCount(font_setup); i32 font_count = ArrayCount(font_setup);
@ -2650,7 +2650,7 @@ App_Step_Sig(app_step){
"\n" "\n"
"New in alpha 4.0.7:\n" "New in alpha 4.0.7:\n"
"-Right click sets the mark\n" "-Right click sets the mark\n"
"-Clicks are now have key codes so they can have event bound in customizations\n" "-Clicks now have key codes so they can have events bound in customizations\n"
"-<alt d> opens a debug view, see more in README.txt\n" "-<alt d> opens a debug view, see more in README.txt\n"
"\n" "\n"
"New in alpha 4.0.6:\n" "New in alpha 4.0.6:\n"

View File

@ -129,15 +129,24 @@ imp_get_file(Command_Data *cmd, Buffer_Summary *buffer){
} }
internal View* internal View*
imp_get_view(Command_Data *cmd, View_Summary *view){ imp_get_view(Command_Data *cmd, int view_id){
View *vptr = 0;
Live_Views *live_set = cmd->live_set; Live_Views *live_set = cmd->live_set;
int view_id = view->view_id - 1; View *vptr = 0;
if (view->exists){ view_id = view_id - 1;
if (view_id >= 0 && view_id < live_set->max){ if (view_id >= 0 && view_id < live_set->max){
vptr = live_set->views + view_id; vptr = live_set->views + view_id;
} }
return(vptr);
}
internal View*
imp_get_view(Command_Data *cmd, View_Summary *view){
View *vptr = 0;
if (view->exists){
vptr = imp_get_view(cmd, view->view_id);
} }
return(vptr); return(vptr);
@ -652,7 +661,7 @@ BUFFER_SET_SETTING_SIG(external_buffer_set_setting){
return(result); return(result);
} }
BUFFER_SAVE_SIG(external_buffer_save){ SAVE_BUFFER_SIG(external_save_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context; Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system; System_Functions *system = cmd->system;
Models *models = cmd->models; Models *models = cmd->models;
@ -670,6 +679,93 @@ BUFFER_SAVE_SIG(external_buffer_save){
return(result); return(result);
} }
// TODO(allen): REPLACE THIS WITH CREATE_BUFFER!!!
CREATE_BUFFER_SIG(external_create_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
General_Memory *general = &models->mem.general;
Partition *part = &models->mem.part;
Buffer_Summary result = {0};
Temp_Memory temp = begin_temp_memory(part);
if (filename != 0){
String filename_string = make_string(filename, filename_len);
Editing_File *file = working_set_contains(system, working_set, filename_string);
if (file == 0){
File_Loading loading = system->file_load_begin(filename);
if (loading.exists){
b32 in_general_mem = false;
char *buffer = push_array(part, char, loading.size);
if (buffer == 0){
buffer = (char*)general_memory_allocate(general, loading.size);
if (buffer != 0){
in_general_mem = true;
}
}
if (system->file_load_end(loading, buffer)){
file = working_set_alloc_always(working_set, general);
if (file){
file_init_strings(file);
file_set_name(working_set, file, filename_string);
working_set_add(system, working_set, file, general);
init_normal_file(system, models, file,
buffer, loading.size);
fill_buffer_summary(&result, file, cmd);
}
}
if (in_general_mem){
general_memory_free(general, buffer);
}
}
else{
file = working_set_alloc_always(working_set, general);
if (file){
file_init_strings(file);
file_set_name(working_set, file, filename_string);
working_set_add(system, working_set, file, general);
init_normal_file(system, models, file, 0, 0);
fill_buffer_summary(&result, file, cmd);
}
}
}
else{
fill_buffer_summary(&result, file, cmd);
}
}
end_temp_memory(temp);
return(result);
}
KILL_BUFFER_SIG(external_kill_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
View *vptr = imp_get_view(cmd, view_id);
Editing_File *file = get_file_from_identifier(system, working_set, buffer);
int result = false;
if (file){
result = true;
if (always_kill){
kill_file(system, models, file, string_zero());
}
else{
try_kill_file(system, models, file, vptr, string_zero());
}
}
return(result);
}
GET_VIEW_FIRST_SIG(external_get_view_first){ GET_VIEW_FIRST_SIG(external_get_view_first){
Command_Data *cmd = (Command_Data*)app->cmd_context; Command_Data *cmd = (Command_Data*)app->cmd_context;
Editing_Layout *layout = &cmd->models->layout; Editing_Layout *layout = &cmd->models->layout;
@ -913,69 +1009,6 @@ VIEW_GET_PASTE_REWRITE__SIG(external_view_get_paste_rewrite_){
return(result); return(result);
} }
VIEW_OPEN_FILE_SIG(external_view_open_file){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
Live_Views *live_set = cmd->live_set;
int result = false;
// TODO(allen): do in background
// option happens in parallel.
Partition *part = &models->mem.part;
Temp_Memory temp = begin_temp_memory(part);
String string = make_string_terminated(part, filename, filename_len);
if (do_in_background){
result = true;
view_open_file(system, models, 0, string);
}
else if (view){
View *vptr = 0;
int view_id = view->view_id - 1;
if (view_id >= 0 && view_id < live_set->max){
vptr = live_set->views + view_id;
result = true;
view_open_file(system, models, 0, string);
fill_view_summary(view, vptr, live_set, working_set);
}
}
end_temp_memory(temp);
return(result);
}
VIEW_KILL_BUFFER_SIG(external_view_kill_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Working_Set *working_set = &models->working_set;
View *vptr = imp_get_view(cmd, view);
Editing_File *file = 0;
int result = false;
if (vptr){
file = get_file_from_identifier(system, working_set, buffer);
if (file){
result = true;
try_kill_file(system, models, file, vptr, string_zero());
fill_view_summary(view, vptr, cmd);
}
}
return(result);
}
GET_USER_INPUT_SIG(external_get_user_input){ GET_USER_INPUT_SIG(external_get_user_input){
Command_Data *cmd = (Command_Data*)app->cmd_context; Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system; System_Functions *system = cmd->system;

View File

@ -382,23 +382,22 @@ file_init_strings(Editing_File *file){
file->name.extension = make_fixed_width_string(file->name.extension_); file->name.extension = make_fixed_width_string(file->name.extension_);
} }
inline void internal void
file_set_name(Working_Set *working_set, Editing_File *file, char *filename){ file_set_name(Working_Set *working_set, Editing_File *file, String filename){
String f, ext; String ext;
Assert(file->name.live_name.str != 0); Assert(file->name.live_name.str != 0);
f = make_string_slowly(filename); copy_checked(&file->name.source_path, filename);
copy_checked(&file->name.source_path, f);
file->name.live_name.size = 0; file->name.live_name.size = 0;
get_front_of_directory(&file->name.live_name, f); get_front_of_directory(&file->name.live_name, filename);
if (file->name.source_path.size == file->name.live_name.size){ if (file->name.source_path.size == file->name.live_name.size){
file->name.extension.size = 0; file->name.extension.size = 0;
} }
else{ else{
ext = file_extension(f); ext = file_extension(filename);
copy(&file->name.extension, ext); copy(&file->name.extension, ext);
} }
@ -435,6 +434,12 @@ file_set_name(Working_Set *working_set, Editing_File *file, char *filename){
} }
} }
inline void
file_set_name(Working_Set *working_set, Editing_File *file, char *filename){
String f = make_string_slowly(filename);
file_set_name(working_set, file, f);
}
inline void inline void
file_synchronize_times(System_Functions *system, Editing_File *file, char *filename){ file_synchronize_times(System_Functions *system, Editing_File *file, char *filename){
u64 stamp = system->file_time_stamp(filename); u64 stamp = system->file_time_stamp(filename);
@ -613,19 +618,6 @@ file_measure_starts_widths(System_Functions *system, General_Memory *general,
buffer->widths_count = state.count; buffer->widths_count = state.count;
} }
struct Opaque_Font_Advance{
void *data;
int stride;
};
inline Opaque_Font_Advance
get_opaque_font_advance(Render_Font *font){
Opaque_Font_Advance result;
result.data = (char*)font->chardata + OffsetOfPtr(font->chardata, xadvance);
result.stride = sizeof(*font->chardata);
return result;
}
inline i32 inline i32
view_wrapped_line_span(f32 line_width, f32 max_width){ view_wrapped_line_span(f32 line_width, f32 max_width){
i32 line_count = CEIL32(line_width / max_width); i32 line_count = CEIL32(line_width / max_width);
@ -700,7 +692,8 @@ view_measure_wraps(General_Memory *general, View *view){
internal void internal void
file_create_from_string(System_Functions *system, Models *models, file_create_from_string(System_Functions *system, Models *models,
Editing_File *file, char *filename, String val, b8 read_only = 0){ Editing_File *file, char *name,
String val, b8 read_only = 0){
Font_Set *font_set = models->font_set; Font_Set *font_set = models->font_set;
Working_Set *working_set = &models->working_set; Working_Set *working_set = &models->working_set;
@ -731,11 +724,12 @@ file_create_from_string(System_Functions *system, Models *models,
} }
file_init_strings(file); file_init_strings(file);
file_set_name(working_set, file, (char*)filename);
file_set_name(working_set, file, (char*)name);
file->state.font_id = models->global_font.font_id; file->state.font_id = models->global_font.font_id;
file_synchronize_times(system, file, filename); file_synchronize_times(system, file, name);
Render_Font *font = get_font_info(font_set, file->state.font_id)->font; Render_Font *font = get_font_info(font_set, file->state.font_id)->font;
float *advance_data = 0; float *advance_data = 0;
@ -5423,7 +5417,14 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
u32 char_color = main_color; u32 char_color = main_color;
if (item->flags & BRFlag_Special_Character) char_color = special_color; if (item->flags & BRFlag_Special_Character) char_color = special_color;
f32_Rect char_rect = f32R(item->x0, item->y0, item->x1, item->y1); #if 0
i32_Rect char_rect = i32R(item->x0, item->y0,
item->x1, item->y1);
#else
f32_Rect char_rect = f32R(item->x0, item->y0,
item->x1, item->y1);
#endif
if (view->file_data.show_whitespace && highlight_color == 0 && if (view->file_data.show_whitespace && highlight_color == 0 &&
char_is_whitespace((char)item->glyphid)){ char_is_whitespace((char)item->glyphid)){
highlight_this_color = style->main.highlight_white_color; highlight_this_color = style->main.highlight_white_color;

View File

@ -119,7 +119,10 @@ font_set_load(Partition *partition, Font_Set *set, i16 font_id){
font__insert(&set->used_slots, slot); font__insert(&set->used_slots, slot);
Render_Font *font = (Render_Font*)(slot + 1); Render_Font *font = (Render_Font*)(slot + 1);
set->font_load(font, info->filename.str, info->pt_size, 4, 1); set->font_load(font,
info->filename.str,
info->name.str,
info->pt_size, 4, true);
info->font = font; info->font = font;
slot->font_id = font_id; slot->font_id = font_id;
} }
@ -182,7 +185,10 @@ font_set_add(Partition *partition, Font_Set *set,
info->filename = filename; info->filename = filename;
info->name = name; info->name = name;
info->pt_size = pt_size; info->pt_size = pt_size;
set->font_load(&dummy_font, info->filename.str, info->pt_size, 4, 0); set->font_load(&dummy_font,
info->filename.str,
info->name.str,
info->pt_size, 4, false);
info->height = dummy_font.height; info->height = dummy_font.height;
info->advance = dummy_font.advance; info->advance = dummy_font.advance;

View File

@ -165,19 +165,56 @@ private_draw_gradient(Render_Target *target, f32_Rect rect,
glEnd(); glEnd();
} }
struct Render_Quad{
f32 x0, y0, x1, y1;
f32 s0, t0, s1, t1;
};
inline Render_Quad
get_render_quad(Glyph_Data *b, int pw, int ph, float xpos, float ypos){
Render_Quad q;
float ipw = 1.0f / pw, iph = 1.0f / ph;
q.x0 = xpos + b->xoff;
q.y0 = ypos + b->yoff;
q.x1 = xpos + b->xoff2;
q.y1 = ypos + b->yoff2;
q.s0 = b->x0 * ipw;
q.t0 = b->y0 * iph;
q.s1 = b->x1 * ipw;
q.t1 = b->y1 * iph;
return(q);
}
inline Render_Quad
get_exact_render_quad(Glyph_Data *b, int pw, int ph, float xpos, float ypos){
Render_Quad q;
float ipw = 1.0f / pw, iph = 1.0f / ph;
q.x0 = xpos;
q.y0 = ypos + b->yoff;
q.x1 = xpos + (b->xoff2 - b->xoff);
q.y1 = ypos + b->yoff2;
q.s0 = b->x0 * ipw;
q.t0 = b->y0 * iph;
q.s1 = b->x1 * ipw;
q.t1 = b->y1 * iph;
return(q);
}
inline void inline void
private_draw_glyph(Render_Target *target, Render_Font *font, private_draw_glyph(Render_Target *target, Render_Font *font,
u8 character, f32 x, f32 y, u32 color){ u8 character, f32 x, f32 y, u32 color){
f32 x_shift, y_shift; Render_Quad q = get_render_quad(
x_shift = 0; font->glyphs + character,
y_shift = (f32)font->ascent; font->tex_width, font->tex_height, x, y
);
x += x_shift;
y += y_shift;
stbtt_aligned_quad q;
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height,
character, &x, &y, &q, 0);
draw_set_color(target, color); draw_set_color(target, color);
draw_bind_texture(target, font->tex); draw_bind_texture(target, font->tex);
@ -194,19 +231,18 @@ private_draw_glyph(Render_Target *target, Render_Font *font,
inline void inline void
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
f32 x, f32 y, f32 advance, u32 color){ f32 x, f32 y, f32 advance, u32 color){
f32 x_shift, y_shift;
i32 left = font->chardata[character].x0; f32 left = font->glyphs[character].x0;
i32 right = font->chardata[character].x1; f32 right = font->glyphs[character].x1;
i32 width = (right - left); f32 width = (right - left);
x_shift = (f32)(advance - width) * .5f - font->chardata[character].xoff; f32 x_shift = (advance - width) * .5f;
y_shift = (f32)font->ascent;
x += x_shift; x += x_shift;
y += y_shift;
stbtt_aligned_quad q; Render_Quad q = get_exact_render_quad(
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height, font->glyphs + character,
character, &x, &y, &q, 0); font->tex_width, font->tex_height, x, y
);
draw_set_color(target, color); draw_set_color(target, color);
draw_bind_texture(target, font->tex); draw_bind_texture(target, font->tex);
@ -305,6 +341,23 @@ launch_rendering(Render_Target *target){
#undef ExtractStruct #undef ExtractStruct
internal void*
part_alloc(int size, void *context){
Partition *part = (Partition*)context;
void *result = push_block(part, size);
return(result);
}
internal void
part_free(void *ptr, void *context){
}
#define STBTT_malloc part_alloc
#define STBTT_free part_free
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
// TODO(allen): Put the burden of translation outside // TODO(allen): Put the burden of translation outside
// of this function (and other functions implementing // of this function (and other functions implementing
// the same interface). // the same interface).
@ -324,7 +377,7 @@ draw_font_load(Partition *part,
i32 result = 1; i32 result = 1;
stbtt_packedchar *chardata = font_out->chardata; stbtt_packedchar chardata[256];
File_Data file = sysshared_load_file(filename.str); File_Data file = sysshared_load_file(filename.str);
@ -364,6 +417,7 @@ draw_font_load(Partition *part,
font_out->tex_width = tex_width; font_out->tex_width = tex_width;
font_out->tex_height = tex_height; font_out->tex_height = tex_height;
/////////////////////////////////////////////////////////////////
stbtt_pack_context spc; stbtt_pack_context spc;
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
@ -380,6 +434,7 @@ draw_font_load(Partition *part,
else{ else{
result = 0; result = 0;
} }
/////////////////////////////////////////////////////////////////
if (result){ if (result){
GLuint font_tex; GLuint font_tex;
@ -395,21 +450,37 @@ draw_font_load(Partition *part,
font_out->tex = font_tex; font_out->tex = font_tex;
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
font_out->chardata['\r'] = font_out->chardata[' ']; f32 *advance_data = font_out->advance_data;
font_out->chardata['\n'] = font_out->chardata[' ']; Glyph_Data *glyphs = font_out->glyphs;
font_out->chardata['\t'] = font_out->chardata[' ']; for (u8 code_point = 0; code_point < 128; ++code_point){
font_out->chardata['\t'].xadvance *= tab_width; advance_data[code_point] = (f32)(CEIL32(chardata[code_point].xadvance));
glyphs[code_point].x0 = chardata[code_point].x0;
glyphs[code_point].y0 = chardata[code_point].y0;
glyphs[code_point].x1 = chardata[code_point].x1;
glyphs[code_point].y1 = chardata[code_point].y1;
glyphs[code_point].xoff = chardata[code_point].xoff;
glyphs[code_point].yoff = chardata[code_point].yoff + font_out->ascent;
glyphs[code_point].xoff2 = chardata[code_point].xoff2;
glyphs[code_point].yoff2 = chardata[code_point].yoff2 + font_out->ascent;
}
glyphs['\r'] = glyphs[' '];
advance_data['\r'] = advance_data[' '];
glyphs['\n'] = glyphs[' '];
advance_data['\n'] = advance_data[' '];
glyphs['\t'] = glyphs[' '];
advance_data['\t'] = advance_data[' ']*tab_width;
i32 max_advance = 0; i32 max_advance = 0;
for (u8 code_point = 0; code_point < 128; ++code_point){ for (u8 code_point = 0; code_point < 128; ++code_point){
if (stbtt_FindGlyphIndex(&font, code_point) != 0){ if (stbtt_FindGlyphIndex(&font, code_point) != 0){
font_out->glyphs[code_point].exists = 1; font_out->glyphs[code_point].exists = 1;
i32 advance = CEIL32(font_out->chardata[code_point].xadvance); i32 advance = CEIL32(advance_data[code_point]);
if (max_advance < advance) max_advance = advance; if (max_advance < advance){
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; max_advance = advance;
} }
else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
} }
} }
font_out->advance = max_advance - 1; font_out->advance = max_advance - 1;

View File

@ -12,25 +12,14 @@
#ifndef FRED_RENDERING_H #ifndef FRED_RENDERING_H
#define FRED_RENDERING_H #define FRED_RENDERING_H
internal void*
part_alloc(int size, void *context){
Partition *part = (Partition*)context;
void *result = push_block(part, size);
return(result);
}
internal void
part_free(void *ptr, void *context){
}
#define STBTT_malloc part_alloc
#define STBTT_free part_free
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
struct Glyph_Data{ struct Glyph_Data{
b32 exists; b32 exists;
f32 x0, x1;
f32 y0, y1;
f32 xoff, yoff;
f32 xoff2, yoff2;
}; };
struct Render_Font{ struct Render_Font{
@ -38,8 +27,10 @@ struct Render_Font{
String name; String name;
b32 loaded; b32 loaded;
// TODO(allen): Have our own type here instead
// of stbtt_packedchar, and have both stb fonts
// and OS fonts go to our type.
Glyph_Data glyphs[256]; Glyph_Data glyphs[256];
stbtt_packedchar chardata[256];
float advance_data[256]; float advance_data[256];
i32 height, ascent, descent, line_skip; i32 height, ascent, descent, line_skip;
i32 advance; i32 advance;
@ -114,6 +105,7 @@ typedef Draw_Push_Piece_Sig(Draw_Push_Piece);
#define Font_Load_Sig(name) i32 name( \ #define Font_Load_Sig(name) i32 name( \
Render_Font *font_out, \ Render_Font *font_out, \
char *filename, \ char *filename, \
char *fontname, \
i32 pt_size, \ i32 pt_size, \
i32 tab_width, \ i32 tab_width, \
b32 store_texture) b32 store_texture)

View File

@ -115,11 +115,6 @@ font_predict_size(i32 pt_size){
return pt_size*pt_size*128; return pt_size*pt_size*128;
} }
internal void
font_set_tabwidth(Render_Font *font, i32 tab_width){
font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width;
}
internal void internal void
font_draw_glyph_mono(Render_Target *target, i16 font_id, font_draw_glyph_mono(Render_Target *target, i16 font_id,
u8 character, f32 x, f32 y, f32 advance, u32 color){ u8 character, f32 x, f32 y, f32 advance, u32 color){
@ -155,117 +150,95 @@ font_draw_glyph(Render_Target *target, i16 font_id,
font_set_use(target->partition, &target->font_set, font_id); font_set_use(target->partition, &target->font_set, font_id);
} }
inline f32 // TODO(allen): Someday let's not punt on the the unicode rendering
font_get_glyph_width(Render_Target *target, i16 font_id, u16 character){
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 result = 0.f;
if (font) result = font->chardata[character].xadvance;
return (result);
}
internal f32 internal f32
font_string_width(Render_Target *target, i16 font_id, char *str){ font_string_width(Render_Target *target, i16 font_id, char *str){
f32 x = 0; f32 x = 0;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; str[i]; ++i){ for (i32 i = 0; str[i]; ++i){
u8 c = str[i]; u8 c = str[i] % 128;
// TODO(allen): Someday let's not punt on the the unicode rendering x += advance_data[c];
c = c % 128;
x += font_get_glyph_width(target, font_id, c);
} }
return x; }
return(x);
} }
internal f32 internal f32
font_string_width(Render_Target *target, i16 font_id, String str){ font_string_width(Render_Target *target, i16 font_id, String str){
f32 x = 0; f32 x = 0;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; i < str.size; ++i){ for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i]; u8 c = str.str[i] % 128;
// TODO(allen): Someday let's not punt on the the unicode rendering x += advance_data[c];
c = c % 128;
x += font_get_glyph_width(target, font_id, c);
} }
return x; }
return(x);
} }
internal f32 internal f32
draw_string(Render_Target *target, i16 font_id, draw_string(Render_Target *target, i16 font_id,
char *str, i32 x_, i32 y, u32 color){ char *str, i32 x_, i32 y, u32 color){
real32 x = (real32)x_; f32 x = (f32)x_;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; str[i]; ++i){ for (i32 i = 0; str[i]; ++i){
u8 c = str[i]; u8 c = str[i] % 128;
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph(target, font_id, c, x, (f32)y, color); font_draw_glyph(target, font_id, c, x, (f32)y, color);
x += font_get_glyph_width(target, font_id, c); x += advance_data[c];
} }
return x; }
return(x);
} }
internal f32 internal f32
draw_string_mono(Render_Target *target, i16 font_id, draw_string_mono(Render_Target *target, i16 font_id,
char *str, f32 x, f32 y, f32 advance, u32 color){ char *str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; str[i]; ++i){ for (i32 i = 0; str[i]; ++i){
u8 c = str[i]; u8 c = str[i] % 128;
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph_mono(target, font_id, c, x, y, advance, color); font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance; x += advance;
} }
return x; return(x);
} }
internal f32 internal f32
draw_string(Render_Target *target, i16 font_id, draw_string(Render_Target *target, i16 font_id,
String str, i32 x_, i32 y, u32 color){ String str, i32 x_, i32 y, u32 color){
f32 x = (f32)x_; f32 x = (f32)x_;
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 *advance_data = font->advance_data;
if (font){
for (i32 i = 0; i < str.size; ++i){ for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i]; u8 c = str.str[i] % 128;
// TODO(allen): Someday let's not punt on the the unicode rendering font_draw_glyph(target, font_id, c, x, (f32)y, color);
c = c % 128; x += advance_data[c];
font_draw_glyph(target, font_id, c,
x, (f32)y, color);
x += font_get_glyph_width(target, font_id, c);
} }
return x; }
return(x);
} }
internal f32 internal f32
draw_string_mono(Render_Target *target, i16 font_id, draw_string_mono(Render_Target *target, i16 font_id,
String str, f32 x, f32 y, f32 advance, u32 color){ String str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; i < str.size; ++i){ for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i]; u8 c = str.str[i] % 128;
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph_mono(target, font_id, c, x, y, advance, color); font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance; x += advance;
} }
return x; return(x);
}
internal f32
font_get_max_width(Font_Set *font_set, i16 font_id, char *characters){
Render_Font *font = get_font_info(font_set, font_id)->font;
f32 cx, x = 0;
if (font){
stbtt_packedchar *chardata = font->chardata;
for (i32 i = 0; characters[i]; ++i){
cx = chardata[characters[i]].xadvance;
if (x < cx) x = cx;
}
}
return x;
}
internal f32
font_get_string_width(Render_Target *target, i16 font_id, String string){
f32 result = 0;
for (i32 i = 0; i < string.size; ++i){
u8 c = string.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_get_glyph_width(target, font_id, c);
}
return result;
} }
// BOTTOM // BOTTOM

View File

@ -31,7 +31,9 @@ int Buffer_Replace_Range(Application_Links *app, Buffer_Summary *buffer, int sta
int Buffer_Seek(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags); int Buffer_Seek(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags);
int Buffer_Set_Setting(Application_Links *app, Buffer_Summary *buffer, int setting, int value); int Buffer_Set_Setting(Application_Links *app, Buffer_Summary *buffer, int setting, int value);
int Buffer_Save(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len); Buffer_Summary Create_Buffer(Application_Links *app, char *filename, int filename_len, int do_in_background);
int Save_Buffer(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len);
int Kill_Buffer(Application_Links *app, Buffer_Identifier buffer, int always_kill, int view_id);
// View manipulation // View manipulation
View_Summary Get_View_First(Application_Links *app); View_Summary Get_View_First(Application_Links *app);
@ -57,10 +59,6 @@ int View_Post_Fade(Application_Links *app, View_Summary *view, int ticks, int st
void View_Set_Paste_Rewrite_(Application_Links *app, View_Summary *view); void View_Set_Paste_Rewrite_(Application_Links *app, View_Summary *view);
int View_Get_Paste_Rewrite_(Application_Links *app, View_Summary *view); int View_Get_Paste_Rewrite_(Application_Links *app, View_Summary *view);
// TODO(allen): Make sure this is just right.
int View_Open_File(Application_Links *app, View_Summary *view, char *filename, int filename_len, int do_in_background);
int View_Kill_Buffer(Application_Links *app, View_Summary *view, Buffer_Identifier buffer);
// Directly get user input // Directly get user input
User_Input Get_User_Input(Application_Links *app, unsigned int get_type, unsigned int abort_type); User_Input Get_User_Input(Application_Links *app, unsigned int get_type, unsigned int abort_type);
User_Input Get_Command_Input(Application_Links *app); User_Input Get_Command_Input(Application_Links *app);

View File

@ -520,7 +520,8 @@ SwitchToOrLoadFile(struct Application_Links *app, String FileName, bool CreateIf
#endif #endif
// NOTE(allen): This opens the file and puts it in &view // NOTE(allen): This opens the file and puts it in &view
app->view_open_file(app, &view, expand_str(FileName), false); // This returns false if the open fails.
view_open_file(app, &view, expand_str(FileName), false);
Result.buffer = app->get_buffer_by_name(app, FileName.str, FileName.size); Result.buffer = app->get_buffer_by_name(app, FileName.str, FileName.size);
@ -655,7 +656,7 @@ CUSTOM_COMMAND_SIG(casey_save_and_make_without_asking)
exec_command(app, cmdid_save); exec_command(app, cmdid_save);
#endif #endif
app->buffer_save(app, &buffer, buffer.file_name, buffer.file_name_len); app->save_buffer(app, &buffer, buffer.file_name, buffer.file_name_len);
} }
#if 0 #if 0
@ -1153,7 +1154,7 @@ OpenProject(Application_Links *app, char *ProjectFileName)
exec_command(app, cmdid_interactive_open); exec_command(app, cmdid_interactive_open);
#endif #endif
app->view_open_file(app, 0, dir.str, dir.size, true); view_open_file(app, 0, dir.str, dir.size, true);
++TotalOpenAttempts; ++TotalOpenAttempts;
} }
} }

View File

@ -1177,6 +1177,7 @@ Font_Load_Sig(system_draw_font_load){
success = win32_draw_font_load(&win32vars.font_part, success = win32_draw_font_load(&win32vars.font_part,
font_out, font_out,
filename, filename,
fontname,
pt_size, pt_size,
tab_width, tab_width,
oversample, oversample,

View File

@ -9,25 +9,36 @@
// TOP // TOP
struct Glyph_Bitmap{ struct GMetrics{
HBITMAP bitmap_handle; f32 advance;
char *pixels; f32 xoff;
f32 xoff2;
}; };
void internal b32
win32_get_box(HDC dc, TCHAR character, int *x0, int *y0, int *x1, int *y1){ win32_glyph_metrics(HDC dc, int code, GMetrics *gmetrics){
SIZE size; b32 result = false;
GetTextExtentPoint32A(dc, &character, 1, &size); ABCFLOAT abc = {0};
*x0 = 0; INT width;
*y0 = 0;
*x1 = size.cx; if (GetCharWidth32W(dc, code, code, &width)){
*y1 = size.cy; gmetrics->advance = (f32)width;
if (GetCharABCWidthsFloat(dc, code, code, &abc)){
gmetrics->xoff = abc.abcfA;
gmetrics->xoff2 = (abc.abcfA + abc.abcfB);
result = true;
}
}
return(result);
} }
internal i32 internal i32
win32_draw_font_load(Partition *part, win32_draw_font_load(Partition *part,
Render_Font *font_out, Render_Font *font_out,
char *filename_untranslated, char *filename_untranslated,
char *fontname,
i32 pt_size, i32 pt_size,
i32 tab_width, i32 tab_width,
i32 oversample, i32 oversample,
@ -36,77 +47,127 @@ win32_draw_font_load(Partition *part,
char space_[1024]; char space_[1024];
String filename = make_fixed_width_string(space_); String filename = make_fixed_width_string(space_);
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated); b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
if (!translate_success) return 0;
i32 result = 0; i32 result = 0;
if (translate_success){
HDC dc = GetDC(win32vars.window_handle);
AddFontResourceEx(filename.str, FR_PRIVATE, 0); AddFontResourceEx(filename.str, FR_PRIVATE, 0);
HFONT font_handle = HFONT font_handle = CreateFont(
CreateFontA(pt_size, 0, 0, 0, pt_size,
FW_NORMAL, // WEIGHT 0,
FALSE, // ITALICS 0,
FALSE, // UNDERLINE 0,
FALSE, // STRIKE-OUT FW_NORMAL,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY, DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE, FF_DONTCARE | DEFAULT_PITCH,
filename.str); fontname
);
HBITMAP bmp_handle = CreateBitmap(
pt_size*2, pt_size*2,
4, 32,
0
);
if (font_handle){
HDC dc = CreateCompatibleDC(0);
if (dc){ if (font_handle != 0 && bmp_handle != 0){
TEXTMETRIC metrics; SelectObject(dc, font_handle);
GetTextMetrics(dc, &metrics); SelectObject(dc, bmp_handle);
font_out->height = metrics.tmHeight + metrics.tmExternalLeading;
font_out->ascent = metrics.tmAscent;
font_out->descent = -metrics.tmDescent;
font_out->line_skip = metrics.tmExternalLeading;
font_out->advance = metrics.tmMaxCharWidth;
memset(font_out, 0, sizeof(*font_out));
TEXTMETRIC metric;
if (GetTextMetrics(dc, &metric)){
font_out->height = (i32)(metric.tmHeight + metric.tmExternalLeading);
font_out->ascent = (i32)(metric.tmAscent);
font_out->descent = (i32)(metric.tmDescent);
font_out->line_skip = (i32)(metric.tmExternalLeading);
if (!store_texture){
result = 1; result = 1;
if (store_texture){ }
else{
Temp_Memory temp = begin_temp_memory(part); Temp_Memory temp = begin_temp_memory(part);
i32 tex_width = pt_size*16*oversample; i32 tex_width = pt_size*16;
i32 tex_height = pt_size*16*oversample; i32 tex_height = pt_size*16;
void *block = sysshared_push_block(part, tex_width * tex_height);
Glyph_Bitmap glyph_bitmap; font_out->tex_width = tex_width;
glyph_bitmap.bitmap_handle = CreateCompatibleBitmap(dc, tex_width, tex_height); font_out->tex_height = tex_height;
glyph_bitmap.pixels = push_array(part, char, tex_width*tex_height);
SelectObject(dc, glyph_bitmap.bitmap_handle); result = 1;
SelectObject(dc, font_handle); /////////////////////////////////////////////////////////////////
stbtt_pack_context spc_;
SetBkColor(dc, RGB(0, 0, 0)); int pack_result;
{
stbtt_pack_context context = {0}; stbtt_pack_context *spc = &spc_;
stbtt_PackBegin(&context, (unsigned char*)glyph_bitmap.pixels, tex_width, tex_height, 0, 1, part); unsigned char *pixels = (u8*)block;
int pw = tex_width;
int ph = tex_height;
int stride_in_bytes = tex_width;
int padding = 1;
void *alloc_context = part;
{ {
stbtt_pack_context *spc = &context; stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
int first_unicode_char_in_range = 0; int num_nodes = pw - padding;
int num_chars_in_range = 128; stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
stbtt_packedchar *chardata_for_range = font_out->chardata;
if (context == NULL || nodes == NULL) {
if (context != NULL) STBTT_free(context, alloc_context);
if (nodes != NULL) STBTT_free(nodes , alloc_context);
pack_result = 0;
goto packbegin_end;
}
spc->user_allocator_context = alloc_context;
spc->width = pw;
spc->height = ph;
spc->pixels = pixels;
spc->pack_info = context;
spc->nodes = nodes;
spc->padding = padding;
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
spc->h_oversample = 1;
spc->v_oversample = 1;
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
pack_result = 1;
goto packbegin_end;
}
}
packbegin_end:;
if (pack_result){
int pack_font_range_result;
{ {
stbtt_pack_range range; stbtt_pack_range range;
range.first_unicode_char_in_range = first_unicode_char_in_range; range.first_unicode_char_in_range = 0;
range.num_chars_in_range = num_chars_in_range; range.num_chars_in_range = 128;
range.chardata_for_range = chardata_for_range; range.chardata_for_range = font_out->chardata;
range.font_size = STBTT_POINT_SIZE((f32)pt_size);
{ stbtt_pack_context *spc = &spc_;
stbtt_pack_range *ranges = &range; stbtt_pack_range *ranges = &range;
int num_ranges = 1; int num_ranges = 1;
{ {
float recip_h = 1.0f / spc->h_oversample;
float recip_v = 1.0f / spc->v_oversample;
float sub_x = stbtt__oversample_shift(spc->h_oversample);
float sub_y = stbtt__oversample_shift(spc->v_oversample);
int i,j,k,n, return_value = 1; int i,j,k,n, return_value = 1;
stbrp_context *context = (stbrp_context *) spc->pack_info; stbrp_context *context = (stbrp_context *) spc->pack_info;
stbrp_rect *rects; stbrp_rect *rects;
@ -124,19 +185,32 @@ win32_draw_font_load(Partition *part,
n += ranges[i].num_chars_in_range; n += ranges[i].num_chars_in_range;
rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
if (rects == NULL) if (rects == NULL){
return 0; pack_font_range_result = 0;
goto pack_font_range_end;
}
//info.userdata = spc->user_allocator_context;
//stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
k=0; k=0;
for (i=0; i < num_ranges; ++i) { for (i=0; i < num_ranges; ++i) {
//float fh = ranges[i].font_size;
//float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
for (j=0; j < ranges[i].num_chars_in_range; ++j) { for (j=0; j < ranges[i].num_chars_in_range; ++j) {
int x0,y0,x1,y1; int w,h;
TCHAR character = (TCHAR)(ranges[i].first_unicode_char_in_range + j); GMetrics gmetrics;
win32_get_box(dc, character, &x0, &y0, &x1, &y1);
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); if (!win32_glyph_metrics(dc, ranges[i].first_unicode_char_in_range + j, &gmetrics)){
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); result = 0;
break;
}
w = CEIL32(gmetrics.xoff2 - gmetrics.xoff);
h = font_out->ascent + font_out->descent;
rects[k].w = (stbrp_coord) (w + spc->padding);
rects[k].h = (stbrp_coord) (h + spc->padding);
++k; ++k;
} }
} }
@ -145,47 +219,65 @@ win32_draw_font_load(Partition *part,
k = 0; k = 0;
for (i=0; i < num_ranges; ++i) { for (i=0; i < num_ranges; ++i) {
//float fh = ranges[i].font_size;
//float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh);
for (j=0; j < ranges[i].num_chars_in_range; ++j) { for (j=0; j < ranges[i].num_chars_in_range; ++j) {
stbrp_rect *r = &rects[k]; stbrp_rect *r = &rects[k];
if (r->was_packed) { if (r->was_packed) {
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
int advance, x0,y0,x1,y1; //int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j);
int glyph = ranges[i].first_unicode_char_in_range + j; int code = ranges[i].first_unicode_char_in_range + j;
stbrp_coord pad = (stbrp_coord) spc->padding; stbrp_coord pad = (stbrp_coord) spc->padding;
GetCharWidth32W(dc, glyph, glyph, &advance);
TCHAR character = (TCHAR)(ranges[i].first_unicode_char_in_range + j);
win32_get_box(dc, character, &x0, &y0, &x1, &y1);
// pad on left and top // pad on left and top
r->x += pad; r->x += pad;
r->y += pad; r->y += pad;
r->w -= pad; r->w -= pad;
r->h -= pad; r->h -= pad;
SetTextColor(dc, RGB(255, 255, 255)); #if 0
TextOutA(dc, r->x, r->y, &character, 1); int advance, lsb, x0,y0,x1,y1;
if (spc->h_oversample > 1) stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb);
stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, stbtt_GetGlyphBitmapBox(&info, glyph,
r->w, r->h, spc->stride_in_bytes, scale * spc->h_oversample,
spc->h_oversample); scale * spc->v_oversample,
&x0,&y0,&x1,&y1);
stbtt_MakeGlyphBitmapSubpixel(&info,
spc->pixels + r->x + r->y*spc->stride_in_bytes,
r->w - spc->h_oversample+1,
r->h - spc->v_oversample+1,
spc->stride_in_bytes,
scale * spc->h_oversample,
scale * spc->v_oversample,
0,0,
glyph);
#else
float advance, x0, y0, x1, y1;
if (spc->v_oversample > 1) GMetrics gmetrics;
stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, if (!win32_glyph_metrics(dc, code, &gmetrics)){
r->w, r->h, spc->stride_in_bytes, result = false;
spc->v_oversample); break;
}
advance = gmetrics.advance;
x0 = gmetrics.xoff;
y0 = -font_out->ascent;
x1 = gmetrics.xoff2;
y1 = font_out->descent;
#endif
bc->x0 = (stbtt_int16) r->x; bc->x0 = (stbtt_int16) r->x;
bc->y0 = (stbtt_int16) r->y; bc->y0 = (stbtt_int16) r->y;
bc->x1 = (stbtt_int16) (r->x + r->w); bc->x1 = (stbtt_int16) (r->x + r->w);
bc->y1 = (stbtt_int16) (r->y + r->h); bc->y1 = (stbtt_int16) (r->y + r->h);
bc->xadvance = (float) advance; bc->xadvance = (float) advance;
bc->xoff = (float) x0 * recip_h + sub_x; bc->xoff = (float) x0;
bc->yoff = (float) y0 * recip_v + sub_y; bc->yoff = (float) y0;
bc->xoff2 = (x0 + r->w) * recip_h + sub_x; bc->xoff2 = (float) (x0 + r->w);
bc->yoff2 = (y0 + r->h) * recip_v + sub_y; bc->yoff2 = (float) (y0 + r->h);
} else { } else {
return_value = 0; // if any fail, report failure return_value = 0; // if any fail, report failure
} }
@ -195,10 +287,31 @@ win32_draw_font_load(Partition *part,
} }
STBTT_free(rects, spc->user_allocator_context); STBTT_free(rects, spc->user_allocator_context);
pack_font_range_result = return_value;
goto pack_font_range_end;
}
}
pack_font_range_end:;
result = return_value;
if (return_value){ if (!pack_font_range_result){
result = 0;
}
{
stbtt_pack_context *spc = &spc_;
{
STBTT_free(spc->nodes , spc->user_allocator_context);
STBTT_free(spc->pack_info, spc->user_allocator_context);
}
}
}
else{
result = 0;
}
/////////////////////////////////////////////////////////////////
if (result){
GLuint font_tex; GLuint font_tex;
glGenTextures(1, &font_tex); glGenTextures(1, &font_tex);
glBindTexture(GL_TEXTURE_2D, font_tex); glBindTexture(GL_TEXTURE_2D, font_tex);
@ -207,7 +320,9 @@ win32_draw_font_load(Partition *part,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, glyph_bitmap.pixels); memset(block, 0xFF, tex_width*tex_height);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block);
font_out->tex = font_tex; font_out->tex = font_tex;
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
@ -216,19 +331,24 @@ win32_draw_font_load(Partition *part,
font_out->chardata['\n'] = font_out->chardata[' ']; font_out->chardata['\n'] = font_out->chardata[' '];
font_out->chardata['\t'] = font_out->chardata[' ']; font_out->chardata['\t'] = font_out->chardata[' '];
font_out->chardata['\t'].xadvance *= tab_width; font_out->chardata['\t'].xadvance *= tab_width;
}
} for (u8 code_point = 0; code_point < 128; ++code_point){
} font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
}
} }
stbtt_PackEnd(&context); i32 max_advance = metric.tmMaxCharWidth;
font_out->advance = max_advance - 1;
}
end_temp_memory(temp); end_temp_memory(temp);
} }
} }
DeleteObject(font_handle); DeleteObject(font_handle);
DeleteObject(bmp_handle);
}
ReleaseDC(win32vars.window_handle, dc);
} }
return(result); return(result);