whitespace virtualization started

master
Allen Webster 2016-09-22 20:03:47 -04:00
parent 93d738240b
commit b84dcf03d7
4 changed files with 297 additions and 179 deletions

View File

@ -269,13 +269,10 @@ cpp_pp_directive_to_state(Cpp_Token_Type type){
// duff-routine defines
#define DrCase(PC) case PC: goto resumespot_##PC
#define DrYield(PC, n) { \
token_array_out->count = token_i; \
*S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
#define DrYield(PC, n)\
{ token_array_out->count = token_i; *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
#define DrReturn(n) { \
token_array_out->count = token_i; \
*S_ptr = S; S_ptr->__pc__ = -1; return(n); }
#define DrReturn(n) { token_array_out->count = token_i; *S_ptr = S; S_ptr->__pc__ = -1; return(n); }
FCPP_INTERNAL Cpp_Lex_Result
cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size,

View File

@ -4794,7 +4794,6 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
Style *style = main_style(models);
i32 line_height = view->line_height;
f32 clip_w = view_width(view);
f32 max_x = view_file_display_width(view);
i32 max_y = rect.y1 - rect.y0 + line_height;
@ -4812,18 +4811,16 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
Temp_Memory temp = begin_temp_memory(part);
partition_align(part, 4);
f32 left_side_space = 0;
i32 max = partition_remaining(part) / sizeof(Buffer_Render_Item);
Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max);
i16 font_id = file->settings.font_id;
Render_Font *font = get_font_info(models->font_set, font_id)->font;
float *advance_data = 0;
// TODO(allen): Why isn't this "Assert(font);"?
if (font){
advance_data = font->advance_data;
}
float *advance_data = font->advance_data;
i32 count = 0;
Full_Cursor render_cursor = {0};
f32 scroll_x = view->edit_pos->scroll.scroll_x;
@ -4834,18 +4831,55 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
// to the gui system.
scroll_y += view->widget_height;
render_cursor = buffer_get_start_cursor(&file->state.buffer, file->state.wraps, scroll_y,
!file->settings.unwrapped_lines,
max_x, advance_data, (f32)line_height);
view->edit_pos->scroll_i = render_cursor.pos;
i32 count = 0;
{
render_cursor = buffer_get_start_cursor(&file->state.buffer, file->state.wraps, scroll_y,
!file->settings.unwrapped_lines,
max_x, advance_data, (f32)line_height);
b32 wrapped = !file->settings.unwrapped_lines;
view->edit_pos->scroll_i = render_cursor.pos;
Buffer_Render_Params params;
params.buffer = &file->state.buffer;
params.items = items;
params.max = max;
params.count = &count;
params.port_x = (f32)rect.x0 + left_side_space;
params.port_y = (f32)rect.y0;
params.clip_w = view_width(view) - left_side_space;
params.scroll_x = scroll_x;
params.scroll_y = scroll_y;
params.width = max_x;
params.height = (f32)max_y;
params.start_cursor = render_cursor;
params.wrapped = wrapped;
params.font_height = (f32)line_height;
params.adv = advance_data;
params.virtual_white = 0;
Buffer_Render_State state = {0};
Buffer_Render_Stop stop = {0};
f32 line_shift = 0;
f32 edge_tolerance = 50.f;
if (edge_tolerance > params.width){
edge_tolerance = params.width;
}
do{
if (line_shift > params.width - edge_tolerance){
line_shift = params.width - edge_tolerance;
}
stop = buffer_render_data(&state, params, line_shift);
switch (stop.status){
case RenderStatus_NeedLineShift: break;
}
}while(stop.status != RenderStatus_Finished);
buffer_get_render_data(&file->state.buffer, items, max, &count,
(f32)rect.x0, (f32)rect.y0, clip_w,
scroll_x, scroll_y, max_x, (f32)max_y,
render_cursor, !file->settings.unwrapped_lines,
advance_data, (f32)line_height);
}
Assert(count > 0);

View File

@ -485,7 +485,7 @@ cursor_seek_step(Seek_State *state, Buffer_Seek seek, i32 xy_seek, f32 max_width
}
}
cursor_seek_step_end:
cursor_seek_step_end:;
state->cursor = cursor;
state->prev_cursor = prev_cursor;
return(result);
@ -694,17 +694,11 @@ typedef struct Buffer_Invert_Batch{
internal_4tech i32
buffer_invert_batch(Buffer_Invert_Batch *state, Buffer_Type *buffer, Buffer_Edit *edits, i32 count,
Buffer_Edit *inverse, char *strings, i32 *str_pos, i32 max){
Buffer_Edit *edit, *inv_edit;
i32 shift_amount;
i32 result;
i32 i;
result = 0;
i = state->i;
shift_amount = state->shift_amount;
edit = edits + i;
inv_edit = inverse + i;
i32 shift_amount = state->shift_amount;
i32 i = state->i;
Buffer_Edit *edit = edits + i;
Buffer_Edit *inv_edit = inverse + i;
i32 result = 0;
for (; i < count; ++i, ++edit, ++inv_edit){
if (*str_pos + edit->end - edit->start <= max){
@ -782,141 +776,238 @@ write_render_item(Render_Item_Write write, i32 index, u16 glyphid, u16 flags){
return(write);
}
internal_4tech void
buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, i32 max, i32 *count,
f32 port_x, f32 port_y, f32 clip_w,
f32 scroll_x, f32 scroll_y, f32 width, f32 height,
Full_Cursor start_cursor,
i32 wrapped, f32 *adv, f32 font_height){
// TODO(allen): Reduce the number of parameters.
struct Buffer_Render_Params{
Buffer_Type *buffer;
Buffer_Render_Item *items;
i32 max;
i32 *count;
f32 port_x;
f32 port_y;
f32 clip_w;
f32 scroll_x;
f32 scroll_y;
f32 width;
f32 height;
Full_Cursor start_cursor;
i32 wrapped;
f32 font_height;
f32 *adv;
b32 virtual_white;
};
struct Buffer_Render_State{
Buffer_Stringify_Type loop;
char *data;
i32 end;
i32 size;
i32 i;
Buffer_Stringify_Type loop = {0};
char *data = 0;
i32 end = 0;
i32 size = buffer_size(buffer);
f32 shift_x = port_x - scroll_x, shift_y = port_y - scroll_y;
if (wrapped){
shift_y += start_cursor.wrapped_y;
}
else{
shift_y += start_cursor.unwrapped_y;
}
Buffer_Render_Item *item_end = items + max;
f32 ch_width;
u8 ch;
Render_Item_Write write;
write.item = items;
write.x = shift_x;
write.y = shift_y;
write.adv = adv;
write.font_height = font_height;
write.x_min = port_x;
write.x_max = port_x + clip_w;
if (adv){
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size);
buffer_stringify_good(&loop) && write.item < item_end;
buffer_stringify_next(&loop)){
i32 line;
b32 skipping_whitespace;
i32 __pc__;
};
// duff-routine defines
#define DrCase(PC) case PC: goto resumespot_##PC
#define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
#define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); }
enum{
RenderStatus_Finished,
RenderStatus_NeedLineShift
};
struct Buffer_Render_Stop{
u32 status;
i32 line_index;
i32 pos;
};
internal_4tech Buffer_Render_Stop
buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 line_shift){
Buffer_Render_State S = *S_ptr;
Buffer_Render_Stop S_stop;
i32 size = buffer_size(params.buffer);
f32 shift_x = params.port_x - params.scroll_x;
f32 shift_y = params.port_y - params.scroll_y;
if (params.wrapped){
shift_y += params.start_cursor.wrapped_y;
}
else{
shift_y += params.start_cursor.unwrapped_y;
}
Buffer_Render_Item *item_end = params.items + params.max;
switch (S.__pc__){
DrCase(1);
DrCase(2);
DrCase(3);
}
S.line = params.start_cursor.line - 1;
if (params.virtual_white){
S_stop.status = RenderStatus_NeedLineShift;
S_stop.line_index = S.line;
S_stop.pos = params.start_cursor.pos;
DrYield(1, S_stop);
}
S.write.item = params.items;
S.write.x = shift_x + line_shift;
S.write.y = shift_y;
S.write.adv = params.adv;
S.write.font_height = params.font_height;
S.write.x_min = params.port_x;
S.write.x_max = params.port_x + params.clip_w;
if (params.adv){
for (S.loop = buffer_stringify_loop(params.buffer, params.start_cursor.pos, size);
buffer_stringify_good(&S.loop) && S.write.item < item_end;
buffer_stringify_next(&S.loop)){
end = loop.size + loop.absolute_pos;
data = loop.data - loop.absolute_pos;
S.end = S.loop.size + S.loop.absolute_pos;
S.data = S.loop.data - S.loop.absolute_pos;
for (i32 i = loop.absolute_pos; i < end; ++i){
u8 ch = (uint8_t)data[i];
f32 ch_width = measure_character(adv, ch);
for (S.i = S.loop.absolute_pos; S.i < S.end; ++S.i){
S.ch = (uint8_t)S.data[S.i];
S.ch_width = measure_character(params.adv, S.ch);
if (ch_width + write.x > width + shift_x && wrapped && ch != '\n'){
write.x = shift_x;
write.y += font_height;
if (S.ch_width + S.write.x > params.width + shift_x && S.ch != '\n' && params.wrapped){
if (params.virtual_white){
S_stop.status = RenderStatus_NeedLineShift;
S_stop.line_index = S.line;
S_stop.pos = S.i+1;
DrYield(2, S_stop);
}
S.write.x = shift_x + line_shift;
S.write.y += params.font_height;
}
if (write.y > height + shift_y){
if (S.write.y > params.height + shift_y){
goto buffer_get_render_data_end;
}
switch (ch){
case '\n':
if (write.item < item_end){
write = write_render_item(write, i, ' ', 0);
write.x = shift_x;
write.y += font_height;
}
break;
case '\r':
if (write.item < item_end){
write = write_render_item(write, i, '\\', BRFlag_Special_Character);
if (write.item < item_end){
write = write_render_item(write, i, 'r', BRFlag_Special_Character);
}
}
break;
case '\t':
if (write.item < item_end){
f32 new_x = write.x + ch_width;
write = write_render_item(write, i, ' ', 0);
write.x = new_x;
}
break;
default:
if (write.item < item_end){
if (ch >= ' ' && ch <= '~'){
write = write_render_item(write, i, ch, 0);
}
else{
write = write_render_item(write, i, '\\', BRFlag_Special_Character);
char C = '0' + (ch / 0x10);
if ((ch / 0x10) > 0x9){
C = ('A' - 0xA) + (ch / 0x10);
}
if (write.item < item_end){
write = write_render_item(write, i, C, BRFlag_Special_Character);
}
ch = (ch % 0x10);
C = '0' + ch;
if (ch > 0x9){
C = ('A' - 0xA) + ch;
}
if (write.item < item_end){
write = write_render_item(write, i, C, BRFlag_Special_Character);
}
}
}
break;
if (S.ch != ' ' && S.ch != '\t'){
S.skipping_whitespace = 0;
}
if (write.y > height + shift_y){
if (!S.skipping_whitespace){
switch (S.ch){
case '\n':
if (S.write.item < item_end){
S.write = write_render_item(S.write, S.i, ' ', 0);
if (params.virtual_white){
S_stop.status = RenderStatus_NeedLineShift;
S_stop.line_index = S.line+1;
S_stop.pos = S.i+1;
DrYield(3, S_stop);
S.skipping_whitespace = 1;
}
++S.line;
S.write.x = shift_x + line_shift;
S.write.y += params.font_height;
}
break;
case '\r':
if (S.write.item < item_end){
S.write = write_render_item(S.write, S.i, '\\', BRFlag_Special_Character);
if (S.write.item < item_end){
S.write = write_render_item(S.write, S.i, 'r', BRFlag_Special_Character);
}
}
break;
case '\t':
if (S.write.item < item_end){
f32 new_x = S.write.x + S.ch_width;
S.write = write_render_item(S.write, S.i, ' ', 0);
S.write.x = new_x;
}
break;
default:
if (S.write.item < item_end){
if (S.ch >= ' ' && S.ch <= '~'){
S.write = write_render_item(S.write, S.i, S.ch, 0);
}
else{
S.write = write_render_item(S.write, S.i, '\\', BRFlag_Special_Character);
char ch = S.ch;
char C = '0' + (ch / 0x10);
if ((ch / 0x10) > 0x9){
C = ('A' - 0xA) + (ch / 0x10);
}
if (S.write.item < item_end){
S.write = write_render_item(S.write, S.i, C, BRFlag_Special_Character);
}
ch = (ch % 0x10);
C = '0' + ch;
if (ch > 0x9){
C = ('A' - 0xA) + ch;
}
if (S.write.item < item_end){
S.write = write_render_item(S.write, S.i, C, BRFlag_Special_Character);
}
}
}
break;
}
}
if (S.write.y > params.height + shift_y){
goto buffer_get_render_data_end;
}
}
}
buffer_get_render_data_end:;
if (write.y <= height + shift_y || write.item == items){
if (write.item < item_end){
write = write_render_item(write, size, ' ', 0);
if (S.write.y <= params.height + shift_y || S.write.item == params.items){
if (S.write.item < item_end){
S.write = write_render_item(S.write, size, ' ', 0);
}
}
}
else{
f32 zero = 0;
write.adv = &zero;
S.write.adv = &zero;
if (write.item < item_end){
write = write_render_item(write, size, 0, 0);
if (S.write.item < item_end){
S.write = write_render_item(S.write, size, 0, 0);
}
}
*count = (i32)(write.item - items);
assert_4tech(*count <= max);
*params.count = (i32)(S.write.item - params.items);
assert_4tech(*params.count <= params.max);
S_stop.status = RenderStatus_Finished;
DrReturn(S_stop);
}
#undef DrYield
#undef DrReturn
#undef DrCase
// BOTTOM

View File

@ -98,80 +98,76 @@ buffer_end_init(Gap_Buffer_Init *init, void *scratch, i32 scratch_size){
return(result);
}
typedef struct Gap_Buffer_Stringify_Loop{
typedef struct Gap_Buffer_Stream{
Gap_Buffer *buffer;
char *data, *base;
char *data;
char *base;
i32 absolute_pos;
i32 pos, end;
i32 pos;
i32 end;
i32 size;
i32 separated;
} Gap_Buffer_Stringify_Loop;
} Gap_Buffer_Stream;
internal_4tech Gap_Buffer_Stringify_Loop
buffer_stringify_loop(Gap_Buffer *buffer, i32 start, i32 end){
Gap_Buffer_Stringify_Loop result = {0};
internal_4tech b32
buffer_stringify_loop(Gap_Buffer_Stream *stream, Gap_Buffer *buffer, i32 start, i32 end){
b32 result = 0;
if (0 <= start && start < end && end <= buffer->size1 + buffer->size2){
result.buffer = buffer;
result.base = buffer->data;
result.absolute_pos = start;
stream->buffer = buffer;
stream->base = buffer->data;
stream->absolute_pos = start;
if (end <= buffer->size1){
result.end = end;
stream->end = end;
}
else{
result.end = end + buffer->gap_size;
stream->end = end + buffer->gap_size;
}
if (start < buffer->size1){
if (end <= buffer->size1){
result.separated = 0;
stream->separated = 0;
}
else{
result.separated = 1;
stream->separated = 1;
}
result.pos = start;
stream->pos = start;
}
else{
result.separated = 0;
result.pos = start + buffer->gap_size;
stream->separated = 0;
stream->pos = start + buffer->gap_size;
}
if (result.separated){
result.size = buffer->size1 - start;
if (stream->separated){
stream->size = buffer->size1 - start;
}
else{
result.size = end - start;
stream->size = end - start;
}
result.data = buffer->data + result.pos;
stream->data = buffer->data + stream->pos;
}
return(result);
}
inline_4tech i32
buffer_stringify_good(Gap_Buffer_Stringify_Loop *loop){
i32 result = (loop->buffer != 0);
return(result);
}
internal_4tech void
buffer_stringify_next(Gap_Buffer_Stringify_Loop *loop){
internal_4tech b32
buffer_stringify_next(Gap_Buffer_Stream *stream){
i32 size1 = 0, temp_end = 0;
if (loop->separated){
loop->separated = 0;
size1 = loop->buffer->size1;
loop->pos = loop->buffer->gap_size + size1;
loop->absolute_pos = size1;
temp_end = loop->end;
if (stream->separated){
stream->separated = 0;
size1 = stream->buffer->size1;
stream->pos = stream->buffer->gap_size + size1;
stream->absolute_pos = size1;
temp_end = stream->end;
}
else{
loop->buffer = 0;
temp_end = loop->pos;
stream->buffer = 0;
temp_end = stream->pos;
}
loop->size = temp_end - loop->pos;
loop->data = loop->base + loop->pos;
stream->size = temp_end - stream->pos;
stream->data = stream->base + stream->pos;
}
internal_4tech i32