Allow multiple fonts

This commit is contained in:
Krzosa Karol
2025-12-01 09:05:06 +01:00
parent c2f4686bc4
commit e34c2b0cef
12 changed files with 102 additions and 112 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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];
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}
}