From e34c2b0cefca28604ffaf4fa30d68550f610e00e Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Mon, 1 Dec 2025 09:05:06 +0100 Subject: [PATCH] Allow multiple fonts --- data/init.lua | 1 - src/backup/todo.txt | 3 +- src/basic/basic_alloc.h | 1 + src/render/font.cpp | 28 +++++---- src/render/opengl.cpp | 81 +++++++++++---------------- src/text_editor/commands.cpp | 18 +++--- src/text_editor/commands_bindings.cpp | 16 +++--- src/text_editor/generated_config.cpp | 1 - src/text_editor/management.cpp | 1 + src/text_editor/text_editor.h | 1 + src/text_editor/window.cpp | 7 ++- src/text_editor/window_draw.cpp | 56 +++++++++--------- 12 files changed, 102 insertions(+), 112 deletions(-) diff --git a/data/init.lua b/data/init.lua index 0d4be0d..8f0c513 100644 --- a/data/init.lua +++ b/data/init.lua @@ -64,7 +64,6 @@ Style.DrawLineNumbers = 1 Style.DrawScrollbar = 1 Style.IndentSize = 4 Style.FontSize = 15 -Style.FontFilter = 0 Style.Font = GetExeDir().."/CascadiaMono.ttf" Style.VCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat" Style.TrimWhitespaceOnSave = true diff --git a/src/backup/todo.txt b/src/backup/todo.txt index 8446628..a032e5b 100644 --- a/src/backup/todo.txt +++ b/src/backup/todo.txt @@ -22,8 +22,7 @@ Things I like: Splits: - Buffer16.cpp / h vs Buffer ? -- Move font params to MainFont, allow for more fonts -- Block arena and refactor alloc +- Try to add Tracking Allocator and rewrite the app, free all memory at the end of the app and check all is well diff --git a/src/basic/basic_alloc.h b/src/basic/basic_alloc.h index 4d97cf0..a2f1302 100644 --- a/src/basic/basic_alloc.h +++ b/src/basic/basic_alloc.h @@ -31,6 +31,7 @@ API void TrackingAllocatorCheck(); API Allocator GetTrackingAllocator(); #define MemoryZero(x, size) memset(x, 0, size) +#define MemoryZeroStruct(x) memset(x, 0, sizeof(*x)) #define MemoryCopy(dst, src, size) memcpy(dst, src, size) #define MemoryMove(dst, src, size) memmove(dst, src, size) diff --git a/src/render/font.cpp b/src/render/font.cpp index ef288c3..7faf020 100644 --- a/src/render/font.cpp +++ b/src/render/font.cpp @@ -16,6 +16,9 @@ struct Font { float ascent; float line_gap; + Int line_spacing; + Int char_spacing; + Rect2 white_texture_bounding_box; }; @@ -92,6 +95,16 @@ Rect2 PackBitmap(Atlas *atlas, uint8_t *bitmap, int width, int height) { return result; } +Glyph *GetGlyph(Font *font, uint32_t codepoint) { + bool is_in_range = codepoint >= font->first_char && codepoint <= font->last_char; + if (is_in_range) { + uint32_t index = codepoint - font->first_char; + return &font->glyphs[index]; + } else { + uint32_t index = '?' - font->first_char; + return &font->glyphs[index]; + } +} Font CreateFont(Atlas *atlas, int32_t size, String path) { Allocator allocator = GetSystemAllocator(); Scratch scratch; @@ -143,16 +156,9 @@ Font CreateFont(Atlas *atlas, int32_t size, String path) { Add(&result.glyphs, glyph); } + Glyph *g = GetGlyph(&result, '_'); + result.char_spacing = (Int)g->xadvance ? (Int)g->xadvance : (Int)g->size.x; + result.line_spacing = (Int)(result.ascent - result.descent + result.line_gap); + return result; } - -Glyph *GetGlyph(Font *font, uint32_t codepoint) { - bool is_in_range = codepoint >= font->first_char && codepoint <= font->last_char; - if (is_in_range) { - uint32_t index = codepoint - font->first_char; - return &font->glyphs[index]; - } else { - uint32_t index = '?' - font->first_char; - return &font->glyphs[index]; - } -} \ No newline at end of file diff --git a/src/render/opengl.cpp b/src/render/opengl.cpp index c5ca191..396a829 100644 --- a/src/render/opengl.cpp +++ b/src/render/opengl.cpp @@ -30,9 +30,8 @@ Shader Shader2D; BlockArena RenderArena; Rect2 CurrentScissor; -Font MainFont; -Int FontLineSpacing; -Int FontCharSpacing; +Font PrimaryFont; +Font SecondaryFont; // ---------- shaders (ES3 / WebGL2) ---------- static const char *glsl_vshader_es3 = R"==(#version 300 es @@ -227,7 +226,7 @@ void EndFrameRender(float wx, float wy, Color color) { // bind texture unit 0 and the font texture glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, MainFont.texture_id); + glBindTexture(GL_TEXTURE_2D, PrimaryFont.texture_id); // draw glDrawArrays(GL_TRIANGLES, 0, it->count); @@ -308,10 +307,10 @@ void PushQuad2D(Allocator arena, VertexList2D *list, Rect2 rect, Rect2 tex, Colo } void DrawRect(Rect2 rect, Color color) { - PushQuad2D(RenderArena, &Vertices, rect, MainFont.white_texture_bounding_box, color); + PushQuad2D(RenderArena, &Vertices, rect, PrimaryFont.white_texture_bounding_box, color); } void DrawRect(Rect2I rect, Color color) { - PushQuad2D(RenderArena, &Vertices, ToRect2(rect), MainFont.white_texture_bounding_box, color); + PushQuad2D(RenderArena, &Vertices, ToRect2(rect), PrimaryFont.white_texture_bounding_box, color); } void DrawRectOutline(Rect2 rect, Color color, float thickness = 2) { @@ -319,29 +318,18 @@ void DrawRectOutline(Rect2 rect, Color color, float thickness = 2) { Rect2 b = CutRight(&rect, thickness); Rect2 c = CutTop(&rect, thickness); Rect2 d = CutBottom(&rect, thickness); - PushQuad2D(RenderArena, &Vertices, a, MainFont.white_texture_bounding_box, color); - PushQuad2D(RenderArena, &Vertices, b, MainFont.white_texture_bounding_box, color); - PushQuad2D(RenderArena, &Vertices, c, MainFont.white_texture_bounding_box, color); - PushQuad2D(RenderArena, &Vertices, d, MainFont.white_texture_bounding_box, color); + PushQuad2D(RenderArena, &Vertices, a, PrimaryFont.white_texture_bounding_box, color); + PushQuad2D(RenderArena, &Vertices, b, PrimaryFont.white_texture_bounding_box, color); + PushQuad2D(RenderArena, &Vertices, c, PrimaryFont.white_texture_bounding_box, color); + PushQuad2D(RenderArena, &Vertices, d, PrimaryFont.white_texture_bounding_box, color); } void DrawRectOutline(Rect2I rect, Color color, Int thickness = 2) { DrawRectOutline(ToRect2(rect), color, (float)thickness); } -Int GetCharSpacing(Font *font, int codepoint = '_') { - Glyph *g = GetGlyph(font, codepoint); - if (g->xadvance) return (Int)g->xadvance; - return (Int)g->size.x; -} - -Int GetLineSpacing(Font *font) { - Int result = (Int)(font->ascent - font->descent + font->line_gap); - return result; -} - Vec2 DrawString(Font *font, String16 string, Vec2 pos, Color color, bool draw = true) { - pos.y += GetLineSpacing(font) + font->descent; + pos.y += font->line_spacing + font->descent; // TODO: descent? Vec2 original_pos = pos; For(string) { Glyph *g = GetGlyph(font, it); @@ -371,7 +359,7 @@ void DrawCircle(Vec2 pos, float radius, Color color) { int point_i = 0; int segment_i = 0; for (; segment_i < vertex_count; segment_i += 3, point_i += 1) { - Rect2 tex = MainFont.white_texture_bounding_box; + Rect2 tex = PrimaryFont.white_texture_bounding_box; Vertex2D *it = vertices + segment_i; it[0].color = color; it[1].color = color; @@ -386,35 +374,30 @@ void DrawCircle(Vec2 pos, float radius, Color color) { } } +GLuint UploadAtlas(Atlas *atlas) { + GLuint tex = 0; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, (GLsizei)atlas->size.x, (GLsizei)atlas->size.y, 0, GL_RED, GL_UNSIGNED_BYTE, atlas->bitmap); + glBindTexture(GL_TEXTURE_2D, 0); + atlas->texture_id = tex; + return tex; +} + void ReloadFont() { - Int size = StyleFontSize; - size = ClampBottom((Int)2, size); - if (MainFont.texture_id) { - glDeleteTextures(1, &MainFont.texture_id); - Dealloc(&MainFont.glyphs); - MainFont = {}; + if (PrimaryFont.texture_id) { + glDeleteTextures(1, &PrimaryFont.texture_id); + Dealloc(&PrimaryFont.glyphs); + PrimaryFont = {}; } Scratch scratch; Atlas atlas = CreateAtlas(scratch, {2048, 2048}); - MainFont = CreateFont(&atlas, (uint32_t)size, StyleFont); - - // create and fill texture with ES3-compatible API - GLint filter = GL_NEAREST; - if (StyleFontFilter == 1) filter = GL_LINEAR; - - GLuint tex = 0; - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // allocate storage and upload - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y, 0, GL_RED, GL_UNSIGNED_BYTE, atlas.bitmap); - glBindTexture(GL_TEXTURE_2D, 0); - - MainFont.texture_id = tex; - FontCharSpacing = GetCharSpacing(&MainFont); - FontLineSpacing = GetLineSpacing(&MainFont); + PrimaryFont = CreateFont(&atlas, (uint32_t)ClampBottom(2u, (U32)StyleFontSize), StyleFont); + SecondaryFont = CreateFont(&atlas, 10, StyleFont); + SecondaryFont.texture_id = PrimaryFont.texture_id = UploadAtlas(&atlas); } diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 5832480..6696e53 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -65,8 +65,8 @@ void Command_EndJump(BSet set) { Int ScreenSpaceToBufferPos(Window *window, View *view, Buffer *buffer, Vec2I mouse) { Vec2I mworld = mouse - window->document_rect.min + view->scroll; - double px = (double)mworld.x / (double)FontCharSpacing; - double py = (double)mworld.y / (double)FontLineSpacing; + double px = (double)mworld.x / (double)window->font->char_spacing; + double py = (double)mworld.y / (double)window->font->line_spacing; XY xy = {(Int)round(px), (Int)floor(py)}; Int result = XYToPosWithoutNL(buffer, xy); return result; @@ -74,8 +74,8 @@ Int ScreenSpaceToBufferPos(Window *window, View *view, Buffer *buffer, Vec2I mou Int ScreenSpaceToBufferPosErrorOutOfBounds(Window *window, View *view, Buffer *buffer, Vec2I mouse) { Vec2I mworld = mouse - window->document_rect.min + view->scroll; - double px = (double)mworld.x / (double)FontCharSpacing; - double py = (double)mworld.y / (double)FontLineSpacing; + double px = (double)mworld.x / (double)window->font->char_spacing; + double py = (double)mworld.y / (double)window->font->line_spacing; XY xy = {(Int)round(px), (Int)floor(py)}; Int result = XYToPosErrorOutOfBounds(buffer, xy); return result; @@ -1342,20 +1342,20 @@ Window *GetOverlappingWindow(Vec2I p, Window *default_window = NULL) { Vec2I GetSideOfWindow(Window *window, int direction) { Vec2I p = {}; Rect2I rect = window->total_rect; - float resizer_size = (float)FontCharSpacing*0.5f; // @check_codebase_when_changing + float resizer_size = (float)window->font->char_spacing*0.5f; // @check_codebase_when_changing if (direction == DIR_LEFT) { - p.x = rect.min.x - (Int)(resizer_size + FontCharSpacing); + p.x = rect.min.x - (Int)(resizer_size + window->font->char_spacing); p.y = rect.min.y + (rect.max.y / 2); } else if (direction == DIR_RIGHT) { - p.x = rect.max.x + (Int)(resizer_size + FontCharSpacing); + p.x = rect.max.x + (Int)(resizer_size + window->font->char_spacing); p.y = rect.min.y + (rect.max.y / 2); } else if (direction == DIR_UP) { p.x = rect.min.x + (rect.max.x / 2); - p.y = rect.min.y - (Int)(resizer_size + FontLineSpacing); + p.y = rect.min.y - (Int)(resizer_size + window->font->line_spacing); } else { Assert(direction == DIR_DOWN); p.x = rect.min.x + (rect.max.x / 2); - p.y = rect.max.y + (Int)(resizer_size + FontLineSpacing); + p.y = rect.max.y + (Int)(resizer_size + window->font->line_spacing); } return p; } diff --git a/src/text_editor/commands_bindings.cpp b/src/text_editor/commands_bindings.cpp index 2452bf8..2f1a6e2 100644 --- a/src/text_editor/commands_bindings.cpp +++ b/src/text_editor/commands_bindings.cpp @@ -10,34 +10,34 @@ void UpdateScroll(Window *window, bool update_caret_scrolling) { Rect2I visible = GetVisibleCells(window); Vec2I visible_cells = GetSize(visible); - Vec2I visible_size = visible_cells * Vec2I{FontCharSpacing, FontLineSpacing}; + Vec2I visible_size = visible_cells * Vec2I{window->font->char_spacing, window->font->line_spacing}; Vec2I rect_size = GetSize(window->document_rect); if (xy.line >= visible.max.y - 2) { Int set_view_at_line = xy.line - (visible_cells.y - 1); Int cut_off_y = Max((Int)0, visible_size.y - rect_size.y); - set.view->scroll.y = (set_view_at_line * FontLineSpacing) + cut_off_y; + set.view->scroll.y = (set_view_at_line * window->font->line_spacing) + cut_off_y; } if (xy.line < visible.min.y + 1) { - set.view->scroll.y = xy.line * FontLineSpacing; + set.view->scroll.y = xy.line * window->font->line_spacing; } if (xy.col >= visible.max.x - 1) { Int set_view_at_line = xy.col - (visible_cells.x - 1); Int cut_off_x = Max((Int)0, visible_size.x - rect_size.x); - set.view->scroll.x = (set_view_at_line * FontCharSpacing) + cut_off_x; + set.view->scroll.x = (set_view_at_line * window->font->char_spacing) + cut_off_x; } if (xy.col <= visible.min.x) { - set.view->scroll.x = xy.col * FontCharSpacing; + set.view->scroll.x = xy.col * window->font->char_spacing; } } // Clip scroll { Int last_line = LastLine(set.buffer); - set.view->scroll.y = Clamp(set.view->scroll.y, (Int)0, Max((Int)0, (last_line - 1) * FontLineSpacing)); + set.view->scroll.y = Clamp(set.view->scroll.y, (Int)0, Max((Int)0, (last_line - 1) * window->font->line_spacing)); // @note: // GetCharCountOfLongestLine is a bottleneck, there is probably an algorithm for @@ -108,7 +108,7 @@ void OnCommand(Event event) { double p = mouse_vec2.y - window->scrollbar_rect.min.y; double v = p / size_y; v = v + (window->mouse_scroller_offset); - view->scroll.y = (Int)(v * (double)s.line_count * (double)FontLineSpacing); + view->scroll.y = (Int)(v * (double)s.line_count * (double)window->font->line_spacing); } if (DocumentSelected != ActiveWindow) { @@ -273,7 +273,7 @@ void OnCommand(Event event) { double size_y = (double)GetSize(it->scrollbar_rect).y; double p = mouse_vec2.y - it->scrollbar_rect.min.y; if (mouse_vec2.y < s.rect.min.y || mouse_vec2.y > s.rect.max.y) { - view->scroll.y = (Int)(p / size_y * (double)s.line_count * (double)FontLineSpacing); + view->scroll.y = (Int)(p / size_y * (double)s.line_count * (double)it->font->line_spacing); it->mouse_scroller_offset = -(double)GetSize(s.rect).y / 2.0 / size_y; } else { it->mouse_scroller_offset = (s.rect.min.y - p) / size_y; diff --git a/src/text_editor/generated_config.cpp b/src/text_editor/generated_config.cpp index ff9e567..7dddf3a 100644 --- a/src/text_editor/generated_config.cpp +++ b/src/text_editor/generated_config.cpp @@ -65,7 +65,6 @@ Style.DrawLineNumbers = 1 Style.DrawScrollbar = 1 Style.IndentSize = 4 Style.FontSize = 15 -Style.FontFilter = 0 Style.Font = GetExeDir().."/CascadiaMono.ttf" Style.VCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat" Style.TrimWhitespaceOnSave = true diff --git a/src/text_editor/management.cpp b/src/text_editor/management.cpp index feab51e..403036e 100644 --- a/src/text_editor/management.cpp +++ b/src/text_editor/management.cpp @@ -174,6 +174,7 @@ Buffer *CreateBuffer(Allocator allocator, String name, Int size) { Window *CreateWind(bool create_command_buffer = true) { Window *w = AllocType(SysAllocator, Window); + w->font = &PrimaryFont; w->visible = true; w->draw_scrollbar = StyleDrawScrollbar; w->draw_line_numbers = StyleDrawLineNumbers; diff --git a/src/text_editor/text_editor.h b/src/text_editor/text_editor.h index 8fffd4c..81052c0 100644 --- a/src/text_editor/text_editor.h +++ b/src/text_editor/text_editor.h @@ -46,6 +46,7 @@ struct Window { ViewID active_goto_list; Int goto_list_pos; + Font *font; Caret search_bar_anchor; double mouse_scroller_offset; int z; diff --git a/src/text_editor/window.cpp b/src/text_editor/window.cpp index 7224f4a..2cc5979 100644 --- a/src/text_editor/window.cpp +++ b/src/text_editor/window.cpp @@ -31,6 +31,7 @@ Window *CreateSearchBar(WindowID parent_window_id) { Window *CreateTitlebar(WindowID parent_window_id) { Window *window = CreateWind(false); + window->font = &SecondaryFont; window->draw_scrollbar = false; window->deactivate_on_escape = true; window->is_title_bar = true; @@ -56,7 +57,7 @@ Window *CreateTitlebar(WindowID parent_window_id) { Int GetTitleBarSize(Window *window) { View *view = GetView(window->active_view); Buffer *buffer = GetBuffer(view->active_buffer); - float result = (float)buffer->line_starts.len * FontLineSpacing; + float result = (float)buffer->line_starts.len * window->font->line_spacing; return (Int)result; } @@ -209,11 +210,11 @@ void InitWindows() { void LayoutWindowSplit(WindowSplit *split, Rect2I rect) { float scrollbar_size = (10.f * DPIScale); - float line_numbers_size = (float)FontCharSpacing * 10; - float resizer_size = (float)FontCharSpacing*0.5f; + float resizer_size = (float)PrimaryFont.char_spacing*0.5f; if (split->kind == WindowSplitKind_Window) { Window *it = split->window; + float line_numbers_size = (float)it->font->char_spacing * 10; Assert(it->split_ref); it->total_rect = rect; diff --git a/src/text_editor/window_draw.cpp b/src/text_editor/window_draw.cpp index 36b4a79..ab59488 100644 --- a/src/text_editor/window_draw.cpp +++ b/src/text_editor/window_draw.cpp @@ -1,5 +1,5 @@ -Vec2I GetCellSize() { - Vec2I result = {(Int)FontCharSpacing, (Int)FontLineSpacing}; +Vec2I GetCellSize(Window *window) { + Vec2I result = {(Int)window->font->char_spacing, (Int)window->font->line_spacing}; return result; } @@ -8,12 +8,12 @@ Rect2I GetVisibleCells(Window *window) { View *view = GetView(window->active_view); Vec2I size = GetSize(window->document_rect); - Int _cx = size.x / FontCharSpacing; - Int _cy = size.y / FontLineSpacing; + Int _cx = size.x / window->font->char_spacing; + Int _cy = size.y / window->font->line_spacing; Int cx = _cx + 1; Int cy = _cy + 2; - Vec2I pos = {SafeDivide(view->scroll.x, FontCharSpacing), SafeDivide(view->scroll.y, FontLineSpacing)}; + Vec2I pos = {SafeDivide(view->scroll.x, window->font->char_spacing), SafeDivide(view->scroll.y, window->font->line_spacing)}; Int x = pos.x; Int y = pos.y; Rect2I result = {x, y, x + cx, y + cy}; @@ -46,14 +46,14 @@ void DrawVisibleText(Window *window, Color tint) { Rect2I visible = GetVisibleCells(window); for (Int line_index = visible.min.y; line_index < visible.max.y && line_index >= 0 && line_index < buffer->line_starts.len; line_index += 1) { String16 line_string = GetLineString(buffer, line_index); - Vec2I pos = Vec2I{visible.min.x, line_index} * (Int)FontLineSpacing - view->scroll + window->document_rect.min; + Vec2I pos = Vec2I{visible.min.x, line_index} * (Int)window->font->line_spacing - view->scroll + window->document_rect.min; float text_offset_x = 0; for (Int col_index = visible.min.x; col_index < visible.max.x && col_index >= 0 && col_index < line_string.len; col_index += 1) { int codepoint = line_string[col_index]; - Glyph *g = GetGlyph(&MainFont, codepoint); + Glyph *g = GetGlyph(window->font, codepoint); Vec2 p = ToVec2(pos); - p.y += FontLineSpacing + MainFont.descent; + p.y += window->font->line_spacing + window->font->descent; p.x += text_offset_x; Rect2 rect = Rect2FromSize(p + g->offset, g->size); @@ -61,25 +61,25 @@ void DrawVisibleText(Window *window, Color tint) { PushQuad2D(RenderArena, &Vertices, rect, g->atlas_bounding_box, tint); } - text_offset_x += FontCharSpacing; + text_offset_x += window->font->char_spacing; } } } -Vec2I XYToWorldPos(View *view, XY xy) { - Vec2I result = {xy.col * (Int)FontCharSpacing, xy.line * (Int)FontLineSpacing}; +Vec2I XYToWorldPos(Window *window, XY xy) { + Vec2I result = {xy.col * (Int)window->font->char_spacing, xy.line * (Int)window->font->line_spacing}; return result; } -Rect2I XYToRect(View *view, XY xy) { - Rect2I result = Rect2IFromSize(XYToWorldPos(view, xy), GetCellSize()); +Rect2I XYToRect(Window *window, XY xy) { + Rect2I result = Rect2IFromSize(XYToWorldPos(window, xy), GetCellSize(window)); return result; } void DrawCaret(Window *window, XY xy, float size, Color color) { View *view = GetView(window->active_view); - Rect2I _rect = XYToRect(view, xy); - Rect2I rect = CutLeft(&_rect, (Int)(size * (float)FontCharSpacing)); + Rect2I _rect = XYToRect(window, xy); + Rect2I rect = CutLeft(&_rect, (Int)(size * (float)window->font->char_spacing)); Rect2I scrolled_rect = rect - view->scroll + window->document_rect.min; DrawRect(ToRect2(scrolled_rect), color); } @@ -92,8 +92,8 @@ void DrawUnderline(Window *window, View *view, Buffer *buffer, Range range, Colo // optimizing and so on if (xy_min.line != xy_max.line) return; - Vec2I min = {xy_min.col * FontCharSpacing, (xy_min.line + 1) * FontLineSpacing - size}; - Vec2I max = {xy_max.col * FontCharSpacing, (xy_max.line + 1) * FontLineSpacing}; + Vec2I min = {xy_min.col * window->font->char_spacing, (xy_min.line + 1) * window->font->line_spacing - size}; + Vec2I max = {xy_max.col * window->font->char_spacing, (xy_max.line + 1) * window->font->line_spacing}; Rect2I rect = {min, max}; Rect2I scrolled_rect = rect - view->scroll + window->document_rect.min; DrawRectOutline(scrolled_rect, color); @@ -153,17 +153,17 @@ void DrawWindow(Window *window, Event &event) { bool d = min.line == max.line && line == max.line && col >= min.col && col < max.col; if (!(a || b || c || d)) continue; - Vec2I pos = {col * FontCharSpacing, line * FontLineSpacing}; + Vec2I pos = {col * window->font->char_spacing, line * window->font->line_spacing}; pos -= view->scroll; pos += window->document_rect.min; - Rect2 rect = Rect2FromSize({(float)pos.x, (float)pos.y}, {(float)FontCharSpacing, (float)FontLineSpacing}); + Rect2 rect = Rect2FromSize({(float)pos.x, (float)pos.y}, {(float)window->font->char_spacing, (float)window->font->line_spacing}); DrawRect(rect, color_selection); } } // Draw the little artifacts signaling whitespace // @copypaste - Glyph *xglyph = GetGlyph(&MainFont, 'x'); + Glyph *xglyph = GetGlyph(window->font, 'x'); for (Int line = visible.min.y; line <= visible.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) { String16 line_string = GetLineString(buffer, line); @@ -174,10 +174,10 @@ void DrawWindow(Window *window, Event &event) { bool d = min.line == max.line && line == max.line && col >= min.col && col < max.col; if (!(a || b || c || d)) continue; if (line_string[col] == ' ' || line_string[col] == '\t' || line_string[col] == '\n' || line_string[col] == '\r') { - Vec2I pos = {col * FontCharSpacing, line * FontLineSpacing}; + Vec2I pos = {col * window->font->char_spacing, line * window->font->line_spacing}; Vec2I scrolled_pos = pos - view->scroll + window->document_rect.min; - Vec2 circle_pos = {scrolled_pos.x + (float)FontCharSpacing / 2.f, (float)scrolled_pos.y + xglyph->size.y}; - float circle_size = MainFont.size / 16.f; + Vec2 circle_pos = {scrolled_pos.x + (float)window->font->char_spacing / 2.f, (float)scrolled_pos.y + xglyph->size.y}; + float circle_size = window->font->size / 16.f; DrawCircle(circle_pos, circle_size, color_whitespace_during_selection); } } @@ -187,11 +187,11 @@ void DrawWindow(Window *window, Event &event) { // Draw highlight Int front = GetFront(it); XY fxy = PosToXY(buffer, front); - Vec2I pos = XYToWorldPos(view, XYLine(fxy.line)); + Vec2I pos = XYToWorldPos(window, XYLine(fxy.line)); Vec2I scrolled_pos = pos - view->scroll + window->document_rect.min; Rect2 rect = { {(float)window->total_rect.min.x, (float)scrolled_pos.y}, - {(float)window->total_rect.max.x, (float)scrolled_pos.y + (float)FontLineSpacing} + {(float)window->total_rect.max.x, (float)scrolled_pos.y + (float)window->font->line_spacing} }; DrawRect(rect, color_line_highlight); } @@ -246,17 +246,17 @@ void DrawWindow(Window *window, Event &event) { Rect2I vlines = GetVisibleCells(window); for (Int line = vlines.min.y; line <= visible.max.y && line >= 0 && line < buffer->line_starts.len; line += 1) { Scratch scratch; - Vec2I pos = {0, line * FontLineSpacing}; + Vec2I pos = {0, line * window->font->line_spacing}; pos.y -= view->scroll.y; pos += window->line_numbers_rect.min; String s = Format(scratch, "%lld", (long long)line + 1ll); String16 string = ToString16(scratch, s); - float x = FontCharSpacing * (float)string.len; + float x = window->font->char_spacing * (float)string.len; Vec2 p = ToVec2(pos); float rectx = (float)GetSize(window->line_numbers_rect).x; p.x += (rectx - x) / 2.f; if (x > rectx) p.x = (float)window->line_numbers_rect.min.x; - DrawString(&MainFont, string, p, color_text_line_numbers); + DrawString(window->font, string, p, color_text_line_numbers); } }