From 94555d2a6029ab9035e99d3935bc9bb8f6c28da9 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sat, 22 Jun 2024 08:35:11 +0200 Subject: [PATCH] Working on rendering --- build_file.cpp | 50 +++--- src/{pdf_browser => basic}/basic.h | 28 +++- .../filesystem.h | 2 +- src/{transcript_browser => basic}/win32.cpp | 0 src/pdf_browser/main.cpp | 12 -- src/pdf_browser/read_pdf.cpp | 24 --- src/pdf_browser/win32.cpp | 27 ---- src/text_editor/buffer.cpp | 152 ++++++++++++++---- src/text_editor/main.cpp | 105 +++++++++--- src/{pdf_browser => text_editor}/read_pdf.py | 0 src/transcript_browser/main.cpp | 8 + 11 files changed, 258 insertions(+), 150 deletions(-) rename src/{pdf_browser => basic}/basic.h (98%) rename src/{transcript_browser => basic}/filesystem.h (91%) rename src/{transcript_browser => basic}/win32.cpp (100%) delete mode 100644 src/pdf_browser/main.cpp delete mode 100644 src/pdf_browser/read_pdf.cpp delete mode 100644 src/pdf_browser/win32.cpp rename src/{pdf_browser => text_editor}/read_pdf.py (100%) diff --git a/build_file.cpp b/build_file.cpp index 7acf594..6bb804c 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -53,6 +53,22 @@ Library BuildZLib() { return l; } +void AddCommonFlags(Array *cmd, bool debug = true) { + cmd->add("/MP /Zi /FC /nologo"); + cmd->add("/WX /W3 /wd4200 /diagnostics:column"); + cmd->add("/Oi"); + cmd->add("-D_CRT_SECURE_NO_WARNINGS"); + if (debug) { + cmd->add("-DDEBUG_BUILD=1"); + cmd->add("-DRELEASE_BUILD=0"); + // cmd->add("-D_DEBUG /MDd"); + } else { + cmd->add("-DDEBUG_BUILD=0"); + cmd->add("-DRELEASE_BUILD=1"); + cmd->add("/O2 /MT /DNDEBUG /GL"); + } +} + int main() { MA_InitScratch(); SRC_InitCache(Perm, "pdf_browser.cache"); @@ -64,25 +80,12 @@ int main() { cmd.add("cl.exe"); cmd.add("-Fe:transcript_browser.exe"); cmd.add("-Fd:transcript_browser.pdb"); - cmd.add("/MP /Zi /FC /nologo"); - cmd.add("/WX /W3 /wd4200 /diagnostics:column"); - cmd.add("/Oi"); cmd.add("-std:c++20"); // semaphore - - cmd.add("-D_CRT_SECURE_NO_WARNINGS"); - if (1) { - cmd.add("-DDEBUG_BUILD=1"); - cmd.add("-DRELEASE_BUILD=0"); - // cmd.add("-D_DEBUG /MDd"); - } else { - cmd.add("-DDEBUG_BUILD=0"); - cmd.add("-DRELEASE_BUILD=1"); - cmd.add("/O2 /MT /DNDEBUG /GL"); - } + AddCommonFlags(&cmd); cmd.add("-I ../src/external/raylib/include"); cmd.add("../src/transcript_browser/main.cpp"); - cmd.add("../src/transcript_browser/win32.cpp"); + cmd.add("../src/basic/win32.cpp"); cmd.add("/link"); cmd.add("../src/external/raylib/lib/raylib.lib"); @@ -99,25 +102,12 @@ int main() { cmd.add("cl.exe"); cmd.add("-Fe:text_editor.exe"); cmd.add("-Fd:text_editor.pdb"); - cmd.add("/MP /Zi /FC /nologo"); - cmd.add("/WX /W3 /wd4200 /diagnostics:column"); - cmd.add("/Oi"); cmd.add("-std:c++20"); // semaphore - - cmd.add("-D_CRT_SECURE_NO_WARNINGS"); - if (1) { - cmd.add("-DDEBUG_BUILD=1"); - cmd.add("-DRELEASE_BUILD=0"); - // cmd.add("-D_DEBUG /MDd"); - } else { - cmd.add("-DDEBUG_BUILD=0"); - cmd.add("-DRELEASE_BUILD=1"); - cmd.add("/O2 /MT /DNDEBUG /GL"); - } + AddCommonFlags(&cmd); cmd.add("-I ../src/external/raylib/include"); cmd.add("../src/text_editor/main.cpp"); - cmd.add("../src/transcript_browser/win32.cpp"); + cmd.add("../src/basic/win32.cpp"); cmd.add("/link"); cmd.add("../src/external/raylib/lib/raylib.lib"); diff --git a/src/pdf_browser/basic.h b/src/basic/basic.h similarity index 98% rename from src/pdf_browser/basic.h rename to src/basic/basic.h index dad7b94..3dcc6e2 100644 --- a/src/pdf_browser/basic.h +++ b/src/basic/basic.h @@ -90,9 +90,8 @@ T ClampBottom(T bottom, T b) { template T Clamp(T value, T min, T max) { - Assert(max >= min); - if (value > max) return max; if (value < min) return min; + if (value > max) return max; return value; } @@ -1394,6 +1393,31 @@ String SkipToLastPeriod(String s) { return result; } +String Merge(Allocator allocator, Array list, String separator = " ") { + int64_t char_count = 0; + For(list) char_count += it.len; + if (char_count == 0) return {}; + int64_t node_count = list.len; + + int64_t base_size = (char_count + 1); + int64_t sep_size = (node_count - 1) * separator.len; + int64_t size = base_size + sep_size; + char *buff = (char *)AllocSize(allocator, sizeof(char) * (size + 1)); + String string = {buff, 0}; + For(list) { + Assert(string.len + it.len <= size); + memcpy(string.data + string.len, it.data, it.len); + string.len += it.len; + if (!list.is_last(it)) { + memcpy(string.data + string.len, separator.data, separator.len); + string.len += separator.len; + } + } + Assert(string.len == size - 1); + string.data[size] = 0; + return string; +} + #include String FormatV(Allocator allocator, const char *data, va_list args1) { va_list args2; diff --git a/src/transcript_browser/filesystem.h b/src/basic/filesystem.h similarity index 91% rename from src/transcript_browser/filesystem.h rename to src/basic/filesystem.h index bedc386..a225af9 100644 --- a/src/transcript_browser/filesystem.h +++ b/src/basic/filesystem.h @@ -1,5 +1,5 @@ #pragma once -#include "../pdf_browser/basic.h" +#include "../basic/basic.h" struct FileIter { bool is_valid; diff --git a/src/transcript_browser/win32.cpp b/src/basic/win32.cpp similarity index 100% rename from src/transcript_browser/win32.cpp rename to src/basic/win32.cpp diff --git a/src/pdf_browser/main.cpp b/src/pdf_browser/main.cpp deleted file mode 100644 index 53de1bf..0000000 --- a/src/pdf_browser/main.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#define BASIC_IMPL -#include "basic.h" - -#include -#include "read_pdf.cpp" - -int main(int argc, char *argv[]) { - InitScratch(); - Scratch scratch; - - return (0); -} \ No newline at end of file diff --git a/src/pdf_browser/read_pdf.cpp b/src/pdf_browser/read_pdf.cpp deleted file mode 100644 index 78f2d33..0000000 --- a/src/pdf_browser/read_pdf.cpp +++ /dev/null @@ -1,24 +0,0 @@ -String Merge(Allocator allocator, Array list, String separator = " ") { - int64_t char_count = 0; - For(list) char_count += it.len; - if (char_count == 0) return {}; - int64_t node_count = list.len; - - int64_t base_size = (char_count + 1); - int64_t sep_size = (node_count - 1) * separator.len; - int64_t size = base_size + sep_size; - char *buff = (char *)AllocSize(allocator, sizeof(char) * (size + 1)); - String string = {buff, 0}; - For(list) { - Assert(string.len + it.len <= size); - memcpy(string.data + string.len, it.data, it.len); - string.len += it.len; - if (!list.is_last(it)) { - memcpy(string.data + string.len, separator.data, separator.len); - string.len += separator.len; - } - } - Assert(string.len == size - 1); - string.data[size] = 0; - return string; -} diff --git a/src/pdf_browser/win32.cpp b/src/pdf_browser/win32.cpp deleted file mode 100644 index c7fc891..0000000 --- a/src/pdf_browser/win32.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef NOMINMAX - #define NOMINMAX -#endif -#ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN -#endif -#include - -void *VReserve(size_t size) { - void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); - return result; -} - -bool VCommit(void *p, size_t size) { - void *result = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE); - return result ? true : false; -} - -bool VRelease(void *p) { - BOOL result = VirtualFree(p, 0, MEM_RELEASE); - return result ? true : false; -} - -bool VDecommit(void *p, size_t size) { - BOOL result = VirtualFree(p, size, MEM_DECOMMIT); - return result ? true : false; -} \ No newline at end of file diff --git a/src/text_editor/buffer.cpp b/src/text_editor/buffer.cpp index d2ba769..3ca508d 100644 --- a/src/text_editor/buffer.cpp +++ b/src/text_editor/buffer.cpp @@ -9,7 +9,8 @@ much better then the rest. First of all you can represent the cursor at the end of the buffer by doing: . This action in itself doesn't select anything, the formation doesn't force you to index the -buffer and so on, it's reduced to a pure position. +buffer and so on, it's reduced to a pure position. In the end +you can nicely represent cursors in select mode and non-select mode. This property of being able to represent pure positions makes it possible to clamp the values to the same range <0, buffer_len>, @@ -23,11 +24,21 @@ struct Range { // <0,4> = 0,1,2,3 }; +struct Line { + int64_t number; + Range range; +}; + struct Edit { Range range; String string; }; +// :buffer_initialized +// @todo: it's very tempting to ensure that buffer is initialized +// then we know: +// - we always have at least one thing in lines array. +// - I think it would be probably easy enough to enforce struct Buffer { Allocator allocator; char *data[2]; @@ -47,54 +58,62 @@ Range GetRange(const Buffer &buffer) { return result; } -int64_t Clamp(Buffer *buffer, int64_t pos) { - int64_t result = Clamp(pos, (int64_t)0, buffer->len); +int64_t Clamp(const Buffer &buffer, int64_t pos) { + int64_t result = Clamp(pos, (int64_t)0, buffer.len); return result; } -Range Clamp(Buffer *buffer, Range range) { +Range Clamp(const Buffer &buffer, Range range) { Range result = {}; result.min = Clamp(buffer, range.min); result.max = Clamp(buffer, range.max); return result; } +Range GetEnd(const Buffer &buffer) { + Range range = {buffer.len, buffer.len}; + return range; +} + void AddEdit(Array *edits, Range range, String string) { edits->add({range, string}); } -bool InBounds(Buffer *buffer, int64_t pos) { - bool result = pos >= 0 && pos < buffer->len; +bool InBounds(const Buffer &buffer, int64_t pos) { + bool result = pos >= 0 && pos < buffer.len; return result; } -char GetChar(Buffer *buffer, int64_t pos) { +char GetChar(const Buffer &buffer, int64_t pos) { if (!InBounds(buffer, pos)) return 0; - return buffer->data[buffer->bi][pos]; + return buffer.data[buffer.bi][pos]; } -char *GetCharP(Buffer *buffer, int64_t pos) { +char *GetCharP(const Buffer &buffer, int64_t pos) { if (!InBounds(buffer, pos)) return 0; - return buffer->data[buffer->bi] + pos; + return buffer.data[buffer.bi] + pos; } -String GetString(Buffer *buffer, Range range) { +String GetString(const Buffer &buffer, Range range = {0, INT64_MAX}) { range = Clamp(buffer, range); String result = {GetCharP(buffer, range.min), GetRangeSize(range)}; return result; } void ApplyEdits(Buffer *buffer, Array edits) { + Assert(edits.len); int64_t size_to_delete = 0; int64_t size_to_insert = 0; For(edits) { - it.range.min = Clamp(buffer, it.range.min); - it.range.max = Clamp(buffer, it.range.max); + Assert(it.range.min >= 0); + Assert(it.range.max >= it.range.min); + Assert(it.range.max <= buffer->len); size_to_delete += GetRangeSize(it.range); size_to_insert += it.string.len; } #if DEBUG_BUILD + // Make sure edit ranges don't overlap ForItem(it1, edits) { ForItem(it2, edits) { if (&it1 == &it2) continue; @@ -176,6 +195,9 @@ void ApplyEdits(Buffer *buffer, Array edits) { buffer->len = new_buffer_len; // Update lines + // Make sure we always have one line, even if the buffer is empty, + // this way we can nicely clamp things without worrying of getting + // a negative when doing (len - 1). { String delimiter = "\n"; String string = {buffer->data[dsti], buffer->len}; @@ -193,9 +215,46 @@ void ApplyEdits(Buffer *buffer, Array edits) { } } -int64_t AdjustUTF8Pos(Buffer *buffer, int64_t pos, int64_t direction = 1) { +void InitBuffer(Buffer *buffer) { + Scratch scratch; + Array edits = {}; + AddEdit(&edits, {}, ""); + ApplyEdits(buffer, edits); +} + +String CopyNullTerminated(Allocator allocator, Buffer &buffer, Range range) { + String buffer_string = GetString(buffer, range); + String result = Copy(allocator, buffer_string); + return result; +} + +Line GetLine(Buffer &buffer, int64_t line) { + // :buffer_initialized + // @todo: do I enfore initialized state of the buffer + + // lines array maybe should always have something + Assert(buffer.lines.len); + + line = Clamp(line, (int64_t)0, buffer.lines.len - 1); + Range range = buffer.lines[line]; + Line result = {line, range}; + return result; +} + +Line FindLine(Buffer &buffer, int64_t pos) { + For(buffer.lines) { + // The program is doing '<= it.max' so as to include the new line. + // Otherwise this function wouldn't be able to find certain positions. + if (pos >= it.min && pos <= it.max) { + Line result = {buffer.lines.get_index(it), it}; + return result; + } + } + return {}; +} + +int64_t AdjustUTF8Pos(const Buffer &buffer, int64_t pos, int64_t direction = 1) { int64_t result = pos; - for (; result >= 0 && result < buffer->len;) { + for (; result >= 0 && result < buffer.len;) { char c = GetChar(buffer, pos); if (IsUTF8ContinuationByte(c)) { result += direction; @@ -206,13 +265,13 @@ int64_t AdjustUTF8Pos(Buffer *buffer, int64_t pos, int64_t direction = 1) { return result; } -uint32_t GetUTF32(Buffer *buffer, int64_t pos, int64_t *codepoint_size) { +uint32_t GetUTF32(Buffer &buffer, int64_t pos, int64_t *codepoint_size) { if (!InBounds(buffer, pos)) { return 0; } char *p = GetCharP(buffer, pos); - int64_t max = buffer->len - pos; + int64_t max = buffer.len - pos; UTF32Result utf32 = UTF8ToUTF32(p, (int)max); Assert(utf32.error == 0); @@ -245,8 +304,8 @@ bool IsValid(const BufferIter &iter) { } if (result) { - Assert(!IsUTF8ContinuationByte(GetChar(iter.buffer, iter.pos))); - Assert(InBounds(iter.buffer, iter.pos)); + Assert(!IsUTF8ContinuationByte(GetChar(*iter.buffer, iter.pos))); + Assert(InBounds(*iter.buffer, iter.pos)); } return result; } @@ -258,19 +317,19 @@ void Advance(BufferIter *iter) { if (iter->direction == ITERATE_FORWARD) { iter->pos += iter->utf8_codepoint_size; } else { - iter->pos = AdjustUTF8Pos(iter->buffer, iter->pos - 1, ITERATE_BACKWARD); + iter->pos = AdjustUTF8Pos(*iter->buffer, iter->pos - 1, ITERATE_BACKWARD); } if (!IsValid(*iter)) return; - iter->item = GetUTF32(iter->buffer, iter->pos, &iter->utf8_codepoint_size); + iter->item = GetUTF32(*iter->buffer, iter->pos, &iter->utf8_codepoint_size); } BufferIter Iterate(Buffer *buffer, Range range, int64_t direction = ITERATE_FORWARD) { Assert(direction == ITERATE_FORWARD || direction == ITERATE_BACKWARD); - Assert(!IsUTF8ContinuationByte(GetChar(buffer, range.min))); + Assert(!IsUTF8ContinuationByte(GetChar(*buffer, range.min))); Assert(range.max >= range.min); - range.min = Clamp(buffer, range.min); - range.max = Clamp(buffer, range.max); + range.min = Clamp(*buffer, range.min); + range.max = Clamp(*buffer, range.max); BufferIter result = {buffer, range.min, range.max, direction}; if (direction == ITERATE_BACKWARD) { @@ -292,12 +351,20 @@ void RunBufferTests() { String string = {buffer.data[buffer.bi], buffer.len}; Assert(string == "Things and other things"); Assert(buffer.lines.len == 1); - Assert(GetString(&buffer, buffer.lines[0]) == "Things and other things"); + Assert(GetString(buffer, buffer.lines[0]) == "Things and other things"); edits.clear(); - AddEdit(&edits, {1000, 1000}, " memes"); + AddEdit(&edits, GetEnd(buffer), " memes"); ApplyEdits(&buffer, edits); - Assert(GetString(&buffer, buffer.lines[0]) == "Things and other things memes"); + Assert(GetString(buffer, buffer.lines[0]) == "Things and other things memes"); + } + { + Buffer buffer = {scratch}; + Array edits = {scratch}; + edits.add({}); + ApplyEdits(&buffer, edits); + Assert("" == GetString(buffer)); + Assert(buffer.lines.len == 1); } { Buffer buffer = {scratch}; @@ -317,7 +384,7 @@ void RunBufferTests() { String string = {buffer.data[buffer.bi], buffer.len}; Assert(string == "Memes dna BigOther things"); Assert(buffer.lines.len == 1); - Assert(GetString(&buffer, buffer.lines[0]) == "Memes dna BigOther things"); + Assert(GetString(buffer, buffer.lines[0]) == "Memes dna BigOther things"); } { Buffer buffer = {scratch}; @@ -329,9 +396,9 @@ void RunBufferTests() { }); ApplyEdits(&buffer, edits); Assert(buffer.lines.len == 3); - Assert(GetString(&buffer, buffer.lines[1]) == "Things and other things"); - Assert(GetString(&buffer, buffer.lines[0]) == "Things and other things"); - Assert(GetString(&buffer, buffer.lines[2]) == ""); + Assert(GetString(buffer, buffer.lines[1]) == "Things and other things"); + Assert(GetString(buffer, buffer.lines[0]) == "Things and other things"); + Assert(GetString(buffer, buffer.lines[2]) == ""); { Array s = {scratch}; @@ -361,7 +428,7 @@ void RunBufferTests() { s.add((char)iter.item); } String str = {s.data, s.len}; - String b = {GetCharP(&buffer, 0), buffer.len}; + String b = {GetCharP(buffer, 0), buffer.len}; Assert(str == b); } { @@ -372,7 +439,7 @@ void RunBufferTests() { s.add((char)iter.item); } String str = {s.data, s.len}; - String b = {GetCharP(&buffer, 0), buffer.len}; + String b = {GetCharP(buffer, 0), buffer.len}; Assert(str.len == b.len); } } @@ -391,11 +458,28 @@ void RunBufferTests() { for (int i = 0; i < iters; i += 1) { ApplyEdits(&buffer, edits); for (int64_t j = 0; j < i; j += 1) { - String string = GetString(&buffer, {edits[0].string.len * j, edits[0].string.len * (j + 1)}); + String string = GetString(buffer, {edits[0].string.len * j, edits[0].string.len * (j + 1)}); Assert(string == edits[0].string); } } Assert(edits[0].string.len * iters == buffer.len); Assert(buffer.lines.len == iters * 2 + 1); + + Line l0 = FindLine(buffer, 4); + Assert(l0.number == 0); + Assert(l0.range.min == 0); + Assert(l0.range.max < 30); + + Line l1 = FindLine(buffer, 30); + Assert(l1.number == 1); + Assert(l1.range.min > 20); + Assert(l1.range.max < 50); + Assert(l1.range.max == GetLine(buffer, 1).range.max); + + // Make sure there are no gaps + for (int64_t i = 100; i < 600; i += 1) { + Line l2 = FindLine(buffer, i); + Assert(l2.number > 0); + } } } \ No newline at end of file diff --git a/src/text_editor/main.cpp b/src/text_editor/main.cpp index 5140697..5ff3462 100644 --- a/src/text_editor/main.cpp +++ b/src/text_editor/main.cpp @@ -1,16 +1,23 @@ #define BASIC_IMPL -#include "../pdf_browser/basic.h" +#include "../basic/basic.h" #include "raylib.h" #include "raymath.h" #include "buffer.cpp" +Arena FrameArena; + using Vec2 = Vector2; struct Rect2 { Vec2 min; Vec2 max; }; +Vec2 GetSize(Rect2 r) { + Vec2 result = {r.max.x - r.min.x, r.max.y - r.min.y}; + return result; +} + Rectangle ToRectangle(Rect2 r) { Rectangle result = {r.min.x, r.min.y, r.max.x - r.min.x, r.max.y - r.min.y}; return result; @@ -19,12 +26,21 @@ Rectangle ToRectangle(Rect2 r) { // Render units - positions ready to draw, y // World units - positions offset by screen movement // Window units - positions inside the window (starts in left top of window) -// World window units +// WindowWorld units - positions offset by a position inside the buffer struct Window { Rect2 rect_in_world_units; + Vec2 window_world_to_window_units; + + Array cursors; + Buffer buffer; }; +Vec2 WindowWorldToWindowUnits(Vec2 value, const Window &window) { + Vec2 result = Vector2Subtract(value, window.window_world_to_window_units); + return result; +} + Vec2 WorldToRenderUnits(Vec2 value, Vec2 camera_offset_world_to_render_units) { Vec2 result = Vector2Subtract(value, camera_offset_world_to_render_units); return result; @@ -47,15 +63,22 @@ int main() { InitScratch(); RunBufferTests(); - return 0; InitWindow(800, 600, "Hello"); SetTargetFPS(60); + InitArena(&FrameArena); float font_size = 14; float font_spacing = 1; Font font = LoadFontEx("C:/Windows/Fonts/consola.ttf", (int)font_size, NULL, 250); - Array buffer = {}; + Buffer buffer = {}; + InitBuffer(&buffer); + for (int i = 0; i < 100; i += 1) { + Array edits = {FrameArena}; + AddEdit(&edits, GetEnd(buffer), Format(FrameArena, "line number: %d\n", i)); + ApplyEdits(&buffer, edits); + } + Array windows = {}; windows.add({GetScreenRectRenderUnits()}); @@ -64,38 +87,80 @@ int main() { if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) || IsKeyDown(KEY_SPACE)) { camera_offset_world_to_render_units = Vector2Subtract(camera_offset_world_to_render_units, GetMouseDelta()); } + { + Window *focused_window = &windows[0]; + float mouse_wheel = GetMouseWheelMove() * 48; + focused_window->window_world_to_window_units.y -= mouse_wheel; + } for (int c = GetCharPressed(); c; c = GetCharPressed()) { - Assert(c >= ' ' && c <= '~'); - buffer.add((char)c); + String string = "?"; + UTF8Result utf8 = UTF32ToUTF8((uint32_t)c); + if (utf8.error == 0) { + string = {(char *)utf8.out_str, (int64_t)utf8.len}; + } + + Array edits = {FrameArena}; + AddEdit(&edits, {}, string); + ApplyEdits(&buffer, edits); } BeginDrawing(); ClearBackground(RAYWHITE); For(windows) { - Rect2 rect_in_render_units = { + 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), }; - Rectangle rectangle_in_render_units = ToRectangle(rect_in_render_units); + Rectangle rectangle_in_render_units = ToRectangle(window_rect_in_render_units); DrawRectangleRec(rectangle_in_render_units, WHITE); - { - Vec2 text_position_in_window_units = {}; - 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); - DrawTextEx(font, "window 1", text_position_in_render_units, font_size, font_spacing, BLACK); - } + // @todo: add window bar? + // { + // Vec2 text_position_in_window_units = {}; + // 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); + // DrawTextEx(font, "window 1", text_position_in_render_units, font_size, font_spacing, BLACK); + // } + // + // Line rendering + // { - Vec2 text_position_in_window_units = {0, font_size}; - 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); + 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); - buffer.add('\0'); - DrawTextEx(font, buffer.data, text_position_in_render_units, font_size, font_spacing, BLACK); - buffer.pop(); + Vec2 s = GetSize(window_rect_in_render_units_clamped_to_screen); + + // buffer_pixel_size := GetRectSize(text_window_rect); + // _miny := w.scroll.y / Monosize.y; + // _maxy := (w.scroll.y + buffer_pixel_size.y) / Monosize.y; + + // _minx := w.scroll.x / Monosize.x; + // _maxx := (w.scroll.x + buffer_pixel_size.x) / Monosize.x; + + // miny := :int(floorf(_miny)); + // minx := :int(floorf(_minx)); + + // 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); + } } } diff --git a/src/pdf_browser/read_pdf.py b/src/text_editor/read_pdf.py similarity index 100% rename from src/pdf_browser/read_pdf.py rename to src/text_editor/read_pdf.py diff --git a/src/transcript_browser/main.cpp b/src/transcript_browser/main.cpp index cfa8e72..96364b9 100644 --- a/src/transcript_browser/main.cpp +++ b/src/transcript_browser/main.cpp @@ -10,6 +10,14 @@ Arena Perm; +/* New threading model idea +I could just spin up a bunch of threads and then +don't kill them. Just use them for searching! Each +one would have it's own xarena and so on. + + +*/ + struct TimeString { uint16_t hour; uint16_t minute;