diff --git a/4ed_color_view.cpp b/4ed_color_view.cpp index 09f7c734..3178a951 100644 --- a/4ed_color_view.cpp +++ b/4ed_color_view.cpp @@ -338,10 +338,10 @@ do_single_slider(i32 sub_id, Color_UI *ui, i32 channel, bool32 is_rgba, x = lerp(slider.x0, color.v[channel], slider.x1); draw_rectangle( - target, real32R(x, slider.y0, x + 1, slider.y1), 0xff000000); + target, f32R(x, slider.y0, x + 1, slider.y1), 0xff000000); draw_rectangle( - target, real32R(x-2, click_box.y0, x+3, slider.y0-4), 0xff777777); + target, f32R(x-2, click_box.y0, x+3, slider.y0-4), 0xff777777); } } @@ -509,7 +509,7 @@ do_channel_field(i32 sub_id, Color_UI *ui, u8 *channel, Channel_Field_Type ftype } } else{ - real32_Rect r = real32R(hit_region); + real32_Rect r = f32R(hit_region); r.x0 += indx*ui->hex_advance+1; r.x1 = r.x0+ui->hex_advance+1; draw_rectangle(target, r, back); @@ -789,7 +789,7 @@ do_color_adjuster(Color_UI *ui, u32 *color, for (i32 i = 0; i < ArrayCount(ui->highlight.ids); ++i){ if (ui->highlight.ids[i] == id){ - draw_rectangle_outline(target, real32R(bar), text_color); + draw_rectangle_outline(target, f32R(bar), text_color); break; } } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index fe5e3d70..fc3f72b3 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1959,106 +1959,44 @@ file_post_history(General_Memory *general, Editing_File *file, } inline Full_Cursor -make_hint(i32 line_index, i32 *starts, i32 font_height, f32 *wrap_ys){ - Full_Cursor hint; - hint.pos = starts[line_index]; - hint.line = line_index + 1; - hint.character = 1; - hint.unwrapped_y = (f32)(line_index * font_height); - hint.unwrapped_x = 0; - hint.wrapped_y = wrap_ys[line_index]; - hint.wrapped_x = 0; - return hint; -} - -internal Full_Cursor view_compute_cursor_from_pos(File_View *view, i32 pos){ Editing_File *file = view->file; Style *style = view->style; Font *font = style->font; - i32 *lines = file->buffer.line_starts; - - i32 line_index = buffer_get_line_index(&file->buffer, pos, 0, file->buffer.line_count); - - Full_Cursor result = make_hint(line_index, lines, font->height, view->line_wrap_y); - real32 max_width = view_compute_width(view); Opaque_Font_Advance opad = get_opaque_font_advance(font); - result = buffer_cursor_seek(&file->buffer, seek_pos(pos), - max_width, (float)font->height, - opad.data, opad.stride, result); - - return result; + return buffer_cursor_from_pos(&file->buffer, pos, view->line_wrap_y, + max_width, (real32)font->height, opad.data, opad.stride); } -internal Full_Cursor +inline Full_Cursor view_compute_cursor_from_unwrapped_xy(File_View *view, real32 seek_x, real32 seek_y, bool32 round_down = 0){ Editing_File *file = view->file; Style *style = view->style; Font *font = style->font; - i32 line_index = FLOOR32(seek_y / font->height); - if (line_index >= file->buffer.line_count) line_index = file->buffer.line_count - 1; - if (line_index < 0) line_index = 0; - - Full_Cursor result = make_hint(line_index, file->buffer.line_starts, font->height, view->line_wrap_y); - real32 max_width = view_compute_width(view); Opaque_Font_Advance opad = get_opaque_font_advance(font); - result = buffer_cursor_seek(&file->buffer, seek_unwrapped_xy(seek_x, seek_y, round_down), - max_width, (float)font->height, - opad.data, opad.stride, result); - - return result; + return buffer_cursor_from_unwrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y, + max_width, (real32)font->height, opad.data, opad.stride); } -internal Full_Cursor +inline Full_Cursor view_compute_cursor_from_wrapped_xy(File_View *view, real32 seek_x, real32 seek_y, bool32 round_down = 0){ Editing_File *file = view->file; Style *style = view->style; Font *font = style->font; - real32 line_height = (real32)font->height; - - real32 *line_wrap = view->line_wrap_y; - i32 line_index; - // NOTE(allen): binary search lines on wrapped y position - { - i32 start = 0; - i32 end = view->line_count; - while (1){ - i32 i = (start + end) / 2; - if (line_wrap[i]+line_height <= seek_y){ - start = i; - } - else if (line_wrap[i] > seek_y){ - end = i; - } - else{ - line_index = i; - break; - } - if (start >= end - 1){ - line_index = start; - break; - } - } - } - - Full_Cursor result = make_hint(line_index, file->buffer.line_starts, font->height, line_wrap); real32 max_width = view_compute_width(view); Opaque_Font_Advance opad = get_opaque_font_advance(font); - result = buffer_cursor_seek(&file->buffer, seek_wrapped_xy(seek_x, seek_y, round_down), - max_width, (real32)font->height, - opad.data, opad.stride, result); - - return result; + return buffer_cursor_from_wrapped_xy(&file->buffer, seek_x, seek_y, round_down, view->line_wrap_y, + max_width, (real32)font->height, opad.data, opad.stride); } inline Full_Cursor @@ -3524,6 +3462,93 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act Assert(file && file->buffer.data && !file->is_dummy); + Opaque_Font_Advance opad = get_opaque_font_advance(font); + b32 tokens_use = file->tokens_complete && (file->token_stack.count > 0); + Cpp_Token_Stack token_stack = file->token_stack; + +#if 1 + Partition *part = &view_->mem->part; + Temp_Memory temp = begin_temp_memory(part); + + partition_align(part, 4); + i32 max = partition_remaining(part) / sizeof(Buffer_Render_Item); + Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max); + + i32 count; + buffer_get_render_data(&file->buffer, view->line_wrap_y, items, max, &count, + (real32)rect.x0, (real32)rect.y0, view->scroll_x, view->scroll_y, view->unwrapped_lines, + (real32)max_x, (real32)max_y, opad.data, opad.stride, (real32)font->height); + Assert(count > 0); + + i32 cursor_begin, cursor_end; + u32 cursor_color, at_cursor_color; + if (view->show_temp_highlight){ + cursor_begin = view->temp_highlight.pos; + cursor_end = view->temp_highlight_end_pos; + cursor_color = style->main.highlight_color; + at_cursor_color = style->main.at_highlight_color; + } + else{ + cursor_begin = view->cursor.pos; + cursor_end = cursor_begin + 1; + cursor_color = style->main.cursor_color; + at_cursor_color = style->main.at_cursor_color; + } + + i32 token_i = 0; + u32 main_color = style->main.default_color; + if (tokens_use){ + Cpp_Get_Token_Result result = cpp_get_token(&token_stack, items->index); + main_color = *style_get_color(style, token_stack.tokens[result.token_index]); + token_i = result.token_index + 1; + } + + u32 mark_color = style->main.mark_color; + Buffer_Render_Item *item = items; + i32 prev_ind = -1; + for (i32 i = 0; i < count; ++i, ++item){ + i32 ind = item->index; + if (tokens_use && ind != prev_ind){ + Cpp_Token current_token = token_stack.tokens[token_i-1]; + + if (token_i < token_stack.count){ + if (ind >= token_stack.tokens[token_i].start){ + main_color = + *style_get_color(style, token_stack.tokens[token_i]); + current_token = token_stack.tokens[token_i]; + ++token_i; + } + else if (ind >= current_token.start + current_token.size){ + main_color = 0xFFFFFFFF; + } + } + +#if 0 + if (current_token.type == CPP_TOKEN_JUNK && + i >= current_token.start && i <= current_token.start + current_token.size){ + highlight_color = style->main.highlight_junk_color; + } +#endif + } + u32 char_color = main_color; + + if (cursor_begin <= ind && ind < cursor_end && (ind != prev_ind || cursor_begin < ind)){ + if (is_active) draw_rectangle(target, f32R(item->x0, item->y0, item->x1, item->y1), cursor_color); + else draw_rectangle_outline(target, f32R(item->x0, item->y0, item->x1, item->y1), cursor_color); + char_color = at_cursor_color; + } + if (ind == view->mark && prev_ind != ind){ + draw_rectangle_outline(target, f32R(item->x0, item->y0, item->x1, item->y1), mark_color); + } + font_draw_glyph(target, font, (u16)item->glyphid, + item->x0, item->y0, char_color); + prev_ind = ind; + } + + end_temp_memory(temp); + +#else + i32 size = (i32)file->buffer.size; u8 *data = (u8*)file->buffer.data; @@ -3541,11 +3566,9 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act real32 pos_x = 0; real32 pos_y = 0; - Cpp_Token_Stack token_stack = file->token_stack; u32 highlight_color = 0; u32 main_color = style->main.default_color; i32 token_i = 0; - bool32 tokens_use = file->tokens_complete && (file->token_stack.count > 0); if (tokens_use){ Cpp_Get_Token_Result result = cpp_get_token(&token_stack, start_character); @@ -3554,9 +3577,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act main_color = *style_get_color(style, token_stack.tokens[token_i]); ++token_i; } - - Opaque_Font_Advance opad = get_opaque_font_advance(font); - + data[size] = 0; for (i32 i = start_character; i <= size; ++i){ u8 to_render; @@ -3602,17 +3623,15 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act if (highlight_color == 0 && view->show_whitespace && char_is_whitespace(data[i])){ highlight_color = style->main.highlight_white_color; } - + i32 cursor_mode = 0; if (view->show_temp_highlight){ - if (view->temp_highlight.pos <= i && i < view->temp_highlight_end_pos){ + if (view->temp_highlight.pos <= i && i < view->temp_highlight_end_pos) cursor_mode = 2; - } } else{ - if (view->cursor.pos == i){ + if (view->cursor.pos == i) cursor_mode = 1; - } } real32_Rect cursor_rect = @@ -3646,7 +3665,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act if (i == view->mark){ draw_rectangle_outline(target, cursor_rect, style->main.mark_color); } - + u32 char_color = main_color; u32 special_char_color = main_color; if (to_render == '\r'){ @@ -3705,6 +3724,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act break; } } +#endif if (view->widget.type != FWIDG_NONE){ UI_Style ui_style = get_ui_style_upper(style); diff --git a/4ed_math.cpp b/4ed_math.cpp index b8d67e8c..59c5af0e 100644 --- a/4ed_math.cpp +++ b/4ed_math.cpp @@ -93,8 +93,8 @@ struct i32_Rect{ }; struct real32_Rect{ - real32 x0, y0; - real32 x1, y1; + f32 x0, y0; + f32 x1, y1; }; inline i32_Rect @@ -124,7 +124,7 @@ i32XYWH(i32 x, i32 y, i32 w, i32 h){ } inline real32_Rect -real32R(real32 l, real32 t, real32 r, real32 b){ +f32R(real32 l, real32 t, real32 r, real32 b){ real32_Rect rect; rect.x0 = l; rect.y0 = t; rect.x1 = r; rect.y1 = b; @@ -132,7 +132,7 @@ real32R(real32 l, real32 t, real32 r, real32 b){ } inline real32_Rect -real32R(i32_Rect r){ +f32R(i32_Rect r){ real32_Rect rect; rect.x0 = (real32)r.x0; rect.y0 = (real32)r.y0; @@ -142,7 +142,7 @@ real32R(i32_Rect r){ } inline real32_Rect -real32XYWH(real32 x, real32 y, real32 w, real32 h){ +f32XYWH(f32 x, f32 y, f32 w, f32 h){ real32_Rect rect; rect.x0 = x; rect.y0 = y; rect.x1 = x+w; rect.y1 = y+h; diff --git a/4ed_rendering.cpp b/4ed_rendering.cpp index 29d77e2c..d90a29cd 100644 --- a/4ed_rendering.cpp +++ b/4ed_rendering.cpp @@ -620,7 +620,7 @@ draw_gradient_2corner_clipped(Render_Target *target, real32_Rect rect, inline void draw_gradient_2corner_clipped(Render_Target *target, real32 l, real32 t, real32 r, real32 b, Vec4 color_left, Vec4 color_right){ - draw_gradient_2corner_clipped(target, real32R(l,t,r,b), color_left, color_right); + draw_gradient_2corner_clipped(target, f32R(l,t,r,b), color_left, color_right); } internal void @@ -646,7 +646,7 @@ draw_rectangle_outline(Render_Target *target, real32_Rect rect, u32 color){ inline void draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){ - draw_rectangle_outline(target, real32R(rect), color); + draw_rectangle_outline(target, f32R(rect), color); } internal void diff --git a/buffer/4coder_golden_array.cpp b/buffer/4coder_golden_array.cpp index a0ce927a..a96d2ab3 100644 --- a/buffer/4coder_golden_array.cpp +++ b/buffer/4coder_golden_array.cpp @@ -214,6 +214,7 @@ measure_character(void *advance_data, int stride, char character){ advances = (char*)advance_data; switch (character){ + case 0: width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '0'); break; case '\n': width = 0; break; case '\r': width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '\r'); break; default: width = *(float*)(advances + stride * character); @@ -465,8 +466,8 @@ typedef struct{ } Full_Cursor; internal_4tech Full_Cursor -buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, - float max_width, float font_height, void *advance_data, int stride, Full_Cursor cursor){ +buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, float max_width, float font_height, + void *advance_data, int stride, Full_Cursor cursor){ Full_Cursor prev_cursor; char *data, *advances; int size; @@ -578,6 +579,82 @@ buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, return(cursor); } +inline_4tech Full_Cursor +make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){ + Full_Cursor hint; + hint.pos = starts[line_index]; + hint.line = line_index + 1; + hint.character = 1; + hint.unwrapped_y = (f32)(line_index * font_height); + hint.unwrapped_x = 0; + hint.wrapped_y = wrap_ys[line_index]; + hint.wrapped_x = 0; + return(hint); +} + +internal_4tech Full_Cursor +buffer_cursor_from_pos(Buffer *buffer, int pos, float *wraps, + float max_width, float font_height, void *advance_data, int stride){ + Full_Cursor result; + int line_index; + + line_index = buffer_get_line_index(buffer, pos, 0, buffer->line_count); + result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height); + result = buffer_cursor_seek(buffer, seek_pos(pos), max_width, font_height, + advance_data, stride, result); + + return(result); +} + +internal_4tech Full_Cursor +buffer_cursor_from_unwrapped_xy(Buffer *buffer, float x, float y, int round_down, float *wraps, + float max_width, float font_height, void *advance_data, int stride){ + Full_Cursor result; + int line_index; + + line_index = (int)(y / font_height); + if (line_index >= buffer->line_count) line_index = buffer->line_count - 1; + if (line_index < 0) line_index = 0; + + result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height); + result = buffer_cursor_seek(buffer, seek_unwrapped_xy(x, y, round_down), max_width, font_height, + advance_data, stride, result); + + return(result); +} + +internal_4tech Full_Cursor +buffer_cursor_from_wrapped_xy(Buffer *buffer, float x, float y, int round_down, float *wraps, + float max_width, float font_height, void *advance_data, int stride){ + Full_Cursor result; + int line_index; + int start, end, i; + + // NOTE(allen): binary search lines on wrapped y position + // TODO(allen): pull this out once other wrap handling code is ready + start = 0; + end = buffer->line_count; + for (;;){ + i = (start + end) / 2; + if (wraps[i]+font_height <= y) start = i; + else if (wraps[i] > y) end = i; + else{ + line_index = i; + break; + } + if (start >= end - 1){ + line_index = start; + break; + } + } + + result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height); + result = buffer_cursor_seek(buffer, seek_wrapped_xy(x, y, round_down), max_width, font_height, + advance_data, stride, result); + + return(result); +} + typedef struct{ int str_start, len; int start, end; @@ -839,5 +916,166 @@ buffer_eol_convert_out(Buffer *buffer){ buffer->size = size; } +typedef struct{ + int index; + int glyphid; + float x0, y0; + float x1, y1; +} Buffer_Render_Item; + +internal_4tech void +buffer_get_render_data(Buffer *buffer, float *wraps, Buffer_Render_Item *items, int max, int *count, + float port_x, float port_y, float scroll_x, float scroll_y, int wrapped, + float width, float height, void *advance_data, int stride, float font_height){ + Full_Cursor start_cursor; + Buffer_Render_Item *item; + char *data; + int size; + float shift_x, shift_y; + float x, y; + int i, item_i; + float ch_width; + char ch; + + data = buffer->data; + size = buffer->size; + assert_4tech(size < buffer->max); + data[size] = 0; + + shift_x = port_x - scroll_x; + shift_y = port_y - scroll_y; + if (wrapped){ + start_cursor = buffer_cursor_from_wrapped_xy(buffer, 0, scroll_y, 0, wraps, + width, font_height, advance_data, stride); + shift_y += start_cursor.wrapped_y; + } + else{ + start_cursor = buffer_cursor_from_unwrapped_xy(buffer, 0, scroll_y, 0, wraps, + width, font_height, advance_data, stride); + shift_y += start_cursor.unwrapped_y; + } + + i = start_cursor.pos; + + x = shift_x; + y = shift_y; + item_i = 0; + item = items + item_i; + + for (; i <= size; ++i){ + ch = data[i]; + ch_width = measure_character(advance_data, stride, ch); + + if (ch_width + x > width + shift_x && wrapped){ + x = shift_x; + y += font_height; + } + if (y > height + shift_y) break; + + switch (ch){ + case '\n': + ch_width = measure_character(advance_data, stride, ' '); + item->index = i; + item->glyphid = ' '; + item->x0 = x; + item->y0 = y; + item->x1 = x + ch_width; + item->y1 = y + font_height; + ++item_i; + ++item; + + x = shift_x; + y += font_height; + break; + + case 0: + ch_width = measure_character(advance_data, stride, '\\'); + item->index = i; + item->glyphid = '\\'; + item->x0 = x; + item->y0 = y; + item->x1 = x + ch_width; + item->y1 = y + font_height; + ++item_i; + ++item; + x += ch_width; + + ch_width = measure_character(advance_data, stride, '0'); + item->index = i; + item->glyphid = '0'; + item->x0 = x; + item->y0 = y; + item->x1 = x + ch_width; + item->y1 = y + font_height; + ++item_i; + ++item; + x += ch_width; + break; + + case '\r': + ch_width = measure_character(advance_data, stride, '\\'); + item->index = i; + item->glyphid = '\\'; + item->x0 = x; + item->y0 = y; + item->x1 = x + ch_width; + item->y1 = y + font_height; + ++item_i; + ++item; + x += ch_width; + + ch_width = measure_character(advance_data, stride, 'r'); + item->index = i; + item->glyphid = 'r'; + item->x0 = x; + item->y0 = y; + item->x1 = x + ch_width; + item->y1 = y + font_height; + ++item_i; + ++item; + x += ch_width; + break; + + case '\t': + item->index = i; + item->glyphid = '\\'; + item->x0 = x; + item->y0 = y; + item->x1 = x + measure_character(advance_data, stride, '\\'); + item->y1 = y + font_height; + ++item_i; + ++item; + + item->index = i; + item->glyphid = 't'; + item->x0 = (item-1)->x1; + item->y0 = y; + item->x1 = item->x0 + measure_character(advance_data, stride, 't'); + item->y1 = y + font_height; + ++item_i; + ++item; + x += ch_width; + break; + + default: + item->index = i; + item->glyphid = ch; + item->x0 = x; + item->y0 = y; + item->x1 = x + ch_width; + item->y1 = y + font_height; + ++item_i; + ++item; + x += ch_width; + break; + } + if (y > height + shift_y) break; + } + + // TODO(allen): handle this with a control state + assert_4tech(item_i <= max); + *count = item_i; +} + // BOTTOM