From 187f91084ab08ecc86c578decbf078ad2b012898 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 28 Oct 2019 21:27:20 -0700 Subject: [PATCH] Initial sloppy setup for customizable line layout --- 4ed_api_implementation.cpp | 110 ++++++--- 4ed_app_models.h | 1 + 4ed_app_target.cpp | 2 +- 4ed_buffer.cpp | 232 ++---------------- 4ed_buffer.h | 38 --- 4ed_file.cpp | 120 ++++++--- 4ed_font_interface.h | 30 +-- 4ed_font_provider_freetype.cpp | 78 +++--- 4ed_render_target.cpp | 12 +- 4ed_text_layout.cpp | 18 +- 4ed_text_layout.h | 1 + 4ed_view.cpp | 111 ++++++--- 4ed_view.h | 1 + .../4coder_codepoint_map.cpp | 41 ++-- custom/4coder_default_hooks.cpp | 183 ++++++++++++++ custom/4coder_default_include.cpp | 1 + custom/4coder_types.h | 66 ++++- custom/generated/custom_api.cpp | 2 + custom/generated/custom_api.h | 5 + custom/generated/custom_api_master_list.h | 1 + platform_win32/win32_4ed.cpp | 2 +- 21 files changed, 613 insertions(+), 442 deletions(-) rename 4ed_font_face.cpp => custom/4coder_codepoint_map.cpp (52%) diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index a0fa6944..4bf61740 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -356,64 +356,84 @@ buffer_seek_character_class(Application_Links *app, Buffer_ID buffer, Character_ } api(custom) function f32 -buffer_line_y_difference(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line_a, i64 line_b){ +buffer_line_y_difference(Application_Links *app, Buffer_ID buffer_id, + f32 width, Face_ID face_id, + i64 line_a, i64 line_b){ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); f32 result = {}; if (api_check_buffer(file)){ Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - result = file_line_y_difference(app->tctx, models, file, width, face, line_a, line_b); + Layout_Function *layout_func = models->layout_func; + result = file_line_y_difference(app->tctx, models, file, + layout_func, width, face, + line_a, line_b); } } return(result); } api(custom) function Line_Shift_Vertical -buffer_line_shift_y(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line, f32 y_shift){ +buffer_line_shift_y(Application_Links *app, Buffer_ID buffer_id, + f32 width, Face_ID face_id, + i64 line, f32 y_shift){ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); Line_Shift_Vertical result = {}; if (api_check_buffer(file)){ Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - result = file_line_shift_y(app->tctx, models, file, width, face, line, y_shift); + Layout_Function *layout_func = models->layout_func; + result = file_line_shift_y(app->tctx, models, file, + layout_func, width, face, + line, y_shift); } } return(result); } api(custom) function i64 -buffer_pos_at_relative_xy(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, Vec2_f32 relative_xy){ +buffer_pos_at_relative_xy(Application_Links *app, Buffer_ID buffer_id, + f32 width, Face_ID face_id, + i64 base_line, Vec2_f32 relative_xy){ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); i64 result = -1; if (api_check_buffer(file)){ Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - result = file_pos_at_relative_xy(app->tctx, models, file, width, face, base_line, relative_xy); + Layout_Function *layout_func = models->layout_func; + result = file_pos_at_relative_xy(app->tctx, models, file, + layout_func, width, face, + base_line, relative_xy); } } return(result); } api(custom) function Vec2_f32 -buffer_relative_xy_of_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos) -{ +buffer_relative_xy_of_pos(Application_Links *app, Buffer_ID buffer_id, + f32 width, Face_ID face_id, + i64 base_line, i64 pos){ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); Vec2_f32 result = {}; if (api_check_buffer(file)){ Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - result = file_relative_xy_of_pos(app->tctx, models, file, width, face, base_line, pos); + Layout_Function *layout_func = models->layout_func; + result = file_relative_xy_of_pos(app->tctx, models, file, + layout_func, width, face, + base_line, pos); } } return(result); } api(custom) function i64 -buffer_relative_character_from_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos) +buffer_relative_character_from_pos(Application_Links *app, Buffer_ID buffer_id, + f32 width, Face_ID face_id, i64 base_line, i64 pos) { Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); @@ -421,7 +441,10 @@ buffer_relative_character_from_pos(Application_Links *app, Buffer_ID buffer_id, if (api_check_buffer(file)){ Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - result = file_relative_character_from_pos(app->tctx, models, file, width, face, base_line, pos); + Layout_Function *layout_func = models->layout_func; + result = file_relative_character_from_pos(app->tctx, models, file, + layout_func, width, face, + base_line, pos); } } return(result); @@ -436,7 +459,10 @@ buffer_pos_from_relative_character(Application_Links *app, Buffer_ID buffer_id, if (api_check_buffer(file)){ Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - result = file_pos_from_relative_character(app->tctx, models, file, width, face, base_line, relative_character); + Layout_Function *layout_func = models->layout_func; + result = file_pos_from_relative_character(app->tctx, models, file, + layout_func, width, face, + base_line, relative_character); } } return(result); @@ -1497,8 +1523,10 @@ view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll sc scroll.target.pixel_shift.x = f32_round32(scroll.target.pixel_shift.x); scroll.target.pixel_shift.y = f32_round32(scroll.target.pixel_shift.y); scroll.target.pixel_shift.x = clamp_bot(0.f, scroll.target.pixel_shift.x); - Buffer_Layout_Item_List line = view_get_line_layout(tctx, models, view, scroll.target.line_number); - scroll.target.pixel_shift.y = clamp(0.f, scroll.target.pixel_shift.y, line.height); + Layout_Item_List line = view_get_line_layout(tctx, models, view, + scroll.target.line_number); + scroll.target.pixel_shift.y = + clamp(0.f, scroll.target.pixel_shift.y, line.height); if (rule == SetBufferScroll_SnapCursorIntoView){ view_set_scroll(tctx, models, view, scroll); } @@ -2139,6 +2167,10 @@ set_custom_hook(Application_Links *app, Hook_ID hook_id, Void_Func *func_ptr){ { models->buffer_region = (Buffer_Region_Function*)func_ptr; }break; + case HookID_Layout: + { + models->layout_func = (Layout_Function*)func_ptr; + }break; } } @@ -2483,13 +2515,20 @@ get_face_metrics(Application_Links *app, Face_ID face_id){ if (face_id != 0){ Face *face = font_set_face_from_id(&models->font_set, face_id); if (face != 0){ - result.text_height = face->text_height; - result.line_height = face->line_height; - result.max_advance = face->max_advance; - result.normal_advance = face->typical_advance; - result.space_advance = face->space_advance; - result.decimal_digit_advance = face->digit_advance; - result.hex_digit_advance = face->hex_advance; + result = face->metrics; + } + } + return(result); +} + +api(custom) function Face_Advance_Map +get_face_advance_map(Application_Links *app, Face_ID face_id){ + Models *models = (Models*)app->cmd_context; + Face_Advance_Map result = {}; + if (face_id != 0){ + Face *face = font_set_face_from_id(&models->font_set, face_id); + if (face != 0){ + result = face->advance_map; } } return(result); @@ -2717,6 +2756,8 @@ text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, B Gap_Buffer *buffer = &file->state.buffer; + Layout_Function *layout_func = models->layout_func; + Vec2_f32 dim = rect_dim(rect); i64 line_count = buffer_line_count(buffer); @@ -2724,7 +2765,9 @@ text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, B f32 y = -buffer_point.pixel_shift.y; for (;line_number <= line_count; line_number += 1){ - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, dim.x, face, line_number); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, dim.x, face, + line_number); f32 next_y = y + line.height; if (next_y >= dim.y){ break; @@ -2743,7 +2786,8 @@ text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, B colors_array[i].id = Stag_Default; } result = text_layout_new(&models->text_layouts, arena, buffer_id, buffer_point, - visible_range, visible_line_number_range, rect, colors_array); + visible_range, visible_line_number_range, rect, colors_array, + layout_func); } return(result); } @@ -2789,6 +2833,9 @@ text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 if (layout == 0){ return(result); } + + Layout_Function *layout_func = layout->layout_func; + Rect_f32 rect = layout->rect; if (range_contains_inclusive(layout->visible_line_number_range, line_number)){ Editing_File *file = imp_get_file(models, layout->buffer_id); @@ -2798,7 +2845,9 @@ text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 for (i64 line_number_it = layout->visible_line_number_range.first;; line_number_it += 1){ - Buffer_Layout_Item_List line = file_get_line_layout(app->tctx, models, file, width, face, line_number_it); + Layout_Item_List line = file_get_line_layout(app->tctx, models, file, + layout_func, width, face, + line_number_it); result.max += line.height; if (line_number_it == line_number){ break; @@ -2816,6 +2865,7 @@ text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 else if (line_number > layout->visible_line_number_range.max){ result = If32(rect.y1, rect.y1); } + return(result); } @@ -2835,11 +2885,15 @@ text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id f32 width = rect_width(rect); Face *face = file_get_face(models, file); + Layout_Function *layout_func = layout->layout_func; + f32 y = 0.f; - Buffer_Layout_Item_List line = {}; + Layout_Item_List line = {}; for (i64 line_number_it = layout->visible_line_number_range.first;; line_number_it += 1){ - line = file_get_line_layout(app->tctx, models, file, width, face, line_number_it); + line = file_get_line_layout(app->tctx, models, file, + layout_func, width, face, + line_number_it); if (line_number_it == line_number){ break; } @@ -2851,10 +2905,10 @@ text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id // Buffer_Layout_Item_List. b32 is_first_item = true; result = Rf32_negative_infinity; - for (Buffer_Layout_Item_Block *block = line.first; + for (Layout_Item_Block *block = line.first; block != 0; block = block->next){ - Buffer_Layout_Item *item_ptr = block->items; + Layout_Item *item_ptr = block->items; i64 count = block->count; for (i32 i = 0; i < count; i += 1, item_ptr += 1){ i64 index = item_ptr->index; diff --git a/4ed_app_models.h b/4ed_app_models.h index f629cc99..b611f5db 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -62,6 +62,7 @@ struct Models{ Buffer_Hook_Function *save_file; Buffer_Edit_Range_Function *buffer_edit_range; Buffer_Region_Function *buffer_region; + Layout_Function *layout_func; Color_Table fallback_color_table; Color_Table color_table; diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index b7b43b93..548083ad 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -74,6 +74,7 @@ #include "4coder_log.cpp" #include "4coder_buffer_seek_constructors.cpp" #include "4coder_command_map.cpp" +#include "4coder_codepoint_map.cpp" #include "generated/custom_api.cpp" #define DYNAMIC_LINK_API @@ -87,7 +88,6 @@ #include "4ed_coroutine.cpp" #include "4ed_mem.cpp" #include "4ed_dynamic_variables.cpp" -#include "4ed_font_face.cpp" #include "4ed_font_set.cpp" #include "4ed_translation.cpp" #include "4ed_render_target.cpp" diff --git a/4ed_buffer.cpp b/4ed_buffer.cpp index d22fecb9..a4789966 100644 --- a/4ed_buffer.cpp +++ b/4ed_buffer.cpp @@ -856,194 +856,8 @@ buffer_chunk_position_iterate(String_Const_u8_Array chunks, Buffer_Chunk_Positio //////////////////////////////// -internal void -buffer_layout__write(Arena *arena, Buffer_Layout_Item_List *list, i64 index, u32 codepoint, - Buffer_Layout_Flag flags, Rect_f32 rect){ - Temp_Memory restore_point = begin_temp(arena); - Buffer_Layout_Item *item = push_array(arena, Buffer_Layout_Item, 1); - - Buffer_Layout_Item_Block *block = list->first; - if (block != 0){ - if (block->items + block->count == item){ - block->count += 1; - } - else{ - block = 0; - } - } - if (block == 0){ - end_temp(restore_point); - block = push_array(arena, Buffer_Layout_Item_Block, 1); - item = push_array(arena, Buffer_Layout_Item, 1); - sll_queue_push(list->first, list->last, block); - list->node_count += 1; - block->items = item; - block->count = 1; - } - list->total_count += 1; - - if (index > list->index_range.max){ - block->character_count += 1; - list->character_count += 1; - list->index_range.max = index; - } - - item->index = index; - item->codepoint = codepoint; - item->flags = flags; - item->rect = rect; - list->height = max(list->height, rect.y1); -} - -internal Buffer_Layout_Item_List -buffer_layout(Thread_Context *tctx, Arena *arena, Gap_Buffer *buffer, Interval_i64 range, Face *face, f32 width){ - Scratch_Block scratch(tctx); - - Buffer_Layout_Item_List list = {}; - list.index_range.first = range.first; - list.index_range.one_past_last = range.first - 1; - - List_String_Const_u8 chunks = buffer_get_chunks(scratch, buffer); - buffer_chunks_clamp(&chunks, range); - - f32 line_height = face->line_height; - f32 text_height = face->text_height; - f32 line_to_text_shift = text_height - line_height; - f32 space_advance = face->space_advance; - - if (chunks.node_count == 0){ - f32 next_x = space_advance; - buffer_layout__write(arena, &list, range.first, ' ', 0, - Rf32(V2(0.f, 0.f), V2f32(next_x, text_height))); - } - else{ - Vec2_f32 p = {}; - f32 line_y = line_height; - f32 text_y = text_height; - - String_Const_u8 text = {}; - if (chunks.node_count == 1){ - text = chunks.first->string; - } - else{ - text = string_list_flatten(scratch, chunks); - } - - i64 index = range.first; - b32 first_of_the_line = true; - - b32 consuming_newline_characters = false; - i64 newline_character_index = -1; - - b32 prev_did_emit_newline = false; - - u8 *ptr = text.str; - u8 *end_ptr = ptr + text.size; - for (;ptr < end_ptr;){ - Character_Consume_Result consume = utf8_consume(ptr, (umem)(end_ptr - ptr)); - u32 render_codepoint = consume.codepoint; - b32 emit_newline = false; - switch (consume.codepoint){ - case '\t': - { - render_codepoint = ' '; - }//fallthrough; - default: - { - f32 advance = font_get_glyph_advance(face, consume.codepoint); - f32 next_x = p.x + advance; - if (!first_of_the_line && next_x >= width){ - p.y = line_y; - p.x = 0.f; - line_y += line_height; - text_y = line_y + line_to_text_shift; - next_x = p.x + advance; - } - buffer_layout__write(arena, &list, index, render_codepoint, 0, - Rf32(p, V2f32(next_x, text_y))); - p.x = next_x; - ptr += consume.inc; - index += consume.inc; - first_of_the_line = false; - }break; - - case '\r': - { - if (!consuming_newline_characters){ - consuming_newline_characters = true; - newline_character_index = index; - } - ptr += 1; - index += 1; - }break; - - case '\n': - { - if (!consuming_newline_characters){ - consuming_newline_characters = true; - newline_character_index = index; - } - emit_newline = true; - ptr += 1; - index += 1; - }break; - - case max_u32: - { - f32 next_x = p.x + face->byte_advance; - if (!first_of_the_line && next_x >= width){ - p.y = line_y; - p.x = 0.f; - line_y += line_height; - text_y = line_y + line_to_text_shift; - next_x = p.x + face->byte_advance; - } - u32 v = *ptr; - u32 lo = v&0xF; - u32 hi = (v >> 4)&0xF; - f32 advance = face->byte_sub_advances[0]; - buffer_layout__write(arena, &list, index, '\\', 0, - Rf32(p, V2f32(p.x + advance, text_y))); - p.x += advance; - advance = face->byte_sub_advances[1]; - buffer_layout__write(arena, &list, index, integer_symbols[lo], 0, - Rf32(p, V2f32(p.x + advance, text_y))); - p.x += advance; - face->byte_sub_advances[2]; - buffer_layout__write(arena, &list, index, integer_symbols[hi], 0, - Rf32(p, V2f32(p.x + advance, text_y))); - p.x = next_x; - ptr += 1; - index += 1; - first_of_the_line = false; - }break; - } - prev_did_emit_newline = false; - if (emit_newline){ - f32 next_x = p.x + space_advance; - buffer_layout__write(arena, &list, newline_character_index, ' ', 0, - Rf32(p, V2f32(next_x, text_y))); - p.y = line_y; - p.x = 0.f; - line_y += line_height; - text_y = line_y + line_to_text_shift; - first_of_the_line = true; - prev_did_emit_newline = true; - } - } - if (!prev_did_emit_newline){ - f32 next_x = p.x + space_advance; - buffer_layout__write(arena, &list, index, ' ', 0, Rf32(p, V2f32(next_x, text_y))); - } - } - list.bottom_extension = -line_to_text_shift; - list.height += list.bottom_extension; - - return(list); -} - internal i64 -buffer_layout_nearest_pos_to_xy(Buffer_Layout_Item_List list, Vec2_f32 p){ +buffer_layout_nearest_pos_to_xy(Layout_Item_List list, Vec2_f32 p){ i64 closest_match = 0; if (p.y < 0.f){ closest_match = list.index_range.min; @@ -1055,11 +869,11 @@ buffer_layout_nearest_pos_to_xy(Buffer_Layout_Item_List list, Vec2_f32 p){ if (0.f < p.x && p.x < max_f32){ f32 bottom_extension = list.bottom_extension; f32 closest_x = -max_f32; - for (Buffer_Layout_Item_Block *block = list.first; + for (Layout_Item_Block *block = list.first; block != 0; block = block->next){ i64 count = block->count; - Buffer_Layout_Item *item = block->items; + Layout_Item *item = block->items; for (i32 i = 0; i < count; i += 1, item += 1){ // NOTE(allen): This only works if we build layouts in y-sorted order. if (p.y < item->rect.y0){ @@ -1088,12 +902,12 @@ buffer_layout_nearest_pos_to_xy(Buffer_Layout_Item_List list, Vec2_f32 p){ } else{ if (p.x == max_f32){ - Buffer_Layout_Item *prev_item = 0; - for (Buffer_Layout_Item_Block *block = list.first; + Layout_Item *prev_item = 0; + for (Layout_Item_Block *block = list.first; block != 0; block = block->next){ i64 count = block->count; - Buffer_Layout_Item *item = block->items; + Layout_Item *item = block->items; for (i32 i = 0; i < count; i += 1, item += 1){ if (p.y < item->rect.y0){ goto double_break_2; @@ -1113,12 +927,12 @@ buffer_layout_nearest_pos_to_xy(Buffer_Layout_Item_List list, Vec2_f32 p){ } } else{ - Buffer_Layout_Item *closest_item = 0; - for (Buffer_Layout_Item_Block *block = list.first; + Layout_Item *closest_item = 0; + for (Layout_Item_Block *block = list.first; block != 0; block = block->next){ i64 count = block->count; - Buffer_Layout_Item *item = block->items; + Layout_Item *item = block->items; for (i32 i = 0; i < count; i += 1, item += 1){ // NOTE(allen): This only works if we build layouts in y-sorted order. if (p.y < item->rect.y0){ @@ -1145,7 +959,7 @@ buffer_layout_nearest_pos_to_xy(Buffer_Layout_Item_List list, Vec2_f32 p){ } internal i64 -buffer_layout_get_pos_at_character(Buffer_Layout_Item_List list, i64 character){ +buffer_layout_get_pos_at_character(Layout_Item_List list, i64 character){ i64 result = 0; if (character <= 0){ result = list.index_range.min; @@ -1155,7 +969,7 @@ buffer_layout_get_pos_at_character(Buffer_Layout_Item_List list, i64 character){ } else{ i64 counter = 0; - for (Buffer_Layout_Item_Block *node = list.first; + for (Layout_Item_Block *node = list.first; node != 0; node = node->next){ i64 next_counter = counter + node->character_count; @@ -1164,7 +978,7 @@ buffer_layout_get_pos_at_character(Buffer_Layout_Item_List list, i64 character){ i64 relative_character = character - counter; i64 relative_character_counter = 0; i64 prev_index = -1; - Buffer_Layout_Item *item = node->items; + Layout_Item *item = node->items; for (i64 i = 0; i < count; i += 1, item += 1){ if (prev_index != item->index){ prev_index = item->index; @@ -1183,15 +997,15 @@ buffer_layout_get_pos_at_character(Buffer_Layout_Item_List list, i64 character){ return(result); } -internal Buffer_Layout_Item* -buffer_layout_get_first_with_index(Buffer_Layout_Item_List list, i64 index){ - Buffer_Layout_Item *result = 0; - Buffer_Layout_Item *prev = 0; - for (Buffer_Layout_Item_Block *block = list.first; +internal Layout_Item* +buffer_layout_get_first_with_index(Layout_Item_List list, i64 index){ + Layout_Item *result = 0; + Layout_Item *prev = 0; + for (Layout_Item_Block *block = list.first; block != 0; block = block->next){ i64 count = block->count; - Buffer_Layout_Item *item = block->items; + Layout_Item *item = block->items; for (i32 i = 0; i < count; i += 1, item += 1){ if (item->index > index){ result = prev; @@ -1212,9 +1026,9 @@ buffer_layout_get_first_with_index(Buffer_Layout_Item_List list, i64 index){ } internal Vec2_f32 -buffer_layout_xy_center_of_pos(Buffer_Layout_Item_List list, i64 index){ +buffer_layout_xy_center_of_pos(Layout_Item_List list, i64 index){ Vec2_f32 result = {}; - Buffer_Layout_Item *item = buffer_layout_get_first_with_index(list, index); + Layout_Item *item = buffer_layout_get_first_with_index(list, index); if (item != 0){ result = rect_center(item->rect); } @@ -1222,7 +1036,7 @@ buffer_layout_xy_center_of_pos(Buffer_Layout_Item_List list, i64 index){ } internal i64 -buffer_layout_character_from_pos(Buffer_Layout_Item_List list, i64 index){ +buffer_layout_character_from_pos(Layout_Item_List list, i64 index){ i64 result = 0; i64 character_count = 0; i64 prev_index = -1; @@ -1233,10 +1047,10 @@ buffer_layout_character_from_pos(Buffer_Layout_Item_List list, i64 index){ result = list.character_count - 1; } else{ - for (Buffer_Layout_Item_Block *node = list.first; + for (Layout_Item_Block *node = list.first; node != 0; node = node->next){ - Buffer_Layout_Item *item = node->items; + Layout_Item *item = node->items; i64 count = node->count; for (i64 i = 0; i < count; i += 1, item += 1){ if (item->index == index){ diff --git a/4ed_buffer.h b/4ed_buffer.h index c0c213c6..2c0dd071 100644 --- a/4ed_buffer.h +++ b/4ed_buffer.h @@ -63,44 +63,6 @@ struct Line_Move{ }; }; -typedef u32 Buffer_Layout_Flag; -enum{ - BRFlag_Special_Character = (1 << 0), - BRFlag_Ghost_Character = (1 << 1) -}; - -struct Buffer_Layout_Item{ - i64 index; - u32 codepoint; - Buffer_Layout_Flag flags; - Rect_f32 rect; -}; - -struct Buffer_Layout_Item_Block{ - Buffer_Layout_Item_Block *next; - Buffer_Layout_Item *items; - i64 count; - i64 character_count; -}; - -struct Buffer_Layout_Item_List{ - Buffer_Layout_Item_Block *first; - Buffer_Layout_Item_Block *last; - i32 node_count; - i32 total_count; - f32 height; - f32 bottom_extension; - i64 character_count; - Interval_i64 index_range; -}; - -#if 0 -struct Edit_Array{ - Edit *vals; - i32 count; -}; -#endif - #endif // BOTTOM diff --git a/4ed_file.cpp b/4ed_file.cpp index 825904cd..6cf50875 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -292,9 +292,10 @@ file_get_managed_scope(Editing_File *file){ //////////////////////////////// -internal Buffer_Layout_Item_List -file_get_line_layout(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 line_number){ - Buffer_Layout_Item_List result = {}; +internal Layout_Item_List +file_get_line_layout(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, i64 line_number){ + Layout_Item_List result = {}; i64 line_count = buffer_line_count(&file->state.buffer); if (1 <= line_number && line_number <= line_count){ @@ -306,19 +307,23 @@ file_get_line_layout(Thread_Context *tctx, Models *models, Editing_File *file, f Data key_data = make_data_struct(&key); - Buffer_Layout_Item_List *list = 0; + Layout_Item_List *list = 0; Table_Lookup lookup = table_lookup(&file->state.line_layout_table, key_data); if (lookup.found_match){ u64 val = 0; table_read(&file->state.line_layout_table, lookup, &val); - list = (Buffer_Layout_Item_List*)IntAsPtr(val); + list = (Layout_Item_List*)IntAsPtr(val); } else{ - list = push_array(&file->state.cached_layouts_arena, Buffer_Layout_Item_List, 1); - Interval_i64 line_range = buffer_get_pos_range_from_line_number(&file->state.buffer, line_number); - *list = buffer_layout(tctx, &file->state.cached_layouts_arena, - &file->state.buffer, line_range, face, width); + list = push_array(&file->state.cached_layouts_arena, Layout_Item_List, 1); + Range_i64 line_range = buffer_get_pos_range_from_line_number(&file->state.buffer, line_number); + + Application_Links app = {}; + app.tctx = tctx; + app.cmd_context = models; + *list = layout_func(&app, &file->state.cached_layouts_arena, + file->id, line_range, face->id, width); key_data = push_data_copy(&file->state.cached_layouts_arena, key_data); table_insert(&file->state.line_layout_table, key_data, (u64)PtrAsInt(list)); } @@ -335,7 +340,9 @@ file_clear_layout_cache(Editing_File *file){ } internal Line_Shift_Vertical -file_line_shift_y(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 line_number, f32 y_delta){ +file_line_shift_y(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + i64 line_number, f32 y_delta){ Line_Shift_Vertical result = {}; f32 line_y = 0.f; @@ -355,7 +362,8 @@ file_line_shift_y(Thread_Context *tctx, Models *models, Editing_File *file, f32 line_number = 1; break; } - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, line_number); + Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, + width, face, line_number); line_y -= line.height; } if (!has_result){ @@ -368,7 +376,8 @@ file_line_shift_y(Thread_Context *tctx, Models *models, Editing_File *file, f32 b32 has_result = false; i64 line_count = buffer_line_count(&file->state.buffer); for (;;line_number += 1){ - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, line_number); + Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, + width, face, line_number); f32 next_y = line_y + line.height; if (y_delta < next_y){ has_result = true; @@ -391,12 +400,15 @@ file_line_shift_y(Thread_Context *tctx, Models *models, Editing_File *file, f32 } internal f32 -file_line_y_difference(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 line_a, i64 line_b){ +file_line_y_difference(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + i64 line_a, i64 line_b){ f32 result = 0.f; if (line_a != line_b){ Interval_i64 line_range = Ii64(line_a, line_b); for (i64 i = line_range.min; i < line_range.max; i += 1){ - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, i); + Layout_Item_List line = file_get_line_layout(tctx, models, file, layout_func, + width, face, i); result += line.height; } if (line_a < line_b){ @@ -407,25 +419,40 @@ file_line_y_difference(Thread_Context *tctx, Models *models, Editing_File *file, } internal i64 -file_pos_at_relative_xy(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 base_line, Vec2_f32 relative_xy){ - Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, width, face, base_line, relative_xy.y); +file_pos_at_relative_xy(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + i64 base_line, Vec2_f32 relative_xy){ + Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, + layout_func, width, face, base_line, + relative_xy.y); relative_xy.y -= shift.y_delta; - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, shift.line); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + shift.line); return(buffer_layout_nearest_pos_to_xy(line, relative_xy)); } internal Vec2_f32 -file_relative_xy_of_pos(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 base_line, i64 pos){ +file_relative_xy_of_pos(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + i64 base_line, i64 pos){ i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1; - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, line_number); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + line_number); Vec2_f32 result = buffer_layout_xy_center_of_pos(line, pos); - result.y += file_line_y_difference(tctx, models, file, width, face, line_number, base_line); + result.y += file_line_y_difference(tctx, models, file, + layout_func, width, face, line_number, base_line); return(result); } internal Buffer_Point -file_normalize_buffer_point(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, Buffer_Point point){ - Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, width, face, point.line_number, point.pixel_shift.y); +file_normalize_buffer_point(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + Buffer_Point point){ + Line_Shift_Vertical shift = file_line_shift_y(tctx, models, file, + layout_func, width, face, point.line_number, + point.pixel_shift.y); point.line_number = shift.line; point.pixel_shift.y -= shift.y_delta; point.pixel_shift.x = clamp_bot(0.f, point.pixel_shift.x); @@ -434,15 +461,21 @@ file_normalize_buffer_point(Thread_Context *tctx, Models *models, Editing_File * } internal Vec2_f32 -file_buffer_point_difference(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, Buffer_Point a, Buffer_Point b){ - f32 y_difference = file_line_y_difference(tctx, models, file, width, face, a.line_number, b.line_number); +file_buffer_point_difference(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + Buffer_Point a, Buffer_Point b){ + f32 y_difference = file_line_y_difference(tctx, models, file, + layout_func, width, face, + a.line_number, b.line_number); Vec2_f32 result = a.pixel_shift - b.pixel_shift; result.y += y_difference; return(result); } internal Line_Shift_Character -file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 line_number, i64 character_delta){ +file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + i64 line_number, i64 character_delta){ Line_Shift_Character result = {}; i64 line_character = 0; @@ -462,7 +495,9 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f line_number = 1; break; } - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, line_number); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + line_number); line_character -= line.character_count; } if (!has_result){ @@ -475,7 +510,9 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f b32 has_result = false; i64 line_count = buffer_line_count(&file->state.buffer); for (;;line_number += 1){ - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, line_number); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + line_number); i64 next_character = line_character + line.character_count; if (character_delta < next_character){ has_result = true; @@ -498,12 +535,15 @@ file_line_shift_characters(Thread_Context *tctx, Models *models, Editing_File *f } internal i64 -file_line_character_difference(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 line_a, i64 line_b){ +file_line_character_difference(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + i64 line_a, i64 line_b){ i64 result = 0; if (line_a != line_b){ Interval_i64 line_range = Ii64(line_a, line_b); for (i64 i = line_range.min; i < line_range.max; i += 1){ - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, i); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, i); result += line.character_count; } if (line_a < line_b){ @@ -514,19 +554,29 @@ file_line_character_difference(Thread_Context *tctx, Models *models, Editing_Fil } internal i64 -file_pos_from_relative_character(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 base_line, i64 relative_character){ - Line_Shift_Character shift = file_line_shift_characters(tctx, models, file, width, face, base_line, relative_character); +file_pos_from_relative_character(Thread_Context *tctx, Models *models, Editing_File *file, + Layout_Function *layout_func, f32 width, Face *face, + i64 base_line, i64 relative_character){ + Line_Shift_Character shift = file_line_shift_characters(tctx, models, file, + layout_func, width, face, + base_line, relative_character); relative_character -= shift.character_delta; - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, shift.line); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + shift.line); return(buffer_layout_get_pos_at_character(line, relative_character)); } internal i64 -file_relative_character_from_pos(Thread_Context *tctx, Models *models, Editing_File *file, f32 width, Face *face, i64 base_line, i64 pos){ +file_relative_character_from_pos(Thread_Context *tctx, Models *models, Editing_File *file, Layout_Function *layout_func, f32 width, Face *face, + i64 base_line, i64 pos){ i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1; - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, line_number); + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + line_number); i64 result = buffer_layout_character_from_pos(line, pos); - result += file_line_character_difference(tctx, models, file, width, face, line_number, base_line); + result += file_line_character_difference(tctx, models, file, + layout_func, width, face, line_number, base_line); return(result); } diff --git a/4ed_font_interface.h b/4ed_font_interface.h index 2ccb3990..34406c1e 100644 --- a/4ed_font_interface.h +++ b/4ed_font_interface.h @@ -30,43 +30,17 @@ struct Glyph_Bounds{ Rect_f32 xy_off; }; -struct Codepoint_Index_Map{ - b32 has_zero_index; - u16 zero_index; - u16 max_index; - Table_u32_u16 table; -}; - struct Face{ Face_Description description; Face_ID id; i32 version_number; // NOTE(allen): Metrics - f32 text_height; - f32 line_height; - f32 ascent; - f32 descent; - f32 line_skip; - f32 max_advance; - - f32 underline_yoff1; - f32 underline_yoff2; - - f32 space_advance; - f32 digit_advance; - f32 hex_advance; - f32 byte_advance; - f32 byte_sub_advances[3]; - f32 typical_lowercase_advance; - f32 typical_uppercase_advance; - f32 typical_advance; + Face_Metrics metrics; // NOTE(allen): Glyph data - Codepoint_Index_Map codepoint_to_index_map; - u16 index_count; + Face_Advance_Map advance_map; Glyph_Bounds *bounds; - f32 *advance; Glyph_Bounds white; Texture_Kind texture_kind; diff --git a/4ed_font_provider_freetype.cpp b/4ed_font_provider_freetype.cpp index ada36ca3..8b53a06f 100644 --- a/4ed_font_provider_freetype.cpp +++ b/4ed_font_provider_freetype.cpp @@ -194,31 +194,35 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor face->description = *description; face->description.font.file_name = file_name; - face->max_advance = f32_ceil32(ft_face->size->metrics.max_advance/64.f); - face->ascent = f32_ceil32(ft_face->size->metrics.ascender/64.f); - face->descent = f32_floor32(ft_face->size->metrics.descender/64.f); - face->text_height = f32_ceil32(ft_face->size->metrics.height/64.f); - face->line_skip = face->text_height - face->ascent + face->descent; - face->line_skip = clamp_bot(1.f, face->line_skip); - face->line_height = face->text_height + face->line_skip; + Face_Metrics *met = &face->metrics; + + met->max_advance = f32_ceil32(ft_face->size->metrics.max_advance/64.f); + met->ascent = f32_ceil32(ft_face->size->metrics.ascender/64.f); + met->descent = f32_floor32(ft_face->size->metrics.descender/64.f); + met->text_height = f32_ceil32(ft_face->size->metrics.height/64.f); + met->line_skip = met->text_height - met->ascent + met->descent; + met->line_skip = clamp_bot(1.f, met->line_skip); + met->line_height = met->text_height + met->line_skip; { - f32 real_over_notional = face->line_height/(f32)ft_face->height; + f32 real_over_notional = met->line_height/(f32)ft_face->height; f32 relative_center = -1.f*real_over_notional*ft_face->underline_position; f32 relative_thickness = real_over_notional*ft_face->underline_thickness; - f32 center = f32_floor32(face->ascent + relative_center); + f32 center = f32_floor32(met->ascent + relative_center); f32 thickness = clamp_bot(1.f, relative_thickness); - face->underline_yoff1 = center - thickness*0.5f; - face->underline_yoff2 = center + thickness*0.5f; + met->underline_yoff1 = center - thickness*0.5f; + met->underline_yoff2 = center + thickness*0.5f; } - face->codepoint_to_index_map = ft__get_codepoint_index_map(arena->base_allocator, ft_face); - u16 index_count = codepoint_index_map_count(&face->codepoint_to_index_map); - face->index_count = index_count; + face->advance_map.codepoint_to_index = + ft__get_codepoint_index_map(arena->base_allocator, ft_face); + u16 index_count = + codepoint_index_map_count(&face->advance_map.codepoint_to_index); + face->advance_map.index_count = index_count; + face->advance_map.advance = push_array_zero(arena, f32, index_count); face->bounds = push_array(arena, Glyph_Bounds, index_count); - face->advance = push_array_zero(arena, f32, index_count); struct FT_Bitmap{ Vec2_i32 dim; @@ -238,7 +242,7 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor bitmap->data = push_array(arena, u8, dim.x*dim.y); face->bounds[i].xy_off.x0 = (f32)(ft_face->glyph->bitmap_left); - face->bounds[i].xy_off.y0 = (f32)(face->ascent - ft_face->glyph->bitmap_top); + face->bounds[i].xy_off.y0 = (f32)(met->ascent - ft_face->glyph->bitmap_top); face->bounds[i].xy_off.x1 = (f32)(face->bounds[i].xy_off.x0 + dim.x); face->bounds[i].xy_off.y1 = (f32)(face->bounds[i].xy_off.y0 + dim.y); @@ -272,7 +276,7 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor }break; } - face->advance[i] = f32_ceil32(ft_glyph->advance.x/64.0f); + face->advance_map.advance[i] = f32_ceil32(ft_glyph->advance.x/64.0f); } } @@ -327,22 +331,30 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor } { - face->space_advance = font_get_glyph_advance(face, ' '); - face->digit_advance = font_get_max_glyph_advance_range(face, '0', '9'); - face->hex_advance = font_get_max_glyph_advance_range(face, 'A', 'F'); - face->hex_advance = Max(face->hex_advance, face->digit_advance); - face->byte_sub_advances[0] = font_get_glyph_advance(face, '\\'); - face->byte_sub_advances[1] = face->hex_advance; - face->byte_sub_advances[2] = face->hex_advance; - face->byte_advance = - face->byte_sub_advances[0] + - face->byte_sub_advances[1] + - face->byte_sub_advances[2]; - face->typical_lowercase_advance = font_get_average_glyph_advance_range(face, 'a', 'z'); - face->typical_uppercase_advance = font_get_average_glyph_advance_range(face, 'A', 'Z'); - face->typical_advance = (26*face->typical_lowercase_advance + - 26*face->typical_uppercase_advance + - 10*face->digit_advance)/62.f; + Face_Advance_Map *advance_map = &face->advance_map; + + met->space_advance = font_get_glyph_advance(advance_map, met, ' '); + met->decimal_digit_advance = + font_get_max_glyph_advance_range(advance_map, met, '0', '9'); + met->hex_digit_advance = + font_get_max_glyph_advance_range(advance_map, met, 'A', 'F'); + met->hex_digit_advance = + max(met->hex_digit_advance, met->decimal_digit_advance); + met->byte_sub_advances[0] = + font_get_glyph_advance(advance_map, met, '\\'); + met->byte_sub_advances[1] = met->hex_digit_advance; + met->byte_sub_advances[2] = met->hex_digit_advance; + met->byte_advance = + met->byte_sub_advances[0] + + met->byte_sub_advances[1] + + met->byte_sub_advances[2]; + met->normal_lowercase_advance = + font_get_average_glyph_advance_range(advance_map, met, 'a', 'z'); + met->normal_uppercase_advance = + font_get_average_glyph_advance_range(advance_map, met, 'A', 'Z'); + met->normal_advance = (26*met->normal_lowercase_advance + + 26*met->normal_uppercase_advance + + 10*met->decimal_digit_advance)/62.f; } } diff --git a/4ed_render_target.cpp b/4ed_render_target.cpp index e3e3795d..afe13a3a 100644 --- a/4ed_render_target.cpp +++ b/4ed_render_target.cpp @@ -167,8 +167,8 @@ draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p, draw__set_face_id(target, face->id); u16 glyph_index = 0; - if (!codepoint_index_map_read(&face->codepoint_to_index_map, codepoint, - &glyph_index)){ + if (!codepoint_index_map_read(&face->advance_map.codepoint_to_index, + codepoint, &glyph_index)){ glyph_index = 0; } Glyph_Bounds bounds = face->bounds[glyph_index]; @@ -230,8 +230,8 @@ draw_string(Render_Target *target, Face *face, String_Const_u8 string, Vec2_f32 if (face != 0){ point = floor32(point); - f32 byte_advance = face->byte_advance; - f32 *byte_sub_advances = face->byte_sub_advances; + f32 byte_advance = face->metrics.byte_advance; + f32 *byte_sub_advances = face->metrics.byte_sub_advances; u8 *str = (u8*)string.str; u8 *str_end = str + string.size; @@ -250,7 +250,9 @@ draw_string(Render_Target *target, Face *face, String_Const_u8 string, Vec2_f32 if (color != 0){ draw_font_glyph(target, face, codepoint, point, color, flags); } - f32 d = font_get_glyph_advance(face, codepoint); + f32 d = font_get_glyph_advance(&face->advance_map, + &face->metrics, + codepoint); point += d*delta; total_delta += d; } diff --git a/4ed_text_layout.cpp b/4ed_text_layout.cpp index 08c9c235..d937e6f1 100644 --- a/4ed_text_layout.cpp +++ b/4ed_text_layout.cpp @@ -37,8 +37,8 @@ text_layout_release(Thread_Context *tctx, Models *models, Text_Layout_Container internal Text_Layout_ID text_layout_new(Text_Layout_Container *container, Arena *arena, Buffer_ID buffer_id, Buffer_Point point, - Interval_i64 visible_range, Interval_i64 visible_line_number_range, - Rect_f32 rect, FColor *item_colors){ + Range_i64 visible_range, Interval_i64 visible_line_number_range, + Rect_f32 rect, FColor *item_colors, Layout_Function *layout_func){ Text_Layout *new_layout_data = text_layout_new__alloc_layout(container); new_layout_data->arena = arena; new_layout_data->buffer_id = buffer_id; @@ -47,6 +47,7 @@ text_layout_new(Text_Layout_Container *container, Arena *arena, new_layout_data->visible_line_number_range = visible_line_number_range; new_layout_data->rect = rect; new_layout_data->item_colors = item_colors; + new_layout_data->layout_func = layout_func; Text_Layout_ID new_id = ++container->id_counter; table_insert(&container->table, new_id, (u64)PtrAsInt(new_layout_data)); return(new_id); @@ -97,21 +98,24 @@ text_layout_render(Thread_Context *tctx, Models *models, Text_Layout *layout){ i64 first_index = layout->visible_range.first; i64 line_number = layout->visible_line_number_range.min; i64 line_number_last = layout->visible_line_number_range.max; + Layout_Function *layout_func = layout->layout_func; for (;line_number <= line_number_last; line_number += 1){ - Buffer_Layout_Item_List line = file_get_line_layout(tctx, models, file, width, face, line_number); - for (Buffer_Layout_Item_Block *block = line.first; + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + line_number); + for (Layout_Item_Block *block = line.first; block != 0; block = block->next){ - Buffer_Layout_Item *item = block->items; + Layout_Item *item = block->items; i64 count = block->count; FColor *item_colors = layout->item_colors; for (i32 i = 0; i < count; i += 1, item += 1){ if (item->codepoint != 0){ ARGB_Color color = 0; - if (HasFlag(item->flags, BRFlag_Special_Character)){ + if (HasFlag(item->flags, LayoutItemFlag_Special_Character)){ color = special_color; } - else if (HasFlag(item->flags, BRFlag_Ghost_Character)){ + else if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){ color = ghost_color; } else{ diff --git a/4ed_text_layout.h b/4ed_text_layout.h index 08ba20a0..bee66a01 100644 --- a/4ed_text_layout.h +++ b/4ed_text_layout.h @@ -22,6 +22,7 @@ union Text_Layout{ Interval_i64 visible_line_number_range; Rect_f32 rect; FColor *item_colors; + Layout_Function *layout_func; }; }; diff --git a/4ed_view.cpp b/4ed_view.cpp index 66afe58d..264399ba 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -177,66 +177,91 @@ view_height(Thread_Context *tctx, Models *models, View *view){ return(rect_height(view_get_buffer_rect(tctx, models, view))); } +function Layout_Function* +view_get_layout_func(View *view){ + return(view->layout_func); +} + //////////////////////////////// -internal Buffer_Layout_Item_List +internal Layout_Item_List view_get_line_layout(Thread_Context *tctx, Models *models, View *view, i64 line_number){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_get_line_layout(tctx, models, file, width, face, line_number)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_get_line_layout(tctx, models, file, layout_func, width, face, line_number)); } internal Line_Shift_Vertical -view_line_shift_y(Thread_Context *tctx, Models *models, View *view, i64 line_number, f32 y_delta){ +view_line_shift_y(Thread_Context *tctx, Models *models, View *view, + i64 line_number, f32 y_delta){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_line_shift_y(tctx, models, file, width, face, line_number, y_delta)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_line_shift_y(tctx, models, file, layout_func, width, face, + line_number, y_delta)); } internal f32 -view_line_y_difference(Thread_Context *tctx, Models *models, View *view, i64 line_a, i64 line_b){ +view_line_y_difference(Thread_Context *tctx, Models *models, View *view, + i64 line_a, i64 line_b){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_line_y_difference(tctx, models, file, width, face, line_a, line_b)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_line_y_difference(tctx, models, file, + layout_func, width, face, line_a, line_b)); } internal i64 -view_pos_at_relative_xy(Thread_Context *tctx, Models *models, View *view, i64 base_line, Vec2_f32 relative_xy){ +view_pos_at_relative_xy(Thread_Context *tctx, Models *models, View *view, + i64 base_line, Vec2_f32 relative_xy){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_pos_at_relative_xy(tctx, models, file, width, face, base_line, relative_xy)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_pos_at_relative_xy(tctx, models, file, + layout_func, width, face, base_line, relative_xy)); } internal Vec2_f32 -view_relative_xy_of_pos(Thread_Context *tctx, Models *models, View *view, i64 base_line, i64 pos){ +view_relative_xy_of_pos(Thread_Context *tctx, Models *models, View *view, + i64 base_line, i64 pos){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_relative_xy_of_pos(tctx, models, file, width, face, base_line, pos)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_relative_xy_of_pos(tctx, models, file, + layout_func, width, face, base_line, pos)); } internal Buffer_Point -view_normalize_buffer_point(Thread_Context *tctx, Models *models, View *view, Buffer_Point point){ +view_normalize_buffer_point(Thread_Context *tctx, Models *models, View *view, + Buffer_Point point){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_normalize_buffer_point(tctx, models, file, width, face, point)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_normalize_buffer_point(tctx, models, file, + layout_func, width, face, point)); } internal Vec2_f32 -view_buffer_point_difference(Thread_Context *tctx, Models *models, View *view, Buffer_Point a, Buffer_Point b){ +view_buffer_point_difference(Thread_Context *tctx, Models *models, View *view, + Buffer_Point a, Buffer_Point b){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_buffer_point_difference(tctx, models, file, width, face, a, b)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_buffer_point_difference(tctx, models, file, + layout_func, width, face, a, b)); } internal Buffer_Point -view_move_buffer_point(Thread_Context *tctx, Models *models, View *view, Buffer_Point buffer_point, Vec2_f32 delta){ +view_move_buffer_point(Thread_Context *tctx, Models *models, View *view, + Buffer_Point buffer_point, Vec2_f32 delta){ delta += buffer_point.pixel_shift; Line_Shift_Vertical shift = view_line_shift_y(tctx, models, view, buffer_point.line_number, delta.y); buffer_point.line_number = shift.line; @@ -245,35 +270,47 @@ view_move_buffer_point(Thread_Context *tctx, Models *models, View *view, Buffer_ } internal Line_Shift_Character -view_line_shift_characters(Thread_Context *tctx, Models *models, View *view, i64 line_number, i64 character_delta){ +view_line_shift_characters(Thread_Context *tctx, Models *models, View *view, + i64 line_number, i64 character_delta){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_line_shift_characters(tctx, models, file, width, face, line_number, character_delta)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_line_shift_characters(tctx, models, file, + layout_func, width, face, line_number, character_delta)); } internal i64 -view_line_character_difference(Thread_Context *tctx, Models *models, View *view, i64 line_a, i64 line_b){ +view_line_character_difference(Thread_Context *tctx, Models *models, View *view, + i64 line_a, i64 line_b){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_line_character_difference(tctx, models, file, width, face, line_a, line_b)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_line_character_difference(tctx, models, file, layout_func, width, face, + line_a, line_b)); } internal i64 -view_pos_from_relative_character(Thread_Context *tctx, Models *models, View *view, i64 base_line, i64 relative_character){ +view_pos_from_relative_character(Thread_Context *tctx, Models *models, View *view, + i64 base_line, i64 relative_character){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_pos_from_relative_character(tctx, models, file, width, face, base_line, relative_character)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_pos_from_relative_character(tctx, models, file, layout_func, width, face, + base_line, relative_character)); } internal i64 -view_relative_character_from_pos(Thread_Context *tctx, Models *models, View *view, i64 base_line, i64 pos){ +view_relative_character_from_pos(Thread_Context *tctx, Models *models, View *view, + i64 base_line, i64 pos){ Editing_File *file = view->file; Face *face = file_get_face(models, file); f32 width = view_width(tctx, models, view); - return(file_relative_character_from_pos(tctx, models, file, width, face, base_line, pos)); + Layout_Function *layout_func = view_get_layout_func(view); + return(file_relative_character_from_pos(tctx, models, file, + layout_func, width, face, base_line, pos)); } internal Buffer_Cursor @@ -291,13 +328,16 @@ view_move_view_to_cursor(Thread_Context *tctx, Models *models, View *view, Buffe Rect_f32 rect = view_get_buffer_rect(tctx, models, view); Vec2_f32 view_dim = rect_dim(rect); + Layout_Function *layout_func = view_get_layout_func(view); + File_Edit_Positions edit_pos = view_get_edit_pos(view); - Vec2_f32 p = file_relative_xy_of_pos(tctx, models, file, view_dim.x, face, scroll->target.line_number, - edit_pos.cursor_pos); + Vec2_f32 p = file_relative_xy_of_pos(tctx, models, file, + layout_func, view_dim.x, face, + scroll->target.line_number, edit_pos.cursor_pos); p -= scroll->target.pixel_shift; - f32 line_height = face->line_height; - f32 typical_advance = face->typical_advance; + f32 line_height = face->metrics.line_height; + f32 normal_advance = face->metrics.normal_advance; Vec2_f32 target_p_relative = {}; if (p.y < 0.f){ @@ -307,10 +347,10 @@ view_move_view_to_cursor(Thread_Context *tctx, Models *models, View *view, Buffe target_p_relative.y = (p.y + line_height*1.5f) - view_dim.y; } if (p.x < 0.f){ - target_p_relative.x = p.x - typical_advance*1.5f; + target_p_relative.x = p.x - normal_advance*1.5f; } else if (p.x > view_dim.x){ - target_p_relative.x = (p.x + typical_advance*1.5f) - view_dim.x; + target_p_relative.x = (p.x + normal_advance*1.5f) - view_dim.x; } scroll->target.pixel_shift += target_p_relative; scroll->target = view_normalize_buffer_point(tctx, models, view, scroll->target); @@ -327,10 +367,14 @@ view_move_cursor_to_view(Thread_Context *tctx, Models *models, View *view, Buffe Rect_f32 rect = view_get_buffer_rect(tctx, models, view); Vec2_f32 view_dim = rect_dim(rect); - Vec2_f32 p = file_relative_xy_of_pos(tctx, models, file, view_dim.x, face, scroll.target.line_number, *pos_in_out); + Layout_Function *layout_func = view_get_layout_func(view); + + Vec2_f32 p = file_relative_xy_of_pos(tctx, models, file, + layout_func, view_dim.x, face, + scroll.target.line_number, *pos_in_out); p -= scroll.target.pixel_shift; - f32 line_height = face->line_height; + f32 line_height = face->metrics.line_height; b32 adjusted_y = true; if (p.y < 0.f){ @@ -346,7 +390,9 @@ view_move_cursor_to_view(Thread_Context *tctx, Models *models, View *view, Buffe b32 result = false; if (adjusted_y){ p += scroll.target.pixel_shift; - *pos_in_out = file_pos_at_relative_xy(tctx, models, file, view_dim.x, face, scroll.target.line_number, p); + *pos_in_out = file_pos_at_relative_xy(tctx, models, file, + layout_func, view_dim.x, face, + scroll.target.line_number, p); result = true; } @@ -515,6 +561,7 @@ view_event_context_base__inner(Coroutine *coroutine){ function void view_init(Thread_Context *tctx, Models *models, View *view, Editing_File *initial_buffer, Custom_Command_Function *event_context_base){ + view->layout_func = models->layout_func; view_set_file(tctx, models, view, initial_buffer); view->node_arena = reserve_arena(tctx); diff --git a/4ed_view.h b/4ed_view.h index 3d2c1947..002aac67 100644 --- a/4ed_view.h +++ b/4ed_view.h @@ -75,6 +75,7 @@ struct View{ File_Edit_Positions edit_pos_; i64 mark; f32 preferred_x; + Layout_Function *layout_func; b8 new_scroll_target; diff --git a/4ed_font_face.cpp b/custom/4coder_codepoint_map.cpp similarity index 52% rename from 4ed_font_face.cpp rename to custom/4coder_codepoint_map.cpp index 18083dd8..74f03fe6 100644 --- a/4ed_font_face.cpp +++ b/custom/4coder_codepoint_map.cpp @@ -1,15 +1,10 @@ /* - * Mr. 4th Dimention - Allen Webster - * - * 23.07.2019 - * - * Face basic operations. - * - */ +4coder_codepoint_map.cpp - Codepoint map to index +*/ // TOP -internal b32 +function b32 codepoint_index_map_read(Codepoint_Index_Map *map, u32 codepoint, u16 *index_out){ b32 success = true; if (codepoint == 0 && map->has_zero_index){ @@ -24,46 +19,48 @@ codepoint_index_map_read(Codepoint_Index_Map *map, u32 codepoint, u16 *index_out return(success); } -internal u16 +function u16 codepoint_index_map_count(Codepoint_Index_Map *map){ return(map->max_index + 1); } -internal f32 -font_get_glyph_advance(Face *face, u32 codepoint){ +function f32 +font_get_glyph_advance(Face_Advance_Map *map, Face_Metrics *metrics, u32 codepoint){ f32 result = 0.f; if (codepoint == '\t'){ - result = face->space_advance*4.f; + result = metrics->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){ - result = face->advance[index]; + if (codepoint_index_map_read(&map->codepoint_to_index, codepoint, &index)){ + if (index < map->index_count){ + result = map->advance[index]; } } } return(result); } -internal f32 -font_get_max_glyph_advance_range(Face *face, u32 codepoint_first, u32 codepoint_last){ - f32 result = font_get_glyph_advance(face, codepoint_first); +function f32 +font_get_max_glyph_advance_range(Face_Advance_Map *map, Face_Metrics *metrics, + u32 codepoint_first, u32 codepoint_last){ + f32 result = font_get_glyph_advance(map, metrics, codepoint_first); for (u32 i = codepoint_first + 1; i <= codepoint_last; i += 1){ - f32 a = font_get_glyph_advance(face, i); + f32 a = font_get_glyph_advance(map, metrics, i); result = Max(a, result); } return(result); } -internal f32 -font_get_average_glyph_advance_range(Face *face, u32 codepoint_first, u32 codepoint_last){ +function f32 +font_get_average_glyph_advance_range(Face_Advance_Map *map, Face_Metrics *metrics, + u32 codepoint_first, u32 codepoint_last){ f32 result = 0.f; for (u32 i = codepoint_first; i <= codepoint_last; i += 1){ - result += font_get_glyph_advance(face, i); + result += font_get_glyph_advance(map, metrics, i); } result /= (f32)(codepoint_last - codepoint_first + 1); return(result); diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index 17454e08..f5ade07d 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -281,6 +281,188 @@ default_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 region){ return(region); } +internal void +buffer_layout__write(Arena *arena, Layout_Item_List *list, + i64 index, u32 codepoint, Layout_Item_Flag flags, Rect_f32 rect){ + Temp_Memory restore_point = begin_temp(arena); + Layout_Item *item = push_array(arena, Layout_Item, 1); + + Layout_Item_Block *block = list->first; + if (block != 0){ + if (block->items + block->count == item){ + block->count += 1; + } + else{ + block = 0; + } + } + if (block == 0){ + end_temp(restore_point); + block = push_array(arena, Layout_Item_Block, 1); + item = push_array(arena, Layout_Item, 1); + sll_queue_push(list->first, list->last, block); + list->node_count += 1; + block->items = item; + block->count = 1; + } + list->total_count += 1; + + if (index > list->index_range.max){ + block->character_count += 1; + list->character_count += 1; + list->index_range.max = index; + } + + item->index = index; + item->codepoint = codepoint; + item->flags = flags; + item->rect = rect; + list->height = max(list->height, rect.y1); +} + +function Layout_Item_List +default_buffer_layout(Application_Links *app, Arena *arena, Buffer_ID buffer, Range_i64 range, + Face_ID face, f32 width){ + Scratch_Block scratch(app); + + Layout_Item_List list = {}; + list.index_range.first = range.first; + list.index_range.one_past_last = range.first - 1; + + String_Const_u8 text = push_buffer_range(app, scratch, buffer, range); + + Face_Metrics metrics = get_face_metrics(app, face); + f32 line_height = metrics.line_height; + f32 text_height = metrics.text_height; + f32 line_to_text_shift = text_height - line_height; + f32 space_advance = metrics.space_advance; + + Face_Advance_Map advance_map = get_face_advance_map(app, face); + + if (text.size == 0){ + f32 next_x = space_advance; + buffer_layout__write(arena, &list, range.first, ' ', 0, + Rf32(V2(0.f, 0.f), V2f32(next_x, text_height))); + } + else{ + Vec2_f32 p = {}; + f32 line_y = line_height; + f32 text_y = text_height; + + i64 index = range.first; + b32 first_of_the_line = true; + + b32 consuming_newline_characters = false; + i64 newline_character_index = -1; + + b32 prev_did_emit_newline = false; + + u8 *ptr = text.str; + u8 *end_ptr = ptr + text.size; + for (;ptr < end_ptr;){ + Character_Consume_Result consume = utf8_consume(ptr, (umem)(end_ptr - ptr)); + u32 render_codepoint = consume.codepoint; + b32 emit_newline = false; + switch (consume.codepoint){ + case '\t': + { + render_codepoint = ' '; + }//fallthrough; + default: + { + f32 advance = font_get_glyph_advance(&advance_map, &metrics, + consume.codepoint); + f32 next_x = p.x + advance; + if (!first_of_the_line && next_x >= width){ + p.y = line_y; + p.x = 0.f; + line_y += line_height; + text_y = line_y + line_to_text_shift; + next_x = p.x + advance; + } + buffer_layout__write(arena, &list, index, render_codepoint, 0, + Rf32(p, V2f32(next_x, text_y))); + p.x = next_x; + ptr += consume.inc; + index += consume.inc; + first_of_the_line = false; + }break; + + case '\r': + { + if (!consuming_newline_characters){ + consuming_newline_characters = true; + newline_character_index = index; + } + ptr += 1; + index += 1; + }break; + + case '\n': + { + if (!consuming_newline_characters){ + consuming_newline_characters = true; + newline_character_index = index; + } + emit_newline = true; + ptr += 1; + index += 1; + }break; + + case max_u32: + { + f32 next_x = p.x + metrics.byte_advance; + if (!first_of_the_line && next_x >= width){ + p.y = line_y; + p.x = 0.f; + line_y += line_height; + text_y = line_y + line_to_text_shift; + next_x = p.x + metrics.byte_advance; + } + u32 v = *ptr; + u32 lo = v&0xF; + u32 hi = (v >> 4)&0xF; + f32 advance = metrics.byte_sub_advances[0]; + buffer_layout__write(arena, &list, index, '\\', 0, + Rf32(p, V2f32(p.x + advance, text_y))); + p.x += advance; + advance = metrics.byte_sub_advances[1]; + buffer_layout__write(arena, &list, index, integer_symbols[lo], 0, + Rf32(p, V2f32(p.x + advance, text_y))); + p.x += advance; + advance = metrics.byte_sub_advances[2]; + buffer_layout__write(arena, &list, index, integer_symbols[hi], 0, + Rf32(p, V2f32(p.x + advance, text_y))); + p.x = next_x; + ptr += 1; + index += 1; + first_of_the_line = false; + }break; + } + prev_did_emit_newline = false; + if (emit_newline){ + f32 next_x = p.x + space_advance; + buffer_layout__write(arena, &list, newline_character_index, ' ', 0, + Rf32(p, V2f32(next_x, text_y))); + p.y = line_y; + p.x = 0.f; + line_y += line_height; + text_y = line_y + line_to_text_shift; + first_of_the_line = true; + prev_did_emit_newline = true; + } + } + if (!prev_did_emit_newline){ + f32 next_x = p.x + space_advance; + buffer_layout__write(arena, &list, index, ' ', 0, Rf32(p, V2f32(next_x, text_y))); + } + } + list.bottom_extension = -line_to_text_shift; + list.height += list.bottom_extension; + + return(list); +} + function void default_render_buffer(Application_Links *app, View_ID view_id, b32 is_active_view, Buffer_ID buffer, Text_Layout_ID text_layout_id, @@ -931,6 +1113,7 @@ set_all_default_hooks(Application_Links *app){ set_custom_hook(app, HookID_SaveFile, default_file_save); set_custom_hook(app, HookID_BufferEditRange, default_buffer_edit_range); set_custom_hook(app, HookID_BufferRegion, default_buffer_region); + set_custom_hook(app, HookID_Layout, default_buffer_layout); } // BOTTOM diff --git a/custom/4coder_default_include.cpp b/custom/4coder_default_include.cpp index 939430f1..f81f8884 100644 --- a/custom/4coder_default_include.cpp +++ b/custom/4coder_default_include.cpp @@ -64,6 +64,7 @@ #include "4coder_log.cpp" #include "4coder_hash_functions.cpp" #include "4coder_table.cpp" +#include "4coder_codepoint_map.cpp" #include "4coder_async_tasks.cpp" #include "4coder_string_match.cpp" #include "4coder_buffer_seek_constructors.cpp" diff --git a/custom/4coder_types.h b/custom/4coder_types.h index a1c90ef0..0cab24da 100644 --- a/custom/4coder_types.h +++ b/custom/4coder_types.h @@ -448,11 +448,35 @@ struct Face_Description{ struct Face_Metrics{ f32 text_height; f32 line_height; + f32 ascent; + f32 descent; + f32 line_skip; + + f32 underline_yoff1; + f32 underline_yoff2; + f32 max_advance; - f32 normal_advance; f32 space_advance; f32 decimal_digit_advance; f32 hex_digit_advance; + f32 byte_advance; + f32 byte_sub_advances[3]; + f32 normal_lowercase_advance; + f32 normal_uppercase_advance; + f32 normal_advance; +}; + +struct Codepoint_Index_Map{ + b32 has_zero_index; + u16 zero_index; + u16 max_index; + Table_u32_u16 table; +}; + +struct Face_Advance_Map{ + Codepoint_Index_Map codepoint_to_index; + f32 *advance; + u16 index_count; }; struct Edit{ @@ -542,6 +566,7 @@ enum{ HookID_SaveFile, HookID_BufferEditRange, HookID_BufferRegion, + HookID_Layout, }; typedef i32 Hook_Function(Application_Links *app); @@ -559,7 +584,7 @@ struct Buffer_Name_Conflict_Entry{ typedef void Buffer_Name_Resolver_Function(Application_Links *app, Buffer_Name_Conflict_Entry *conflicts, i32 conflict_count); #define BUFFER_NAME_RESOLVER_SIG(n) \ void n(Application_Links *app, Buffer_Name_Conflict_Entry *conflicts, \ - i32 conflict_count) +i32 conflict_count) typedef i32 Buffer_Hook_Function(Application_Links *app, Buffer_ID buffer_id); #define BUFFER_HOOK_SIG(name) i32 name(Application_Links *app, Buffer_ID buffer_id) @@ -568,7 +593,7 @@ typedef i32 Buffer_Edit_Range_Function(Application_Links *app, Buffer_ID buffer_ Range_i64 new_range, umem original_size); #define BUFFER_EDIT_RANGE_SIG(name) \ i32 name(Application_Links *app, Buffer_ID buffer_id, \ - Interval_i64 new_range, umem original_size) +Interval_i64 new_range, umem original_size) typedef Vec2_f32 Delta_Rule_Function(Vec2_f32 pending, b32 is_new_target, f32 dt, void *data); #define DELTA_RULE_SIG(name) \ @@ -584,6 +609,41 @@ typedef void Render_Caller_Function(Application_Links *app, Frame_Info frame_inf #define RENDER_CALLER_SIG(name) \ void name(Application_Links *app, Frame_Info frame_info, View_ID view) +typedef u32 Layout_Item_Flag; +enum{ + LayoutItemFlag_Special_Character = (1 << 0), + LayoutItemFlag_Ghost_Character = (1 << 1) +}; + +struct Layout_Item{ + i64 index; + u32 codepoint; + Layout_Item_Flag flags; + Rect_f32 rect; +}; + +struct Layout_Item_Block{ + Layout_Item_Block *next; + Layout_Item *items; + i64 count; + i64 character_count; +}; + +struct Layout_Item_List{ + Layout_Item_Block *first; + Layout_Item_Block *last; + i32 node_count; + i32 total_count; + f32 height; + f32 bottom_extension; + i64 character_count; + Interval_i64 index_range; +}; + +typedef Layout_Item_List Layout_Function(Application_Links *app, Arena *arena, + Buffer_ID buffer, Range_i64 range, + Face_ID face, f32 width); + typedef i64 Command_Map_ID; struct Command_Trigger{ diff --git a/custom/generated/custom_api.cpp b/custom/generated/custom_api.cpp index 1e29847e..676164fe 100644 --- a/custom/generated/custom_api.cpp +++ b/custom/generated/custom_api.cpp @@ -143,6 +143,7 @@ vtable->global_history_edit_group_end = global_history_edit_group_end; vtable->buffer_set_face = buffer_set_face; vtable->get_face_description = get_face_description; vtable->get_face_metrics = get_face_metrics; +vtable->get_face_advance_map = get_face_advance_map; vtable->get_face_id = get_face_id; vtable->try_create_new_face = try_create_new_face; vtable->try_modify_face = try_modify_face; @@ -319,6 +320,7 @@ global_history_edit_group_end = vtable->global_history_edit_group_end; buffer_set_face = vtable->buffer_set_face; get_face_description = vtable->get_face_description; get_face_metrics = vtable->get_face_metrics; +get_face_advance_map = vtable->get_face_advance_map; get_face_id = vtable->get_face_id; try_create_new_face = vtable->try_create_new_face; try_modify_face = vtable->try_modify_face; diff --git a/custom/generated/custom_api.h b/custom/generated/custom_api.h index 7e3c36be..3bd90f0c 100644 --- a/custom/generated/custom_api.h +++ b/custom/generated/custom_api.h @@ -141,6 +141,7 @@ #define custom_buffer_set_face_sig() b32 custom_buffer_set_face(Application_Links* app, Buffer_ID buffer_id, Face_ID id) #define custom_get_face_description_sig() Face_Description custom_get_face_description(Application_Links* app, Face_ID face_id) #define custom_get_face_metrics_sig() Face_Metrics custom_get_face_metrics(Application_Links* app, Face_ID face_id) +#define custom_get_face_advance_map_sig() Face_Advance_Map custom_get_face_advance_map(Application_Links* app, Face_ID face_id) #define custom_get_face_id_sig() Face_ID custom_get_face_id(Application_Links* app, Buffer_ID buffer_id) #define custom_try_create_new_face_sig() Face_ID custom_try_create_new_face(Application_Links* app, Face_Description* description) #define custom_try_modify_face_sig() b32 custom_try_modify_face(Application_Links* app, Face_ID id, Face_Description* description) @@ -313,6 +314,7 @@ typedef void custom_global_history_edit_group_end_type(Application_Links* app); typedef b32 custom_buffer_set_face_type(Application_Links* app, Buffer_ID buffer_id, Face_ID id); typedef Face_Description custom_get_face_description_type(Application_Links* app, Face_ID face_id); typedef Face_Metrics custom_get_face_metrics_type(Application_Links* app, Face_ID face_id); +typedef Face_Advance_Map custom_get_face_advance_map_type(Application_Links* app, Face_ID face_id); typedef Face_ID custom_get_face_id_type(Application_Links* app, Buffer_ID buffer_id); typedef Face_ID custom_try_create_new_face_type(Application_Links* app, Face_Description* description); typedef b32 custom_try_modify_face_type(Application_Links* app, Face_ID id, Face_Description* description); @@ -486,6 +488,7 @@ custom_global_history_edit_group_end_type *global_history_edit_group_end; custom_buffer_set_face_type *buffer_set_face; custom_get_face_description_type *get_face_description; custom_get_face_metrics_type *get_face_metrics; +custom_get_face_advance_map_type *get_face_advance_map; custom_get_face_id_type *get_face_id; custom_try_create_new_face_type *try_create_new_face; custom_try_modify_face_type *try_modify_face; @@ -660,6 +663,7 @@ internal void global_history_edit_group_end(Application_Links* app); internal b32 buffer_set_face(Application_Links* app, Buffer_ID buffer_id, Face_ID id); internal Face_Description get_face_description(Application_Links* app, Face_ID face_id); internal Face_Metrics get_face_metrics(Application_Links* app, Face_ID face_id); +internal Face_Advance_Map get_face_advance_map(Application_Links* app, Face_ID face_id); internal Face_ID get_face_id(Application_Links* app, Buffer_ID buffer_id); internal Face_ID try_create_new_face(Application_Links* app, Face_Description* description); internal b32 try_modify_face(Application_Links* app, Face_ID id, Face_Description* description); @@ -834,6 +838,7 @@ global custom_global_history_edit_group_end_type *global_history_edit_group_end global custom_buffer_set_face_type *buffer_set_face = 0; global custom_get_face_description_type *get_face_description = 0; global custom_get_face_metrics_type *get_face_metrics = 0; +global custom_get_face_advance_map_type *get_face_advance_map = 0; global custom_get_face_id_type *get_face_id = 0; global custom_try_create_new_face_type *try_create_new_face = 0; global custom_try_modify_face_type *try_modify_face = 0; diff --git a/custom/generated/custom_api_master_list.h b/custom/generated/custom_api_master_list.h index 2171a1f8..c4ccee6d 100644 --- a/custom/generated/custom_api_master_list.h +++ b/custom/generated/custom_api_master_list.h @@ -141,6 +141,7 @@ api(custom) function void global_history_edit_group_end(Application_Links* app); api(custom) function b32 buffer_set_face(Application_Links* app, Buffer_ID buffer_id, Face_ID id); api(custom) function Face_Description get_face_description(Application_Links* app, Face_ID face_id); api(custom) function Face_Metrics get_face_metrics(Application_Links* app, Face_ID face_id); +api(custom) function Face_Advance_Map get_face_advance_map(Application_Links* app, Face_ID face_id); api(custom) function Face_ID get_face_id(Application_Links* app, Buffer_ID buffer_id); api(custom) function Face_ID try_create_new_face(Application_Links* app, Face_Description* description); api(custom) function b32 try_modify_face(Application_Links* app, Face_ID id, Face_Description* description); diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index c281018b..099ab38f 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -108,8 +108,8 @@ struct Win32_Input_Chunk{ #include "4coder_hash_functions.cpp" #include "4coder_system_allocator.cpp" +#include "4coder_codepoint_map.cpp" -#include "4ed_font_face.cpp" #include "4ed_mem.cpp" #include "4ed_font_set.cpp"