From 2e0992fdd322e314bcd946272fc3666761ed54e2 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 31 Jul 2019 19:13:36 -0700 Subject: [PATCH] extended text layouts to easily get character and line rectangles --- 4coder_API/4coder_types.h | 6 + 4coder_api_transition_30_31_helpers.cpp | 7 - 4coder_base_types.cpp | 4 + 4coder_default_hooks.cpp | 239 +++++++----------------- 4coder_generated/app_functions.h | 35 +++- 4coder_helper.cpp | 61 +++++- 4ed_api_implementation.cpp | 112 ++++++++++- 4ed_buffer.cpp | 12 +- 4ed_font_face.cpp | 3 + 4ed_render_target.cpp | 3 +- 4ed_text_layout.cpp | 3 +- 4ed_text_layout.h | 3 + 4ed_view.cpp | 20 +- 4ed_view.h | 4 +- things_ive_broken.txt | 2 + 15 files changed, 307 insertions(+), 207 deletions(-) diff --git a/4coder_API/4coder_types.h b/4coder_API/4coder_types.h index 5f408ed0..c0ebcf62 100644 --- a/4coder_API/4coder_types.h +++ b/4coder_API/4coder_types.h @@ -670,6 +670,12 @@ static Managed_Scope ManagedScope_NULL = 0; static Managed_Variable_ID ManagedVariableIndex_ERROR = -1; static Managed_Object ManagedObject_NULL = 0; +STRUCT Text_Layout_Coordinates{ + Vec2_f32 on_screen_p0; + Vec2_f32 in_buffer_p0; + Vec2_f32 dim; +}; + /* DOC(A multi-member identifier for a marker visual. A marker visual is attached to a marker object (Marker_Object), it is freed when the marker object is freed or when it is specifically destroyed. Multiple marker visuals can be placed on a single marker object.) DOC_SEE(Marker_Visual_Type) DOC_SEE(Marker_Visual_Symbolic_Color) diff --git a/4coder_api_transition_30_31_helpers.cpp b/4coder_api_transition_30_31_helpers.cpp index a4966c57..c1f073a0 100644 --- a/4coder_api_transition_30_31_helpers.cpp +++ b/4coder_api_transition_30_31_helpers.cpp @@ -541,13 +541,6 @@ find_prev_scope(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, u return(result); } -static void -mark_enclosures(Application_Links *app, Managed_Scope render_scope, Buffer_Summary *buffer, i32 pos, u32 flags, Marker_Visual_Type type, int_color *back_colors, int_color *fore_colors, i32 color_count){ - if (buffer != 0){ - mark_enclosures(app, render_scope, buffer->buffer_id, pos, flags, type, back_colors, fore_colors, color_count); - } -} - struct Hard_Start_Result{ i32 char_pos; i32 indent_pos; diff --git a/4coder_base_types.cpp b/4coder_base_types.cpp index a3bb5ee8..520c7ffb 100644 --- a/4coder_base_types.cpp +++ b/4coder_base_types.cpp @@ -2096,6 +2096,8 @@ rect_intersect(Rect_i32 a, Rect_i32 b){ a.y0 = Max(a.y0, b.y0); a.x1 = Min(a.x1, b.x1); a.y1 = Min(a.y1, b.y1); + a.x0 = Min(a.x0, a.x1); + a.y0 = Min(a.y0, a.y1); return(a); } internal Rect_i32 @@ -2112,6 +2114,8 @@ rect_intersect(Rect_f32 a, Rect_f32 b){ a.y0 = Max(a.y0, b.y0); a.x1 = Min(a.x1, b.x1); a.y1 = Min(a.y1, b.y1); + a.x0 = Min(a.x0, a.x1); + a.y0 = Min(a.y0, a.y1); return(a); } internal Rect_f32 diff --git a/4coder_default_hooks.cpp b/4coder_default_hooks.cpp index 0397fcc3..a954d5dc 100644 --- a/4coder_default_hooks.cpp +++ b/4coder_default_hooks.cpp @@ -162,55 +162,45 @@ get_enclosure_ranges(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 return(array); } +typedef i32 Range_Highlight_Kind; +enum{ + RangeHighlightKind_LineHighlight, + RangeHighlightKind_CharacterHighlight, +}; + static void -mark_enclosures(Application_Links *app, Managed_Scope render_scope, Buffer_ID buffer, i64 pos, u32 flags, - Marker_Visual_Type type, int_color *back_colors, int_color *fore_colors, i32 color_count){ - Arena *scratch = context_get_arena(app); - Temp_Memory temp = begin_temp(scratch); +draw_enclosures(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID buffer, + i64 pos, u32 flags, Range_Highlight_Kind kind, + int_color *back_colors, int_color *fore_colors, i32 color_count){ + Scratch_Block scratch(app); Range_i64_Array ranges = get_enclosure_ranges(app, scratch, buffer, pos, flags); - if (ranges.count > 0){ - i32 marker_count = ranges.count*2; - Marker *markers = push_array(scratch, Marker, marker_count); - Marker *marker = markers; - Range_i64 *range = ranges.ranges; - for (i32 i = 0; - i < ranges.count; - i += 1, range += 1, marker += 2){ - marker[0].pos = (i32)range->first; - marker[1].pos = (i32)range->one_past_last - 1; - } - Managed_Object o = alloc_buffer_markers_on_buffer(app, buffer, marker_count, &render_scope); - managed_object_store_data(app, o, 0, marker_count, markers); - - Marker_Visual_Take_Rule take_rule = {}; - take_rule.take_count_per_step = 2; - take_rule.step_stride_in_marker_count = 8; - - i32 first_color_index = (ranges.count - 1)%color_count; - for (i32 i = 0, color_index = first_color_index; - i < color_count; - i += 1){ - Marker_Visual visual = create_marker_visual(app, o); - int_color back = 0; - int_color fore = 0; + i32 color_index = 0; + for (i32 i = 0; i < ranges.count; i += 1){ + Range_i64 range = ranges.ranges[i]; + if (kind == RangeHighlightKind_LineHighlight){ + Range_i64 line_range = get_line_range_from_pos_range(app, buffer, range); if (back_colors != 0){ - back = back_colors[color_index]; + draw_line_highlight(app, text_layout_id, line_range, back_colors[color_index]); } if (fore_colors != 0){ - fore = fore_colors[color_index]; - } - marker_visual_set_effect(app, visual, type, back, fore, 0); - take_rule.first_index = i*2; - marker_visual_set_take_rule(app, visual, take_rule); - color_index = color_index - 1; - if (color_index < 0){ - color_index += color_count; + Range_i64 pos_range = get_pos_range_from_line_range(app, buffer, line_range); + paint_text_color(app, text_layout_id, pos_range, fore_colors[color_index]); } } + else{ + if (back_colors != 0){ + draw_character_block(app, text_layout_id, range.min, back_colors[color_index]); + draw_character_block(app, text_layout_id, range.max - 1, back_colors[color_index]); + } + if (fore_colors != 0){ + paint_text_color(app, text_layout_id, range.min, fore_colors[color_index]); + paint_text_color(app, text_layout_id, range.max - 1, fore_colors[color_index]); + } + } + color_index += 1; + color_index = (color_index%color_count); } - - end_temp(temp); } static argb_color default_colors[Stag_COUNT] = {}; @@ -353,18 +343,12 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View Buffer_Point buffer_point = buffer_position_from_scroll_position(app, view_id, scroll.scroll_p); Text_Layout_ID text_layout_id = compute_render_layout(app, view_id, buffer, buffer_rect.p0, rect_dim(buffer_rect), buffer_point, max_i32); Range_i64 on_screen_range = text_layout_get_on_screen_range(app, text_layout_id); - text_layout_free(app, text_layout_id); View_ID active_view = get_active_view(app, AccessAll); b32 is_active_view = (active_view == view_id); Scratch_Block scratch(app); - static Managed_Scope render_scope = 0; - if (render_scope == 0){ - render_scope = create_user_managed_scope(app); - } - { Rect_f32 r_cursor = view_get_screen_rect(app, view_id); r_cursor.p1 -= r_cursor.p0; @@ -535,157 +519,66 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View } } - Highlight_Record *records = push_array(scratch, Highlight_Record, record_count); - i32 record_index = 0; for (Highlight_Record *node = record_first; node != 0; node = node->next){ - records[record_index] = *node; - record_index += 1; - } - - if (record_count > 0){ - sort_highlight_record(records, 0, record_count); - Marker *markers = push_array_zero(scratch, Marker, 2*record_count); - i32 marker_index_first = 0; - i32 marker_index = 0; - int_color current_color = records[0].color; - { - Marker *marker = &markers[marker_index]; - marker[0].pos = (i32)records[0].range.first; - marker[1].pos = (i32)records[0].range.one_past_last; - marker_index += 2; - } - for (i32 i = 1; i <= record_count; i += 1){ - b32 do_emit = (i == record_count || records[i].color != current_color); - if (do_emit){ - i32 marker_count = marker_index - marker_index_first; - Managed_Object o = alloc_buffer_markers_on_buffer(app, buffer, marker_count, &render_scope); - managed_object_store_data(app, o, 0, marker_count, markers + marker_index_first); - Marker_Visual v = create_marker_visual(app, o); - marker_visual_set_effect(app, v, VisualType_CharacterHighlightRanges, SymbolicColor_Default, current_color, 0); - marker_visual_set_priority(app, v, VisualPriority_Lowest); - current_color = records[i].color; - marker_index_first = marker_index; - } - if (i < record_count){ - Marker *marker = &markers[marker_index]; - marker[0].pos = (i32)records[i].range.first; - marker[1].pos = (i32)records[i].range.one_past_last; - marker_index += 2; - } - } + paint_text_color(app, text_layout_id, node->range, node->color); } end_temp(temp); } - // NOTE(allen): Cursor and mark i64 cursor_pos = view_get_cursor_pos(app, view_id); i64 mark_pos = view_get_mark_pos(app, view_id); - Managed_Object cursor_and_mark = alloc_buffer_markers_on_buffer(app, buffer, 2, &render_scope); - Marker cm_markers[2] = {}; - cm_markers[0].pos = (i32)cursor_pos; - cm_markers[1].pos = (i32)mark_pos; - managed_object_store_data(app, cursor_and_mark, 0, 2, cm_markers); + // NOTE(allen): Scope highlight + if (do_matching_enclosure_highlight){ + static const i32 color_count = 4; + int_color colors[color_count]; + for (u16 i = 0; i < color_count; i += 1){ + colors[i] = Stag_Back_Cycle_1 + i; + } + draw_enclosures(app, text_layout_id, buffer, + cursor_pos, FindScope_Brace, RangeHighlightKind_LineHighlight, + colors, 0, color_count); + } + // NOTE(allen): Line highlight + if (highlight_line_at_cursor && is_active_view){ + i64 line_number = get_line_number_from_pos(app, buffer, cursor_pos); + draw_line_highlight(app, text_layout_id, line_number, Stag_Highlight_Cursor_Line); + } + + // NOTE(allen): Cursor and mark b32 cursor_is_hidden_in_this_view = (cursor_is_hidden && is_active_view); if (!cursor_is_hidden_in_this_view){ switch (fcoder_mode){ case FCoderMode_Original: { - Marker_Visual_Take_Rule take_rule = {}; - take_rule.first_index = 0; - take_rule.take_count_per_step = 1; - take_rule.step_stride_in_marker_count = 1; - take_rule.maximum_number_of_markers = 1; - - Marker_Visual visual = create_marker_visual(app, cursor_and_mark); - Marker_Visual_Type type = is_active_view?VisualType_CharacterBlocks:VisualType_CharacterWireFrames; - int_color cursor_color = Stag_Cursor; - int_color text_color = is_active_view?Stag_At_Cursor:Stag_Default; - marker_visual_set_effect(app, visual, type, cursor_color, text_color, 0); - marker_visual_set_take_rule(app, visual, take_rule); - marker_visual_set_priority(app, visual, VisualPriority_Highest); - - visual = create_marker_visual(app, cursor_and_mark); - marker_visual_set_effect(app, visual, VisualType_CharacterWireFrames, Stag_Mark, 0, 0); - take_rule.first_index = 1; - marker_visual_set_take_rule(app, visual, take_rule); - marker_visual_set_priority(app, visual, VisualPriority_Highest); + if (is_active_view){ + draw_character_block(app, text_layout_id, cursor_pos, Stag_Cursor); + paint_text_color(app, text_layout_id, make_range_i64(cursor_pos), Stag_At_Cursor); + draw_character_wire_frame(app, text_layout_id, mark_pos, Stag_Mark); + } + else{ + draw_character_wire_frame(app, text_layout_id, mark_pos, Stag_Mark); + draw_character_wire_frame(app, text_layout_id, cursor_pos, Stag_Cursor); + } }break; case FCoderMode_NotepadLike: { - int_color cursor_color = Stag_Cursor; - int_color highlight_color = Stag_Highlight; - - Marker_Visual_Take_Rule take_rule = {}; - take_rule.first_index = 0; - take_rule.take_count_per_step = 1; - take_rule.step_stride_in_marker_count = 1; - take_rule.maximum_number_of_markers = 1; - - Marker_Visual visual = create_marker_visual(app, cursor_and_mark); - marker_visual_set_effect(app, visual, VisualType_CharacterIBars, cursor_color, 0, 0); - marker_visual_set_take_rule(app, visual, take_rule); - marker_visual_set_priority(app, visual, VisualPriority_Highest); - if (cursor_pos != mark_pos){ - visual = create_marker_visual(app, cursor_and_mark); - marker_visual_set_effect(app, visual, VisualType_CharacterHighlightRanges, highlight_color, Stag_At_Highlight, 0); - take_rule.maximum_number_of_markers = 2; - marker_visual_set_take_rule(app, visual, take_rule); - marker_visual_set_priority(app, visual, VisualPriority_Highest); + Range_i64 range = Ii64(cursor_pos, mark_pos); + draw_character_block(app, text_layout_id, range, Stag_Highlight); + paint_text_color(app, text_layout_id, range, Stag_At_Highlight); } + draw_character_i_bar(app, text_layout_id, cursor_pos, Stag_Cursor); }break; } } - // NOTE(allen): Line highlight setup - if (highlight_line_at_cursor && is_active_view){ - u32 line_color = Stag_Highlight_Cursor_Line; - Marker_Visual visual = create_marker_visual(app, cursor_and_mark); - marker_visual_set_effect(app, visual, VisualType_LineHighlights, line_color, 0, 0); - Marker_Visual_Take_Rule take_rule = {}; - take_rule.first_index = 0; - take_rule.take_count_per_step = 1; - take_rule.step_stride_in_marker_count = 1; - take_rule.maximum_number_of_markers = 1; - marker_visual_set_take_rule(app, visual, take_rule); - marker_visual_set_priority(app, visual, VisualPriority_Highest); - } - - // NOTE(allen): Token highlight setup - b32 do_token_highlight = false; - if (do_token_highlight){ - int_color token_color = 0x5000EE00; - - Temp_Memory temp = begin_temp(scratch); - Boundary_Function_List funcs = push_boundary_list(scratch, boundary_token, boundary_non_whitespace); - Range_i64 snipe_range = get_snipe_range(app, funcs, buffer, cursor_pos, Scan_Backward); - if (range_size(snipe_range) > 0){ - Managed_Object token_highlight = alloc_buffer_markers_on_buffer(app, buffer, 2, &render_scope); - Marker range_markers[2] = {}; - range_markers[0].pos = (i32)snipe_range.min; - range_markers[1].pos = (i32)snipe_range.max; - managed_object_store_data(app, token_highlight, 0, 2, range_markers); - Marker_Visual visual = create_marker_visual(app, token_highlight); - marker_visual_set_effect(app, visual, VisualType_CharacterHighlightRanges, token_color, Stag_At_Highlight, 0); - } - end_temp(temp); - } - // NOTE(allen): Matching enclosure highlight setup - static const i32 color_count = 4; - if (do_matching_enclosure_highlight){ - int_color colors[color_count]; - for (u16 i = 0; i < color_count; i += 1){ - colors[i] = Stag_Back_Cycle_1 + i; - } - mark_enclosures(app, render_scope, buffer, cursor_pos, FindScope_Brace, VisualType_LineHighlightRanges, colors, 0, color_count); - } if (do_matching_paren_highlight){ i64 pos = cursor_pos; if (buffer_get_char(app, buffer, pos) == '('){ @@ -696,15 +589,19 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View pos -= 1; } } + static const i32 color_count = 4; int_color colors[color_count]; for (u16 i = 0; i < color_count; i += 1){ colors[i] = Stag_Text_Cycle_1 + i; } - mark_enclosures(app, render_scope, buffer, pos, FindScope_Paren, VisualType_CharacterBlocks, 0, colors, color_count); + draw_enclosures(app, text_layout_id, buffer, + cursor_pos, FindScope_Paren, RangeHighlightKind_CharacterHighlight, + colors, 0, color_count); } draw_clip_push(app, buffer_rect); draw_render_layout(app, view_id); + text_layout_free(app, text_layout_id); draw_clip_pop(app); // NOTE(allen): FPS HUD @@ -768,7 +665,7 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View animate_in_n_milliseconds(app, 1000); } - managed_scope_clear_self_all_dependent_scopes(app, render_scope); + //managed_scope_clear_self_all_dependent_scopes(app, render_scope); } static int_color diff --git a/4coder_generated/app_functions.h b/4coder_generated/app_functions.h index 04db0b52..dc06fedb 100644 --- a/4coder_generated/app_functions.h +++ b/4coder_generated/app_functions.h @@ -170,7 +170,10 @@ struct Application_Links; #define TEXT_LAYOUT_BUFFER_POINT_TO_LAYOUT_POINT_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 buffer_relative_p, Vec2 *p_out) #define TEXT_LAYOUT_LAYOUT_POINT_TO_BUFFER_POINT_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 layout_relative_p, Vec2 *p_out) #define TEXT_LAYOUT_GET_ON_SCREEN_RANGE_SIG(n) Range_i64 n(Application_Links *app, Text_Layout_ID text_layout_id) -#define TEXT_LAYOUT_GET_HEIGHT_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, f32 *height_out) +#define TEXT_LAYOUT_ON_SCREEN_SIG(n) Rect_f32 n(Application_Links *app, Text_Layout_ID text_layout_id) +#define TEXT_LAYOUT_LINE_ON_SCREEN_SIG(n) Rect_f32 n(Application_Links *app, Text_Layout_ID layout_id, i64 line_number) +#define TEXT_LAYOUT_CHARACTER_ON_SCREEN_SIG(n) Rect_f32 n(Application_Links *app, Text_Layout_ID layout_id, i64 pos) +#define PAINT_TEXT_COLOR_SIG(n) void n(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color) #define TEXT_LAYOUT_FREE_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id) #define COMPUTE_RENDER_LAYOUT_SIG(n) Text_Layout_ID n(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Vec2 screen_p, Vec2 layout_dim, Buffer_Point buffer_point, i32 one_past_last) #define DRAW_RENDER_LAYOUT_SIG(n) void n(Application_Links *app, View_ID view_id) @@ -349,7 +352,10 @@ typedef TEXT_LAYOUT_GET_BUFFER_SIG(Text_Layout_Get_Buffer_Function); typedef TEXT_LAYOUT_BUFFER_POINT_TO_LAYOUT_POINT_SIG(Text_Layout_Buffer_Point_To_Layout_Point_Function); typedef TEXT_LAYOUT_LAYOUT_POINT_TO_BUFFER_POINT_SIG(Text_Layout_Layout_Point_To_Buffer_Point_Function); typedef TEXT_LAYOUT_GET_ON_SCREEN_RANGE_SIG(Text_Layout_Get_On_Screen_Range_Function); -typedef TEXT_LAYOUT_GET_HEIGHT_SIG(Text_Layout_Get_Height_Function); +typedef TEXT_LAYOUT_ON_SCREEN_SIG(Text_Layout_On_Screen_Function); +typedef TEXT_LAYOUT_LINE_ON_SCREEN_SIG(Text_Layout_Line_On_Screen_Function); +typedef TEXT_LAYOUT_CHARACTER_ON_SCREEN_SIG(Text_Layout_Character_On_Screen_Function); +typedef PAINT_TEXT_COLOR_SIG(Paint_Text_Color_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); @@ -530,7 +536,10 @@ Text_Layout_Get_Buffer_Function *text_layout_get_buffer; Text_Layout_Buffer_Point_To_Layout_Point_Function *text_layout_buffer_point_to_layout_point; Text_Layout_Layout_Point_To_Buffer_Point_Function *text_layout_layout_point_to_buffer_point; Text_Layout_Get_On_Screen_Range_Function *text_layout_get_on_screen_range; -Text_Layout_Get_Height_Function *text_layout_get_height; +Text_Layout_On_Screen_Function *text_layout_on_screen; +Text_Layout_Line_On_Screen_Function *text_layout_line_on_screen; +Text_Layout_Character_On_Screen_Function *text_layout_character_on_screen; +Paint_Text_Color_Function *paint_text_color; Text_Layout_Free_Function *text_layout_free; Compute_Render_Layout_Function *compute_render_layout; Draw_Render_Layout_Function *draw_render_layout; @@ -710,7 +719,10 @@ Text_Layout_Get_Buffer_Function *text_layout_get_buffer_; Text_Layout_Buffer_Point_To_Layout_Point_Function *text_layout_buffer_point_to_layout_point_; Text_Layout_Layout_Point_To_Buffer_Point_Function *text_layout_layout_point_to_buffer_point_; Text_Layout_Get_On_Screen_Range_Function *text_layout_get_on_screen_range_; -Text_Layout_Get_Height_Function *text_layout_get_height_; +Text_Layout_On_Screen_Function *text_layout_on_screen_; +Text_Layout_Line_On_Screen_Function *text_layout_line_on_screen_; +Text_Layout_Character_On_Screen_Function *text_layout_character_on_screen_; +Paint_Text_Color_Function *paint_text_color_; Text_Layout_Free_Function *text_layout_free_; Compute_Render_Layout_Function *compute_render_layout_; Draw_Render_Layout_Function *draw_render_layout_; @@ -898,7 +910,10 @@ app_links->text_layout_get_buffer_ = Text_Layout_Get_Buffer;\ app_links->text_layout_buffer_point_to_layout_point_ = Text_Layout_Buffer_Point_To_Layout_Point;\ app_links->text_layout_layout_point_to_buffer_point_ = Text_Layout_Layout_Point_To_Buffer_Point;\ app_links->text_layout_get_on_screen_range_ = Text_Layout_Get_On_Screen_Range;\ -app_links->text_layout_get_height_ = Text_Layout_Get_Height;\ +app_links->text_layout_on_screen_ = Text_Layout_On_Screen;\ +app_links->text_layout_line_on_screen_ = Text_Layout_Line_On_Screen;\ +app_links->text_layout_character_on_screen_ = Text_Layout_Character_On_Screen;\ +app_links->paint_text_color_ = Paint_Text_Color;\ app_links->text_layout_free_ = Text_Layout_Free;\ app_links->compute_render_layout_ = Compute_Render_Layout;\ app_links->draw_render_layout_ = Draw_Render_Layout;\ @@ -1078,7 +1093,10 @@ static b32 text_layout_get_buffer(Application_Links *app, Text_Layout_ID text_la static b32 text_layout_buffer_point_to_layout_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 buffer_relative_p, Vec2 *p_out){return(app->text_layout_buffer_point_to_layout_point(app, text_layout_id, buffer_relative_p, p_out));} static b32 text_layout_layout_point_to_buffer_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 layout_relative_p, Vec2 *p_out){return(app->text_layout_layout_point_to_buffer_point(app, text_layout_id, layout_relative_p, p_out));} static Range_i64 text_layout_get_on_screen_range(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_get_on_screen_range(app, text_layout_id));} -static b32 text_layout_get_height(Application_Links *app, Text_Layout_ID text_layout_id, f32 *height_out){return(app->text_layout_get_height(app, text_layout_id, height_out));} +static Rect_f32 text_layout_on_screen(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_on_screen(app, text_layout_id));} +static Rect_f32 text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 line_number){return(app->text_layout_line_on_screen(app, layout_id, line_number));} +static Rect_f32 text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 pos){return(app->text_layout_character_on_screen(app, layout_id, pos));} +static void paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color){(app->paint_text_color(app, layout_id, range, color));} static b32 text_layout_free(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_free(app, text_layout_id));} static Text_Layout_ID compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Vec2 screen_p, Vec2 layout_dim, Buffer_Point buffer_point, i32 one_past_last){return(app->compute_render_layout(app, view_id, buffer_id, screen_p, layout_dim, buffer_point, one_past_last));} static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout(app, view_id));} @@ -1258,7 +1276,10 @@ static b32 text_layout_get_buffer(Application_Links *app, Text_Layout_ID text_la static b32 text_layout_buffer_point_to_layout_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 buffer_relative_p, Vec2 *p_out){return(app->text_layout_buffer_point_to_layout_point_(app, text_layout_id, buffer_relative_p, p_out));} static b32 text_layout_layout_point_to_buffer_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 layout_relative_p, Vec2 *p_out){return(app->text_layout_layout_point_to_buffer_point_(app, text_layout_id, layout_relative_p, p_out));} static Range_i64 text_layout_get_on_screen_range(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_get_on_screen_range_(app, text_layout_id));} -static b32 text_layout_get_height(Application_Links *app, Text_Layout_ID text_layout_id, f32 *height_out){return(app->text_layout_get_height_(app, text_layout_id, height_out));} +static Rect_f32 text_layout_on_screen(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_on_screen_(app, text_layout_id));} +static Rect_f32 text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 line_number){return(app->text_layout_line_on_screen_(app, layout_id, line_number));} +static Rect_f32 text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 pos){return(app->text_layout_character_on_screen_(app, layout_id, pos));} +static void paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color){(app->paint_text_color_(app, layout_id, range, color));} static b32 text_layout_free(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_free_(app, text_layout_id));} static Text_Layout_ID compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Vec2 screen_p, Vec2 layout_dim, Buffer_Point buffer_point, i32 one_past_last){return(app->compute_render_layout_(app, view_id, buffer_id, screen_p, layout_dim, buffer_point, one_past_last));} static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout_(app, view_id));} diff --git a/4coder_helper.cpp b/4coder_helper.cpp index fc862ff6..7abddfed 100644 --- a/4coder_helper.cpp +++ b/4coder_helper.cpp @@ -2353,10 +2353,63 @@ draw_string(Application_Links *app, Face_ID font_id, String_Const_u8 string, Vec internal void draw_margin(Application_Links *app, f32_Rect outer, f32_Rect inner, int_color color){ - draw_rectangle(app, f32R(outer.x0, outer.y0, outer.x1, inner.y0), color); - draw_rectangle(app, f32R(outer.x0, inner.y1, outer.x1, outer.y1), color); - draw_rectangle(app, f32R(outer.x0, inner.y0, inner.x0, inner.y1), color); - draw_rectangle(app, f32R(inner.x1, inner.y0, outer.x1, inner.y1), color); + draw_rectangle(app, Rf32(outer.x0, outer.y0, outer.x1, inner.y0), color); + draw_rectangle(app, Rf32(outer.x0, inner.y1, outer.x1, outer.y1), color); + draw_rectangle(app, Rf32(outer.x0, inner.y0, inner.x0, inner.y1), color); + draw_rectangle(app, Rf32(inner.x1, inner.y0, outer.x1, inner.y1), color); +} + +internal void +draw_character_block(Application_Links *app, Text_Layout_ID layout, i64 pos, int_color color){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); + draw_rectangle(app, rect, color); +} + +internal void +draw_character_block(Application_Links *app, Text_Layout_ID layout, Range_i64 range, int_color color){ + for (i64 i = range.first; i < range.one_past_last; i += 1){ + draw_character_block(app, layout, i, color); + } +} + +internal void +draw_character_wire_frame(Application_Links *app, Text_Layout_ID layout, i64 pos, int_color color){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); + draw_rectangle_outline(app, rect, color); +} + +internal void +draw_character_wire_frame(Application_Links *app, Text_Layout_ID layout, Range_i64 range, int_color color){ + for (i64 i = range.first; i < range.one_past_last; i += 1){ + draw_character_wire_frame(app, layout, i, color); + } +} + +internal void +draw_character_i_bar(Application_Links *app, Text_Layout_ID layout, i64 pos, int_color color){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); + rect.x1 = rect.x0 + 1.f; + draw_rectangle(app, rect, color); +} + +internal void +draw_line_highlight(Application_Links *app, Text_Layout_ID layout, Range_i64 line_range, int_color color){ + Rect_f32 rect = text_layout_line_on_screen(app, layout, line_range.min); + for (i64 i = line_range.min + 1; i <= line_range.max; i += 1){ + Rect_f32 r = text_layout_line_on_screen(app, layout, i); + rect = rect_union(rect, r); + } + draw_rectangle(app, rect, color); +} + +internal void +draw_line_highlight(Application_Links *app, Text_Layout_ID layout, i64 line, int_color color){ + draw_line_highlight(app, layout, Ii64(line), color); +} + +internal void +paint_text_color(Application_Links *app, Text_Layout_ID layout, i64 pos, int_color color){ + paint_text_color(app, layout, Ii64(pos, pos + 1), color); } //////////////////////////////// diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 59a077c6..781b1153 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -3804,18 +3804,113 @@ Text_Layout_Get_On_Screen_Range(Application_Links *app, Text_Layout_ID text_layo return(result); } -API_EXPORT b32 -Text_Layout_Get_Height(Application_Links *app, Text_Layout_ID text_layout_id, f32 *height_out){ +API_EXPORT Rect_f32 +Text_Layout_On_Screen(Application_Links *app, Text_Layout_ID text_layout_id){ Models *models = (Models*)app->cmd_context; Text_Layout layout = {}; - b32 result = false; + Rect_f32 result = {}; if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ - *height_out = layout.height; - result = true; + result = Rf32_xy_wh(layout.coordinates.on_screen_p0, layout.coordinates.dim); + Vec2_f32 coordinate_center = models_get_coordinate_center(models); + result.p0 -= coordinate_center; + result.p1 -= coordinate_center; } return(result); } +API_EXPORT Rect_f32 +Text_Layout_Line_On_Screen(Application_Links *app, Text_Layout_ID layout_id, i64 line_number){ + Models *models = (Models*)app->cmd_context; + Text_Layout layout = {}; + Rect_f32 result = {}; + if (text_layout_get(&models->text_layouts, layout_id, &layout)){ + Editing_File *file = imp_get_file(models, layout.buffer_id); + if (api_check_buffer(file)){ + Partial_Cursor first_partial = file_compute_partial_cursor(file, seek_line_char(line_number, 1)); + Partial_Cursor last_partial = file_compute_partial_cursor(file, seek_line_char(line_number, -1)); + Full_Cursor first = file_compute_cursor(models, file, seek_pos(first_partial.pos)); + Full_Cursor last = file_compute_cursor(models, file, seek_pos(last_partial.pos)); + + f32 top = first.wrapped_y; + f32 bot = last.wrapped_y; + if (file->settings.unwrapped_lines){ + top = first.unwrapped_y; + bot = last.unwrapped_y; + } + + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); + f32 line_height = face->height; + bot += line_height; + + result = Rf32(layout.coordinates.on_screen_p0.x, top, + layout.coordinates.on_screen_p0.x + layout.coordinates.dim.x, bot); + + f32 shift_y = layout.coordinates.on_screen_p0.y - layout.coordinates.in_buffer_p0.y; + result.y0 += shift_y; + result.y1 += shift_y; + + Rect_f32 whole_layout = Rf32_xy_wh(layout.coordinates.on_screen_p0, layout.coordinates.dim); + result = rect_intersect(result, whole_layout); + + Vec2_f32 coordinate_center = models_get_coordinate_center(models); + result.p0 -= coordinate_center; + result.p1 -= coordinate_center; + } + } + return(result); +} + +API_EXPORT Rect_f32 +Text_Layout_Character_On_Screen(Application_Links *app, Text_Layout_ID layout_id, i64 pos){ + Models *models = (Models*)app->cmd_context; + Text_Layout layout = {}; + Rect_f32 result = {}; + if (text_layout_get(&models->text_layouts, layout_id, &layout)){ + Editing_File *file = imp_get_file(models, layout.buffer_id); + if (api_check_buffer(file)){ + Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(pos)); + + f32 top = cursor.wrapped_y; + f32 left = cursor.wrapped_x; + if (file->settings.unwrapped_lines){ + top = cursor.unwrapped_y; + left = cursor.unwrapped_x; + } + + Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); + f32 line_height = face->height; + f32 bot = top + line_height; + + i64 size = buffer_size(&file->state.buffer); + Range_i64 range = Ii64(pos, pos + 4); + range.max = clamp_top(range.max, size); + u8 space[4]; + buffer_read_range(app, layout.buffer_id, range, (char*)space); + u32 codepoint = utf8_to_u32_unchecked(space); + f32 advance = font_get_glyph_advance(face, codepoint); + + result = Rf32(left, top, left + advance, bot); + + Vec2_f32 shift = layout.coordinates.on_screen_p0 - layout.coordinates.in_buffer_p0; + result.p0 += shift; + result.p1 += shift; + + Rect_f32 whole_layout = Rf32_xy_wh(layout.coordinates.on_screen_p0, layout.coordinates.dim); + result = rect_intersect(result, whole_layout); + + Vec2_f32 coordinate_center = models_get_coordinate_center(models); + result.p0 -= coordinate_center; + result.p1 -= coordinate_center; + } + } + return(result); +} + +API_EXPORT void +Paint_Text_Color(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color){ + //NotImplemented; +} + API_EXPORT b32 Text_Layout_Free(Application_Links *app, Text_Layout_ID text_layout_id){ Models *models = (Models*)app->cmd_context; @@ -3859,6 +3954,7 @@ Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_ scroll_y = intermediate_cursor.unwrapped_y; } scroll_y += buffer_point.pixel_shift.y; + Vec2_f32 in_buffer_p = V2f32(scroll_x, scroll_y); Full_Cursor render_cursor = file_get_render_cursor(models, file, scroll_y); i32 item_count = 0; @@ -3948,7 +4044,11 @@ Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_ Buffer_Render_Item *render_item_last = items + item_count - 1; height = render_item_last->y1 - render_item_first->y0; } - result = text_layout_new(&models->mem.heap, &models->text_layouts, buffer_id, buffer_point, range, height); + Text_Layout_Coordinates coordinates = {}; + coordinates.on_screen_p0 = screen_p; + coordinates.in_buffer_p0 = in_buffer_p; + coordinates.dim = layout_dim; + result = text_layout_new(&models->mem.heap, &models->text_layouts, buffer_id, buffer_point, range, height, coordinates); } return(result); } diff --git a/4ed_buffer.cpp b/4ed_buffer.cpp index 766826a1..e692d089 100644 --- a/4ed_buffer.cpp +++ b/4ed_buffer.cpp @@ -38,8 +38,12 @@ buffer_quick_sort_cursors(Cursor_With_Index *positions, i32 start, i32 pivot){ } CursorSwap__(positions[mid], positions[pivot]); - if (start < mid - 1) buffer_quick_sort_cursors(positions, start, mid - 1); - if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot); + if (start < mid - 1){ + buffer_quick_sort_cursors(positions, start, mid - 1); + } + if (mid + 1 < pivot){ + buffer_quick_sort_cursors(positions, mid + 1, pivot); + } } // TODO(allen): Rewrite this without being a dumbass. @@ -1744,7 +1748,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 switch (params.wrap_slashes){ case WrapIndicator_Show_After_Line: { - S.write = write_render_item(S.write, S.step.i-1, '\\', BRFlag_Ghost_Character, 0); + S.write = write_render_item(S.write, S.step.i - 1, '\\', BRFlag_Ghost_Character, 0); }break; case WrapIndicator_Show_At_Wrap_Edge: @@ -1752,7 +1756,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 if (S.write.x < S.shift_x + params.width){ S.write.x = S.shift_x + params.width; } - S.write = write_render_item(S.write, S.step.i-1, '\\', BRFlag_Ghost_Character, 0); + S.write = write_render_item(S.write, S.step.i - 1, '\\', BRFlag_Ghost_Character, 0); }break; } diff --git a/4ed_font_face.cpp b/4ed_font_face.cpp index bdcdc598..18083dd8 100644 --- a/4ed_font_face.cpp +++ b/4ed_font_face.cpp @@ -36,6 +36,9 @@ font_get_glyph_advance(Face *face, u32 codepoint){ result = face->space_advance*4.f; } else{ + if (character_is_whitespace(codepoint)){ + codepoint = ' '; + } u16 index = 0; if (codepoint_index_map_read(&face->codepoint_to_index_map, codepoint, &index)){ if (index < face->index_count){ diff --git a/4ed_render_target.cpp b/4ed_render_target.cpp index b6127358..40f98a7b 100644 --- a/4ed_render_target.cpp +++ b/4ed_render_target.cpp @@ -193,8 +193,7 @@ draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, f32 x, f32 y, Glyph_Bounds bounds = face->bounds[glyph_index]; Vec3_f32 texture_dim = face->texture_dim; - f32_Rect uv = Rf32(bounds.uv.x0, bounds.uv.y0, - bounds.uv.x1, bounds.uv.y1); + Rect_f32 uv = bounds.uv; Render_Vertex vertices[6] = {}; if (!HasFlag(flags, GlyphFlag_Rotate90)){ diff --git a/4ed_text_layout.cpp b/4ed_text_layout.cpp index af994ff4..4b9d6e2a 100644 --- a/4ed_text_layout.cpp +++ b/4ed_text_layout.cpp @@ -29,12 +29,13 @@ text_layout_new__alloc_layout(Text_Layout_Container *container){ } internal Text_Layout_ID -text_layout_new(Heap *heap, Text_Layout_Container *container, Buffer_ID buffer_id, Buffer_Point point, Range on_screen_range, f32 height){ +text_layout_new(Heap *heap, Text_Layout_Container *container, Buffer_ID buffer_id, Buffer_Point point, Range on_screen_range, f32 height, Text_Layout_Coordinates coordinates){ Text_Layout *new_layout_data = text_layout_new__alloc_layout(container); new_layout_data->buffer_id = buffer_id; new_layout_data->point = point; new_layout_data->on_screen_range = on_screen_range; new_layout_data->height = height; + new_layout_data->coordinates = coordinates; Text_Layout_ID new_id = ++container->id_counter; insert_u32_Ptr_table(heap, &container->table, new_id, new_layout_data); return(new_id); diff --git a/4ed_text_layout.h b/4ed_text_layout.h index 29986479..23f4d820 100644 --- a/4ed_text_layout.h +++ b/4ed_text_layout.h @@ -19,10 +19,13 @@ struct Text_Layout{ // For now, since the engine cannot be easily consolidated, // this just stores the parameters that should be handed to any // system that attempts to query the layout for hit testing. + View_ID view_id; Buffer_ID buffer_id; Buffer_Point point; Range on_screen_range; f32 height; + + Text_Layout_Coordinates coordinates; }; union Text_Layout_Node{ diff --git a/4ed_view.cpp b/4ed_view.cpp index 67f7f7e6..284ee132 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -137,8 +137,8 @@ view_cursor_limits(Models *models, View *view){ i32 line_height = (i32)face->height; i32 visible_height = (i32)view_height(models, view); Cursor_Limits limits = {}; - limits.max = visible_height - line_height*3; limits.min = line_height*2; + limits.max = visible_height - line_height*3; if (limits.max - limits.min <= line_height){ if (visible_height >= line_height){ limits.max = visible_height - line_height; @@ -148,8 +148,8 @@ view_cursor_limits(Models *models, View *view){ } limits.min = 0; } - limits.max = clamp_bot(0, limits.max); limits.min = clamp(0, limits.min, limits.max); + limits.max = clamp_bot(0, limits.max); limits.delta = clamp_top(line_height*5, (limits.max - limits.min + 1)/2); return(limits); } @@ -806,6 +806,7 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v b32 wrapped = !file->settings.unwrapped_lines; Face_ID font_id = file->settings.font_id; +#if 0 // NOTE(allen): Get visual markers Render_Marker_List markers_list = {}; { @@ -873,6 +874,7 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v Render_Range_Record *line_range_stack = push_array(scratch, Render_Range_Record, line_range_markers.count); i32 line_range_stack_top = -1; +#endif i32 *line_starts = file->state.buffer.line_starts; i32 line_count = file->state.buffer.line_count; @@ -899,8 +901,10 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v first_byte_index_of_next_wrap = max_i32; } +#if 0 visual_markers_replace_pos_with_first_byte_of_line(line_markers, line_starts, line_count, line_scan_index); visual_markers_replace_pos_with_first_byte_of_line(line_range_markers, line_starts, line_count, line_scan_index); +#endif i32 visual_markers_scan_index = 0; @@ -991,7 +995,7 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v } if (item->y1 > 0){ - f32_Rect char_rect = f32R(item->x0, item->y0, item->x1, item->y1); + Rect_f32 char_rect = f32R(item->x0, item->y0, item->x1, item->y1); u32 char_color = main_color; if (item->flags & BRFlag_Special_Character){ @@ -1008,6 +1012,7 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v highlight_this_color = highlight_color; } +#if 0 // NOTE(allen): Line marker color if (is_new_line){ visual_line_markers_color = 0; @@ -1138,12 +1143,14 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v }break; } } +#endif // NOTE(allen): Perform highlight, wireframe, and ibar renders u32 color_highlight = 0; u32 color_wireframe = 0; u32 color_ibar = 0; +#if 0 if (marker_highlight != 0){ if (color_highlight == 0){ color_highlight = marker_highlight; @@ -1159,23 +1166,28 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v color_ibar = marker_ibar; } } +#endif if (highlight_this_color != 0){ if (color_highlight == 0){ color_highlight = highlight_this_color; } } +#if 0 if (marker_line_highlight != 0){ f32_Rect line_rect = f32R((f32)rect.x0, char_rect.y0, (f32)rect.x1, char_rect.y1); draw_rectangle(target, line_rect, marker_line_highlight); } +#endif if (color_highlight != 0){ draw_rectangle(target, char_rect, color_highlight); } +#if 0 if (marker_highlight_text != SymbolicColor_Default){ char_color = marker_highlight_text; } +#endif u32 fade_color = 0xFFFF00FF; f32 fade_amount = 0.f; @@ -1194,10 +1206,12 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v if (color_wireframe != 0){ draw_rectangle_outline(target, char_rect, color_wireframe); } +#if 0 if (color_ibar != 0){ f32_Rect ibar_rect = f32R(char_rect.x0, char_rect.y0, char_rect.x0 + 1, char_rect.y1); draw_rectangle_outline(target, ibar_rect, color_ibar); } +#endif } prev_ind = ind; diff --git a/4ed_view.h b/4ed_view.h index fe8fde21..9213fe70 100644 --- a/4ed_view.h +++ b/4ed_view.h @@ -47,8 +47,8 @@ struct View{ Arena layout_arena; struct{ - i32_Rect view_rect; - i32_Rect buffer_rect; + Rect_i32 view_rect; + Rect_i32 buffer_rect; Full_Cursor cursor; Range range; Buffer_Render_Item *items; diff --git a/things_ive_broken.txt b/things_ive_broken.txt index 32333998..08d041e8 100644 --- a/things_ive_broken.txt +++ b/things_ive_broken.txt @@ -44,3 +44,5 @@ set_buffer_face_by_name -> set_buffer_face_by_font_load_location get_existing_face_id_matching_name -> face_id_from_font_load_target get_face_id_by_name set_global_face_by_name -> set_buffer_face_by_font_load_location (with id = 0) + +mark_enclosures -> draw_enclosures \ No newline at end of file