summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-04-26 05:51:35 +0200
committerMitya Selivanov <automainint@guattari.tech>2025-04-26 05:51:35 +0200
commitba9fa367c824b515a66e28368ccf24757f02db93 (patch)
tree2621419c9d2546c8eaa149f9d6e49374d8564ded
parent7322f1c5e94d6b4ceef742636fe8233b53b08347 (diff)
downloadreduced_system_layer-ba9fa367c824b515a66e28368ccf24757f02db93.zip
UTF-16; Refactor dynamic libraries loading
-rw-r--r--graphics.c35
-rw-r--r--runtime.c317
2 files changed, 204 insertions, 148 deletions
diff --git a/graphics.c b/graphics.c
index 208d29a..02a0e63 100644
--- a/graphics.c
+++ b/graphics.c
@@ -589,8 +589,8 @@ b8 hit_line(vec2 vertices[2], f64 width, vec2 point) {
tx /= tl;
ty /= tl;
}
- tx *= width * .5;
- ty *= width * .5;
+ tx *= width * 0.5;
+ ty *= width * 0.5;
return hit_quad((vec2[4]) {
{ x0 - tx, y0 - ty },
@@ -890,7 +890,7 @@ static b8 quad_from_line_(vec2 *dst, vec2 vertices[2], f64 width) {
if (tl < EPSILON)
return 0;
- f64 k = .5 / tl;
+ f64 k = 0.5 / tl;
tx *= width * k;
ty *= width * k;
@@ -1365,7 +1365,7 @@ void draw_text_cursor_to_buffer(Pixel_Buffer dst, i32 font, vec4_f32 color, Box
(Box) {
.x = area.x + kx * cursor_x,
.y = area.y + ky * cursor_y - ky * LCD_Height,
- .width = kx * .5,
+ .width = kx * 0.5,
.height = ky * (LCD_Height - 1),
}
);
@@ -1694,10 +1694,10 @@ static Box graphics_request_area_(Graphics_Request req) {
static Graphics_Request_Norm_ normalize_graphics_request_(Graphics_Request req) {
Box area = graphics_request_area_(req);
- i64 x = (i64) floor(area.x - .5);
- i64 y = (i64) floor(area.y - .5);
- i64 w = (i64) ceil (area.x + area.width + .5) - x;
- i64 h = (i64) ceil (area.y + area.height + .5) - y;
+ i64 x = (i64) floor(area.x - 0.5);
+ i64 y = (i64) floor(area.y - 0.5);
+ i64 w = (i64) ceil (area.x + area.width + 0.5) - x;
+ i64 h = (i64) ceil (area.y + area.height + 0.5) - y;
return (Graphics_Request_Norm_) {
.req = graphics_request_moved_(req, (vec2) { -x, -y }),
@@ -2454,6 +2454,21 @@ TEST("rectangle aliasing") {
(Box) { .x = 7.4, .y = 4.4, .width = 1.2, .height = 1.2, }
);
+ fill_rectangle_to_buffer(
+ (Pixel_Buffer) { .width = w, .height = h, .stride = w, .pixels = pixels },
+ (vec4_f32) { 1.0f, 1.0f, 1.0f, 1.0f, },
+ (Box) { .x = 7.44, .y = 6.51, .width = 1.07, .height = 1.991, }
+ );
+
+ // printf("\n");
+ // for (i64 j = 0; j < h; ++j) {
+ // for (i64 i = 0; i < w; ++i) {
+ // printf(" %c", pixels[j * w + i].x > 0.5 ? 'x' : '.');
+ // }
+ // printf("\n");
+ // }
+ // printf("\n");
+
b8 expect_bits[100] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
@@ -2462,8 +2477,8 @@ TEST("rectangle aliasing") {
0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
diff --git a/runtime.c b/runtime.c
index 06cc828..620e6ef 100644
--- a/runtime.c
+++ b/runtime.c
@@ -44,15 +44,6 @@
// To-Do list
//
// - Work in progress
-// - Graphics perf - request cache
-// Requires:
-// + [x] Graphics tests
-// + [x] Graphics requests
-// + [x] Memory buffer allocator
-// + [x] Blake2 hash
-// + [x] Requests cache
-// + [x] Global anti-aliasing
-// + [x] Fill triangles
// - Examples
// - Conway's Game of Life
// - Julia Set
@@ -133,7 +124,7 @@
// - Graph
// - Sine Wave
// - Utility
-// - UTF-8
+// - UTF-8, UTF-16
// - Testing
// - Stackless coroutines
// - Allocator
@@ -286,6 +277,7 @@ typedef unsigned short u16;
typedef unsigned u32;
typedef unsigned long long u64;
typedef char c8;
+typedef short c16;
typedef int c32;
typedef unsigned char b8;
typedef float f32;
@@ -604,6 +596,11 @@ typedef struct {
} UTF8_Char;
typedef struct {
+ c32 code;
+ i8 len;
+} UTF16_Char;
+
+typedef struct {
u16 protocol;
u16 port;
union {
@@ -672,10 +669,15 @@ typedef struct {
} Platform;
// UTF-8
-i8 utf8_size (c32 c);
+i8 utf8_len (c32 c);
UTF8_Char utf8_read (i64 len, c8 *s);
i8 utf8_write(c32 c, c8 *buffer);
+// UTF-16
+i8 utf16_len (c32 c);
+UTF16_Char utf16_read (i64 len, c16 *s);
+i8 utf16_write(c32 c, c16 *buffer);
+
// Time and sleep
i64 current_utc_time_in_milliseconds(void);
void current_utc_time_in_sec_and_nsec(i64 *seconds, i64 *nanoseconds);
@@ -1269,11 +1271,11 @@ i32 blake2b(u8 *out, void *in, void *key, u8 outlen, u64 inlen, u8 keylen) {
// ================================================================
//
-// UTF-8
+// Unicode
//
// ================================================================
-i8 utf8_size(c32 c) {
+i8 utf8_len(c32 c) {
if ((c & 0x00007f) == c) return 1;
if ((c & 0x0007ff) == c) return 2;
if ((c & 0x00ffff) == c) return 3;
@@ -1282,13 +1284,13 @@ i8 utf8_size(c32 c) {
}
UTF8_Char utf8_read(i64 len, c8 *s) {
- if (len >= 1 &&
+ if ( len >= 1 &&
(s[0] & 0x80) == 0)
return (UTF8_Char) {
.code = s[0],
.len = 1,
};
- if (len >= 2 &&
+ if ( len >= 2 &&
(s[0] & 0xe0) == 0xc0 &&
(s[1] & 0xc0) == 0x80)
return (UTF8_Char) {
@@ -1296,7 +1298,7 @@ UTF8_Char utf8_read(i64 len, c8 *s) {
| ((s[0] & 0x1f) << 6),
.len = 2,
};
- if (len >= 3 &&
+ if ( len >= 3 &&
(s[0] & 0xf0) == 0xe0 &&
(s[1] & 0xc0) == 0x80 &&
(s[2] & 0xc0) == 0x80)
@@ -1306,7 +1308,7 @@ UTF8_Char utf8_read(i64 len, c8 *s) {
| ((s[0] & 0x0f) << 12),
.len = 3,
};
- if (len >= 4 &&
+ if ( len >= 4 &&
(s[0] & 0xf8) == 0xf0 &&
(s[1] & 0xc0) == 0x80 &&
(s[2] & 0xc0) == 0x80 &&
@@ -1351,6 +1353,55 @@ i8 utf8_write(c32 c, c8 *buffer) {
return 0;
}
+i8 utf16_len(c32 c) {
+ // TODO: Testing.
+
+ if (c >= 0x000000 && c <= 0x00d7ff) return 1;
+ if (c >= 0x00e000 && c <= 0x00ffff) return 1;
+ if (c >= 0x010000 && c <= 0x10ffff) return 2;
+ return 0;
+}
+
+UTF16_Char utf16_read(i64 len, c16 *s) {
+ // TODO: Testing.
+
+ if ( len >= 1 &&
+ (s[0] & 0x8000) == 0)
+ return (UTF16_Char) {
+ .code = s[0],
+ .len = 1,
+ };
+ if ( len >= 2 &&
+ (s[0] & 0xfc00) == 0xd800 &&
+ (s[1] & 0xfc00) == 0xdc00)
+ return (UTF16_Char) {
+ .code = 0x10000
+ + ( (s[1] & 0x3ff)
+ | ((s[0] & 0x3ff) << 10)),
+ .len = 2,
+ };
+ return (UTF16_Char) {0};
+}
+
+i8 utf16_write(c32 c, c16 *buffer) {
+ // TODO: Testing.
+
+ if ((c >= 0x0000 && c <= 0xd7ff)
+ || (c >= 0xe000 && c <= 0xffff)) {
+ buffer[0] = (c16) c;
+ return 1;
+ }
+
+ if (c >= 0x010000 && c <= 0x10ffff) {
+ c32 cc = c - 0x10000;
+ buffer[0] = 0xd800 | ((cc >> 10) & 0x3ff);
+ buffer[1] = 0xdc00 | ( cc & 0x3ff);
+ return 2;
+ }
+
+ return 0;
+}
+
// ================================================================
//
// Colors
@@ -2159,95 +2210,79 @@ static void store_clipboard_text_(i64 size, c8 *data) {
// ================================================================
//
-// PLATFORM-SPECIFIC CODE
-//
-// ================================================================
-//
-// Dynamic libraries
+// UTF-16 buffer
//
// ================================================================
-typedef struct {
- void *handle;
-} Dynamic_Library_Slot_;
+static i64 _utf16_buffer_len = 0;
+static c16 *_utf16_buffer = NULL;
-typedef struct {
- i64 num_slots;
- Dynamic_Library_Slot_ *slots;
-} Dynamic_Libraries_;
+static void buffer_utf16_set_len_(i16 len) {
+ if (_utf16_buffer_len >= len)
+ return;
-static Dynamic_Libraries_ _dynamic_libraries = {0};
+ resize_dynamic_array_exact(&_utf16_buffer_len, (void **) &_utf16_buffer, sizeof *_utf16_buffer, _utf16_buffer_len);
+}
-#if defined(__unix__)
-#include <dlfcn.h>
+static c16 *buffer_utf16_empty_(void) {
+ buffer_utf16_set_len_(1);
+ if (_utf16_buffer != NULL && _utf16_buffer_len > 0)
+ _utf16_buffer[0] = '\0';
+ return _utf16_buffer;
+}
-void dynamic_library_open(u16 slot, c8 *name) {
- if (name == NULL) {
+static c16 *buffer_utf16_from_utf8_(c8 *s) {
+ if (s == NULL) {
LOG_error("Sanity");
- return;
- }
-
- if ((i64) (u64) slot >= _dynamic_libraries.num_slots)
- resize_dynamic_array_exact(&_dynamic_libraries.num_slots, (void **) &_dynamic_libraries.slots, sizeof *_dynamic_libraries.slots, (i64) slot + 1);
-
- if ((i64) (u64) slot >= _dynamic_libraries.num_slots) {
- LOG_error("Invalid slot: %d", (i32) slot);
- return;
+ return buffer_utf16_empty_();
}
- if (_dynamic_libraries.slots[slot].handle != NULL) {
- dlclose(_dynamic_libraries.slots[slot].handle);
- _dynamic_libraries.slots[slot].handle = NULL;
- }
+ c8 *s_end = s;
+ while (*s_end != '\0') ++s_end;
- void *h = dlopen(name, RTLD_LAZY);
+ i64 len = 0;
- if (h == NULL) {
- LOG_error("Failed to open: %s", name);
- LOG_error("%s", dlerror());
- return;
- }
+ for (c8 *a = s; a < s_end;) {
+ UTF8_Char c = utf8_read(s_end - a, a);
- _dynamic_libraries.slots[slot].handle = h;
-}
+ if (c.len == 0) {
+ LOG_error("Invalid UTF-8 string.");
+ return buffer_utf16_empty_();
+ }
-void *dynamic_library_get_proc_address(u16 slot, c8 *proc) {
- if ((i64) (u64) slot >= _dynamic_libraries.num_slots) {
- LOG_error("Invalid slot: %d", (i32) slot);
- return NULL;
- }
+ buffer_utf16_set_len_(len + 2);
+ i8 n = utf16_write(c.code, _utf16_buffer + len);
- if (proc == NULL) {
- LOG_error("Sanity");
- return NULL;
- }
+ if (n == 0) {
+ LOG_error("Unexpected UTF-16 character.");
+ return buffer_utf16_empty_();
+ }
- if (_dynamic_libraries.slots[slot].handle == NULL) {
- LOG_error("Slot is closed: %d", (i32) slot);
- return NULL;
+ len += n;
+ a += c.len;
}
- void *proc_address = dlsym(_dynamic_libraries.slots[slot].handle, proc);
+ buffer_utf16_set_len_(len + 1);
+ _utf16_buffer[len] = '\0';
- if (proc_address == NULL) {
- LOG_error("Failed to get proc: %s", proc);
- LOG_error("%s", dlerror());
- }
-
- return proc_address;
+ return _utf16_buffer;
}
-static void close_all_dynamic_libraries_(void) {
- for (i64 i = 0; i < _dynamic_libraries.num_slots; ++i)
- if (_dynamic_libraries.slots[i].handle != NULL)
- dlclose(_dynamic_libraries.slots[i].handle);
- resize_dynamic_array_exact(&_dynamic_libraries.num_slots, (void **) &_dynamic_libraries.slots, sizeof *_dynamic_libraries.slots, 0);
-}
+// ================================================================
+//
+// PLATFORM-SPECIFIC CODE
+//
+// ================================================================
+//
+// Dynamic libraries
+//
+// ================================================================
-#elif defined(_WIN32)
+#if defined(__unix__)
+#include <dlfcn.h>
+#endif
-// Windows definitions
-#if !defined(_INC_WINDOWS)
+#if defined(_WIN32) && !defined(_INC_WINDOWS)
#ifndef WINAPI
#if defined(_ARM_)
#define WINAPI
@@ -2256,18 +2291,30 @@ static void close_all_dynamic_libraries_(void) {
#endif
#endif
- typedef c8 const *LPCSTR;
- typedef void ** HMODULE;
- typedef int WINBOOL;
+ typedef c8 const *LPCSTR;
+ typedef c16 const *LPCWSTR;
+ typedef void ** HMODULE;
+ typedef int WINBOOL;
typedef iptr (WINAPI *FARPROC)();
// Kernel32.dll
- HMODULE WINAPI LoadLibraryA (LPCSTR lpLibFileName);
+ HMODULE WINAPI LoadLibraryW (LPCWSTR lpLibFileName);
WINBOOL WINAPI FreeLibrary (HMODULE hLibModule);
FARPROC WINAPI GetProcAddress (HMODULE hModule, LPCSTR lpProcName);
DWORD WINAPI GetLastError (void);
#endif
+typedef struct {
+ void *handle;
+} Dynamic_Library_Slot_;
+
+typedef struct {
+ i64 num_slots;
+ Dynamic_Library_Slot_ *slots;
+} Dynamic_Libraries_;
+
+static Dynamic_Libraries_ _dynamic_libraries = {0};
+
void dynamic_library_open(u16 slot, c8 *name) {
if (name == NULL) {
LOG_error("Sanity");
@@ -2283,16 +2330,30 @@ void dynamic_library_open(u16 slot, c8 *name) {
}
if (_dynamic_libraries.slots[slot].handle != NULL) {
+ #if defined(__unix__)
+ dlclose(_dynamic_libraries.slots[slot].handle);
+ #elif defined(_WIN32)
FreeLibrary((HMODULE) _dynamic_libraries.slots[slot].handle);
+ #endif
_dynamic_libraries.slots[slot].handle = NULL;
}
- void *h = (void *) LoadLibraryA(name);
+ void *h = NULL;
+
+ #if defined(__unix__)
+ h = dlopen(name, RTLD_LAZY);
+ #elif defined(_WIN32)
+ h = (void *) LoadLibraryW(buffer_utf16_from_utf8(name));
+ #endif
if (h == NULL) {
LOG_error("Failed to open: %s", name);
+
+ #if defined(__unix__)
LOG_error("%s", dlerror());
- return;
+ #elif defined(_WIN32)
+ LOG_error("Error code: %d", GetLastError());
+ #endif
}
_dynamic_libraries.slots[slot].handle = h;
@@ -2314,59 +2375,39 @@ void *dynamic_library_get_proc_address(u16 slot, c8 *proc) {
return NULL;
}
- void *proc_address = GetProcAddress((HMODULE) _dynamic_libraries.slots[slot].handle, proc);
+ void *proc_address = NULL;
- if (proc_address == NULL)
- LOG_error("Failed to get proc: %s (error code %d)", proc, GetLastError());
-
- return proc_address;
-}
-
-static void close_all_dynamic_libraries_(void) {
- for (i64 i = 0; i < _dynamic_libraries.num_slots; ++i)
- if (_dynamic_libraries.slots[i].handle != NULL)
- FreeLibrary((HMODULE) _dynamic_libraries.slots[i].handle);
- resize_dynamic_array_exact(&_dynamic_libraries.num_slots, (void **) &_dynamic_libraries.slots, sizeof *_dynamic_libraries.slots, 0);
-}
-
-#elif defined(__wasm__)
-
-void dynamic_library_open(u16 slot, c8 *name) {
- if (name == NULL) {
- LOG_error("Sanity");
- return;
- }
-
- (void) slot;
- (void) name;
-
- LOG_error("Dynamic library not found: %s", name);
-}
+ #if defined(__unix__)
+ proc_address = dlsym(_dynamic_libraries.slots[slot].handle, proc);
+ #elif defined(_WIN32)
+ proc_address = (void *) GetProcAddress((HMODULE) _dynamic_libraries.slots[slot].handle, proc);
+ #endif
-void *dynamic_library_get_proc_address(u16 slot, c8 *proc) {
- if ((i64) (u64) slot >= _dynamic_libraries.num_slots) {
- LOG_error("Invalid slot: %d", (i32) slot);
- return NULL;
- }
+ if (proc_address == NULL) {
+ LOG_error("Failed to get proc: %s", proc);
- if (proc == NULL) {
- LOG_error("Sanity");
- return NULL;
+ #if defined(__unix__)
+ LOG_error("%s", dlerror());
+ #elif defined(_WIN32)
+ LOG_error("Error code: %d", GetLastError());
+ #endif
}
- (void) slot;
- (void) proc;
-
- LOG_error("Proc address not found: %s", proc);
- return NULL;
+ return proc_address;
}
static void close_all_dynamic_libraries_(void) {
+ for (i64 i = 0; i < _dynamic_libraries.num_slots; ++i)
+ if (_dynamic_libraries.slots[i].handle != NULL) {
+ #if defined(__unix__)
+ dlclose(_dynamic_libraries.slots[i].handle);
+ #elif defined(_WIN32)
+ FreeLibrary((HMODULE) _dynamic_libraries.slots[i].handle);
+ #endif
+ }
resize_dynamic_array_exact(&_dynamic_libraries.num_slots, (void **) &_dynamic_libraries.slots, sizeof *_dynamic_libraries.slots, 0);
}
-#endif
-
// ================================================================
//
// Time
@@ -5135,13 +5176,13 @@ TEST("math sanity") {
}
TEST("utf8") {
- REQUIRE_EQ(utf8_size(1), 1);
- REQUIRE_EQ(utf8_size(127), 1);
- REQUIRE_EQ(utf8_size(128), 2);
- REQUIRE_EQ(utf8_size((1 << 11) - 1), 2);
- REQUIRE_EQ(utf8_size((1 << 11)), 3);
- REQUIRE_EQ(utf8_size((1 << 16) - 1), 3);
- REQUIRE_EQ(utf8_size((1 << 16)), 4);
+ REQUIRE_EQ(utf8_len(1), 1);
+ REQUIRE_EQ(utf8_len(127), 1);
+ REQUIRE_EQ(utf8_len(128), 2);
+ REQUIRE_EQ(utf8_len((1 << 11) - 1), 2);
+ REQUIRE_EQ(utf8_len((1 << 11)), 3);
+ REQUIRE_EQ(utf8_len((1 << 16) - 1), 3);
+ REQUIRE_EQ(utf8_len((1 << 16)), 4);
}
TEST("time sanity") {