extended text layouts to easily get character and line rectangles

master
Allen Webster 2019-07-31 19:13:36 -07:00
parent 7fd8196485
commit 2e0992fdd3
15 changed files with 307 additions and 207 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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));}

View File

@ -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);
}
////////////////////////////////

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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){

View File

@ -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)){

View File

@ -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);

View File

@ -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{

View File

@ -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;

View File

@ -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;

View File

@ -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