Arbitrary text rotation in immediate mode text draw
parent
d23135dfed
commit
4ae8883d4c
|
@ -163,7 +163,7 @@ draw_rectangle(Render_Target *target, Rect_f32 rect, f32 roundness, u32 color){
|
|||
|
||||
internal void
|
||||
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);
|
||||
|
||||
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];
|
||||
Vec3_f32 texture_dim = face->texture_dim;
|
||||
|
||||
Rect_f32 uv = bounds.uv;
|
||||
|
||||
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)){
|
||||
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].uvw = V3f32(uv.x0, uv.y0, bounds.w);
|
||||
}
|
||||
#endif
|
||||
|
||||
vertices[3] = vertices[1];
|
||||
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'){
|
||||
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;
|
||||
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;
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,8 @@ text_layout_render(Thread_Context *tctx, Models *models, Text_Layout *layout,
|
|||
Face *face = file_get_face(models, file);
|
||||
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;
|
||||
i64 first_index = layout->visible_range.first;
|
||||
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];
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
Scratch_Block scratch(app);
|
||||
draw_string_oriented(app, face_id, finalize_color(defcolor_text_default, 0),
|
||||
SCu8("Hello, World!"), center,
|
||||
GlyphFlag_Rotate90, V2f32(0.f, 1.f));
|
||||
SCu8("Hello, World!"), center - V2f32(200.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(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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
word_complete_iter_init(Buffer_ID buffer, Range_i64 range, Word_Complete_Iterator *iter){
|
||||
if (iter->app != 0 && iter->arena != 0){
|
||||
Base_Allocator *allocator = get_base_allocator_system();
|
||||
|
||||
Application_Links *app = iter->app;
|
||||
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_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);
|
||||
word_complete_iter_init__inner(buffer, needle, range, iter);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
word_complete_iter_next(Word_Complete_Iterator *it){
|
||||
for (;;){
|
||||
|
@ -346,6 +375,10 @@ word_complete_iter_next(Word_Complete_Iterator *it){
|
|||
break;
|
||||
}
|
||||
|
||||
if (!it->scan_all_buffers){
|
||||
break;
|
||||
}
|
||||
|
||||
Application_Links *app = it->app;
|
||||
Buffer_ID next = get_buffer_next_looped(app, it->current_buffer, Access_Read);
|
||||
if (next == it->first_buffer){
|
||||
|
|
|
@ -20,6 +20,7 @@ struct Word_Complete_Iterator{
|
|||
Temp_Memory arena_restore;
|
||||
Buffer_ID first_buffer;
|
||||
Buffer_ID current_buffer;
|
||||
b32 scan_all_buffers;
|
||||
String_Const_u8 needle;
|
||||
|
||||
List_String_Const_u8 list;
|
||||
|
|
|
@ -469,7 +469,6 @@ api(custom)
|
|||
typedef u32 Glyph_Flag;
|
||||
enum{
|
||||
GlyphFlag_None = 0x0,
|
||||
GlyphFlag_Rotate90 = 0x1,
|
||||
};
|
||||
|
||||
api(custom)
|
||||
|
|
|
@ -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(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(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_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, 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, 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_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 },
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
4.1.6
|
||||
+ 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: on windows the window has the 4coder icon
|
||||
+ Fix: by default platform layer uses key codes arranged by the system language
|
||||
|
|
Loading…
Reference in New Issue