diff --git a/4coder_custom.h b/4coder_custom.h index e5a495a1..5098406b 100644 --- a/4coder_custom.h +++ b/4coder_custom.h @@ -103,7 +103,7 @@ typedef struct File_List{ int block_size; } 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 // identify it by id or by name. typedef struct Buffer_Identifier{ @@ -117,6 +117,8 @@ enum Command_ID{ cmdid_center_view, cmdid_left_adjust_view, + cmdid_page_up, + cmdid_page_down, cmdid_word_complete, @@ -125,6 +127,18 @@ enum Command_ID{ cmdid_history_backward, 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_open, cmdid_reopen, @@ -134,31 +148,15 @@ enum Command_ID{ cmdid_interactive_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_config, cmdid_open_menu, cmdid_open_debug, - cmdid_hide_scrollbar, - cmdid_show_scrollbar, + cmdid_open_panel_vsplit, + cmdid_open_panel_hsplit, + cmdid_close_panel, + cmdid_change_active_panel, // cmdid_count diff --git a/4coder_custom_api.h b/4coder_custom_api.h index 92a43b5c..3d635e85 100644 --- a/4coder_custom_api.h +++ b/4coder_custom_api.h @@ -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_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_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_NEXT_SIG(n) void n(Application_Links *app, View_Summary *view) #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_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_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_COMMAND_INPUT_SIG(n) User_Input 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_SEEK_SIG(Buffer_Seek_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_NEXT_SIG(Get_View_Next_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_SET_PASTE_REWRITE__SIG(View_Set_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_COMMAND_INPUT_SIG(Get_Command_Input_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_Seek_Function *buffer_seek; 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_Next_Function *get_view_next; Get_View_Function *get_view; @@ -137,8 +139,6 @@ struct Application_Links{ View_Post_Fade_Function *view_post_fade; View_Set_Paste_Rewrite__Function *view_set_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_Command_Input_Function *get_command_input; 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_seek = external_buffer_seek;\ 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_next = external_get_view_next;\ 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_set_paste_rewrite_ = external_view_set_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_command_input = external_get_command_input;\ app_links->get_event_message = external_get_event_message;\ diff --git a/4coder_default_bindings.cpp b/4coder_default_bindings.cpp index 20f131a1..72d7874c 100644 --- a/4coder_default_bindings.cpp +++ b/4coder_default_bindings.cpp @@ -96,7 +96,7 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){ CUSTOM_COMMAND_SIG(open_my_files){ // TODO(allen|a4.0.8): comment 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){ diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index 2ae82367..40fa2a8f 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -784,7 +784,7 @@ CUSTOM_COMMAND_SIG(open_file_in_quotes){ append(&file_name, make_string(short_file_name, size)); 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){ - app->view_kill_buffer(app, &view, buffer_identifier(buffers_to_close[i])); + app->kill_buffer(app, buffer_identifier(buffers_to_close[i]), true, 0); } } diff --git a/4coder_helper.h b/4coder_helper.h index f5cefcdb..40f45efb 100644 --- a/4coder_helper.h +++ b/4coder_helper.h @@ -725,4 +725,25 @@ buffer_identifier(int id){ 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); +} + diff --git a/4coder_rect.h b/4coder_rect.h index 3a4283d9..9ca23027 100644 --- a/4coder_rect.h +++ b/4coder_rect.h @@ -31,7 +31,7 @@ i32R(int32_t l, int32_t t, int32_t r, int32_t b){ i32_Rect rect; rect.x0 = l; rect.y0 = t; rect.x1 = r; rect.y1 = b; - return rect; + return(rect); } inline i32_Rect @@ -41,7 +41,7 @@ i32R(f32_Rect r){ rect.y0 = (int32_t)r.y0; rect.x1 = (int32_t)r.x1; rect.y1 = (int32_t)r.y1; - return rect; + return(rect); } inline i32_Rect @@ -49,7 +49,7 @@ i32XYWH(int32_t x, int32_t y, int32_t w, int32_t h){ i32_Rect rect; rect.x0 = x; rect.y0 = y; rect.x1 = x+w; rect.y1 = y+h; - return rect; + return(rect); } inline f32_Rect @@ -57,7 +57,7 @@ f32R(float l, float t, float r, float b){ f32_Rect rect; rect.x0 = l; rect.y0 = t; rect.x1 = r; rect.y1 = b; - return rect; + return(rect); } inline f32_Rect @@ -67,7 +67,7 @@ f32R(i32_Rect r){ rect.y0 = (float)r.y0; rect.x1 = (float)r.x1; rect.y1 = (float)r.y1; - return rect; + return(rect); } inline f32_Rect @@ -75,7 +75,7 @@ f32XYWH(float x, float y, float w, float h){ f32_Rect rect; rect.x0 = x; rect.y0 = y; rect.x1 = x+w; rect.y1 = y+h; - return rect; + return(rect); } inline int diff --git a/4ed.cpp b/4ed.cpp index 7ad5a71d..4a7081c5 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -1793,23 +1793,23 @@ App_Init_Sig(app_init){ Font_Setup font_setup[] = { {literal("LiberationSans-Regular.ttf"), - literal("liberation sans"), + literal("Liberation Sans"), font_size}, {literal("liberation-mono.ttf"), - literal("liberation mono"), + literal("Liberation Mono"), font_size}, {literal("Hack-Regular.ttf"), - literal("hack"), + literal("Hack"), font_size}, {literal("CutiveMono-Regular.ttf"), - literal("cutive mono"), + literal("Cutive Mono"), font_size}, {literal("Inconsolata-Regular.ttf"), - literal("inconsolata"), + literal("Inconsolata"), font_size}, }; i32 font_count = ArrayCount(font_setup); @@ -2650,7 +2650,7 @@ App_Step_Sig(app_step){ "\n" "New in alpha 4.0.7:\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" "- opens a debug view, see more in README.txt\n" "\n" "New in alpha 4.0.6:\n" diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 555fc298..13e3f482 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -128,16 +128,25 @@ imp_get_file(Command_Data *cmd, Buffer_Summary *buffer){ return(file); } +internal View* +imp_get_view(Command_Data *cmd, int view_id){ + Live_Views *live_set = cmd->live_set; + View *vptr = 0; + + view_id = view_id - 1; + if (view_id >= 0 && view_id < live_set->max){ + vptr = live_set->views + view_id; + } + + return(vptr); +} + internal View* imp_get_view(Command_Data *cmd, View_Summary *view){ View *vptr = 0; - Live_Views *live_set = cmd->live_set; - int view_id = view->view_id - 1; if (view->exists){ - if (view_id >= 0 && view_id < live_set->max){ - vptr = live_set->views + view_id; - } + vptr = imp_get_view(cmd, view->view_id); } return(vptr); @@ -652,7 +661,7 @@ BUFFER_SET_SETTING_SIG(external_buffer_set_setting){ return(result); } -BUFFER_SAVE_SIG(external_buffer_save){ +SAVE_BUFFER_SIG(external_save_buffer){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Models *models = cmd->models; @@ -670,6 +679,93 @@ BUFFER_SAVE_SIG(external_buffer_save){ 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){ Command_Data *cmd = (Command_Data*)app->cmd_context; Editing_Layout *layout = &cmd->models->layout; @@ -913,69 +1009,6 @@ VIEW_GET_PASTE_REWRITE__SIG(external_view_get_paste_rewrite_){ 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){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index ed5f03ba..355d1032 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -382,23 +382,22 @@ file_init_strings(Editing_File *file){ file->name.extension = make_fixed_width_string(file->name.extension_); } -inline void -file_set_name(Working_Set *working_set, Editing_File *file, char *filename){ - String f, ext; +internal void +file_set_name(Working_Set *working_set, Editing_File *file, String filename){ + String ext; Assert(file->name.live_name.str != 0); - f = make_string_slowly(filename); - copy_checked(&file->name.source_path, f); + copy_checked(&file->name.source_path, filename); 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){ file->name.extension.size = 0; } else{ - ext = file_extension(f); + ext = file_extension(filename); 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 file_synchronize_times(System_Functions *system, Editing_File *file, char *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; } -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 view_wrapped_line_span(f32 line_width, f32 max_width){ i32 line_count = CEIL32(line_width / max_width); @@ -700,7 +692,8 @@ view_measure_wraps(General_Memory *general, View *view){ internal void 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; 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_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_synchronize_times(system, file, filename); + file_synchronize_times(system, file, name); Render_Font *font = get_font_info(font_set, file->state.font_id)->font; 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; 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 && char_is_whitespace((char)item->glyphid)){ highlight_this_color = style->main.highlight_white_color; diff --git a/4ed_font_set.cpp b/4ed_font_set.cpp index ab107521..18de619c 100644 --- a/4ed_font_set.cpp +++ b/4ed_font_set.cpp @@ -119,7 +119,10 @@ font_set_load(Partition *partition, Font_Set *set, i16 font_id){ font__insert(&set->used_slots, slot); Render_Font *font = (Render_Font*)(slot + 1); - set->font_load(font, info->filename.str, info->pt_size, 4, 1); + set->font_load(font, + info->filename.str, + info->name.str, + info->pt_size, 4, true); info->font = font; slot->font_id = font_id; } @@ -182,7 +185,10 @@ font_set_add(Partition *partition, Font_Set *set, info->filename = filename; info->name = name; 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->advance = dummy_font.advance; diff --git a/4ed_rendering.cpp b/4ed_rendering.cpp index 45705544..f1fc53aa 100644 --- a/4ed_rendering.cpp +++ b/4ed_rendering.cpp @@ -1,11 +1,11 @@ /* - * Mr. 4th Dimention - Allen Webster - * - * 12.17.2014 - * - * Rendering layer for project codename "4ed" - * - */ +* Mr. 4th Dimention - Allen Webster +* +* 12.17.2014 +* +* Rendering layer for project codename "4ed" +* +*/ // TOP @@ -90,7 +90,7 @@ draw_push_clip(Render_Target *target, i32_Rect clip_box){ fits_inside(clip_box, target->clip_boxes[target->clip_top])); Assert(target->clip_top+1 < ArrayCount(target->clip_boxes)); target->clip_boxes[++target->clip_top] = clip_box; - + draw_push_piece_clip(target, clip_box); } @@ -114,14 +114,14 @@ inline void private_draw_rectangle(Render_Target *target, f32_Rect rect, u32 color){ draw_set_color(target, color); draw_bind_texture(target, 0); - glBegin(GL_QUADS); + glBegin(GL_QUADS); { glVertex2f(rect.x0, rect.y0); glVertex2f(rect.x0, rect.y1); glVertex2f(rect.x1, rect.y1); glVertex2f(rect.x1, rect.y0); } - glEnd(); + glEnd(); } inline void @@ -152,7 +152,7 @@ private_draw_gradient(Render_Target *target, f32_Rect rect, Vec4 cr = color_right; draw_bind_texture(target, 0); - glBegin(GL_QUADS); + glBegin(GL_QUADS); { glColor4f(cl.r, cl.g, cl.b, cl.a); glVertex2f(rect.x0, rect.y0); @@ -162,22 +162,59 @@ private_draw_gradient(Render_Target *target, f32_Rect rect, glVertex2f(rect.x1, rect.y1); glVertex2f(rect.x1, rect.y0); } - 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 private_draw_glyph(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, u32 color){ - f32 x_shift, y_shift; - x_shift = 0; - y_shift = (f32)font->ascent; - - 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); + Render_Quad q = get_render_quad( + font->glyphs + character, + font->tex_width, font->tex_height, x, y + ); draw_set_color(target, color); draw_bind_texture(target, font->tex); @@ -194,19 +231,18 @@ private_draw_glyph(Render_Target *target, Render_Font *font, inline void private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, f32 advance, u32 color){ - f32 x_shift, y_shift; - i32 left = font->chardata[character].x0; - i32 right = font->chardata[character].x1; - i32 width = (right - left); - x_shift = (f32)(advance - width) * .5f - font->chardata[character].xoff; - y_shift = (f32)font->ascent; + + f32 left = font->glyphs[character].x0; + f32 right = font->glyphs[character].x1; + f32 width = (right - left); + f32 x_shift = (advance - width) * .5f; x += x_shift; - y += y_shift; - stbtt_aligned_quad q; - stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height, - character, &x, &y, &q, 0); + Render_Quad q = get_exact_render_quad( + font->glyphs + character, + font->tex_width, font->tex_height, x, y + ); draw_set_color(target, color); draw_bind_texture(target, font->tex); @@ -230,81 +266,98 @@ internal void launch_rendering(Render_Target *target){ byte *cursor = target->push_buffer; byte *cursor_end = cursor + target->size; - + for (; cursor < cursor_end;){ Render_Piece_Header *header = ExtractStruct(Render_Piece_Header); i32 type = header->type; switch (type){ - case piece_type_rectangle: - { - Render_Piece_Rectangle *rectangle = - ExtractStruct(Render_Piece_Rectangle); - private_draw_rectangle(target, rectangle->rect, rectangle->color); - }break; - - case piece_type_outline: - { - Render_Piece_Rectangle *rectangle = - ExtractStruct(Render_Piece_Rectangle); - private_draw_rectangle_outline(target, rectangle->rect, rectangle->color); - }break; - - case piece_type_gradient: - { - Render_Piece_Gradient *gradient = - ExtractStruct(Render_Piece_Gradient); - private_draw_gradient(target, gradient->rect, - unpack_color4(gradient->left_color), - unpack_color4(gradient->right_color)); - }break; - - case piece_type_glyph: - { - Render_Piece_Glyph *glyph = - ExtractStruct(Render_Piece_Glyph); + case piece_type_rectangle: + { + Render_Piece_Rectangle *rectangle = + ExtractStruct(Render_Piece_Rectangle); + private_draw_rectangle(target, rectangle->rect, rectangle->color); + }break; - Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; - if (font) - private_draw_glyph(target, font, glyph->character, - glyph->pos.x, glyph->pos.y, glyph->color); - }break; - - case piece_type_mono_glyph: - { - Render_Piece_Glyph *glyph = - ExtractStruct(Render_Piece_Glyph); + case piece_type_outline: + { + Render_Piece_Rectangle *rectangle = + ExtractStruct(Render_Piece_Rectangle); + private_draw_rectangle_outline(target, rectangle->rect, rectangle->color); + }break; - Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; - if (font) - private_draw_glyph_mono(target, font, glyph->character, - glyph->pos.x, glyph->pos.y, glyph->color); - }break; - - case piece_type_mono_glyph_advance: - { - Render_Piece_Glyph_Advance *glyph = - ExtractStruct(Render_Piece_Glyph_Advance); + case piece_type_gradient: + { + Render_Piece_Gradient *gradient = + ExtractStruct(Render_Piece_Gradient); + private_draw_gradient(target, gradient->rect, + unpack_color4(gradient->left_color), + unpack_color4(gradient->right_color)); + }break; - Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; - if (font) - private_draw_glyph_mono(target, font, glyph->character, - glyph->pos.x, glyph->pos.y, - glyph->advance, glyph->color); - }break; - - case piece_type_change_clip: - { - Render_Piece_Change_Clip *clip = - ExtractStruct(Render_Piece_Change_Clip); - draw_set_clip(target, clip->box); - }break; + case piece_type_glyph: + { + Render_Piece_Glyph *glyph = + ExtractStruct(Render_Piece_Glyph); + + Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; + if (font) + private_draw_glyph(target, font, glyph->character, + glyph->pos.x, glyph->pos.y, glyph->color); + }break; + + case piece_type_mono_glyph: + { + Render_Piece_Glyph *glyph = + ExtractStruct(Render_Piece_Glyph); + + Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; + if (font) + private_draw_glyph_mono(target, font, glyph->character, + glyph->pos.x, glyph->pos.y, glyph->color); + }break; + + case piece_type_mono_glyph_advance: + { + Render_Piece_Glyph_Advance *glyph = + ExtractStruct(Render_Piece_Glyph_Advance); + + Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font; + if (font) + private_draw_glyph_mono(target, font, glyph->character, + glyph->pos.x, glyph->pos.y, + glyph->advance, glyph->color); + }break; + + case piece_type_change_clip: + { + Render_Piece_Change_Clip *clip = + ExtractStruct(Render_Piece_Change_Clip); + draw_set_clip(target, clip->box); + }break; } } } #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 // of this function (and other functions implementing // the same interface). @@ -324,7 +377,7 @@ draw_font_load(Partition *part, i32 result = 1; - stbtt_packedchar *chardata = font_out->chardata; + stbtt_packedchar chardata[256]; 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_height = tex_height; + ///////////////////////////////////////////////////////////////// stbtt_pack_context spc; if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, @@ -380,6 +434,7 @@ draw_font_load(Partition *part, else{ result = 0; } + ///////////////////////////////////////////////////////////////// if (result){ GLuint font_tex; @@ -395,21 +450,37 @@ draw_font_load(Partition *part, font_out->tex = font_tex; glBindTexture(GL_TEXTURE_2D, 0); - font_out->chardata['\r'] = font_out->chardata[' ']; - font_out->chardata['\n'] = font_out->chardata[' ']; - font_out->chardata['\t'] = font_out->chardata[' ']; - font_out->chardata['\t'].xadvance *= tab_width; + f32 *advance_data = font_out->advance_data; + Glyph_Data *glyphs = font_out->glyphs; + for (u8 code_point = 0; code_point < 128; ++code_point){ + advance_data[code_point] = (f32)(CEIL32(chardata[code_point].xadvance)); + glyphs[code_point].x0 = chardata[code_point].x0; + glyphs[code_point].y0 = chardata[code_point].y0; + glyphs[code_point].x1 = chardata[code_point].x1; + glyphs[code_point].y1 = chardata[code_point].y1; + glyphs[code_point].xoff = chardata[code_point].xoff; + glyphs[code_point].yoff = chardata[code_point].yoff + font_out->ascent; + glyphs[code_point].xoff2 = chardata[code_point].xoff2; + glyphs[code_point].yoff2 = chardata[code_point].yoff2 + font_out->ascent; + } + + glyphs['\r'] = glyphs[' ']; + advance_data['\r'] = advance_data[' ']; + + glyphs['\n'] = glyphs[' ']; + advance_data['\n'] = advance_data[' ']; + + glyphs['\t'] = glyphs[' ']; + advance_data['\t'] = advance_data[' ']*tab_width; i32 max_advance = 0; for (u8 code_point = 0; code_point < 128; ++code_point){ if (stbtt_FindGlyphIndex(&font, code_point) != 0){ font_out->glyphs[code_point].exists = 1; - i32 advance = CEIL32(font_out->chardata[code_point].xadvance); - if (max_advance < advance) max_advance = advance; - font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; - } - else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){ - font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance; + i32 advance = CEIL32(advance_data[code_point]); + if (max_advance < advance){ + max_advance = advance; + } } } font_out->advance = max_advance - 1; diff --git a/4ed_rendering.h b/4ed_rendering.h index 0c2e8d4b..8d1f08e9 100644 --- a/4ed_rendering.h +++ b/4ed_rendering.h @@ -12,25 +12,14 @@ #ifndef 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{ b32 exists; + + f32 x0, x1; + f32 y0, y1; + + f32 xoff, yoff; + f32 xoff2, yoff2; }; struct Render_Font{ @@ -38,8 +27,10 @@ struct Render_Font{ String name; 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]; - stbtt_packedchar chardata[256]; float advance_data[256]; i32 height, ascent, descent, line_skip; i32 advance; @@ -114,6 +105,7 @@ typedef Draw_Push_Piece_Sig(Draw_Push_Piece); #define Font_Load_Sig(name) i32 name( \ Render_Font *font_out, \ char *filename, \ + char *fontname, \ i32 pt_size, \ i32 tab_width, \ b32 store_texture) diff --git a/4ed_rendering_helper.cpp b/4ed_rendering_helper.cpp index 9da8507f..da27cf7f 100644 --- a/4ed_rendering_helper.cpp +++ b/4ed_rendering_helper.cpp @@ -115,11 +115,6 @@ font_predict_size(i32 pt_size){ 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 font_draw_glyph_mono(Render_Target *target, i16 font_id, 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); } -inline f32 -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); -} - +// TODO(allen): Someday let's not punt on the the unicode rendering internal f32 font_string_width(Render_Target *target, i16 font_id, char *str){ f32 x = 0; - for (i32 i = 0; str[i]; ++i){ - u8 c = str[i]; - // TODO(allen): Someday let's not punt on the the unicode rendering - c = c % 128; - x += font_get_glyph_width(target, font_id, c); + 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){ + u8 c = str[i] % 128; + x += advance_data[c]; + } } - return x; + + return(x); } internal f32 font_string_width(Render_Target *target, i16 font_id, String str){ f32 x = 0; - for (i32 i = 0; i < str.size; ++i){ - u8 c = str.str[i]; - // TODO(allen): Someday let's not punt on the the unicode rendering - c = c % 128; - x += font_get_glyph_width(target, font_id, c); + 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){ + u8 c = str.str[i] % 128; + x += advance_data[c]; + } } - return x; + + return(x); } internal f32 draw_string(Render_Target *target, i16 font_id, char *str, i32 x_, i32 y, u32 color){ - real32 x = (real32)x_; - for (i32 i = 0; str[i]; ++i){ - u8 c = str[i]; - // 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); - x += font_get_glyph_width(target, font_id, c); + 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){ + u8 c = str[i] % 128; + font_draw_glyph(target, font_id, c, x, (f32)y, color); + x += advance_data[c]; + } } - return x; + + return(x); } internal f32 draw_string_mono(Render_Target *target, i16 font_id, char *str, f32 x, f32 y, f32 advance, u32 color){ for (i32 i = 0; str[i]; ++i){ - u8 c = str[i]; - // TODO(allen): Someday let's not punt on the the unicode rendering - c = c % 128; + u8 c = str[i] % 128; font_draw_glyph_mono(target, font_id, c, x, y, advance, color); x += advance; } - return x; + return(x); } internal f32 draw_string(Render_Target *target, i16 font_id, String str, i32 x_, i32 y, u32 color){ f32 x = (f32)x_; - for (i32 i = 0; i < str.size; ++i){ - u8 c = str.str[i]; - // 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); - x += font_get_glyph_width(target, font_id, c); + 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){ + u8 c = str.str[i] % 128; + font_draw_glyph(target, font_id, c, x, (f32)y, color); + x += advance_data[c]; + } } - return x; + + return(x); } internal f32 draw_string_mono(Render_Target *target, i16 font_id, String str, f32 x, f32 y, f32 advance, u32 color){ for (i32 i = 0; i < str.size; ++i){ - u8 c = str.str[i]; - // TODO(allen): Someday let's not punt on the the unicode rendering - c = c % 128; + u8 c = str.str[i] % 128; font_draw_glyph_mono(target, font_id, c, x, y, advance, color); x += advance; } - 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; + return(x); } // BOTTOM diff --git a/custom_api_spec.cpp b/custom_api_spec.cpp index a2c43fd4..784c8c71 100644 --- a/custom_api_spec.cpp +++ b/custom_api_spec.cpp @@ -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_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_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); 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 User_Input Get_User_Input(Application_Links *app, unsigned int get_type, unsigned int abort_type); User_Input Get_Command_Input(Application_Links *app); diff --git a/power/4coder_casey.cpp b/power/4coder_casey.cpp index 3a9cc290..208d02be 100644 --- a/power/4coder_casey.cpp +++ b/power/4coder_casey.cpp @@ -520,7 +520,8 @@ SwitchToOrLoadFile(struct Application_Links *app, String FileName, bool CreateIf #endif // 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); @@ -655,7 +656,7 @@ CUSTOM_COMMAND_SIG(casey_save_and_make_without_asking) exec_command(app, cmdid_save); #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 @@ -1153,7 +1154,7 @@ OpenProject(Application_Links *app, char *ProjectFileName) exec_command(app, cmdid_interactive_open); #endif - app->view_open_file(app, 0, dir.str, dir.size, true); + view_open_file(app, 0, dir.str, dir.size, true); ++TotalOpenAttempts; } } diff --git a/win32_4ed.cpp b/win32_4ed.cpp index 1eddc909..c820c626 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -1177,6 +1177,7 @@ Font_Load_Sig(system_draw_font_load){ success = win32_draw_font_load(&win32vars.font_part, font_out, filename, + fontname, pt_size, tab_width, oversample, diff --git a/win32_font.cpp b/win32_font.cpp index c9384621..1c08a091 100644 --- a/win32_font.cpp +++ b/win32_font.cpp @@ -9,25 +9,36 @@ // TOP -struct Glyph_Bitmap{ - HBITMAP bitmap_handle; - char *pixels; +struct GMetrics{ + f32 advance; + f32 xoff; + f32 xoff2; }; -void -win32_get_box(HDC dc, TCHAR character, int *x0, int *y0, int *x1, int *y1){ - SIZE size; - GetTextExtentPoint32A(dc, &character, 1, &size); - *x0 = 0; - *y0 = 0; - *x1 = size.cx; - *y1 = size.cy; +internal b32 +win32_glyph_metrics(HDC dc, int code, GMetrics *gmetrics){ + b32 result = false; + ABCFLOAT abc = {0}; + INT width; + + if (GetCharWidth32W(dc, code, code, &width)){ + 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 win32_draw_font_load(Partition *part, Render_Font *font_out, char *filename_untranslated, + char *fontname, i32 pt_size, i32 tab_width, i32 oversample, @@ -36,77 +47,127 @@ win32_draw_font_load(Partition *part, char space_[1024]; String filename = make_fixed_width_string(space_); b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated); - if (!translate_success) return 0; i32 result = 0; - AddFontResourceEx(filename.str, FR_PRIVATE, 0); - - HFONT font_handle = - CreateFontA(pt_size, 0, 0, 0, - FW_NORMAL, // WEIGHT - FALSE, // ITALICS - FALSE, // UNDERLINE - FALSE, // STRIKE-OUT - ANSI_CHARSET, - OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, - ANTIALIASED_QUALITY, - DEFAULT_PITCH|FF_DONTCARE, - filename.str); - - if (font_handle){ - HDC dc = CreateCompatibleDC(0); + if (translate_success){ + HDC dc = GetDC(win32vars.window_handle); - if (dc){ - TEXTMETRIC metrics; - GetTextMetrics(dc, &metrics); - 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; + AddFontResourceEx(filename.str, FR_PRIVATE, 0); + + HFONT font_handle = CreateFont( + pt_size, + 0, + 0, + 0, + FW_NORMAL, + FALSE, + FALSE, + FALSE, + ANSI_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + FF_DONTCARE | DEFAULT_PITCH, + fontname + ); + HBITMAP bmp_handle = CreateBitmap( + pt_size*2, pt_size*2, + 4, 32, + 0 + ); + + + if (font_handle != 0 && bmp_handle != 0){ + SelectObject(dc, font_handle); + SelectObject(dc, bmp_handle); - result = 1; - if (store_texture){ - Temp_Memory temp = begin_temp_memory(part); + memset(font_out, 0, sizeof(*font_out)); + + TEXTMETRIC metric; + if (GetTextMetrics(dc, &metric)){ - i32 tex_width = pt_size*16*oversample; - i32 tex_height = pt_size*16*oversample; + 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); - Glyph_Bitmap glyph_bitmap; - glyph_bitmap.bitmap_handle = CreateCompatibleBitmap(dc, tex_width, tex_height); - glyph_bitmap.pixels = push_array(part, char, tex_width*tex_height); - - SelectObject(dc, glyph_bitmap.bitmap_handle); - SelectObject(dc, font_handle); - - SetBkColor(dc, RGB(0, 0, 0)); - - stbtt_pack_context context = {0}; - stbtt_PackBegin(&context, (unsigned char*)glyph_bitmap.pixels, tex_width, tex_height, 0, 1, part); - - { - stbtt_pack_context *spc = &context; - int first_unicode_char_in_range = 0; - int num_chars_in_range = 128; - stbtt_packedchar *chardata_for_range = font_out->chardata; + if (!store_texture){ + result = 1; + } + else{ + Temp_Memory temp = begin_temp_memory(part); + i32 tex_width = pt_size*16; + i32 tex_height = pt_size*16; + void *block = sysshared_push_block(part, tex_width * tex_height); + + font_out->tex_width = tex_width; + font_out->tex_height = tex_height; + + result = 1; + ///////////////////////////////////////////////////////////////// + stbtt_pack_context spc_; + + int pack_result; { - stbtt_pack_range range; - range.first_unicode_char_in_range = first_unicode_char_in_range; - range.num_chars_in_range = num_chars_in_range; - range.chardata_for_range = chardata_for_range; + stbtt_pack_context *spc = &spc_; + 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; { + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + 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; + range.first_unicode_char_in_range = 0; + range.num_chars_in_range = 128; + 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 = ⦥ 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; stbrp_context *context = (stbrp_context *) spc->pack_info; stbrp_rect *rects; @@ -124,19 +185,32 @@ win32_draw_font_load(Partition *part, n += ranges[i].num_chars_in_range; rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); - if (rects == NULL) - return 0; + if (rects == NULL){ + 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; 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) { - int x0,y0,x1,y1; + int w,h; - TCHAR character = (TCHAR)(ranges[i].first_unicode_char_in_range + j); - win32_get_box(dc, character, &x0, &y0, &x1, &y1); + GMetrics gmetrics; - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (!win32_glyph_metrics(dc, ranges[i].first_unicode_char_in_range + j, &gmetrics)){ + 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; } } @@ -145,47 +219,65 @@ win32_draw_font_load(Partition *part, k = 0; 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) { stbrp_rect *r = &rects[k]; if (r->was_packed) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; - int advance, x0,y0,x1,y1; - int glyph = ranges[i].first_unicode_char_in_range + j; + //int glyph = stbtt_FindGlyphIndex(&info, 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; - 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 r->x += pad; r->y += pad; r->w -= pad; r->h -= pad; - SetTextColor(dc, RGB(255, 255, 255)); - TextOutA(dc, r->x, r->y, &character, 1); +#if 0 + int advance, lsb, x0,y0,x1,y1; - if (spc->h_oversample > 1) - stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->h_oversample); + stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&info, glyph, + scale * 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) - stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, - spc->v_oversample); + GMetrics gmetrics; + if (!win32_glyph_metrics(dc, code, &gmetrics)){ + result = false; + 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->y0 = (stbtt_int16) r->y; bc->x1 = (stbtt_int16) (r->x + r->w); bc->y1 = (stbtt_int16) (r->y + r->h); - bc->xadvance = (float) advance; - bc->xoff = (float) x0 * recip_h + sub_x; - bc->yoff = (float) y0 * recip_v + sub_y; - bc->xoff2 = (x0 + r->w) * recip_h + sub_x; - bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + bc->xadvance = (float) advance; + bc->xoff = (float) x0; + bc->yoff = (float) y0; + bc->xoff2 = (float) (x0 + r->w); + bc->yoff2 = (float) (y0 + r->h); } else { return_value = 0; // if any fail, report failure } @@ -195,40 +287,68 @@ win32_draw_font_load(Partition *part, } STBTT_free(rects, spc->user_allocator_context); - - result = return_value; - - if (return_value){ - GLuint font_tex; - glGenTextures(1, &font_tex); - glBindTexture(GL_TEXTURE_2D, font_tex); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, glyph_bitmap.pixels); - - font_out->tex = font_tex; - glBindTexture(GL_TEXTURE_2D, 0); - - font_out->chardata['\r'] = font_out->chardata[' ']; - font_out->chardata['\n'] = font_out->chardata[' ']; - font_out->chardata['\t'] = font_out->chardata[' ']; - font_out->chardata['\t'].xadvance *= tab_width; - } + pack_font_range_result = return_value; + goto pack_font_range_end; + } + } + pack_font_range_end:; + + + 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; + glGenTextures(1, &font_tex); + glBindTexture(GL_TEXTURE_2D, font_tex); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + 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; + glBindTexture(GL_TEXTURE_2D, 0); + + font_out->chardata['\r'] = font_out->chardata[' ']; + font_out->chardata['\n'] = font_out->chardata[' ']; + font_out->chardata['\t'] = font_out->chardata[' ']; + 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; + } + + i32 max_advance = metric.tmMaxCharWidth; + font_out->advance = max_advance - 1; + } + + end_temp_memory(temp); } - - stbtt_PackEnd(&context); - - end_temp_memory(temp); } + + DeleteObject(font_handle); + DeleteObject(bmp_handle); } - DeleteObject(font_handle); + ReleaseDC(win32vars.window_handle, dc); } return(result);