Allow multiple fonts
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user