diff --git a/src/text_editor/main.cpp b/src/text_editor/main.cpp index 5ff3462..0995584 100644 --- a/src/text_editor/main.cpp +++ b/src/text_editor/main.cpp @@ -59,6 +59,32 @@ Rect2 GetScreenRectRenderUnits() { return result; } +// Draw text using Font +// NOTE: chars spacing is NOT proportional to fontSize +void DrawTextNew(Font font, String text, Vector2 position, float fontSize, float spacing, Color tint) { + if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font + + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scaleFactor = fontSize / font.baseSize; // Character quad scaling factor + + for (int i = 0; i < text.len;) { + // Get next codepoint from byte string and glyph index in font + int codepointByteCount = 0; + int codepoint = GetCodepointNext(&text.data[i], &codepointByteCount); + int index = GetGlyphIndex(font, codepoint); + + if ((codepoint != ' ') && (codepoint != '\t')) { + DrawTextCodepoint(font, codepoint, {position.x + textOffsetX, position.y}, fontSize, tint); + } + + if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width * scaleFactor + spacing); + else textOffsetX += ((float)font.glyphs[index].advanceX * scaleFactor + spacing); + + i += codepointByteCount; // Move text bytes counter to next codepoint + } +} + int main() { InitScratch(); RunBufferTests(); @@ -91,6 +117,7 @@ int main() { Window *focused_window = &windows[0]; float mouse_wheel = GetMouseWheelMove() * 48; focused_window->window_world_to_window_units.y -= mouse_wheel; + focused_window->window_world_to_window_units.y = ClampBottom(focused_window->window_world_to_window_units.y, 0.f); } for (int c = GetCharPressed(); c; c = GetCharPressed()) { @@ -108,10 +135,10 @@ int main() { BeginDrawing(); ClearBackground(RAYWHITE); - For(windows) { + ForItem(window, windows) { Rect2 window_rect_in_render_units = { - WorldToRenderUnits(it.rect_in_world_units.min, camera_offset_world_to_render_units), - WorldToRenderUnits(it.rect_in_world_units.max, camera_offset_world_to_render_units), + WorldToRenderUnits(window.rect_in_world_units.min, camera_offset_world_to_render_units), + WorldToRenderUnits(window.rect_in_world_units.max, camera_offset_world_to_render_units), }; Rectangle rectangle_in_render_units = ToRectangle(window_rect_in_render_units); DrawRectangleRec(rectangle_in_render_units, WHITE); @@ -128,39 +155,39 @@ int main() { // Line rendering // { - Rect2 screen_rect_in_render_units = GetScreenRectRenderUnits(); - Rect2 window_rect_in_render_units_clamped_to_screen = window_rect_in_render_units; - window_rect_in_render_units_clamped_to_screen.min.x = Clamp(window_rect_in_render_units_clamped_to_screen.min.x, screen_rect_in_render_units.min.x, screen_rect_in_render_units.max.x); - window_rect_in_render_units_clamped_to_screen.max.x = Clamp(window_rect_in_render_units_clamped_to_screen.max.x, screen_rect_in_render_units.min.x, screen_rect_in_render_units.max.x); - window_rect_in_render_units_clamped_to_screen.min.y = Clamp(window_rect_in_render_units_clamped_to_screen.min.y, screen_rect_in_render_units.min.y, screen_rect_in_render_units.max.y); - window_rect_in_render_units_clamped_to_screen.max.y = Clamp(window_rect_in_render_units_clamped_to_screen.max.y, screen_rect_in_render_units.min.y, screen_rect_in_render_units.max.y); + // @todo: how do I implement the minimal drawing of text + // Rect2 screen_rect_in_render_units = GetScreenRectRenderUnits(); + // Rect2 window_rect_in_render_units_clamped_to_screen = window_rect_in_render_units; + // window_rect_in_render_units_clamped_to_screen.min.x = Clamp(window_rect_in_render_units_clamped_to_screen.min.x, screen_rect_in_render_units.min.x, screen_rect_in_render_units.max.x); + // window_rect_in_render_units_clamped_to_screen.max.x = Clamp(window_rect_in_render_units_clamped_to_screen.max.x, screen_rect_in_render_units.min.x, screen_rect_in_render_units.max.x); + // window_rect_in_render_units_clamped_to_screen.min.y = Clamp(window_rect_in_render_units_clamped_to_screen.min.y, screen_rect_in_render_units.min.y, screen_rect_in_render_units.max.y); + // window_rect_in_render_units_clamped_to_screen.max.y = Clamp(window_rect_in_render_units_clamped_to_screen.max.y, screen_rect_in_render_units.min.y, screen_rect_in_render_units.max.y); - Vec2 s = GetSize(window_rect_in_render_units_clamped_to_screen); + // @todo: x + Vec2 s = GetSize(window_rect_in_render_units); + float line_offset = font_size; + float _line_min_y = (window.window_world_to_window_units.y) / line_offset; + float _line_max_y = (s.y + window.window_world_to_window_units.y) / line_offset; + int64_t line_min_y = (int64_t)floorf(_line_min_y); + int64_t line_max_y = (int64_t)ceilf(_line_max_y); - // buffer_pixel_size := GetRectSize(text_window_rect); - // _miny := w.scroll.y / Monosize.y; - // _maxy := (w.scroll.y + buffer_pixel_size.y) / Monosize.y; + Vec2 window_rect_in_render_units_size = GetSize(window_rect_in_render_units); + BeginScissorMode((int)window_rect_in_render_units.min.x, (int)window_rect_in_render_units.min.y, (int)window_rect_in_render_units_size.x, (int)window_rect_in_render_units_size.y); + for (int64_t line = line_min_y; line < line_max_y; line += 1) { + if (line < 0) break; + if (line >= buffer.lines.len) break; - // _minx := w.scroll.x / Monosize.x; - // _maxx := (w.scroll.x + buffer_pixel_size.x) / Monosize.x; + Range line_range = buffer.lines[line]; - // miny := :int(floorf(_miny)); - // minx := :int(floorf(_minx)); + Vec2 text_position_in_world_window_units = {0, line_offset * (float)line}; + Vec2 text_position_in_window_units = WindowWorldToWindowUnits(text_position_in_world_window_units, window); + Vec2 text_position_in_world_units = WindowToWorldUnits(text_position_in_window_units, window); + Vec2 text_position_in_render_units = WorldToRenderUnits(text_position_in_world_units, camera_offset_world_to_render_units); - // maxy := :int(ceilf(_maxy)); - // maxx := :int(ceilf(_maxx)); - - float y = 0; - ForItem(line_range, buffer.lines) { - Vec2 text_position_in_world_window_units = {0, y}; - y += font_size; - Vec2 text_position_in_window_units = WindowWorldToWindowUnits(text_position_in_world_window_units, it); - Vec2 text_position_in_world_units = WindowToWorldUnits(text_position_in_window_units, it); - Vec2 text_position_in_render_units = WorldToRenderUnits(text_position_in_world_units, camera_offset_world_to_render_units); - - String string = CopyNullTerminated(FrameArena, buffer, line_range); - DrawTextEx(font, string.data, text_position_in_render_units, font_size, font_spacing, BLACK); + String string = GetString(buffer, line_range); + DrawTextNew(font, string, text_position_in_render_units, font_size, font_spacing, BLACK); } + EndScissorMode(); } }