Arbitrary text rotation in immediate mode text draw

master
Allen Webster 2020-05-09 09:55:01 -07:00
parent d23135dfed
commit 4ae8883d4c
8 changed files with 107 additions and 33 deletions

View File

@ -163,7 +163,7 @@ draw_rectangle(Render_Target *target, Rect_f32 rect, f32 roundness, u32 color){
internal void internal void
draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p, draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p,
ARGB_Color color, u32 flags){ ARGB_Color color, Glyph_Flag flags, Vec2_f32 x_axis){
draw__set_face_id(target, face->id); draw__set_face_id(target, face->id);
u16 glyph_index = 0; u16 glyph_index = 0;
@ -174,9 +174,37 @@ draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p,
Glyph_Bounds bounds = face->bounds[glyph_index]; Glyph_Bounds bounds = face->bounds[glyph_index];
Vec3_f32 texture_dim = face->texture_dim; Vec3_f32 texture_dim = face->texture_dim;
Rect_f32 uv = bounds.uv;
Render_Vertex vertices[6] = {}; Render_Vertex vertices[6] = {};
Rect_f32 uv = bounds.uv;
vertices[0].uvw = V3f32(uv.x0, uv.y0, bounds.w);
vertices[1].uvw = V3f32(uv.x1, uv.y0, bounds.w);
vertices[2].uvw = V3f32(uv.x0, uv.y1, bounds.w);
vertices[5].uvw = V3f32(uv.x1, uv.y1, bounds.w);
Vec2_f32 y_axis = V2f32(-x_axis.y, x_axis.x);
Vec2_f32 x_min = bounds.xy_off.x0*x_axis;
Vec2_f32 x_max = bounds.xy_off.x1*x_axis;
Vec2_f32 y_min = bounds.xy_off.y0*y_axis;
Vec2_f32 y_max = bounds.xy_off.y1*y_axis;
Vec2_f32 p_x_min = p + x_min;
Vec2_f32 p_x_max = p + x_max;
vertices[0].xy = p_x_min + y_min;
vertices[1].xy = p_x_max + y_min;
vertices[2].xy = p_x_min + y_max;
vertices[5].xy = p_x_max + y_max;
#if 0
Vec2_f32 xy_min = p + bounds.xy_off.x0*x_axis + bounds.xy_off.y0*y_axis;
Vec2_f32 xy_max = p + bounds.xy_off.x1*x_axis + bounds.xy_off.y1*y_axis;
vertices[0].xy = V2f32(xy_min.x, xy_min.y);
vertices[1].xy = V2f32(xy_max.x, xy_min.y);
vertices[2].xy = V2f32(xy_min.x, xy_max.y);
vertices[5].xy = V2f32(xy_max.x, xy_max.y);
#endif
#if 0
if (!HasFlag(flags, GlyphFlag_Rotate90)){ if (!HasFlag(flags, GlyphFlag_Rotate90)){
Rect_f32 xy = Rf32(p + bounds.xy_off.p0, p + bounds.xy_off.p1); Rect_f32 xy = Rf32(p + bounds.xy_off.p0, p + bounds.xy_off.p1);
@ -202,6 +230,7 @@ draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p,
vertices[5].xy = V2f32(xy.x1, xy.y0); vertices[5].xy = V2f32(xy.x1, xy.y0);
vertices[5].uvw = V3f32(uv.x0, uv.y0, bounds.w); vertices[5].uvw = V3f32(uv.x0, uv.y0, bounds.w);
} }
#endif
vertices[3] = vertices[1]; vertices[3] = vertices[1];
vertices[4] = vertices[2]; vertices[4] = vertices[2];
@ -252,7 +281,7 @@ draw_string(Render_Target *target, Face *face, String_Const_u8 string, Vec2_f32
if (draw_codepoint == '\t'){ if (draw_codepoint == '\t'){
draw_codepoint = ' '; draw_codepoint = ' ';
} }
draw_font_glyph(target, face, draw_codepoint, point, color, flags); draw_font_glyph(target, face, draw_codepoint, point, color, flags, delta);
} }
local_const f32 internal_tab_width = 4.f; local_const f32 internal_tab_width = 4.f;
f32 d = font_get_glyph_advance(&face->advance_map, &face->metrics, codepoint, internal_tab_width); f32 d = font_get_glyph_advance(&face->advance_map, &face->metrics, codepoint, internal_tab_width);
@ -279,7 +308,7 @@ draw_string(Render_Target *target, Face *face, String_Const_u8 string, Vec2_f32
Vec2_f32 pp = point; Vec2_f32 pp = point;
for (u32 j = 0; j < 3; ++j){ for (u32 j = 0; j < 3; ++j){
draw_font_glyph(target, face, cs[j], pp, color, flags); draw_font_glyph(target, face, cs[j], pp, color, flags, delta);
pp += delta*byte_sub_advances[j]; pp += delta*byte_sub_advances[j];
} }
} }

View File

@ -92,6 +92,8 @@ text_layout_render(Thread_Context *tctx, Models *models, Text_Layout *layout,
Face *face = file_get_face(models, file); Face *face = file_get_face(models, file);
f32 width = rect_width(layout->rect); f32 width = rect_width(layout->rect);
Vec2_f32 delta = V2f32(1.f, 0.f);
Vec2_f32 shift_p = layout->rect.p0 - layout->point.pixel_shift; Vec2_f32 shift_p = layout->rect.p0 - layout->point.pixel_shift;
i64 first_index = layout->visible_range.first; i64 first_index = layout->visible_range.first;
i64 line_number = layout->visible_line_number_range.min; i64 line_number = layout->visible_line_number_range.min;
@ -120,7 +122,7 @@ text_layout_render(Thread_Context *tctx, Models *models, Text_Layout *layout,
color = item_colors[item->index - first_index]; color = item_colors[item->index - first_index];
} }
Vec2_f32 p = item->rect.p0 + shift_p; Vec2_f32 p = item->rect.p0 + shift_p;
draw_font_glyph(target, face, item->codepoint, p, color, GlyphFlag_None); draw_font_glyph(target, face, item->codepoint, p, color, GlyphFlag_None, delta);
} }
} }
} }

View File

@ -483,8 +483,17 @@ default_whole_screen_render_caller(Application_Links *app, Frame_Info frame_info
Face_ID face_id = get_face_id(app, 0); Face_ID face_id = get_face_id(app, 0);
Scratch_Block scratch(app); Scratch_Block scratch(app);
draw_string_oriented(app, face_id, finalize_color(defcolor_text_default, 0), draw_string_oriented(app, face_id, finalize_color(defcolor_text_default, 0),
SCu8("Hello, World!"), center, SCu8("Hello, World!"), center - V2f32(200.f, 300.f),
GlyphFlag_Rotate90, V2f32(0.f, 1.f)); 0, V2f32(0.f, -1.f));
draw_string_oriented(app, face_id, finalize_color(defcolor_text_default, 0),
SCu8("Hello, World!"), center - V2f32(240.f, 300.f),
0, V2f32(0.f, 1.f));
draw_string_oriented(app, face_id, finalize_color(defcolor_text_default, 0),
SCu8("Hello, World!"), center - V2f32(400.f, 400.f),
0, V2f32(-1.f, 0.f));
draw_string_oriented(app, face_id, finalize_color(defcolor_text_default, 0),
SCu8("Hello, World!"), center - V2f32(400.f, -100.f),
0, V2f32(cos_f32(pi_f32*.333f), sin_f32(pi_f32*.333f)));
#endif #endif
} }

View File

@ -301,37 +301,66 @@ word_complete_list_extend_from_raw(Application_Links *app, Arena *arena, String_
} }
} }
function void
word_complete_iter_init__inner(Buffer_ID buffer, String_Const_u8 needle, Range_i64 range, Word_Complete_Iterator *iter){
Application_Links *app = iter->app;
Arena *arena = iter->arena;
Base_Allocator *allocator = get_base_allocator_system();
if (iter->already_used_table.allocator != 0){
end_temp(iter->arena_restore);
table_clear(&iter->already_used_table);
}
block_zero_struct(iter);
iter->app = app;
iter->arena = arena;
Scratch_Block scratch(app);
String_Match_List list = get_complete_list_raw(app, scratch, buffer, range, needle);
iter->arena_restore = begin_temp(arena);
iter->first_buffer = buffer;
iter->current_buffer = buffer;
iter->needle = needle;
iter->already_used_table = make_table_Data_u64(allocator, 100);
word_complete_list_extend_from_raw(app, arena, &list, &iter->list, &iter->already_used_table);
iter->scan_all_buffers = true;
}
function void function void
word_complete_iter_init(Buffer_ID buffer, Range_i64 range, Word_Complete_Iterator *iter){ word_complete_iter_init(Buffer_ID buffer, Range_i64 range, Word_Complete_Iterator *iter){
if (iter->app != 0 && iter->arena != 0){ if (iter->app != 0 && iter->arena != 0){
Base_Allocator *allocator = get_base_allocator_system();
Application_Links *app = iter->app; Application_Links *app = iter->app;
Arena *arena = iter->arena; Arena *arena = iter->arena;
if (iter->already_used_table.allocator != 0){
end_temp(iter->arena_restore);
table_clear(&iter->already_used_table);
}
block_zero_struct(iter);
iter->app = app;
iter->arena = arena;
Scratch_Block scratch(app);
String_Const_u8 needle = push_buffer_range(app, arena, buffer, range); String_Const_u8 needle = push_buffer_range(app, arena, buffer, range);
String_Match_List list = get_complete_list_raw(app, scratch, buffer, range, needle); word_complete_iter_init__inner(buffer, needle, range, iter);
iter->arena_restore = begin_temp(arena);
iter->first_buffer = buffer;
iter->current_buffer = buffer;
iter->needle = needle;
iter->already_used_table = make_table_Data_u64(allocator, 100);
word_complete_list_extend_from_raw(app, arena, &list, &iter->list, &iter->already_used_table);
} }
} }
function void
word_complete_iter_init(Buffer_ID first_buffer, String_Const_u8 needle, Word_Complete_Iterator *iter){
if (iter->app != 0 && iter->arena != 0){
word_complete_iter_init__inner(first_buffer, needle, Ii64(), iter);
}
}
function void
word_complete_iter_init(String_Const_u8 needle, Word_Complete_Iterator *iter){
if (iter->app != 0 && iter->arena != 0){
Application_Links *app = iter->app;
Buffer_ID first_buffer = get_buffer_next(app, 0, Access_Read);
word_complete_iter_init__inner(first_buffer, needle, Ii64(), iter);
}
}
function void
word_complete_iter_stop_on_this_buffer(Word_Complete_Iterator *iter){
iter->scan_all_buffers = false;
}
function void function void
word_complete_iter_next(Word_Complete_Iterator *it){ word_complete_iter_next(Word_Complete_Iterator *it){
for (;;){ for (;;){
@ -346,6 +375,10 @@ word_complete_iter_next(Word_Complete_Iterator *it){
break; break;
} }
if (!it->scan_all_buffers){
break;
}
Application_Links *app = it->app; Application_Links *app = it->app;
Buffer_ID next = get_buffer_next_looped(app, it->current_buffer, Access_Read); Buffer_ID next = get_buffer_next_looped(app, it->current_buffer, Access_Read);
if (next == it->first_buffer){ if (next == it->first_buffer){

View File

@ -20,6 +20,7 @@ struct Word_Complete_Iterator{
Temp_Memory arena_restore; Temp_Memory arena_restore;
Buffer_ID first_buffer; Buffer_ID first_buffer;
Buffer_ID current_buffer; Buffer_ID current_buffer;
b32 scan_all_buffers;
String_Const_u8 needle; String_Const_u8 needle;
List_String_Const_u8 list; List_String_Const_u8 list;

View File

@ -469,7 +469,6 @@ api(custom)
typedef u32 Glyph_Flag; typedef u32 Glyph_Flag;
enum{ enum{
GlyphFlag_None = 0x0, GlyphFlag_None = 0x0,
GlyphFlag_Rotate90 = 0x1,
}; };
api(custom) api(custom)

View File

@ -501,8 +501,8 @@ static Command_Metadata fcoder_metacmd_table[245] = {
{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1862 }, { PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1862 },
{ PROC_LINKS(view_buffer_other_panel, 0), false, "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1623 }, { PROC_LINKS(view_buffer_other_panel, 0), false, "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1623 },
{ PROC_LINKS(view_jump_list_with_lister, 0), false, "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 59 }, { PROC_LINKS(view_jump_list_with_lister, 0), false, "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 59 },
{ PROC_LINKS(word_complete, 0), false, "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 397 }, { PROC_LINKS(word_complete, 0), false, "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 430 },
{ PROC_LINKS(word_complete_drop_down, 0), false, "word_complete_drop_down", 23, "Word complete with drop down menu.", 34, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 644 }, { PROC_LINKS(word_complete_drop_down, 0), false, "word_complete_drop_down", 23, "Word complete with drop down menu.", 34, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 677 },
{ PROC_LINKS(write_block, 0), false, "write_block", 11, "At the cursor, insert a block comment.", 38, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 94 }, { PROC_LINKS(write_block, 0), false, "write_block", 11, "At the cursor, insert a block comment.", 38, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 94 },
{ PROC_LINKS(write_hack, 0), false, "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 82 }, { PROC_LINKS(write_hack, 0), false, "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 82 },
{ PROC_LINKS(write_note, 0), false, "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 88 }, { PROC_LINKS(write_note, 0), false, "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 88 },

View File

@ -1,6 +1,7 @@
4.1.6 4.1.6
+ In config.4coder "bind_by_physical_key" uses a key-layout that does not change with language + In config.4coder "bind_by_physical_key" uses a key-layout that does not change with language
+ Deprecated GlyphFlag_Rotate90, rotation of immediate mode text is entirely derived from the delta vector
+ Fix: notepad like mode scrolling only creates selection when holding mouse L-buttoon + Fix: notepad like mode scrolling only creates selection when holding mouse L-buttoon
+ Fix: on windows the window has the 4coder icon + Fix: on windows the window has the 4coder icon
+ Fix: by default platform layer uses key codes arranged by the system language + Fix: by default platform layer uses key codes arranged by the system language