summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rwxr-xr-xexamples/gravity.c17
-rwxr-xr-xexamples/rf64.c252
-rw-r--r--examples/test.c989
-rwxr-xr-xexamples/ui.c321
4 files changed, 2 insertions, 1577 deletions
diff --git a/examples/gravity.c b/examples/gravity.c
index 70f279f..8bc45e0 100755
--- a/examples/gravity.c
+++ b/examples/gravity.c
@@ -25,7 +25,7 @@ gcc \
exit $? # */
#endif
-#include "../reduced_system_layer.c"
+#include "../graphics.c"
typedef struct {
f64 x;
@@ -47,21 +47,6 @@ i64 time_milliseconds() {
return (i64) t.tv_sec * 1000ll + (i64) t.tv_nsec / 1000000ll;
}
-u32 u32_from_rgb(f32 red, f32 green, f32 blue) {
- i32 r = (i32) floor(red * 255.f);
- i32 g = (i32) floor(green * 255.f);
- i32 b = (i32) floor(blue * 255.f);
-
- if (r < 0) r = 0;
- if (r > 255) r = 255;
- if (g < 0) g = 0;
- if (g > 255) g = 255;
- if (b < 0) b = 0;
- if (b > 255) b = 255;
-
- return (r << 16) | (g << 8) | b;
-}
-
i32 main(i32 argc, c8 **argv) {
(void) argc;
(void) argv;
diff --git a/examples/rf64.c b/examples/rf64.c
deleted file mode 100755
index aeba85a..0000000
--- a/examples/rf64.c
+++ /dev/null
@@ -1,252 +0,0 @@
-#if 0 /*
-#/ ================================================================
-#/
-#/ rf64.c
-#/
-#/ Probabalistic floating-point numbers
-#/
-#/ ----------------------------------------------------------------
-#/
-#/ (C) 2024 Mitya Selivanov <guattari.tech>, MIT License
-#/
-#/ ================================================================
-#/
-#/ Self-compilation shell script
-#/
-SRC=${0##*./}
-BIN=${SRC%.*}
-gcc \
- -Wall -Wextra -Werror -pedantic \
- -Wno-old-style-declaration \
- -Wno-missing-braces \
- -Wno-unused-variable \
- -Wno-unused-but-set-variable \
- -Wno-unused-parameter \
- -Wno-overlength-strings \
- -O3 \
- -fsanitize=undefined,address,leak -mshstk \
- -D RF64_TESTS \
- -o $BIN $SRC && \
- ./$BIN $@ && rm $BIN
-exit $? # */
-#endif
-
-// ================================================================
-
-#ifndef TYPES_HEADER_GUARD_
-#define TYPES_HEADER_GUARD_
-
-typedef signed char i8;
-typedef signed short i16;
-typedef signed i32;
-typedef signed long long i64;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned u32;
-typedef unsigned long long u64;
-typedef char c8;
-typedef int c32;
-typedef signed char b8;
-typedef float f32;
-typedef double f64;
-
-#endif // TYPES_HEADER_GUARD_
-
-// ================================================================
-
-#ifndef RF64_HEADER_GUARD_
-#define RF64_HEADER_GUARD_
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-
-#ifndef RF64_RAND
-static i32 rf64_rand(i32 min, i32 max) {
- if (max <= min)
- return min;
- return min + (rand() % (max - min + 1));
-}
-
-#define RF64_RAND(min, max) rf64_rand((min), (max))
-#endif
-
-#define RF64_EXPONENT_NUM_BITS 30
-#define RF64_MANTISSA_NUM_BITS 32
-#define RF64_EXPONENT_ZERO (1 << (RF64_EXPONENT_NUM_BITS / 2))
-#define RF64_EXPONENT_MAX ((1 << RF64_EXPONENT_NUM_BITS) - 1)
-#define RF64_MANTISSA_MAX 0xffffffffu
-
-typedef struct {
- u32 infinity : 1;
- u32 sign : 1;
- i32 exponent : RF64_EXPONENT_NUM_BITS;
- u32 mantissa;
-} rf64;
-
-rf64 rf64_from_i64(i64 x);
-i64 i64_from_rf64(rf64 x);
-void rf64_inc(rf64 *x);
-void rf64_dec(rf64 *x);
-void rf64_add(rf64 *x, rf64 y);
-void rf64_sub(rf64 *x, rf64 y);
-void rf64_mul(rf64 *x, rf64 y);
-void rf64_div(rf64 *x, rf64 y);
-
-#endif // RF64_HEADER_GUARD_
-
-#ifndef RF64_HEADER
-#ifndef RF64_IMPL_GUARD_
-#define RF64_IMPL_GUARD_
-
-rf64 rf64_from_i64(i64 x) {
- rf64 z = {
- .sign = x < 0,
- .exponent = RF64_EXPONENT_ZERO,
- };
-
- u64 a = z.sign ? -x : x;
-
- while (a > RF64_MANTISSA_MAX) {
- u64 loss_comp = (a & 1) == 1 ? RF64_RAND(0, 1) : 0;
-
- z.exponent += 1;
-
- a /= 2;
- a += loss_comp;
- }
-
- z.mantissa = (u32) a;
-
- return z;
-}
-
-i64 i64_from_rf64(rf64 x) {
- assert(0);
-}
-
-void rf64_inc(rf64 *x) {
- assert(0);
-}
-
-void rf64_dec(rf64 *x) {
- assert(x != NULL);
- if (x == NULL) return;
-
- assert(0);
-}
-
-void rf64_add(rf64 *x, rf64 y) {
- assert(x != NULL);
- if (x == NULL) return;
-
- assert(0);
-}
-
-void rf64_sub(rf64 *x, rf64 y) {
- assert(x != NULL);
- if (x == NULL) return;
-
- assert(0);
-}
-
-void rf64_mul(rf64 *x, rf64 y) {
- assert(x != NULL);
- if (x == NULL) return;
-
- assert(0);
-}
-
-void rf64_div(rf64 *x, rf64 y) {
- assert(x != NULL);
- if (x == NULL) return;
-
- assert(0);
-}
-
-#ifdef RF64_TESTS
-
-#include <stdio.h>
-#include <string.h>
-
-void report_test(c8 *name, b8 success) {
- i32 l = 20 - (i32) strlen(name);
-
- printf("%s %.*s %s\n",
- name,
- l < 1 ? 1 : l,
- "....................",
- success ? "OK" : "FAIL"
- );
-}
-
-#define TEST_(x) report_test(#x, test_##x())
-
-b8 test_from_i64() {
- return 1
- && rf64_from_i64( 0 ).infinity == 0
- && rf64_from_i64( 0 ).sign == 0
- && rf64_from_i64( 0 ).exponent == RF64_EXPONENT_ZERO
- && rf64_from_i64( 0 ).mantissa == 0
- && rf64_from_i64( 42 ).infinity == 0
- && rf64_from_i64( 42 ).sign == 0
- && rf64_from_i64( 42 ).exponent == RF64_EXPONENT_ZERO
- && rf64_from_i64( 42 ).mantissa == 42
- && rf64_from_i64(-42 ).infinity == 0
- && rf64_from_i64(-42 ).sign == 1
- && rf64_from_i64(-42 ).exponent == RF64_EXPONENT_ZERO
- && rf64_from_i64(-42 ).mantissa == 42
- && rf64_from_i64( 0xffffffff ).infinity == 0
- && rf64_from_i64( 0xffffffff ).sign == 0
- && rf64_from_i64( 0xffffffff ).exponent == RF64_EXPONENT_ZERO
- && rf64_from_i64( 0xffffffff ).mantissa == 0xffffffff
- && rf64_from_i64(-0xffffffffll ).infinity == 0
- && rf64_from_i64(-0xffffffffll ).sign == 1
- && rf64_from_i64(-0xffffffffll ).exponent == RF64_EXPONENT_ZERO
- && rf64_from_i64(-0xffffffffll ).mantissa == 0xffffffff
- && rf64_from_i64( 0x100000000ll).infinity == 0
- && rf64_from_i64( 0x100000000ll).sign == 0
- && rf64_from_i64( 0x100000000ll).exponent == RF64_EXPONENT_ZERO + 1
- && rf64_from_i64( 0x100000000ll).mantissa == 0x80000000u
- && rf64_from_i64(-0x100000000ll).infinity == 0
- && rf64_from_i64(-0x100000000ll).sign == 1
- && rf64_from_i64(-0x100000000ll).exponent == RF64_EXPONENT_ZERO + 1
- && rf64_from_i64(-0x100000000ll).mantissa == 0x80000000u
- && 1;
-}
-
-b8 test_to_i64() {
- return 1
- && i64_from_rf64(rf64_from_i64( 0 )) == 0
- && i64_from_rf64(rf64_from_i64( 1 )) == 1
- && i64_from_rf64(rf64_from_i64(-1 )) == -1
- && i64_from_rf64(rf64_from_i64( 42 )) == 42
- && i64_from_rf64(rf64_from_i64(-42 )) == -42
- && i64_from_rf64(rf64_from_i64( 0xffffffff )) == 0xffffffff
- && i64_from_rf64(rf64_from_i64(-0xffffffff )) == -0xffffffff
- && i64_from_rf64(rf64_from_i64( 0x100000000ll )) == 0x100000000ll
- && i64_from_rf64(rf64_from_i64(-0x100000000ll )) == -0x100000000ll
- && i64_from_rf64(rf64_from_i64( 0x42000000000ll)) == 0x42000000000ll
- && i64_from_rf64(rf64_from_i64(-0x42000000000ll)) == -0x42000000000ll
- && 1;
-}
-
-i32 main(i32 argc, c8 **argv) {
- (void) argc;
- (void) argv;
-
- TEST_(from_i64);
- TEST_(to_i64);
-
- return 0;
-}
-
-#undef TEST_
-
-#endif // RF64_TESTS
-
-#endif // RF64_IMPL_GUARD_
-#endif // RF64_HEADER
diff --git a/examples/test.c b/examples/test.c
deleted file mode 100644
index c5e17bd..0000000
--- a/examples/test.c
+++ /dev/null
@@ -1,989 +0,0 @@
-// ================================================================
-//
-// test.c
-//
-// Unit-testing and microbenchmarks modular library for C
-//
-// ----------------------------------------------------------------
-//
-// Optional settings
-//
-// - MAX_NUM_TESTS
-// - MAX_NUM_TEST_ASSECTIONS
-// - MAX_NUM_BENCHS
-// - MAX_NUM_BENCH_REPEATS
-// - MAX_NUM_BENCH_CYCLES
-// - NUM_BENCH_REPEATS_DEFAULT_1
-// - NUM_BENCH_REPEATS_DEFAULT_2
-//
-// ----------------------------------------------------------------
-//
-// Usage
-//
-// - Define a unique TEST_FILE for each file to avoid name
-// collisions.
-//
-// Example
-//
-// // foo.test.c
-// #define TEST_FILE foo // This is required if you want to
-// // use multiple test files.
-// #define TEST_HEADER // Do not include the implementation.
-// #include "test.c"
-// TEST("foo") {
-// REQUIRE(1);
-// REQUIRE_EQ(2 + 2, 4);
-// }
-//
-// // main.c
-// #include "test.c"
-// int main(int argc, char **argv) {
-// return run_tests(argc, argv);
-// }
-//
-// ----------------------------------------------------------------
-//
-// (C) 2024 Mitya Selivanov <guattari.tech>, MIT License
-//
-// ================================================================
-
-#ifndef TYPES_HEADER_GUARD_
-#define TYPES_HEADER_GUARD_
-
-typedef signed char i8;
-typedef signed short i16;
-typedef signed i32;
-typedef signed long long i64;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned u32;
-typedef unsigned long long u64;
-typedef char c8;
-typedef int c32;
-typedef signed char b8;
-typedef float f32;
-typedef double f64;
-
-#endif // TYPES_HEADER_GUARD_
-
-// ================================================================
-
-#ifndef TEST_HEADER_GUARD_
-#define TEST_HEADER_GUARD_
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#ifdef __GNUC__
-# pragma GCC diagnostic ignored "-Wunused-value"
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifndef TEST_FILE
-#define TEST_FILE test
-#endif
-
-#ifndef MAX_NUM_TESTS
-#define MAX_NUM_TESTS 0x1000
-#endif
-
-#ifndef MAX_NUM_TEST_ASSECTIONS
-#define MAX_NUM_TEST_ASSECTIONS 0x50
-#endif
-
-#ifndef MAX_NUM_BENCHS
-#define MAX_NUM_BENCHS 200
-#endif
-
-#ifndef MAX_NUM_BENCH_REPEATS
-#define MAX_NUM_BENCH_REPEATS 4000
-#endif
-
-#ifndef MAX_NUM_BENCH_CYCLES
-#define MAX_NUM_BENCH_CYCLES 40
-#endif
-
-#ifndef NUM_BENCH_REPEATS_DEFAULT_1
-#define NUM_BENCH_REPEATS_DEFAULT_1 40
-#endif
-
-#ifndef NUM_BENCH_REPEATS_DEFAULT_2
-#define NUM_BENCH_REPEATS_DEFAULT_2 400
-#endif
-
-typedef void (*test_report_fn)(i32 test_index, i32 line, i64 value, i64 expected);
-typedef void (*test_run_fn) (i32 test_index_, test_report_fn test_report_fn_);
-
-typedef struct {
- c8 const *test_name;
- c8 const *test_file;
- test_run_fn test_fn;
- i32 assertions;
- i32 line [MAX_NUM_TEST_ASSECTIONS];
- i32 status [MAX_NUM_TEST_ASSECTIONS];
- i64 value [MAX_NUM_TEST_ASSECTIONS];
- i64 expected[MAX_NUM_TEST_ASSECTIONS];
- i32 signal;
-} Test_Case;
-
-typedef struct {
- i32 size;
- Test_Case v[MAX_NUM_TESTS];
-} Tests_List;
-
-extern Tests_List tests_list;
-
-#define TEST_CONCAT4_(a, b, c, d) a##b##c##d
-#define TEST_CONCAT3_(a, b, c) TEST_CONCAT4_(a, b, _, c)
-
-#ifdef __cplusplus
-# define TEST_ON_START_(f) \
- static void f(void); \
- static i32 TEST_CONCAT3_(_test_init_, __LINE__, f) = (f(), 0); \
- static void f(void)
-#else
-# ifdef _MSC_VER
-# pragma section(".CRT$XCU", read)
-# define TEST_ON_START_2_(f, p) \
- static void f(void); \
- __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
- __pragma(comment(linker, "/include:" p #f "_")) static void f(void)
-# ifdef _WIN64
-# define TEST_ON_START_(f) TEST_ON_START_2_(f, "")
-# else
-# define TEST_ON_START_(f) TEST_ON_START_2_(f, "_")
-# endif
-# else
-# define TEST_ON_START_(f) \
- static void f(void) __attribute__((constructor)); \
- static void f(void)
-# endif
-#endif
-
-void test_register(c8 const *name, c8 const *file, test_run_fn fn);
-
-#define TEST(name) \
- static void TEST_CONCAT3_(test_run_, TEST_FILE, __LINE__)(i32, test_report_fn); \
- TEST_ON_START_(TEST_CONCAT3_(test_case_, TEST_FILE, __LINE__)) { \
- test_register(name, __FILE__, TEST_CONCAT3_(test_run_, TEST_FILE, __LINE__)); \
- } \
- static void TEST_CONCAT3_(test_run_, TEST_FILE, __LINE__) \
- (i32 test_index_, test_report_fn test_report_fn_)
-
-#define REQUIRE(...) test_report_fn_(test_index_, __LINE__, (__VA_ARGS__), 1)
-#define REQUIRE_EQ(...) test_report_fn_(test_index_, __LINE__, __VA_ARGS__)
-
-i32 run_tests(i32 argc, c8 **argv);
-
-// ================================================================
-
-typedef void (*bench_set_repeats_limit_fn)(i32 bench_index, i32 repeats_limit);
-typedef i32 (*bench_loop_fn) (i32 bench_index);
-typedef void (*bench_begin_fn) (i32 bench_index);
-typedef void (*bench_end_fn) (i32 bench_index);
-
-typedef void (*bench_run_fn)(
- i32 bench_index_,
- bench_set_repeats_limit_fn bench_set_repeats_limit_,
- bench_loop_fn bench_loop_,
- bench_begin_fn bench_begin_,
- bench_end_fn bench_end_
-);
-
-typedef struct {
- c8 const *bench_name;
- c8 const *bench_file;
- bench_run_fn bench_fn;
- i64 sec [MAX_NUM_BENCH_REPEATS];
- i32 nsec [MAX_NUM_BENCH_REPEATS];
- i64 duration_nsec [MAX_NUM_BENCH_REPEATS];
- i64 duration_sorted_nsec[MAX_NUM_BENCH_REPEATS];
- i32 repeats;
- i32 cycles_size;
- i32 cycles[MAX_NUM_BENCH_CYCLES];
- i32 cycle;
- i32 signal;
- i32 ready;
-} Benchmark;
-
-typedef struct {
- i32 size;
- Benchmark v[MAX_NUM_BENCHS];
-} Benchs_List;
-
-extern Benchs_List benchs_list;
-
-void bench_register(c8 const *name, c8 const *file, bench_run_fn fn);
-
-#define BENCHMARK(name) \
- static void TEST_CONCAT3_(bench_run_, TEST_FILE, __LINE__) \
- (i32, bench_set_repeats_limit_fn, bench_loop_fn, bench_begin_fn, bench_end_fn); \
- TEST_ON_START_(TEST_CONCAT3_(benchmark_, TEST_FILE, __LINE__)) { \
- bench_register(name, __FILE__, TEST_CONCAT3_(bench_run_, TEST_FILE, __LINE__)); \
- } \
- static void TEST_CONCAT3_(bench_run_, TEST_FILE, __LINE__)( \
- i32 bench_index_, \
- bench_set_repeats_limit_fn bench_set_repeats_limit_, \
- bench_loop_fn bench_loop_, \
- bench_begin_fn bench_begin_, \
- bench_end_fn bench_end_ \
- )
-
-#define BENCHMARK_REPEAT(repeats_limit_) \
- bench_set_repeats_limit_(bench_index_, repeats_limit_)
-
-#define BENCHMARK_BEGIN \
- while (bench_loop_(bench_index_)) { \
- bench_begin_(bench_index_); {
-
-#define BENCHMARK_END \
- } bench_end_(bench_index_); }
-
-// FIXME
-// Does this work reliably?
-//
-#define DO_NOT_OPTIMIZE(x) \
- do { \
- volatile void *bench_ptr_ = &(x); \
- (void) bench_ptr_; \
- } while (0)
-
-i32 run_benchmarks(i32 argc, c8 **argv);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // TEST_HEADER_GUARD_
-
-// ================================================================
-//
-// Implementation
-//
-// ================================================================
-
-#ifndef TEST_HEADER
-#ifndef TEST_IMPL_GUARD_
-#define TEST_IMPL_GUARD_
-
-#include <setjmp.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-enum {
- white_,
- blue_,
- light_,
- yellow_,
- red_,
- green_
-};
-
-static c8 const *color_codes_[] = {
- "\x1b[38m", "\x1b[34m",
- "\x1b[37m", "\x1b[33m",
- "\x1b[31m", "\x1b[32m"
-};
-
-static i32 print_color_(i32 c) {
- return printf("%s", color_codes_[c]);
-}
-
-static i32 signums_[] = { SIGINT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTERM };
-
-static c8 const *signames_[64];
-
-static void signames_init_(void) {
- memset(signames_, 0, sizeof signames_);
- signames_[SIGINT] = "Interactive attention signal";
- signames_[SIGILL] = "Illegal instruction";
- signames_[SIGABRT] = "Abnormal termination";
- signames_[SIGFPE] = "Erroneous arithmetic operation";
- signames_[SIGSEGV] = "Invalid access to storage";
- signames_[SIGTERM] = "Termination request";
-}
-
-Tests_List tests_list = { 0 };
-
-static void report_(i32 i, i32 line, i64 value, i64 expected) {
- i32 n = tests_list.v[i].assertions++;
-
- if (n >= MAX_NUM_TEST_ASSECTIONS)
- return;
-
- tests_list.v[i].line[n] = line;
- tests_list.v[i].status[n] = value == expected;
- tests_list.v[i].value[n] = value;
- tests_list.v[i].expected[n] = expected;
-}
-
-static i64 ns_to_ms(i64 ns) {
- return (ns + 500000) / 1000000;
-}
-
-static i64 sec_to_ms(int64_t sec) {
- return 1000 * sec;
-}
-
-void test_register(c8 const *name, c8 const *file, test_run_fn fn) {
- i32 n = tests_list.size++;
- if (n < MAX_NUM_TESTS) {
- tests_list.v[n].test_fn = fn;
- tests_list.v[n].test_name = name;
- tests_list.v[n].test_file = file;
- tests_list.v[n].assertions = 0;
- }
-}
-
-static jmp_buf test_restore_execution;
-
-static void test_handle_signal(i32 signum) {
- longjmp(test_restore_execution, signum);
-}
-
-static void test_setup_signals() {
- for (u32 i = 0; i < sizeof signums_ / sizeof *signums_; i++)
- signal(signums_[i], test_handle_signal);
-}
-
-static i32 run_test_(volatile i32 i) {
- i32 signum = setjmp(test_restore_execution);
-
- if (signum != 0) {
- tests_list.v[i].signal = signum;
- return 0;
- }
-
- tests_list.v[i].test_fn(i, report_);
- return 1;
-}
-
-i32 run_tests(i32 argc, c8 **argv) {
- signames_init_();
-
- i32 success_count = 0;
- i32 fail_assertion_count = 0;
- i32 total_assertion_count = 0;
- i32 status = 0;
- i32 quiet = 0;
- i32 no_color = 0;
- i32 line_width = 20;
- i32 carriage_return = 1;
-
- i32 i, j;
-
- c8 const *specific_test = NULL;
-
- test_setup_signals();
-
- for (i = 0; i < argc; i++)
- if (strcmp("--no-term-color", argv[i]) == 0)
- no_color = 1;
- else if (strcmp("--no-carriage-return", argv[i]) == 0)
- carriage_return = 0;
- else if (strcmp("--quiet", argv[i]) == 0)
- quiet = 1;
- else if (strcmp("--match", argv[i]) == 0)
- specific_test = argv[++i];
-
- quiet && (no_color = 1);
-
- if (specific_test != NULL) {
- no_color || print_color_(light_);
- quiet || printf("Run tests matching ");
- no_color || print_color_(white_);
- quiet || printf("*%s*", specific_test);
- no_color || print_color_(light_);
- quiet || printf("\n\n");
- }
-
- c8 const *file = NULL;
- i64 file_root = -1;
- i32 tests_total = 0;
-
- for (i = 0; i < tests_list.size && i < MAX_NUM_TESTS;
- i++) {
- if (specific_test != NULL &&
- strstr(tests_list.v[i].test_name, specific_test) == NULL)
- continue;
- tests_total++;
- i32 l = 2 + (int) strlen(tests_list.v[i].test_name);
- if (line_width < l)
- line_width = l;
- }
-
- if (tests_total > 0) {
- c8 const *s = tests_list.v[0].test_file;
-
- for (j = 1; j < tests_list.size && j < MAX_NUM_TESTS;
- j++) {
- if (specific_test != NULL &&
- strstr(tests_list.v[j].test_name, specific_test) ==
- NULL)
- continue;
- if (strcmp(s, tests_list.v[j].test_file) == 0)
- continue;
- i32 k = 0;
- for (;
- s[k] != '\0' && tests_list.v[j].test_file[k] != '\0' &&
- s[k] == tests_list.v[j].test_file[k];
- k++) { }
- if (file_root == -1 || file_root > k)
- file_root = k;
- }
-
- if (file_root == -1) {
- for (i = 0; s[i] != '\0'; i++)
- if (s[i] == '/' || s[i] == '\\')
- file_root = i + 1;
- }
- }
-
- for (i = 0; i < tests_list.size && i < MAX_NUM_TESTS; i++) {
- if (specific_test != NULL && strstr(tests_list.v[i].test_name, specific_test) == NULL)
- continue;
- if (file == NULL || strcmp(file, tests_list.v[i].test_file) != 0) {
- if (file != NULL)
- quiet || printf("\n");
- file = tests_list.v[i].test_file;
- no_color || print_color_(blue_);
- quiet || printf("* ");
- no_color || print_color_(white_);
- quiet || printf("%s\n", file + file_root);
- }
-
- !carriage_return || no_color || print_color_(yellow_);
- carriage_return || no_color || print_color_(light_);
- quiet || printf("` %s ", tests_list.v[i].test_name);
- !carriage_return || quiet || printf("\r");
- quiet || fflush(stdout);
-
- struct timespec begin, end;
- timespec_get(&begin, TIME_UTC);
-
- i32 test_status = run_test_(i);
-
- timespec_get(&end, TIME_UTC);
- i32 duration = (i32) (ns_to_ms(end.tv_nsec - begin.tv_nsec) + sec_to_ms(end.tv_sec - begin.tv_sec));
-
- for (j = 0; j < tests_list.v[i].assertions && j < MAX_NUM_TEST_ASSECTIONS; j++)
- if (tests_list.v[i].status[j] == 0) {
- fail_assertion_count++;
- test_status = 0;
- }
-
- if (tests_list.v[i].assertions > MAX_NUM_TEST_ASSECTIONS)
- test_status = 0;
-
- total_assertion_count += tests_list.v[i].assertions;
-
- !carriage_return || no_color || print_color_(light_);
- !carriage_return || quiet || printf("` %s ", tests_list.v[i].test_name);
-
- i32 l = (i32) strlen(tests_list.v[i].test_name);
- quiet || printf("%*c", line_width - l, ' ');
-
- if (test_status == 0) {
- no_color || print_color_(red_);
- quiet || printf("FAIL");
- no_color || print_color_(light_);
- duration == 0 || quiet || printf(" %d ms", duration);
- quiet || printf("\n");
- status = 1;
- } else {
- no_color || print_color_(green_);
- quiet || printf("OK");
- no_color || print_color_(light_);
- duration == 0 || quiet || printf(" %d ms", duration);
- quiet || printf("\n");
- success_count++;
- }
-
- quiet || fflush(stdout);
- }
-
- no_color || print_color_(white_);
- quiet || printf("\n%d of %d tests passed.\n", success_count, tests_total);
- quiet || printf("%d of %d assertions passed.\n\n", total_assertion_count - fail_assertion_count, total_assertion_count);
- no_color || print_color_(light_);
-
- if (!quiet && status != 0) {
- i32 have_report_s = 0;
-
- for (i = 0; i < tests_list.size && i < MAX_NUM_TESTS; i++) {
- if (specific_test != NULL && strstr(tests_list.v[i].test_name, specific_test) == NULL)
- continue;
- if (tests_list.v[i].signal != 0) {
- i32 signum = tests_list.v[i].signal;
- if (signum >= 0 && signum < (int) (sizeof signames_ / sizeof *signames_) && signames_[signum] != NULL) {
- no_color || print_color_(light_);
- printf("Signal \"%s\" (%d) for \"", signames_[signum], signum);
- no_color || print_color_(white_);
- printf("%s", tests_list.v[i].test_name);
- no_color || print_color_(light_);
- printf("\" in \"");
- no_color || print_color_(white_);
-
- printf("%s", tests_list.v[i].test_file + file_root);
- no_color || print_color_(light_);
- printf("\"!\n");
- } else {
- no_color || print_color_(light_);
- printf("Unknown signal (%d) for \"", signum);
- no_color || print_color_(white_);
- printf("%s", tests_list.v[i].test_name);
- no_color || print_color_(light_);
- printf("\" in \"");
- no_color || print_color_(white_);
- printf("%s", tests_list.v[i].test_file + file_root);
- no_color || print_color_(light_);
- printf("\"!\n");
- }
- have_report_s = 1;
- }
- if (tests_list.v[i].assertions >
- MAX_NUM_TEST_ASSECTIONS) {
- no_color || print_color_(light_);
- printf("Too many assertions for \"");
- no_color || print_color_(white_);
- printf("%s", tests_list.v[i].test_name);
- no_color || print_color_(light_);
- printf("\" in \"");
- no_color || print_color_(white_);
- printf("%s", tests_list.v[i].test_file + file_root);
- no_color || print_color_(light_);
- printf("\"!\n");
- have_report_s = 1;
- }
- }
-
- have_report_s && printf("\n");
- }
-
- if (!quiet && status != 0) {
- for (i = 0; i < tests_list.size && i < MAX_NUM_TESTS; i++) {
- if (specific_test != NULL && strstr(tests_list.v[i].test_name, specific_test) == NULL)
- continue;
-
- if (tests_list.v[i].assertions <= MAX_NUM_TEST_ASSECTIONS)
- for (j = 0; j < tests_list.v[i].assertions; j++)
- if (!tests_list.v[i].status[j]) {
- no_color || print_color_(light_);
- printf("Assertion on line ");
- no_color || print_color_(white_);
- printf("%d", tests_list.v[i].line[j]);
- no_color || print_color_(light_);
- printf(" in \"");
- no_color || print_color_(white_);
- printf("%s", tests_list.v[i].test_file + file_root);
- no_color || print_color_(light_);
- printf("\" failed.\n");
- no_color || print_color_(red_);
- printf(" -> ");
- no_color || print_color_(light_);
- printf("Got wrong value ");
- no_color || print_color_(white_);
- printf("%10lld", (i64) tests_list.v[i].value[j]);
- no_color || print_color_(light_);
- printf(" (");
- no_color || print_color_(white_);
- printf("0x%08llx", (u64) tests_list.v[i].value[j]);
- no_color || print_color_(light_);
- printf(")\n");
- no_color || print_color_(green_);
- printf(" -> ");
- no_color || print_color_(light_);
- printf("Expected value ");
- no_color || print_color_(white_);
- printf("%10lld", (i64) tests_list.v[i].expected[j]);
- no_color || print_color_(light_);
- printf(" (");
- no_color || print_color_(white_);
- printf("0x%08llx", (u64) tests_list.v[i].expected[j]);
- no_color || print_color_(light_);
- printf(")\n\n");
- }
- }
- }
-
- if (tests_list.size > MAX_NUM_TESTS) {
- no_color || print_color_(light_);
- quiet || printf("Too many tests!\n\n");
- status = 1;
- }
-
- if (status == 0) {
- no_color || print_color_(green_);
- quiet || printf("OK\n");
- } else {
- no_color || print_color_(red_);
- quiet || printf("FAILED\n");
- }
-
- no_color || print_color_(light_);
- quiet || printf("\n");
- return status;
-}
-
-// ================================================================
-
-Benchs_List benchs_list = { 0 };
-
-static void bench_set_repeats_limit(i32 i, i32 repeats_limit) {
- if (benchs_list.v[i].ready)
- return;
- if (benchs_list.v[i].cycles_size >= MAX_NUM_BENCH_CYCLES)
- return;
- benchs_list.v[i].cycles[benchs_list.v[i].cycles_size] = repeats_limit;
- benchs_list.v[i].cycles_size++;
-}
-
-static i32 bench_loop(i32 i) {
- if (!benchs_list.v[i].ready)
- return 0;
- return benchs_list.v[i].repeats < benchs_list.v[i].cycles[benchs_list.v[i].cycle];
-}
-
-static void bench_begin(i32 i) {
- i32 n = benchs_list.v[i].repeats++;
-
- if (n >= MAX_NUM_BENCH_REPEATS)
- return;
-
- struct timespec tv;
- timespec_get(&tv, TIME_UTC);
-
- benchs_list.v[i].sec[n] = (int64_t) tv.tv_sec;
- benchs_list.v[i].nsec[n] = (int64_t) tv.tv_nsec;
-}
-
-static void bench_end(i32 i) {
- i32 n = benchs_list.v[i].repeats - 1;
-
- if (n < 0 || n >= MAX_NUM_BENCH_REPEATS)
- return;
-
- struct timespec tv;
- timespec_get(&tv, TIME_UTC);
-
- i64 sec = ((i64) tv.tv_sec) - benchs_list.v[i].sec[n];
- i64 nsec = ((i64) tv.tv_nsec) - benchs_list.v[i].nsec[n];
-
- benchs_list.v[i].duration_nsec[n] = sec * 1000000000 + nsec;
-}
-
-void bench_register(c8 const *name, c8 const *file, bench_run_fn fn) {
- i32 n = benchs_list.size++;
- if (n < MAX_NUM_BENCHS) {
- Benchmark *bench = benchs_list.v + n;
-
- bench->bench_fn = fn;
- bench->bench_name = name;
- bench->bench_file = file;
- bench->cycles_size = 0;
- bench->ready = 0;
- }
-}
-
-static void bench_setup_signals() {
- for (u32 i = 0; i < sizeof signums_ / sizeof *signums_; i++)
- signal(signums_[i], test_handle_signal);
-}
-
-static i32 run_bench_(volatile i32 i) {
- i32 signum = setjmp(test_restore_execution);
-
- if (signum != 0) {
- benchs_list.v[i].signal = signum;
- return 0;
- }
-
- benchs_list.v[i].bench_fn(i, bench_set_repeats_limit, bench_loop, bench_begin, bench_end);
- return 1;
-}
-
-static i32 compare_64_(void const *x_, void const *y_) {
- i64 const *x = (i64 const *) x_;
- i64 const *y = (i64 const *) y_;
- return *x - *y;
-}
-
-static i32 compare_32_(void const *x_, void const *y_) {
- i32 const *x = (i32 const *) x_;
- i32 const *y = (i32 const *) y_;
- return *x - *y;
-}
-
-i32 run_benchmarks(i32 argc, c8 **argv) {
- i32 success_count = 0;
- i32 status = 0;
- i32 no_color = 0;
- i32 line_width = 20;
- i32 carriage_return = 1;
-
- c8 const *specific_bench = NULL;
-
- bench_setup_signals();
-
- for (i32 i = 0; i < argc; i++)
- if (strcmp("--no-term-color", argv[i]) == 0)
- no_color = 1;
- else if (strcmp("--no-carriage-return", argv[i]) == 0)
- carriage_return = 0;
- else if (strcmp("--match", argv[i]) == 0)
- specific_bench = argv[++i];
-
- if (specific_bench != NULL) {
- no_color || print_color_(light_);
- printf("Run benchmarks matching ");
- no_color || print_color_(white_);
- printf("*%s*", specific_bench);
- no_color || print_color_(light_);
- printf("\n\n");
- }
-
- c8 const *file = NULL;
- i64 file_root = -1;
- i32 benchs_total = 0;
-
- for (i32 i = 0; i < benchs_list.size && i < MAX_NUM_BENCHS; i++) {
- if (specific_bench != NULL && strstr(benchs_list.v[i].bench_name, specific_bench) == NULL)
- continue;
- benchs_total++;
- i32 l = 2 + (int) strlen(benchs_list.v[i].bench_name);
- if (line_width < l)
- line_width = l;
- }
-
- if (benchs_total > 0) {
- c8 const *s = benchs_list.v[0].bench_file;
-
- for (i32 j = 1; j < benchs_list.size && j < MAX_NUM_BENCHS; j++) {
- Benchmark *bench = benchs_list.v + j;
-
- if (specific_bench != NULL && strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (strcmp(s, bench->bench_file) == 0)
- continue;
- i32 k = 0;
- for (; s[k] != '\0' && bench->bench_file[k] != '\0' && s[k] == bench->bench_file[k]; k++) { }
- if (file_root == -1 || file_root > k)
- file_root = k;
- }
-
- if (file_root == -1) {
- for (i32 i = 0; s[i] != '\0'; i++)
- if (s[i] == '/' || s[i] == '\\')
- file_root = i + 1;
- }
- }
-
- no_color || print_color_(blue_);
- printf("# ");
- no_color || print_color_(light_);
- printf("BENCHMARK");
- printf("%*c", line_width - 9, ' ');
- no_color || print_color_(green_);
- printf(" LOW ");
- no_color || print_color_(light_);
- printf("|");
- no_color || print_color_(blue_);
- printf(" MEDIAN ");
- no_color || print_color_(light_);
- printf("|");
- no_color || print_color_(yellow_);
- printf(" HIGH\n");
- no_color || print_color_(light_);
- printf(" (in microseconds)\n\n");
-
- // Prepare cycles.
- //
-
- for (i32 i = 0; i < benchs_list.size && i < MAX_NUM_BENCHS; i++) {
- Benchmark *bench = benchs_list.v + i;
-
- if (specific_bench != NULL && strstr(bench->bench_name, specific_bench) == NULL)
- continue;
-
- run_bench_(i);
-
- if (bench->cycles_size == 0) {
- bench->cycles_size = 2;
- bench->cycles[0] = NUM_BENCH_REPEATS_DEFAULT_1;
- bench->cycles[1] = NUM_BENCH_REPEATS_DEFAULT_2;
- }
-
- qsort(bench->cycles, bench->cycles_size, sizeof *bench->cycles, compare_32_);
-
- benchs_list.v[i].ready = 1;
- }
-
- // Run cycles.
- //
-
- for (i32 cycle = 0; cycle < MAX_NUM_BENCH_CYCLES; cycle++) {
- // Prepare cycle.
- //
-
- i32 cycles_done = 1;
-
- for (i32 i = 0; i < benchs_list.size && i < MAX_NUM_BENCHS; i++) {
- Benchmark *bench = benchs_list.v + i;
-
- if (specific_bench != NULL && strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (cycle >= bench->cycles_size)
- continue;
-
- bench->repeats = 0;
- bench->cycle = cycle;
- cycles_done = 0;
- }
-
- if (cycles_done)
- break;
-
- // Run benchmarks.
- //
-
- for (i32 i = 0; i < benchs_list.size && i < MAX_NUM_BENCHS; i++) {
- Benchmark *bench = benchs_list.v + i;
-
- if (specific_bench != NULL && strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (cycle >= bench->cycles_size)
- continue;
-
- if (file == NULL || strcmp(file, bench->bench_file) != 0) {
- if (file != NULL)
- printf("\n");
- file = bench->bench_file;
- no_color || print_color_(blue_);
- printf("* ");
- no_color || print_color_(white_);
- printf("%s\n", file + file_root);
- }
-
- !carriage_return || no_color || print_color_(yellow_);
- carriage_return || no_color || print_color_(light_);
- printf("` %s ", bench->bench_name);
- !carriage_return || printf("\r");
- fflush(stdout);
-
- i32 bench_status = run_bench_(i);
-
- if (bench->repeats > MAX_NUM_BENCH_REPEATS)
- bench_status = 0;
-
- !carriage_return || no_color || print_color_(light_);
- !carriage_return || printf("` %s ", bench->bench_name);
-
- i32 l = (i32) strlen(bench->bench_name);
- printf("%*c", line_width - l, ' ');
-
- if (bench->repeats <= 0) {
- no_color || print_color_(yellow_);
- printf(" 0 runs\n");
- success_count++;
- } else if (bench_status == 0) {
- no_color || print_color_(red_);
- printf(" FAIL\n");
- status = 1;
- } else {
- i32 repeats = bench->repeats;
-
- memcpy(bench->duration_sorted_nsec, bench->duration_nsec, repeats * sizeof *bench->duration_sorted_nsec);
- qsort(bench->duration_sorted_nsec, repeats, sizeof *bench->duration_sorted_nsec, compare_64_);
-
- i64 average = bench->duration_sorted_nsec[repeats / 2];
- i64 floor = bench->duration_sorted_nsec[repeats / 20];
- i64 roof = bench->duration_sorted_nsec[repeats - repeats / 20 - 1];
-
- no_color || print_color_(white_);
- printf("%-9g", (f64) floor * 0.001);
- no_color || print_color_(light_);
- printf("| ");
- no_color || print_color_(white_);
- printf("%-9g", (f64) average * 0.001);
- no_color || print_color_(light_);
- printf("| ");
- no_color || print_color_(white_);
- printf("%-9g", (f64) roof * 0.001);
- no_color || print_color_(light_);
- printf(" %d runs\n", repeats);
- success_count++;
- }
- }
- }
-
- printf("\n");
-
- if (status != 0) {
- for (i32 i = 0; i < benchs_list.size && i < MAX_NUM_BENCHS; i++) {
- Benchmark *bench = benchs_list.v + i;
-
- if (specific_bench != NULL && strstr(bench->bench_name, specific_bench) == NULL)
- continue;
- if (bench->signal != 0) {
- i32 signum = bench->signal;
- if (signum >= 0 && signum < (i32) (sizeof signames_ / sizeof *signames_) && signames_[signum] != NULL) {
- no_color || print_color_(light_);
- printf("Signal \"%s\" (%d) for \"", signames_[signum], signum);
- no_color || print_color_(white_);
- printf("%s", bench->bench_name);
- no_color || print_color_(light_);
- printf("\" in \"");
- no_color || print_color_(white_);
- printf("%s", bench->bench_file + file_root);
- no_color || print_color_(light_);
- printf("\"!.\n");
- } else {
- no_color || print_color_(light_);
- printf("Unknown signal (%d) for \"", signum);
- no_color || print_color_(white_);
- printf("%s", bench->bench_name);
- no_color || print_color_(light_);
- printf("\" in \"");
- no_color || print_color_(white_);
- printf("%s", bench->bench_file + file_root);
- no_color || print_color_(light_);
- printf("\"!.\n");
- }
- }
- }
-
- printf("\n");
- }
-
- if (benchs_list.size > MAX_NUM_BENCHS) {
- no_color || print_color_(light_);
- printf("Too many benchmarks!\n\n");
- status = 1;
- }
-
- if (status == 0) {
- no_color || print_color_(green_);
- printf("DONE\n");
- } else {
- no_color || print_color_(red_);
- printf("DONE WITH ERRORS\n");
- }
-
- no_color || print_color_(light_);
- printf("\n");
- return status;
-}
-
-#endif // TEST_IMPL_GUARD_
-#endif // TEST_HEADER
diff --git a/examples/ui.c b/examples/ui.c
index bd508e8..0847af3 100755
--- a/examples/ui.c
+++ b/examples/ui.c
@@ -25,326 +25,7 @@ gcc \
exit $? # */
#endif
-#include "../reduced_system_layer.c"
-
-#define CHAR_NUM_BITS_X 6
-#define CHAR_NUM_BITS_Y 7
-#define CHAR_NUM_BITS (CHAR_NUM_BITS_X * CHAR_NUM_BITS_Y)
-
-enum {
- OP_SET,
- OP_XOR,
-};
-
-u64 bitfont[] = {
- 0xbc0000000000, 0xc00300000, 0x5fd5040093f24fc9, 0xa00a2c2a1a280105, 0xc000415e6f, 0x400000020be0000, 0x1c38a8400000007d, 0x40002043e1020215, 0x408102000000010, 0x9800000000020002, 0xf913e00000033, 0x53200000207c8800, 0x3654880000099, 0x54b800000f840e00, 0xe953c000001a, 0x953e000000674080, 0x1e54b800000f, 0x490000000000240, 0x88a08000000, 0x20a220050a142850, 0x6520800000, 0x912f801eab260be, 0x800034952bf0001f, 0xc850bf0000921427, 0xf00010a54afc0003, 0xd29427800002142b, 0x840007e1023f0000, 0x7d09100000217e, 0x3f000188a08fc000, 0xc30c0cfc00000810, 0x27803f101013f00f, 0xc244bf0000f214, 0x4bf0002f21427800, 0xc254a480006c24, 0x407c00102fc08100, 0xf208080f0000fa0, 0x531007d81c607c0, 0xc208288c031141, 0x83fc00046954b10, 0x180e03000000, 0x41040000000ff04, 0x8102040810000404, 0x2a54600000000101, 0x309123e0000e, 0xc912180000a22447, 0x8000062a54700007, 0xe52a4300000029f0, 0xa0000602043e0001, 0x1d48000002074, 0x1f000003610f8000, 0x13e04f800000010, 0x470000780813e00f, 0x184893e0000e224, 0x23e0001f12243000, 0x82a54100000008, 0x40780000009f0200, 0xe208080e0001f20, 0xa22007981860780, 0x82082888022282, 0x16c200004ca95320, 0x7f000004, 0x408200000086d04, 0x8204,
-};
-
-#define BITFONT_LEN ((i64) (sizeof bitfont / sizeof *bitfont))
-
-i64 char_column_offset(c32 c, i64 column_index) {
- if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
- return -1;
- return (c - 32) * CHAR_NUM_BITS + column_index * CHAR_NUM_BITS_Y;
-}
-
-b8 char_bit(i64 column_offset, i64 row_index) {
- if (column_offset < 0 || column_offset / 64 >= BITFONT_LEN || row_index < 0 || row_index >= CHAR_NUM_BITS_Y)
- return 0;
-
- i64 bit_index = column_offset + row_index;
- i64 qword_index = bit_index / 64;
- if (qword_index < 0 || qword_index >= BITFONT_LEN)
- return 0;
- u64 mask = 1ull << (bit_index % 64);
- return !!(bitfont[qword_index] & mask);
-}
-
-u64 char_column_convolved(c32 c, i64 column_index) {
- if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
- return 0;
-
- u64 column = 0;
- i64 offset = char_column_offset(c, column_index);
-
- for (i64 y = 0; y < CHAR_NUM_BITS_Y; ++y)
- if (char_bit(offset, y))
- column |= 3ull << y;
-
- return column;
-}
-
-b8 char_column_empty(c32 c, i64 column_index) {
- if (column_index < 0 || column_index >= CHAR_NUM_BITS_X)
- return 1;
-
- i64 offset = char_column_offset(c, column_index);
-
- for (i64 y = 0; y < CHAR_NUM_BITS_Y; ++y)
- if (char_bit(offset, y))
- return 0;
-
- return 1;
-}
-
-i64 char_width(c32 c) {
- if (c < 32)
- return 0;
- if (c == ' ' || c > 127)
- return 4;
-
- i64 width = 0;
-
- for (; width < CHAR_NUM_BITS_X; ++width)
- if (char_column_empty(c, width) && char_column_empty(c, width + 1))
- break;
-
- return width;
-}
-
-i64 char_spacing(i64 num_chars, c32 *text, i64 index) {
- assert(text != NULL);
-
- if (index < 0 || index + 1 >= num_chars)
- return 0;
-
- u64 a = char_column_convolved(text[index], char_width(text[index]) - 1);
- u64 b = char_column_convolved(text[index + 1], 0);
-
- if (!!(a & b))
- return 1;
-
- return 0;
-}
-
-i64 text_cursor(i64 num_chars, c32 *text) {
- assert(text != NULL);
-
- i64 cursor = 0;
-
- for (i64 i = 0; i < num_chars; ++i) {
- if (text[i] <= ' ') {
- if (text[i] == '\n')
- cursor = 0;
- else if (text[i] == '\b' && i > 0)
- cursor -= char_width(text[i - 1]) + char_spacing(num_chars, text, i - 1);
- else if (text[i] == '\r')
- cursor = 0;
- else
- cursor += char_width(' ') + char_spacing(num_chars, text, i);
- continue;
- }
- cursor += char_width(text[i]) + char_spacing(num_chars, text, i);
- }
-
- return cursor;
-}
-
-i64 enum_text_columns(i64 num_chars, c32 *text) {
- assert(text != NULL);
-
- i64 cols = 0;
- i64 n = 0;
-
- for (i64 i = 0; i < num_chars; ++i) {
- if (text[i] <= ' ') {
- if (text[i] == '\n') {
- if (cols < n)
- cols = n;
- n = 0;
- } else if (text[i] == '\b' && i > 0) {
- if (cols < n)
- cols = n;
- n -= char_width(text[i - 1]) + char_spacing(num_chars, text, i - 1);
- } else if (text[i] == '\r') {
- if (cols < n)
- cols = n;
- n = 0;
- } else
- n += char_width(' ') + char_spacing(num_chars, text, i);
- continue;
- }
- n += char_width(text[i]) + char_spacing(num_chars, text, i);
- }
-
- if (cols < n)
- cols = n;
-
- return cols;
-}
-
-i64 enum_text_rows(i64 num_chars, c32 *text) {
- assert(text != NULL);
-
- i64 rows = 0;
-
- for (i64 i = 0; i <= num_chars; ++i)
- if (i == num_chars || text[i] == '\n') {
- if (rows > 0)
- ++rows;
- rows += CHAR_NUM_BITS_Y;
- }
-
- return rows;
-}
-
-void print_text(u32 color, f64 x0, f64 y0, f64 scale_x, f64 scale_y, i64 num_chars, c32 *text) {
- assert(text != NULL);
-
- f64 x = x0;
- f64 y = y0;
-
- f64 kx = scale_x;
- f64 h = scale_y * CHAR_NUM_BITS_Y;
-
- for (i64 n = 0; n < num_chars; ++n) {
- if (text[n] <= ' ') {
- if (text[n] == '\n') {
- x = x0;
- y += scale_y * (CHAR_NUM_BITS_Y + 1);
- }
- else if (text[n] == '\b' && n > 0)
- x -= kx * (char_width(text[n - 1]) + char_spacing(num_chars, text, n - 1));
- else if (text[n] == '\r')
- x = x0;
- else
- x += kx * (char_width(' ') + char_spacing(num_chars, text, n));
- continue;
- }
-
- i64 num_cols = char_width(text[n]);
- f64 w = num_cols * kx;
-
- i64 i0 = (i64) floor(x + .5);
- i64 i1 = (i64) floor(x + w + .5);
- i64 j0 = (i64) floor(y + .5);
- i64 j1 = (i64) floor(y + h + .5);
-
- for (i64 i = i0; i < i1; ++i) {
- if (i < 0) continue;
- if (i >= platform.frame_width) break;
-
- i64 column = ((i - i0) * num_cols) / (i1 - i0);
- i64 offset = char_column_offset(text[n], column);
-
- for (i64 j = j0; j < j1; ++j) {
- if (j < 0) continue;
- if (j >= platform.frame_height) break;
-
- i64 row = ((j - j0) * CHAR_NUM_BITS_Y) / (j1 - j0);
-
- if (char_bit(offset, row))
- platform.pixels[j * platform.frame_width + i] = color;
- }
- }
-
- x += kx * (num_cols + char_spacing(num_chars, text, n));
- }
-}
-
-void draw_panel(u32 op, u32 color, f64 x0, f64 y0, f64 width, f64 height) {
- i64 i0 = (i64) floor(x0 + .5);
- i64 j0 = (i64) floor(y0 + .5);
- i64 i1 = (i64) floor(x0 + width + .5);
- i64 j1 = (i64) floor(y0 + height + .5);
-
- if (i0 < 0) i0 = 0;
- if (j0 < 0) j0 = 0;
- if (i1 >= platform.frame_width) i1 = platform.frame_width - 1;
- if (j1 >= platform.frame_height) j1 = platform.frame_height - 1;
-
- for (i64 j = j0; j < j1; ++j)
- for (i64 i = i0; i < i1; ++i)
- if (op == OP_XOR)
- platform.pixels[j * platform.frame_width + i] ^= color;
- else
- platform.pixels[j * platform.frame_width + i] = color;
-}
-
-void draw_text_area(u32 color, f64 x0, f64 y0, f64 width, f64 height, f64 max_scale_x, f64 max_scale_y, i64 num_chars, c32 *text) {
- assert(max_scale_x > 1e-6);
- assert(max_scale_y > 1e-6);
-
- i64 num_columns = enum_text_columns(num_chars, text);
- i64 num_rows = enum_text_rows(num_chars, text);
-
- f64 scale_x = width / num_columns;
- f64 scale_y = height / num_rows;
-
- f64 kx = scale_x / max_scale_x;
- f64 ky = scale_y / max_scale_y;
-
- f64 k = kx < ky ? kx : ky;
-
- kx = k * max_scale_x;
- ky = k * max_scale_y;
-
- print_text(color, x0, y0, kx, ky, num_chars, text);
-}
-
-void draw_text_cursor(u32 color, f64 x0, f64 y0, f64 width, f64 height, f64 max_scale_x, f64 max_scale_y, i64 cursor, i64 selection, i64 num_chars, c32 *text) {
- assert(max_scale_x > 1e-6);
- assert(max_scale_y > 1e-6);
-
- i64 num_columns = enum_text_columns(num_chars, text);
- i64 num_rows = enum_text_rows(num_chars, text);
- i64 cursor_x = text_cursor(cursor, text);
- i64 cursor_y = enum_text_rows(cursor, text);
- f64 scale_x = width / num_columns;
- f64 scale_y = height / num_rows;
-
- f64 kx = scale_x / max_scale_x;
- f64 ky = scale_y / max_scale_y;
-
- f64 k = kx < ky ? kx : ky;
-
- kx = k * max_scale_x;
- ky = k * max_scale_y;
-
- if (selection != 0) {
- i64 selection_x, selection_y;
-
- if (selection > 0) {
- selection_x = text_cursor(cursor + selection, text);
- selection_y = enum_text_rows(cursor + selection, text);
- } else {
- selection_x = cursor_x;
- selection_y = cursor_y;
- cursor_x = text_cursor(cursor + selection, text);
- cursor_y = enum_text_rows(cursor + selection, text);
- }
-
- if (cursor_y == selection_y)
- draw_panel(OP_XOR, color,
- x0 + kx * cursor_x,
- y0 + ky * cursor_y - ky * (CHAR_NUM_BITS_Y + 1),
- kx * (selection_x - cursor_x),
- ky * (CHAR_NUM_BITS_Y + 1)
- );
- else {
- draw_panel(OP_XOR, color,
- x0 + kx * cursor_x,
- y0 + ky * cursor_y - ky * (CHAR_NUM_BITS_Y + 1),
- kx * (num_columns - cursor_x),
- ky * (CHAR_NUM_BITS_Y + 1)
- );
- for (i64 j = cursor_y + CHAR_NUM_BITS_Y + 1; j < selection_y; j += CHAR_NUM_BITS_Y + 1)
- draw_panel(OP_XOR, color,
- x0,
- y0 + ky * j - ky * (CHAR_NUM_BITS_Y + 1),
- kx * num_columns,
- ky * (CHAR_NUM_BITS_Y + 1)
- );
- draw_panel(OP_XOR, color,
- x0,
- y0 + ky * selection_y - ky * (CHAR_NUM_BITS_Y + 1),
- kx * selection_x,
- ky * (CHAR_NUM_BITS_Y + 1)
- );
- }
- } else
- draw_panel(OP_XOR, color, x0 + kx * cursor_x, y0 + ky * cursor_y - ky * CHAR_NUM_BITS_Y, kx * .5, ky * (CHAR_NUM_BITS_Y - 1));
-}
+#include "../graphics.c"
i32 main(i32 argc, c8 **argv) {
(void) argc;