Word wrapping works!
This commit is contained in:
parent
187f91084a
commit
2ba875a474
|
@ -2717,8 +2717,6 @@ draw_rectangle(Application_Links *app, Rect_f32 rect, f32 roundness, FColor colo
|
||||||
if (models->in_render_mode){
|
if (models->in_render_mode){
|
||||||
Color_Table color_table = models->color_table;
|
Color_Table color_table = models->color_table;
|
||||||
u32 actual_color = finalize_color(color_table, color);
|
u32 actual_color = finalize_color(color_table, color);
|
||||||
f32 scale = system_get_screen_scale_factor();
|
|
||||||
roundness *= scale;
|
|
||||||
draw_rectangle(models->target, rect, roundness, actual_color);
|
draw_rectangle(models->target, rect, roundness, actual_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2730,9 +2728,6 @@ draw_rectangle_outline(Application_Links *app, Rect_f32 rect,
|
||||||
if (models->in_render_mode){
|
if (models->in_render_mode){
|
||||||
Color_Table color_table = models->color_table;
|
Color_Table color_table = models->color_table;
|
||||||
u32 actual_color = finalize_color(color_table, color);
|
u32 actual_color = finalize_color(color_table, color);
|
||||||
f32 scale = system_get_screen_scale_factor();
|
|
||||||
roundness *= scale;
|
|
||||||
thickness *= scale;
|
|
||||||
draw_rectangle_outline(models->target, rect, roundness, thickness, actual_color);
|
draw_rectangle_outline(models->target, rect, roundness, thickness, actual_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,188 +281,6 @@ default_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 region){
|
||||||
return(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
|
function void
|
||||||
default_render_buffer(Application_Links *app, View_ID view_id, b32 is_active_view,
|
default_render_buffer(Application_Links *app, View_ID view_id, b32 is_active_view,
|
||||||
Buffer_ID buffer, Text_Layout_ID text_layout_id,
|
Buffer_ID buffer, Text_Layout_ID text_layout_id,
|
||||||
|
@ -1113,7 +931,8 @@ set_all_default_hooks(Application_Links *app){
|
||||||
set_custom_hook(app, HookID_SaveFile, default_file_save);
|
set_custom_hook(app, HookID_SaveFile, default_file_save);
|
||||||
set_custom_hook(app, HookID_BufferEditRange, default_buffer_edit_range);
|
set_custom_hook(app, HookID_BufferEditRange, default_buffer_edit_range);
|
||||||
set_custom_hook(app, HookID_BufferRegion, default_buffer_region);
|
set_custom_hook(app, HookID_BufferRegion, default_buffer_region);
|
||||||
set_custom_hook(app, HookID_Layout, default_buffer_layout);
|
|
||||||
|
set_custom_hook(app, HookID_Layout, layout_wrap_whitespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
#include "4coder_font_helper.cpp"
|
#include "4coder_font_helper.cpp"
|
||||||
#include "4coder_config.cpp"
|
#include "4coder_config.cpp"
|
||||||
#include "4coder_default_framework.cpp"
|
#include "4coder_default_framework.cpp"
|
||||||
|
#include "4coder_layout_rule.cpp"
|
||||||
#include "4coder_lister_base.cpp"
|
#include "4coder_lister_base.cpp"
|
||||||
#include "4coder_base_commands.cpp"
|
#include "4coder_base_commands.cpp"
|
||||||
#include "4coder_insertion.cpp"
|
#include "4coder_insertion.cpp"
|
||||||
|
|
|
@ -0,0 +1,390 @@
|
||||||
|
/*
|
||||||
|
4coder_layout_rule.cpp - Built in layout rules and layout rule helpers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
function void
|
||||||
|
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
|
||||||
|
layout_wrap_anywhere(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_Advance_Map advance_map = get_face_advance_map(app, face);
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (text.size == 0){
|
||||||
|
f32 next_x = space_advance;
|
||||||
|
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 = advance;
|
||||||
|
}
|
||||||
|
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];
|
||||||
|
layout_write(arena, &list, index, '\\', 0,
|
||||||
|
Rf32(p, V2f32(p.x + advance, text_y)));
|
||||||
|
p.x += advance;
|
||||||
|
advance = metrics.byte_sub_advances[1];
|
||||||
|
layout_write(arena, &list, index, integer_symbols[hi], 0,
|
||||||
|
Rf32(p, V2f32(p.x + advance, text_y)));
|
||||||
|
p.x += advance;
|
||||||
|
advance = metrics.byte_sub_advances[2];
|
||||||
|
layout_write(arena, &list, index, integer_symbols[lo], 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;
|
||||||
|
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;
|
||||||
|
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 Layout_Item_List
|
||||||
|
layout_wrap_whitespace(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_Advance_Map advance_map = get_face_advance_map(app, face);
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (text.size == 0){
|
||||||
|
f32 next_x = space_advance;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
u8 *word_ptr = ptr;
|
||||||
|
|
||||||
|
if (character_is_whitespace(*ptr)){
|
||||||
|
goto consuming_whitespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
consuming_non_whitespace:
|
||||||
|
consuming_newline_characters = false;
|
||||||
|
newline_character_index = -1;
|
||||||
|
|
||||||
|
for (;ptr <= end_ptr; ptr += 1){
|
||||||
|
if (ptr == end_ptr || character_is_whitespace(*ptr)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
String_Const_u8 word = SCu8(word_ptr, ptr);
|
||||||
|
u8 *word_end = ptr;
|
||||||
|
|
||||||
|
if (!first_of_the_line){
|
||||||
|
f32 total_advance = 0.f;
|
||||||
|
ptr = word.str;
|
||||||
|
for (; ptr < word_end;){
|
||||||
|
Character_Consume_Result consume =
|
||||||
|
utf8_consume(ptr, (umem)(word_end - ptr));
|
||||||
|
if (consume.codepoint != max_u32){
|
||||||
|
f32 advance = font_get_glyph_advance(&advance_map, &metrics,
|
||||||
|
consume.codepoint);
|
||||||
|
total_advance += advance;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
total_advance += metrics.byte_advance;
|
||||||
|
}
|
||||||
|
ptr += consume.inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 next_x = p.x + total_advance;
|
||||||
|
if (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 = total_advance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = word.str;
|
||||||
|
|
||||||
|
for (; ptr < word_end;){
|
||||||
|
Character_Consume_Result consume =
|
||||||
|
utf8_consume(ptr, (umem)(word_end - ptr));
|
||||||
|
|
||||||
|
if (consume.codepoint != max_u32){
|
||||||
|
f32 advance = font_get_glyph_advance(&advance_map, &metrics,
|
||||||
|
consume.codepoint);
|
||||||
|
i64 index = (i64)(ptr - text.str) + range.first;
|
||||||
|
layout_write(arena, &list, index,
|
||||||
|
consume.codepoint, 0,
|
||||||
|
Rf32(p, V2f32(p.x + advance, text_y)));
|
||||||
|
p.x += advance;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
u32 v = *ptr;
|
||||||
|
u32 lo = v&0xF;
|
||||||
|
u32 hi = (v >> 4)&0xF;
|
||||||
|
i64 index = (i64)(ptr - text.str) + range.first;
|
||||||
|
f32 advance = metrics.byte_sub_advances[0];
|
||||||
|
layout_write(arena, &list, index, '\\', 0,
|
||||||
|
Rf32(p, V2f32(p.x + advance, text_y)));
|
||||||
|
p.x += advance;
|
||||||
|
advance = metrics.byte_sub_advances[1];
|
||||||
|
layout_write(arena, &list, index, integer_symbols[hi], 0,
|
||||||
|
Rf32(p, V2f32(p.x + advance, text_y)));
|
||||||
|
p.x += advance;
|
||||||
|
advance = metrics.byte_sub_advances[2];
|
||||||
|
layout_write(arena, &list, index, integer_symbols[lo], 0,
|
||||||
|
Rf32(p, V2f32(p.x + advance, text_y)));
|
||||||
|
p.x += advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += consume.inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_of_the_line = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
consuming_whitespace:
|
||||||
|
for (; ptr < end_ptr; ptr += 1){
|
||||||
|
if (!character_is_whitespace(*ptr)){
|
||||||
|
word_ptr = ptr;
|
||||||
|
goto consuming_non_whitespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 emit_newline = false;
|
||||||
|
|
||||||
|
switch (*ptr){
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
f32 advance = space_advance;
|
||||||
|
if (*ptr == '\t'){
|
||||||
|
advance *= 4.f;
|
||||||
|
}
|
||||||
|
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 = advance;
|
||||||
|
}
|
||||||
|
i64 index = (i64)(ptr - text.str) + range.first;
|
||||||
|
layout_write(arena, &list, index,
|
||||||
|
' ', 0,
|
||||||
|
Rf32(p, V2f32(next_x, text_y)));
|
||||||
|
p.x = next_x;
|
||||||
|
first_of_the_line = false;
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
{
|
||||||
|
if (!consuming_newline_characters){
|
||||||
|
consuming_newline_characters = true;
|
||||||
|
newline_character_index = (i64)(ptr - text.str) + range.first;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
{
|
||||||
|
if (!consuming_newline_characters){
|
||||||
|
consuming_newline_characters = true;
|
||||||
|
newline_character_index = (i64)(ptr - text.str) + range.first;
|
||||||
|
}
|
||||||
|
emit_newline = true;
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emit_newline){
|
||||||
|
f32 next_x = p.x + space_advance;
|
||||||
|
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 = emit_newline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prev_did_emit_newline){
|
||||||
|
f32 next_x = p.x + space_advance;
|
||||||
|
i64 index = (i64)(ptr - text.str) + range.first;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
|
Loading…
Reference in New Issue