From 197739409661d1818eb87d1d2e2974dd1142eb48 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Sun, 31 Mar 2019 17:36:09 -0700 Subject: [PATCH] layout handles, looking up cursor values --- 4coder_API/4coder_types.h | 7 ++++ 4coder_default_hooks.cpp | 18 ++++----- 4coder_fancy.cpp | 7 +++- 4coder_generated/app_functions.h | 27 +++++++++++-- 4ed.cpp | 3 +- 4ed_api_implementation.cpp | 57 +++++++++++++++++++++++++--- 4ed_app_models.h | 1 + 4ed_app_target.cpp | 2 + 4ed_text_layout.cpp | 65 ++++++++++++++++++++++++++++++++ 4ed_text_layout.h | 17 +++++++-- 10 files changed, 179 insertions(+), 25 deletions(-) create mode 100644 4ed_text_layout.cpp diff --git a/4coder_API/4coder_types.h b/4coder_API/4coder_types.h index 85be328a..338609a9 100644 --- a/4coder_API/4coder_types.h +++ b/4coder_API/4coder_types.h @@ -34,6 +34,13 @@ TYPEDEF i32 View_ID; TYPEDEF i32 Panel_ID; +TYPEDEF u32 Text_Layout_ID; + +STRUCT Buffer_Point{ + i32 line_number; + Vec2 pixel_shift; +}; + ENUM(u32, Child_Process_Set_Target_Flags){ ChildProcessSet_FailIfBufferAlreadyAttachedToAProcess = 1, ChildProcessSet_FailIfProcessAlreadyAttachedToABuffer = 2, diff --git a/4coder_default_hooks.cpp b/4coder_default_hooks.cpp index b83389a2..a3f72342 100644 --- a/4coder_default_hooks.cpp +++ b/4coder_default_hooks.cpp @@ -321,16 +321,11 @@ struct View_Render_Parameters{ Rect_i32 buffer_rect; }; -struct Buffer_Position{ - i32 line_number; - Vec2 pixel_shift; -}; - -static Buffer_Position +static Buffer_Point buffer_position_from_scroll_position(Application_Links *app, View_ID view_id, Vec2 scroll){ Full_Cursor render_cursor = {}; view_compute_cursor(app, view_id, seek_wrapped_xy(scroll.x, scroll.y, false), &render_cursor); - Buffer_Position result = {}; + Buffer_Point result = {}; result.line_number = render_cursor.line; result.pixel_shift.x = scroll.x; result.pixel_shift.y = scroll.y - render_cursor.wrapped_y; @@ -355,11 +350,11 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View GUI_Scroll_Vars scroll = {}; view_get_scroll_vars(app, view_id, &scroll); - Buffer_Position buffer_pos = buffer_position_from_scroll_position(app, view_id, scroll.scroll_p); + Buffer_Point buffer_point = buffer_position_from_scroll_position(app, view_id, scroll.scroll_p); Range on_screen_range = {}; - compute_render_layout(app, view_id, buffer_id, buffer_rect, - buffer_pos.line_number, buffer_pos.pixel_shift.y, buffer_pos.pixel_shift.x, - &on_screen_range); + Text_Layout_ID text_layout_id = 0; + compute_render_layout(app, view_id, buffer_id, buffer_rect, buffer_point, + &on_screen_range, &text_layout_id); View_Summary view = get_view(app, view_id, AccessAll); Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessAll); @@ -704,6 +699,7 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View } draw_render_layout(app, view_id); + text_layout_free(app, text_layout_id); // NOTE(allen): FPS HUD if (show_fps_hud){ diff --git a/4coder_fancy.cpp b/4coder_fancy.cpp index 29d0832b..4d92880e 100644 --- a/4coder_fancy.cpp +++ b/4coder_fancy.cpp @@ -216,9 +216,12 @@ draw_fancy_string(Application_Links *app, Face_ID font_id, Fancy_String *string, // TODO(casey): need to fill the background here, but I don't know the line height, // and I can't actually render filled shapes, so, like, I can't properly do dP :( - P += (string->pre_margin)*dP; + Face_Metrics metrics = {}; + get_face_metrics(app, font_id, &metrics); + + P += (string->pre_margin*metrics.typical_character_width)*dP; draw_string(app, use_font_id, string->value, P, use_fore, flags, dP); - P += (adv + string->post_margin)*dP; + P += (adv + string->post_margin*metrics.typical_character_width)*dP; } return(P); } diff --git a/4coder_generated/app_functions.h b/4coder_generated/app_functions.h index 47c47f53..685ce342 100644 --- a/4coder_generated/app_functions.h +++ b/4coder_generated/app_functions.h @@ -168,7 +168,10 @@ struct Application_Links; #define DRAW_COORDINATE_CENTER_PUSH_SIG(n) void n(Application_Links *app, Vec2 point) #define DRAW_COORDINATE_CENTER_POP_SIG(n) Vec2 n(Application_Links *app) #define GET_DEFAULT_FONT_FOR_VIEW_SIG(n) Face_ID n(Application_Links *app, View_ID view_id) -#define COMPUTE_RENDER_LAYOUT_SIG(n) b32 n(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, i32 buffer_line_number, f32 y_pixel_shift, f32 scroll_x, Range *on_screen_range_out) +#define TEXT_LAYOUT_GET_BUFFER_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out) +#define TEXT_LAYOUT_COMPUTE_CURSOR_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 p, b32 round_down, Full_Cursor *cursor_out) +#define TEXT_LAYOUT_FREE_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id) +#define COMPUTE_RENDER_LAYOUT_SIG(n) b32 n(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, Buffer_Point buffer_point, Range *on_screen_range_out, Text_Layout_ID *text_layout_id_out) #define DRAW_RENDER_LAYOUT_SIG(n) void n(Application_Links *app, View_ID view_id) #define OPEN_COLOR_PICKER_SIG(n) void n(Application_Links *app, color_picker *picker) #define ANIMATE_IN_N_MILLISECONDS_SIG(n) void n(Application_Links *app, u32 n) @@ -343,6 +346,9 @@ typedef DRAW_CLIP_POP_SIG(Draw_Clip_Pop_Function); typedef DRAW_COORDINATE_CENTER_PUSH_SIG(Draw_Coordinate_Center_Push_Function); typedef DRAW_COORDINATE_CENTER_POP_SIG(Draw_Coordinate_Center_Pop_Function); typedef GET_DEFAULT_FONT_FOR_VIEW_SIG(Get_Default_Font_For_View_Function); +typedef TEXT_LAYOUT_GET_BUFFER_SIG(Text_Layout_Get_Buffer_Function); +typedef TEXT_LAYOUT_COMPUTE_CURSOR_SIG(Text_Layout_Compute_Cursor_Function); +typedef TEXT_LAYOUT_FREE_SIG(Text_Layout_Free_Function); typedef COMPUTE_RENDER_LAYOUT_SIG(Compute_Render_Layout_Function); typedef DRAW_RENDER_LAYOUT_SIG(Draw_Render_Layout_Function); typedef OPEN_COLOR_PICKER_SIG(Open_Color_Picker_Function); @@ -520,6 +526,9 @@ Draw_Clip_Pop_Function *draw_clip_pop; Draw_Coordinate_Center_Push_Function *draw_coordinate_center_push; Draw_Coordinate_Center_Pop_Function *draw_coordinate_center_pop; Get_Default_Font_For_View_Function *get_default_font_for_view; +Text_Layout_Get_Buffer_Function *text_layout_get_buffer; +Text_Layout_Compute_Cursor_Function *text_layout_compute_cursor; +Text_Layout_Free_Function *text_layout_free; Compute_Render_Layout_Function *compute_render_layout; Draw_Render_Layout_Function *draw_render_layout; Open_Color_Picker_Function *open_color_picker; @@ -696,6 +705,9 @@ Draw_Clip_Pop_Function *draw_clip_pop_; Draw_Coordinate_Center_Push_Function *draw_coordinate_center_push_; Draw_Coordinate_Center_Pop_Function *draw_coordinate_center_pop_; Get_Default_Font_For_View_Function *get_default_font_for_view_; +Text_Layout_Get_Buffer_Function *text_layout_get_buffer_; +Text_Layout_Compute_Cursor_Function *text_layout_compute_cursor_; +Text_Layout_Free_Function *text_layout_free_; Compute_Render_Layout_Function *compute_render_layout_; Draw_Render_Layout_Function *draw_render_layout_; Open_Color_Picker_Function *open_color_picker_; @@ -880,6 +892,9 @@ app_links->draw_clip_pop_ = Draw_Clip_Pop;\ app_links->draw_coordinate_center_push_ = Draw_Coordinate_Center_Push;\ app_links->draw_coordinate_center_pop_ = Draw_Coordinate_Center_Pop;\ app_links->get_default_font_for_view_ = Get_Default_Font_For_View;\ +app_links->text_layout_get_buffer_ = Text_Layout_Get_Buffer;\ +app_links->text_layout_compute_cursor_ = Text_Layout_Compute_Cursor;\ +app_links->text_layout_free_ = Text_Layout_Free;\ app_links->compute_render_layout_ = Compute_Render_Layout;\ app_links->draw_render_layout_ = Draw_Render_Layout;\ app_links->open_color_picker_ = Open_Color_Picker;\ @@ -1056,7 +1071,10 @@ static f32_Rect draw_clip_pop(Application_Links *app){return(app->draw_clip_pop( static void draw_coordinate_center_push(Application_Links *app, Vec2 point){(app->draw_coordinate_center_push(app, point));} static Vec2 draw_coordinate_center_pop(Application_Links *app){return(app->draw_coordinate_center_pop(app));} static Face_ID get_default_font_for_view(Application_Links *app, View_ID view_id){return(app->get_default_font_for_view(app, view_id));} -static b32 compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, i32 buffer_line_number, f32 y_pixel_shift, f32 scroll_x, Range *on_screen_range_out){return(app->compute_render_layout(app, view_id, buffer_id, screen_rect, buffer_line_number, y_pixel_shift, scroll_x, on_screen_range_out));} +static b32 text_layout_get_buffer(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out){return(app->text_layout_get_buffer(app, text_layout_id, buffer_id_out));} +static b32 text_layout_compute_cursor(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 p, b32 round_down, Full_Cursor *cursor_out){return(app->text_layout_compute_cursor(app, text_layout_id, p, round_down, cursor_out));} +static b32 text_layout_free(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_free(app, text_layout_id));} +static b32 compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, Buffer_Point buffer_point, Range *on_screen_range_out, Text_Layout_ID *text_layout_id_out){return(app->compute_render_layout(app, view_id, buffer_id, screen_rect, buffer_point, on_screen_range_out, text_layout_id_out));} static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout(app, view_id));} static void open_color_picker(Application_Links *app, color_picker *picker){(app->open_color_picker(app, picker));} static void animate_in_n_milliseconds(Application_Links *app, u32 n){(app->animate_in_n_milliseconds(app, n));} @@ -1232,7 +1250,10 @@ static f32_Rect draw_clip_pop(Application_Links *app){return(app->draw_clip_pop_ static void draw_coordinate_center_push(Application_Links *app, Vec2 point){(app->draw_coordinate_center_push_(app, point));} static Vec2 draw_coordinate_center_pop(Application_Links *app){return(app->draw_coordinate_center_pop_(app));} static Face_ID get_default_font_for_view(Application_Links *app, View_ID view_id){return(app->get_default_font_for_view_(app, view_id));} -static b32 compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, i32 buffer_line_number, f32 y_pixel_shift, f32 scroll_x, Range *on_screen_range_out){return(app->compute_render_layout_(app, view_id, buffer_id, screen_rect, buffer_line_number, y_pixel_shift, scroll_x, on_screen_range_out));} +static b32 text_layout_get_buffer(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out){return(app->text_layout_get_buffer_(app, text_layout_id, buffer_id_out));} +static b32 text_layout_compute_cursor(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 p, b32 round_down, Full_Cursor *cursor_out){return(app->text_layout_compute_cursor_(app, text_layout_id, p, round_down, cursor_out));} +static b32 text_layout_free(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_free_(app, text_layout_id));} +static b32 compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, Buffer_Point buffer_point, Range *on_screen_range_out, Text_Layout_ID *text_layout_id_out){return(app->compute_render_layout_(app, view_id, buffer_id, screen_rect, buffer_point, on_screen_range_out, text_layout_id_out));} static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout_(app, view_id));} static void open_color_picker(Application_Links *app, color_picker *picker){(app->open_color_picker_(app, picker));} static void animate_in_n_milliseconds(Application_Links *app, u32 n){(app->animate_in_n_milliseconds_(app, n));} diff --git a/4ed.cpp b/4ed.cpp index 1769233e..d4febcbb 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -869,8 +869,9 @@ App_Init_Sig(app_init){ models->working_set.default_display_width = DEFAULT_DISPLAY_WIDTH; models->working_set.default_minimum_base_display_width = DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH; - // NOTE(allen): history setup + // NOTE(allen): global_history_init(&models->global_history); + text_layout_init(&models->app_links, &models->text_layouts); // NOTE(allen): clipboard setup models->working_set.clipboard_max_size = ArrayCount(models->working_set.clipboards); diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 004a1cb5..5e736cd2 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -2402,7 +2402,6 @@ DOC_SEE(Full_Cursor) b32 result = false; if (view_api_check_view(view)){ Editing_File *file = view->file; - Assert(file != 0); if (buffer_api_check_file(file)){ if (file->settings.unwrapped_lines && seek.type == buffer_seek_wrapped_xy){ seek.type = buffer_seek_unwrapped_xy; @@ -4634,7 +4633,49 @@ Get_Default_Font_For_View(Application_Links *app, View_ID view_id) } API_EXPORT b32 -Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, i32 buffer_line_number, f32 y_pixel_shift, f32 scroll_x, Range *on_screen_range_out){ +Text_Layout_Get_Buffer(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out){ + Models *models = (Models*)app->cmd_context; + Text_Layout layout = {}; + b32 result = false; + if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ + *buffer_id_out = layout.buffer_id; + result = true; + } + return(result); +} + +API_EXPORT b32 +Text_Layout_Compute_Cursor(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 p, b32 round_down, Full_Cursor *cursor_out){ + Models *models = (Models*)app->cmd_context; + Text_Layout layout = {}; + b32 result = false; + if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ + Editing_File *file = imp_get_file(models, layout.buffer_id); + if (buffer_api_check_file(file)){ + System_Functions *system = models->system; + Full_Cursor top = file_compute_cursor(system, file, seek_line_char(layout.point.line_number, 1)); + f32 top_y = top.wrapped_y; + if (file->settings.unwrapped_lines){ + top_y = top.unwrapped_y; + } + p += layout.point.pixel_shift; + p.y += top_y; + Buffer_Seek seek = seek_xy(p.x, p.y, round_down, file->settings.unwrapped_lines); + *cursor_out = file_compute_cursor(system, file, seek); + result = true; + } + } + return(result); +} + +API_EXPORT b32 +Text_Layout_Free(Application_Links *app, Text_Layout_ID text_layout_id){ + Models *models = (Models*)app->cmd_context; + return(text_layout_erase(&models->text_layouts, text_layout_id)); +} + +API_EXPORT b32 +Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Rect_i32 screen_rect, Buffer_Point buffer_point, Range *on_screen_range_out, Text_Layout_ID *text_layout_id_out){ Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; View *view = imp_get_view(models, view_id); @@ -4672,8 +4713,9 @@ Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_ Full_Cursor render_cursor = view_get_render_cursor(system, view); #else - Full_Cursor intermediate_cursor = file_compute_cursor(system, file, seek_line_char(buffer_line_number, 1)); - f32 scroll_y = intermediate_cursor.unwrapped_y + y_pixel_shift; + Full_Cursor intermediate_cursor = file_compute_cursor(system, file, seek_line_char(buffer_point.line_number, 1)); + f32 scroll_x = buffer_point.pixel_shift.x; + f32 scroll_y = intermediate_cursor.unwrapped_y + buffer_point.pixel_shift.y; Full_Cursor render_cursor = view_get_render_cursor(system, view, scroll_y); #endif @@ -4755,7 +4797,12 @@ Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_ view->render.items = items; view->render.item_count = item_count; - *on_screen_range_out = range; + if (on_screen_range_out != 0){ + *on_screen_range_out = range; + } + if (text_layout_id_out != 0){ + *text_layout_id_out = text_layout_new(&models->mem.heap, &models->text_layouts, buffer_id, buffer_point); + } } return(result); } diff --git a/4ed_app_models.h b/4ed_app_models.h index 186375fe..d9b34498 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -70,6 +70,7 @@ struct Models{ Live_Views live_set; Parse_Context_Memory parse_context_memory; Global_History global_history; + Text_Layout_Container text_layouts; Dynamic_Variable_Layout variable_layout; Dynamic_Workspace dynamic_workspace; diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index 6f15d227..99001cdf 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -62,6 +62,7 @@ struct Mem_Options{ #include "4ed_layout.h" #include "4ed_view.h" #include "4ed_edit.h" +#include "4ed_text_layout.h" #include "4ed_app_models.h" #include "4ed_mem.cpp" @@ -89,6 +90,7 @@ struct Mem_Options{ #include "4ed_view.cpp" #include "4ed_edit.cpp" #include "4ed_view_ui.cpp" +#include "4ed_text_layout.cpp" #include "4ed.cpp" // BOTTOM diff --git a/4ed_text_layout.cpp b/4ed_text_layout.cpp new file mode 100644 index 00000000..0492f653 --- /dev/null +++ b/4ed_text_layout.cpp @@ -0,0 +1,65 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 31.03.2019 + * + * Text layout representation + * + */ + +// TOP + +internal void +text_layout_init(Application_Links *app, Text_Layout_Container *container){ + block_zero_struct(container); + container->node_arena = make_arena(app); +} + +internal Text_Layout* +text_layout_new__alloc_layout(Text_Layout_Container *container){ + Text_Layout_Node *node = container->free_nodes; + if (node == 0){ + node = push_array(&container->node_arena, Text_Layout_Node, 1); + } + else{ + container->free_nodes = node->next; + } + return(&node->layout); +} + +internal Text_Layout_ID +text_layout_new(Heap *heap, Text_Layout_Container *container, Buffer_ID buffer_id, Buffer_Point point){ + Text_Layout *new_layout_data = text_layout_new__alloc_layout(container); + new_layout_data->buffer_id = buffer_id; + new_layout_data->point = point; + Text_Layout_ID new_id = ++container->id_counter; + insert_u32_Ptr_table(heap, &container->table, new_id, new_layout_data); + return(new_id); +} + +internal b32 +text_layout_get(Text_Layout_Container *container, Text_Layout_ID id, Text_Layout *out){ + b32 result = false; + void *ptr = 0; + if (lookup_u32_Ptr_table(&container->table, id, &ptr)){ + block_copy(out, ptr, sizeof(*out)); + result = true; + } + return(result); +} + +internal b32 +text_layout_erase(Text_Layout_Container *container, Text_Layout_ID id){ + b32 result = false; + void *ptr = 0; + if (lookup_u32_Ptr_table(&container->table, id, &ptr)){ + erase_u32_Ptr_table(&container->table, id); + Text_Layout_Node *node = CastFromMember(Text_Layout_Node, layout, ptr); + node->next = container->free_nodes; + container->free_nodes = node; + result = true; + } + return(result); +} + +// BOTTOM diff --git a/4ed_text_layout.h b/4ed_text_layout.h index e8c323eb..f3b8dde4 100644 --- a/4ed_text_layout.h +++ b/4ed_text_layout.h @@ -3,7 +3,7 @@ * * 31.03.2019 * - * Implementation of the API functions. + * Text layout representation * */ @@ -20,8 +20,19 @@ struct Text_Layout{ // this just stores the parameters that should be handed to any // system that attempts to query the layout for hit testing. Buffer_ID buffer_id; - i32 line; - Vec2 pixel_shift; + Buffer_Point point; +}; + +union Text_Layout_Node{ + Text_Layout_Node *next; + Text_Layout layout; +}; + +struct Text_Layout_Container{ + Arena node_arena; + Text_Layout_Node *free_nodes; + u32_Ptr_Table table; + u32 id_counter; }; #endif