diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index cc313c7..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-
-# top-most EditorConfig file
-root = true
-
-# Unix-style newlines with a newline ending every file
-[*]
-end_of_line = lf
-insert_final_newline = true
-indent_style = space
-indent_size = 2
-
-# Matches multiple files with brace expansion notation
-# Set default charset
-[*.{c,h,js,py}]
-charset = utf-8
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index f9d668b..0000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# app_codebase
-
diff --git a/app_codebase_rdbg.rdbg b/app_codebase_rdbg.rdbg
deleted file mode 100644
index 57f0e77..0000000
Binary files a/app_codebase_rdbg.rdbg and /dev/null differ
diff --git a/base_app.10x b/base_app.10x
deleted file mode 100644
index d77bfa5..0000000
--- a/base_app.10x
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
- *.c,*.cc,*.cpp,*.c++,*.cp,*.cxx,*.h,*.hh,*.hpp,*.h++,*.hp,*.hxx,*.inl,*.cs,*.rs,*.java,*.jav,*.js,*.jsc,*.jsx,*.json,*.cls,*.py,*.rpy,*.php,*.php3,*.phl,*.phtml,*.rhtml,*.tpl,*.phps,*.lua,*.html,*.html5,*.htm,*.xml,*.xaml,*.css,*.ssi,*.haml,*.yaml,*.bat,*.wbf,*.wbt,*.txt,*.cmake,*.make,*.makefile,*.mak,*.mk,*.sh,*.bash,*.csv,*.asp,*.pl,*.mac,*.ws,*.vbs,*.perl,*.src,*.rss,*.inc,*.f,*.go,*.prl,*.plx,*.rb,*.lsp,*.lpx,*.ps1,*.command,*.cbl,*.cob,*.qs,*.wxs,*.ph,*.msc,*.glsl,*.hlsl,*.fx,*.vert,*.tesc,*.tese,*.geom,*.frag,*.comp,*.pssl,*.scons,*.cu,*.jai,
-
- true
- true
- true
- false
- false
- build.bat
-
-
-
-
-
-
-
-
-
-
- false
-
- Debug
- Release
-
-
- x64
- Win32
-
-
- C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\ATLMFC\include
-C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include
-C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\ucrt
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\winrt
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\cppwinrt
-C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\ATLMFC\include
-C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include
-C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\ucrt
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\winrt
-C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\cppwinrt
-
-
-
- OS_WINDOWS 1
-
-
-
- Debug:x64
-
-
- base_inc.h
- os_inc.h
-
-
-
- Debug
-
-
-
- x64
-
-
-
-
-
- .git
- *.c,*.cc,*.cpp,*.c++,*.cp,*.cxx,*.h,*.hh,*.hpp,*.h++,*.hp,*.hxx,*.inl,*.cs,*.rs,*.java,*.jav,*.js,*.jsc,*.jsx,*.json,*.cls,*.py,*.rpy,*.php,*.php3,*.phl,*.phtml,*.rhtml,*.tpl,*.phps,*.lua,*.html,*.html5,*.htm,*.xml,*.xaml,*.css,*.ssi,*.haml,*.yaml,*.bat,*.wbf,*.wbt,*.txt,*.cmake,*.make,*.makefile,*.mak,*.mk,*.sh,*.bash,*.csv,*.asp,*.pl,*.mac,*.ws,*.vbs,*.perl,*.src,*.rss,*.inc,*.f,*.go,*.prl,*.plx,*.rb,*.lsp,*.lpx,*.ps1,*.command,*.cbl,*.cob,*.qs,*.wxs,*.ph,*.msc,*.glsl,*.hlsl,*.fx,*.vert,*.tesc,*.tese,*.geom,*.frag,*.comp,*.pssl,*.scons,*.cu,*.jai,
-
- true
- true
- true
- false
-
-
-
- build
- *.c,*.cc,*.cpp,*.c++,*.cp,*.cxx,*.h,*.hh,*.hpp,*.h++,*.hp,*.hxx,*.inl,*.cs,*.rs,*.java,*.jav,*.js,*.jsc,*.jsx,*.json,*.cls,*.py,*.rpy,*.php,*.php3,*.phl,*.phtml,*.rhtml,*.tpl,*.phps,*.lua,*.html,*.html5,*.htm,*.xml,*.xaml,*.css,*.ssi,*.haml,*.yaml,*.bat,*.wbf,*.wbt,*.txt,*.cmake,*.make,*.makefile,*.mak,*.mk,*.sh,*.bash,*.csv,*.asp,*.pl,*.mac,*.ws,*.vbs,*.perl,*.src,*.rss,*.inc,*.f,*.go,*.prl,*.plx,*.rb,*.lsp,*.lpx,*.ps1,*.command,*.cbl,*.cob,*.qs,*.wxs,*.ph,*.msc,*.glsl,*.hlsl,*.fx,*.vert,*.tesc,*.tese,*.geom,*.frag,*.comp,*.pssl,*.scons,*.cu,*.jai,
-
- true
- true
- true
- false
-
-
-
- build.bat
-
-
- src
- *.c,*.cc,*.cpp,*.c++,*.cp,*.cxx,*.h,*.hh,*.hpp,*.h++,*.hp,*.hxx,*.inl,*.cs,*.rs,*.java,*.jav,*.js,*.jsc,*.jsx,*.json,*.cls,*.py,*.rpy,*.php,*.php3,*.phl,*.phtml,*.rhtml,*.tpl,*.phps,*.lua,*.html,*.html5,*.htm,*.xml,*.xaml,*.css,*.ssi,*.haml,*.yaml,*.bat,*.wbf,*.wbt,*.txt,*.cmake,*.make,*.makefile,*.mak,*.mk,*.sh,*.bash,*.csv,*.asp,*.pl,*.mac,*.ws,*.vbs,*.perl,*.src,*.rss,*.inc,*.f,*.go,*.prl,*.plx,*.rb,*.lsp,*.lpx,*.ps1,*.command,*.cbl,*.cob,*.qs,*.wxs,*.ph,*.msc,*.glsl,*.hlsl,*.fx,*.vert,*.tesc,*.tese,*.geom,*.frag,*.comp,*.pssl,*.scons,*.cu,*.jai,
-
- true
- true
- true
- false
-
-
-
- run.bat
-
-
-
-
diff --git a/build.bat b/build.bat
index 6280fbd..fd41a54 100644
--- a/build.bat
+++ b/build.bat
@@ -2,15 +2,45 @@
ctime -begin timeBuild.ctm
-set CommonCompilerFlags=/nologo /Zi /FC /WX /W4 /wd4201 /wd4100 /wd4189 /wd4244 /wd4127 /wd4456
-@rem set Sources=../src/main.c
-@rem set OutputName=program.exe
-set Sources=../src/algorithms_main.c
-set OutputName=algorithms_test.exe
+@rem /WX /W4 /wd4201 /wd4100 /wd4189 /wd4244 /wd4127 /wd4456
+@rem set CommonCompilerFlags="/nologo /Zi /FC"
+set CommonCompilerFlags=/nologo /Zi /FC /Od
+@rem /WX /W4 /wd4201 /wd4100 /wd4189 /wd4244 /wd4127 /wd4456
+@rem
+
+set mkl_root=D:/lib/oneAPI_mkl/mkl/2021.3.0
+set mkl_core=%mkl_root%/lib/intel64/mkl_core.lib
+set mkl_intel_lp64=%mkl_root%/lib/intel64/mkl_intel_lp64.lib
+set mkl_intel_thread=%mkl_root%/lib/intel64/mkl_intel_thread.lib
+set MKLCOMPILER=D:/lib/oneAPI_mkl/compiler/2021.3.0/windows/compiler
+set libiomp5md=%MKLCOMPILER%/lib/intel64_win/libiomp5md.lib
+
+set libiompdll_path=D:\lib\oneAPI_mkl\compiler\2021.3.0\windows\redist\intel64_win\compiler
+set libiompdll_name=libiomp5md.dll
+set libiompdll=%libiompdll_path%\%libiompdll_name%
+
+set Sources=../src/main.c
+
+
+
+IF NOT EXIST .\out mkdir .\out
IF NOT EXIST .\build mkdir .\build
pushd .\build
-cl %CommonCompilerFlags% %Sources% -Fe%OutputName%
+
+if not exist "%libiompdll_name%" (
+ echo Copying %libiompdll%
+ copy "%libiompdll%" .
+ if errorlevel 1 (
+ echo Error copying openmp dll
+ ) else (
+ echo Copied openmp dll: %libiompdll_name%
+ )
+
+)
+
+cl %CommonCompilerFlags% %Sources% /I"%mkl_root%\include" /link %mkl_core% %mkl_intel_lp64% %mkl_intel_thread% %libiomp5md%
+
set LastError=%ERRORLEVEL%
popd
diff --git a/build/algorithms_test.rdi b/build/algorithms_test.rdi
deleted file mode 100644
index 07e5098..0000000
Binary files a/build/algorithms_test.rdi and /dev/null differ
diff --git a/build/program.raddbgi b/build/program.raddbgi
deleted file mode 100644
index 4104d5f..0000000
Binary files a/build/program.raddbgi and /dev/null differ
diff --git a/data/LiberationMono-Regular.ttf b/data/LiberationMono-Regular.ttf
deleted file mode 100644
index e774859..0000000
Binary files a/data/LiberationMono-Regular.ttf and /dev/null differ
diff --git a/data/arial.ttf b/data/arial.ttf
deleted file mode 100644
index 8682d94..0000000
Binary files a/data/arial.ttf and /dev/null differ
diff --git a/run.bat b/run.bat
deleted file mode 100644
index 752c0f1..0000000
--- a/run.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-@echo off
-pushd build
-@rem call program.exe
-call algorithms_test.exe
-popd
diff --git a/src/algorithms_main.c b/src/algorithms_main.c
deleted file mode 100644
index 23d6f0a..0000000
--- a/src/algorithms_main.c
+++ /dev/null
@@ -1,104 +0,0 @@
-// header includes
-#include "base/base_inc.h"
-#include "os/os_inc.h"
-
-// .c includes
-#include "base/base_inc.c"
-#include "os/os_inc.c"
-#include "os/os_entry_point.c"
-
-#define LOG DebugPrintf
-function void
-DebugPrintf(const char* format, ...)
-{
- char buffer[4096];
- va_list args;
- va_start(args, format);
- vsprintf_s(buffer, sizeof(buffer), format, args);
- OutputDebugString(buffer);
- va_end(args);
-}
-
-typedef struct F64Node F64Node;
-struct F64Node
-{
- F64Node *prev;
- F64Node *next;
- F64 value;
-};
-
-typedef struct F64List F64List;
-struct F64List
-{
- F64Node *first;
- F64Node *last;
- U32 length;
-};
-
-F64Node g_f64_nil_node = {0};
-
-function void
-F64_push_node(F64List *list, F64Node *n)
-{
- if(list->first == 0)
- {
- list->first = n;
- list->last = n;
- } else {
- list->last->next = n;
- list->last = n;
- }
- list->length += 1;
-}
-
-function void
-F64_push(Arena *arena, F64List *list, F64 value)
-{
- F64Node *node = PushArrayZero(arena, F64Node, 1);
- node->value = value;
- F64_push_node(list, node);
-}
-
-function void
-print_F64_ll(F64List *list)
-{
- for(F64Node *n = list->first; n != 0; n = n->next)
- {
- LOG(" %2.f \n", n->value);
- }
-}
-
-function void
-reverse_linked_list_lol(void)
-{
- Arena *ll_arena = m_make_arena();
- F64List list = {0};
- for (U32 i = 0; i < 10; i++)
- {
- F64_push(ll_arena, &list, (F64)i);
- }
-
- print_F64_ll(&list);
-
- F64Node *prev = 0;
- F64Node *current = list.first;
- F64Node *next_temp = 0;
- while(current != 0)
- {
- next_temp = current->next;
- current->next = prev;
- prev = current;
- current = next_temp;
- }
- list.first = prev;
-
- print_F64_ll(&list);
-}
-
-
-
-void
-EntryPoint(void)
-{
- reverse_linked_list_lol();
-}
diff --git a/src/base/base_context_cracking.h b/src/base/base_context_cracking.h
deleted file mode 100644
index f3ed4d6..0000000
--- a/src/base/base_context_cracking.h
+++ /dev/null
@@ -1,178 +0,0 @@
-#ifndef BASE_CONTEXT_CRACKING_H
-#define BASE_CONTEXT_CRACKING_H
-
-// NOTE(antonl):
-// This header is used for "context cracking", ie figuring out compile time context things like
-// platform etc.
-
-// For now this is just copy pasted from RJFs layer, and probably that's all that's needed.
-
-
-///////////////////////////////////////////////
-//~ MSVC extraction
-
-#if defined(_MSC_VER)
-
-# define COMPILER_MSVC 1
-
-# if defined(_WIN32)
-# define OS_WINDOWS 1
-# else
-# error _MSC_VER is defined, but _WIN32 is not. This setup is not supported.
-# endif
-
-# if defined(_M_AMD64)
-# define ARCH_X64 1
-# elif defined(_M_IX86)
-# define ARCH_X86 1
-# elif defined(_M_ARM64)
-# define ARCH_ARM64 1
-# elif defined(_M_ARM)
-# define ARCH_ARM32 1
-# else
-# error Target architecture is not supported. _MSC_VER is defined, but one of {_M_AMD64, _M_IX86, _M_ARM64, _M_ARM} is not.
-# endif
-
-#if _MSC_VER >= 1920
-#define COMPILER_MSVC_YEAR 2019
-#elif _MSC_VER >= 1910
-#define COMPILER_MSVC_YEAR 2017
-#elif _MSC_VER >= 1900
-#define COMPILER_MSVC_YEAR 2015
-#elif _MSC_VER >= 1800
-#define COMPILER_MSVC_YEAR 2013
-#elif _MSC_VER >= 1700
-#define COMPILER_MSVC_YEAR 2012
-#elif _MSC_VER >= 1600
-#define COMPILER_MSVC_YEAR 2010
-#elif _MSC_VER >= 1500
-#define COMPILER_MSVC_YEAR 2008
-#elif _MSC_VER >= 1400
-#define COMPILER_MSVC_YEAR 2005
-#else
-#define COMPILER_MSVC_YEAR 0
-#endif
-
-////////////////////////////////
-//~ rjf: Clang Extraction
-
-#elif defined(__clang__)
-
-# define COMPILER_CLANG 1
-
-# if defined(__APPLE__) && defined(__MACH__)
-# define OS_MAC 1
-# elif defined(__gnu_linux__)
-# define OS_LINUX 1
-# else
-# error __clang__ is defined, but one of {__APPLE__, __gnu_linux__} is not. This setup is not supported.
-# endif
-
-# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
-# define ARCH_X64 1
-# elif defined(i386) || defined(__i386) || defined(__i386__)
-# define ARCH_X86 1
-# elif defined(__aarch64__)
-# define ARCH_ARM64 1
-# elif defined(__arm__)
-# define ARCH_ARM32 1
-# else
-# error Target architecture is not supported. __clang__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__} is not.
-# endif
-
-////////////////////////////////
-//~ rjf: GCC Extraction
-
-#elif defined(__GNUC__) || defined(__GNUG__)
-
-# define COMPILER_GCC 1
-
-# if defined(__gnu_linux__)
-# define OS_LINUX 1
-# else
-# error __GNUC__ or __GNUG__ is defined, but __gnu_linux__ is not. This setup is not supported.
-# endif
-
-# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
-# define ARCH_X64 1
-# elif defined(i386) || defined(__i386) || defined(__i386__)
-# define ARCH_X86 1
-# elif defined(__aarch64__)
-# define ARCH_ARM64 1
-# elif defined(__arm__)
-# define ARCH_ARM32 1
-# else
-# error Target architecture is not supported. __GNU_C__ or __GNUG__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__} is not.
-# endif
-
-#else
-# error Compiler is not supported. _MSC_VER, __clang__, __GNUC__, or __GNUG__ must be defined.
-#endif
-
-#if defined(ARCH_X64)
-# define ARCH_64BIT 1
-#elif defined(ARCH_X86)
-# define ARCH_32BIT 1
-
-#endif
-
-////////////////////////////////
-//~ rjf: Language
-
-#if defined(__cplusplus)
-# define LANG_CPP 1
-#else
-# define LANG_C 1
-#endif
-
-////////////////////////////////
-//~ rjf: Zero
-
-#if !defined(ARCH_32BIT)
-# define ARCH_32BIT 0
-#endif
-#if !defined(ARCH_64BIT)
-# define ARCH_64BIT 0
-#endif
-#if !defined(ARCH_X64)
-# define ARCH_X64 0
-#endif
-#if !defined(ARCH_X86)
-# define ARCH_X86 0
-#endif
-#if !defined(ARCH_ARM64)
-# define ARCH_ARM64 0
-#endif
-#if !defined(ARCH_ARM32)
-# define ARCH_ARM32 0
-#endif
-#if !defined(COMPILER_MSVC)
-# define COMPILER_MSVC 0
-#endif
-#if !defined(COMPILER_GCC)
-# define COMPILER_GCC 0
-#endif
-#if !defined(COMPILER_CLANG)
-# define COMPILER_CLANG 0
-#endif
-#if !defined(OS_WINDOWS)
-# define OS_WINDOWS 0
-#endif
-#if !defined(OS_LINUX)
-# define OS_LINUX 0
-#endif
-#if !defined(OS_MAC)
-# define OS_MAC 0
-#endif
-#if !defined(LANG_CPP)
-# define LANG_CPP 0
-#endif
-#if !defined(LANG_C)
-# define LANG_C 0
-#endif
-
-// TODO(antonl);
-// Build options context cracking, need to figure out what we should use here first.
-#define BUILD_DEBUG 1
-
-#endif /* BASE_CONTEXT_CRACKING_H */
diff --git a/src/base/base_core.h b/src/base/base_core.h
deleted file mode 100644
index dbf3b67..0000000
--- a/src/base/base_core.h
+++ /dev/null
@@ -1,294 +0,0 @@
-#ifndef BASE_TYPES_H
-#define BASE_TYPES_H
-
-#include
-#include
-#include
-
-/////////////////////////
-//~ Macros
-
-/////////////////////////
-//- Linking keywords
-
-// TODO(anton): Understand this, yoinked from rjf's layer.
-#if LANG_CPP
-# define no_name_mangle extern "C"
-#else
-# define no_name_mangle
-#endif
-
-// TODO(anton): OS_WINDOWS dll import/export macros
-
-/////////////////////////
-//- Keywords
-// Static is stupid and means different things depending on context in C and C++.
-// These defines increases readability.
-#define function static // Function internal to compilation unit.
-#define local_persist static
-#define global static
-#define fallthrough // for use in switch statements, for clarity..
-
-// TODO(anton): Understand and add good comment on this.
-#if LANG_CPP
-# define root_global no_name_mangle
-# define root_function function
-#else
-# define root_global extern
-# define root_function function
-#endif
-
-#define inline_function inline static
-
-#if OS_WINDOWS
-# pragma section(".roglob", read)
-# define read_only __declspec(allocate(".roglob"))
-#else
-# define read_only
-#endif
-
-#if COMPILER_MSVC
-# define per_thread __declspec(thread)
-#else
-# error Thread keyword not abstracted on compiler.
-#endif
-
-/////////////////////////
-//- Memory operations
-// It's nice to put these in macros, so we can swap out the functionality from standard library, eventually.
-#define MemoryCopy memcpy
-#define MemoryMove memmove
-#define MemorySet memset
-
-// NOTE(anton): This gives a 4127 compiler warning for the sizeof conditional. This should be ignored
-#define MemoryCopyStruct(dst, src) do { Assert(sizeof(*(dst)) == sizeof(*(src))); MemoryCopy((dst), (src), sizeof(*(dst))); } while(0)
-
-#define MemoryZero(ptr, size) MemorySet((ptr), 0, (size))
-#define MemoryZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
-#define MemoryZeroArray(arr) MemoryZero((arr), sizeof(arr))
-
-/////////////////////////
-//- Integer/pointer/array/type manipulations
-
-#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
-#define IntFromPtr(p) (U64)(((U8*)p) - 0)
-#define PtrFromInt(i) (void*)(((U8*)0) + i)
-#define Member(type, member_name) ((type *)0)->member_name
-// TODO(anton): Understand why this becomes offset actually
-#define OffsetOf(type, member_name) IntFromPtr(&Member(type, member_name))
-// TODO(anton): Understand this
-#define BaseFromMember(type, member_name, ptr) (type *)((U8 *)(ptr) - OffsetOf(type, member_name))
-
-#define Bytes(n) (n)
-#define Kilobytes(n) (n << 10) // 2^10 == 1024 etc
-#define Megabytes(n) (n << 20)
-#define Gigabytes(n) (((U64)n) << 30)
-#define Terabytes(n) (((U64)n) << 40)
-
-#define Thousand(n) ((n)*1000)
-#define Million(n) ((n)*1000000)
-#define Billion(n) ((n)*1000000000LL)
-
-#define AbsoluteValueU64(x) (U64)llabs((U64)(x))
-
-/////////////////////////
-//- Linked list helpers
-
-#define CheckNull(p) ((p)==0)
-#define SetNull(p) ((p)=0)
-// Link list helper macros that are a bit involved
-
-// Suffixes N,P,Z means that we have (N)ext, (P)rev arguments and/or a (Z)ero check and/or set argument
-// f, l, n are "first", "last", "node" I think?
-// DLL
-// Doubly Linked List: Each node has a prev and next pointer. Operations: Push back, Push front, remove
-#define DLLInsert_NPZ(f,l,p,n,next,prev,zchk,SetNull) \
-(zchk(f) ? (((f) = (l) = (n)), SetNull((n)->next), SetNull((n)->prev)) :\
-zchk(p) ? (SetNull((n)->prev), (n)->next = (f), (zchk(f) ? (0) : ((f)->prev = (n))), (f) = (n)) :\
-((zchk((p)->next) ? (0) : (((p)->next->prev) = (n))), (n)->next = (p)->next, (n)->prev = (p), (p)->next = (n),\
-((p) == (l) ? (l) = (n) : (0))))
-
-#define DLLPushBack_NPZ(f,l,n,next,prev,zchk,SetNull) DLLInsert_NPZ(f,l,l,n,next,prev,zchk,SetNull)
-
-#define DLLPushBack_NP(f, l, n, next, prev, zchk) \
-(zchk(f) ? ((f)=(l)=(n),(n)->next=(n)->prev=0) : ((n)->prev=(l),(l)->next=(n),(l)=(n),(n)->next=0))
-
-// If f == n we put f to f->next, and f->prev = 0.
-// Else if l == n, we put l=l->prev, l->next = 0.
-// If l != n and f != n we set n->next->prev to n->prev, and n->prev->next to n->next
-
-#define DLLRemove_NP(f, l, n, next, prev) (((f) == (n) ? \
-((f)=(f)->next, (f)->prev=0) : \
-(l) == (n) ? \
-((l)=(l)->prev, (l)->next=0) : \
-((n)->next->prev=(n)->prev, \
-(n)->prev->next=(n)->next) ))
-
-#define DLLRemove_NPZ(f,l,n,next,prev,zchk,SetNull) (((f)==(n))?\
-((f)=(f)->next, (zchk(f) ? (SetNull(l)) : SetNull((f)->prev))):\
-((l)==(n))?\
-((l)=(l)->prev, (zchk(l) ? (SetNull(f)) : SetNull((l)->next))):\
-((zchk((n)->next) ? (0) : ((n)->next->prev=(n)->prev)),\
-(zchk((n)->prev) ? (0) : ((n)->prev->next=(n)->next))))
-
-#define DLLPushBack(f, l, n) DLLPushBack_NPZ(f, l, n, next, prev, CheckNull, SetNull)
-// For front push I can just switch prev/next!
-#define DLLPushFront(f, l, n) DLLPushBack_NPZ(l, f, n, prev, next, CheckNull, SetNull)
-#define DLLRemove(f, l, n) DLLRemove_NPZ(f, l, n, next, prev, CheckNull, SetNull)
-
-
-// SLL, queue or stack.
-// These are from rjf's layer.
-
-////////////////
-// Queue
-// Queue has only a next pointer. But we can push from front also.
-// zchk = zero check, SetNull = zero set
-#define QueuePush_NZ(f, l, n, next, zchk, SetNull) (zchk(f)?\
-(((f)=(l)=(n)), SetNull((n)->next)):\
-((l)->next=(n),(l)=(n),SetNull((n)->next)))
-
-#define QueuePushFront_NZ(f, l, n, next, zchk, SetNull) ( zchk(f) ? \
-((f)=(l)=(n)), SetNull((n)->next) : \
-((n)->next = (f)), ((f) = (n)) )
-
-#define QueuePop_NZ(f, l, next, zchk, SetNull) ( (f)==(l) ? \
-(SetNull(f), SetNull(l)) : ((f)=(f)->next))
-
-#define QueuePush(f, l, n) QueuePush_NZ(f, l, n, next, CheckNull, SetNull)
-#define QueuePushFront(f, l, n) QueuePushFront_NZ(f, l, n, next, CheckNull, SetNull)
-#define QueuePop(f, l) QueuePop_NZ(f, l, next, CheckNull, SetNull)
-
-////////////////
-// Stack
-#define StackPush_N(f, n, next) ((n)->next=(f), (f)=(n)) // Take the first element and set it to n->next, and set the first element to the node n.
-#define StackPop_NZ(f, next, zchk) (zchk(f) ? 0 : ((f)=(f)->next)) // If first element is not zero we say that the first element is f->next, ie we pop f and put f->next on top.
-
-#define StackPush(f, n) StackPush_N(f, n, next)
-#define StackPop(f) StackPop_NZ(f, next, CheckNull)
-
-/////////////////////////
-//- Clamp/min/max
-#define Min(a, b) (((a)<(b)) ? (a) : (b))
-#define Max(a, b) (((a)>(b)) ? (a) : (b))
-#define ClampTop(x, a) Min(x,a) // "Top" since we are cutting off anything above Min(x,a)
-#define ClampBot(a, x) Max(a,x) // "Bot" since we're cutting off anything below Max(a,x)
-// If a > x we get a, else we see if b < x and then get b if true, else x.
-// TODO(anton): Is this actually what we want from a Clamp?
-#define Clamp(a, x, b) (((a)>(x))?(a):((b)<(x))?(b):(x))
-
-//- loop
-#define DeferLoop(start, end) for(int _i_ = ((start), 0); _i_ == 0; _i_ += 1, (end))
-#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
-
-#define EachEnumVal(type, it) type it = (type)0; it < type##_COUNT; it = (type)(it+1)
-#define EachNonZeroEnumVal(type, it) type it = (type)1; it < type##_COUNT; it = (type)(it+1)
-
-
-/////////////////////////
-//~ Base types
-typedef int8_t S8;
-typedef int16_t S16;
-typedef int32_t S32;
-typedef int64_t S64;
-typedef uint8_t U8;
-typedef uint16_t U16;
-typedef uint32_t U32;
-typedef uint64_t U64;
-typedef S8 B8;
-typedef S16 B16;
-typedef S32 B32;
-typedef S64 B64;
-typedef float F32;
-typedef double F64;
-typedef void VoidFunction(void);
-
-/////////////////////////
-//~ Numerical limits
-read_only global U8 U8Max = 0xFF;
-read_only global U8 U8Min = 0;
-read_only global U32 U32Max = 0xFFFFFFFF;
-read_only global U32 U32Min = 0;
-read_only global U64 U64Max = 0xFFFFFFFFFFFFFFFF;
-
-// TODO(anton): Rest of the limits, unsigned and signed integer values
-read_only global U32 SignF32 = 0x80000000;
-
-
-//- compiler, shut up! helpers
-#define unused_variable(name) (void)name
-
-/////////////////////////
-//~ Base enums
-
-// Describing a 2-coordinate system
-typedef enum Axis2
-{
- Axis2_Invalid = -1,
- Axis2_X,
- Axis2_Y,
- Axis2_COUNT
-}
-Axis2;
-#define Axis2_flip(a) ((Axis2)(!(a)))
-
-// Corners of a rectangle.
-// 00 ----- 10
-// | |
-// 01 ----- 11
-typedef enum Corner
-{
- Corner_Invalid = -1,
- Corner_00,
- Corner_01,
- Corner_10,
- Corner_11,
- Corner_COUNT
-}
-Corner;
-
-////////////////////////////////
-//~ Member Offset Helper
-
-typedef struct MemberOffset MemberOffset;
-struct MemberOffset
-{
- U64 v;
-};
-
-#define MemberOff(S, member) (MemberOffset){OffsetOf(S, member)}
-#define MemberOffLit(S, member) {OffsetOf(S, member)}
-#define MemberFromOff(ptr, type, memoff) (*(type *)((U8 *)ptr + memoff.v))
-
-/////////////////////////
-//~ Assertions
-
-#if OS_WINDOWS
-# define break_debugger() __debugbreak()
-#else
-# error not implemented
-#endif
-
-#undef Assert
-#define Assert(b) do { if(!(b)) { break_debugger(); } } while(0)
-
-#if !defined(LOG_NOT_IMPLEMENTED)
-# define LOG_NOT_IMPLEMENTED printf("\nFATAL ERROR: Not implemented yet.\n"); Assert(false); exit(1);
-#endif
-
-/////////////////////////
-//~ Bit patterns
-#define AlignUpToPow2(bytes_to_align, alignment_bytes) (((bytes_to_align) + (alignment_bytes - 1)) & ~(alignment_bytes - 1))
-
-inline_function F32
-absolute_value_F32(F32 f)
-{
- union { U32 u; F32 f; } x;
- x.f = f;
- x.u = x.u & ~SignF32;
- return x.f;
-}
-
-// TODO(anton): Understand rjf's bit patterns
-
-#endif //BASE_TYPES_H
diff --git a/src/base/base_inc.c b/src/base/base_inc.c
deleted file mode 100644
index 7194c58..0000000
--- a/src/base/base_inc.c
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "base_math.c"
-#include "base_memory.c"
-#include "base_strings.c"
-#include "base_thread_context.c"
\ No newline at end of file
diff --git a/src/base/base_inc.h b/src/base/base_inc.h
deleted file mode 100644
index 0598745..0000000
--- a/src/base/base_inc.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef BASE_H
-#define BASE_H
-
-#include "base_context_cracking.h"
-#include "base_core.h"
-#include "base_math.h"
-#include "base_memory.h"
-#include "base_strings.h"
-#include "base_thread_context.h"
-
-#endif //BASE_H
diff --git a/src/base/base_math.c b/src/base/base_math.c
deleted file mode 100644
index 40e9cb0..0000000
--- a/src/base/base_math.c
+++ /dev/null
@@ -1,107 +0,0 @@
-//- Vec2 F32
-root_function Vec2_F32
-vec2_F32(F32 x, F32 y)
-{
- Vec2_F32 result;
- result.x = x;
- result.y = y;
- return result;
-}
-
-root_function Vec2_F32 add2_F32(Vec2_F32 a, Vec2_F32 b) { return vec2_F32(a.x+b.x, a.y+b.y); }
-root_function Vec2_F32 sub2_F32(Vec2_F32 a, Vec2_F32 b) { return vec2_F32(a.x-b.x, a.y-b.y); }
-
-//- Vec2 S32
-root_function Vec2_S32
-vec2_S32(S32 x, S32 y)
-{
- Vec2_S32 result;
- result.x = x;
- result.y = y;
- return result;
-}
-
-
-root_function Vec2_S64
-vec2_S64(S64 x, S64 y)
-{
- Vec2_S64 result;
- result.x = x;
- result.y = y;
- return result;
-}
-
-root_function Vec3_F32
-vec3_F32(F32 x, F32 y, F32 z)
-{
- Vec3_F32 result;
- result.x = x;
- result.y = y;
- result.z = z;
- return result;
-}
-
-root_function Vec4_F32
-vec4_F32(F32 x, F32 y, F32 z, F32 w)
-{
- Vec4_F32 result;
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
-}
-
-//~ Range functions
-root_function Rng2_F32
-rng2_F32(Vec2_F32 min, Vec2_F32 max)
-{
- Rng2_F32 result = { min, max };
- return result;
-}
-
-root_function Rng2_F32
-shift2_F32(Rng2_F32 r, Vec2_F32 v) {
- // Shift the rectangle r by vector v.
- r.x0 += v.x;
- r.y0 += v.y;
- r.x1 += v.x;
- r.y1 += v.y;
- return r;
-}
-
-root_function Rng2_F32
-pad2_F32(Rng2_F32 r, F32 x)
-{
- // Pad subtracts the p0 by value x on both axes, and adds to p1 on both axes,
- // resulting in a rectangle that is value x larger than input rectangle r on both axes.
- Vec2_F32 min = sub2_F32(r.min, vec2_F32(x, x));
- Vec2_F32 max = add2_F32(r.max, vec2_F32(x, x));
- return rng2_F32(min, max);
-}
-
-root_function Vec2_F32
-dim2_F32(Rng2_F32 rng)
-{
- return vec2_F32(absolute_value_F32(rng.max.x - rng.min.x),
- absolute_value_F32(rng.max.y - rng.min.y));
-}
-
-// Check if a rect contains a point
-root_function B32
-rng2_contains_vec2_F32(Rng2_F32 r, Vec2_F32 x)
-{
- B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y);
- return c;
-}
-
-root_function Rng2_F32
-rng2_intersect_f32(Rng2_F32 a, Rng2_F32 b)
-{
- Rng2_F32 c;
- c.p0.x = Max(a.min.x, b.min.x);
- c.p0.y = Max(a.min.y, b.min.y);
- c.p1.x = Min(a.max.x, b.max.x);
- c.p1.y = Min(a.max.y, b.max.y);
- return c;
-}
\ No newline at end of file
diff --git a/src/base/base_math.h b/src/base/base_math.h
deleted file mode 100644
index 9942379..0000000
--- a/src/base/base_math.h
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef BASE_MATH_H
-#define BASE_MATH_H
-
-//////////////////////////
-//~ Macros
-
-#define floor_F32(f) floorf(f)
-
-
-//////////////////////////
-//~ Vector types
-
-//- 2-vectors
-typedef union Vec2_S32 Vec2_S32;
-union Vec2_S32
-{
- struct
- {
- S32 x;
- S32 y;
- };
- S32 v[2];
-};
-
-typedef union Vec2_S64 Vec2_S64;
-union Vec2_S64
-{
- struct
- {
- S64 x;
- S64 y;
- };
- S64 v[2];
-};
-
-typedef union Vec2_F32 Vec2_F32;
-union Vec2_F32
-{
- struct
- {
- F32 x;
- F32 y;
- };
- F32 v[2];
-};
-
-//- 3-vectors
-
-typedef union Vec3_F32 Vec3_F32;
-union Vec3_F32
-{
- struct
- {
- F32 x;
- F32 y;
- F32 z;
- };
- F32 v[3];
-};
-
-//- 4-vectors
-typedef union Vec4_F32 Vec4_F32;
-union Vec4_F32
-{
- struct
- {
- F32 x;
- F32 y;
- F32 z;
- F32 w;
- };
- struct
- {
- Vec2_F32 xy;
- Vec2_F32 zw;
- };
- F32 v[4];
-};
-
-//- vector macros
-#define vec2_F32_from_vec(v) vec2_F32((F32)(v).x, (F32)(v).y);
-#define vec2_S32_from_vec(v) vec2_S32((S32)(v).x, (S32)(v).y);
-#define vec2_S64_from_vec(v) vec2_S64((S64)(v).x, (S64)(v).y);
-//////////////////////////
-//~ Matrix types
-typedef struct Mat3x3_F32 Mat3x3_F32;
-struct Mat3x3_F32
-{
- F32 elements[3][3];
-};
-
-typedef struct Mat4x4_F32 Mat4x4_F32;
-struct Mat4x4_F32
-{
- F32 elements[4][4];
-};
-
-//////////////////////////
-//~ Range types
-
-//- 2D interval
-//
-typedef union Rng2_F32 Rng2_F32;
-union Rng2_F32
-{
- struct
- {
- Vec2_F32 min;
- Vec2_F32 max;
- };
- struct
- {
- Vec2_F32 p0;
- Vec2_F32 p1;
- };
- struct
- {
- F32 x0;
- F32 y0;
- F32 x1;
- F32 y1;
- };
- Vec2_F32 v[2];
-};
-
-//~ Vector functions
-
-//- Vec2 F32
-root_function Vec2_F32 vec2_F32(F32 x, F32 y);
-root_function Vec2_F32 add2_F32(Vec2_F32 a, Vec2_F32 b);
-root_function Vec2_F32 sub2_F32(Vec2_F32 a, Vec2_F32 b);
-
-//- Vec2 S32
-root_function Vec2_S32 vec2_S32(S32 x, S32 y);
-
-root_function Vec2_S64 vec2_S64(S64 x, S64 y);
-
-root_function Vec3_F32 vec3_F32(F32 x, F32 y, F32 z);
-
-root_function Vec4_F32 vec4_F32(F32 x, F32 y, F32 z, F32 w);
-
-//~ Range functions
-root_function Rng2_F32 rng2_F32(Vec2_F32 min, Vec2_F32 max);
-root_function Rng2_F32 shift2_F32(Rng2_F32 r, Vec2_F32 v);
-root_function Rng2_F32 pad2_F32(Rng2_F32 r, F32 x);
-root_function Vec2_F32 dim2_F32(Rng2_F32 rng);
-root_function B32 rng2_contains_vec2_F32(Rng2_F32 r, Vec2_F32 x);
-root_function Rng2_F32 rng2_intersect_f32(Rng2_F32 a, Rng2_F32 b);
-#endif //BASE_MATH_H
diff --git a/src/base/base_memory.c b/src/base/base_memory.c
deleted file mode 100644
index e92d4a1..0000000
--- a/src/base/base_memory.c
+++ /dev/null
@@ -1,166 +0,0 @@
-#include
-#include
-
-#if !defined(m_reserve)
-#error missing definition for 'm_reserve' type: (U64)->void*
-#endif
-#if !defined(m_commit)
-#error missing definition for 'm_commit' type: (void*, U64)->void
-#endif
-#if !defined(m_decommit)
-#error missing definition for 'm_decommit' type: (void*, U64)->void
-#endif
-#if !defined(m_release)
-#error missing definition for 'm_release' type: (void*, U64)->void
-#endif
-
-static Arena *g_scratch_arena = 0;
-
-root_function void
-m_change_memory_noop(void *ptr, U64 size) {}
-
-// Malloc implementation of the M_Base_memory
-root_function void*
-m_malloc_reserve(U64 size) {
- return malloc(size);
-}
-
-root_function void
-m_malloc_release(void *ptr, U64 size) {
- free(ptr);
-}
-
-//~ 64-bit memory arena
-
-root_function Arena
-*m_make_arena_reserve(U64 reserve_size) {
- Arena *result = 0;
- U64 initial_commit_size = ARENA_COMMIT_GRANULARITY;
- if (reserve_size >= initial_commit_size) {
- void *memory = m_reserve(reserve_size);
- // Since we use "header" space we must ensure the initial commit can fit the Arena struct.
- Assert(initial_commit_size >= sizeof(Arena));
- m_commit(memory, ARENA_COMMIT_GRANULARITY);
- result = (Arena*)memory;//(Arena*)result; <- this has to be mistake in Allen's video.. ?
- // After we have pointed to our newly reserved and commited memory,
- // we fill in the "header" parts, which are just the members of the arena type.
- result->capacity = reserve_size;
- result->commit_pos = initial_commit_size;
- result->align = 8; // 8-bytes alignment?
- result->pos = sizeof(Arena); // Here we point the position to after the Arena "header" section.
- }
- return result;
-}
-
-root_function Arena*
-m_make_arena() {
- Arena* result = m_make_arena_reserve(M_DEFAULT_RESERVE_SIZE);
- return result;
-}
-
-// NOTE(anton): rjf calls this "arena push no zero", as opposed to pushing a zeroed array.
-// Not sure why we would make this differentiation, maybe not important.
-
-root_function void*
-m_arena_push(Arena *arena, U64 size) {
- void *result = 0;
- if (arena->pos + size <= arena->capacity) {
- /*U8 *base = (U8 *)arena; // Get memory base pointer.
- // Adjust by any alignment if necessary.
- // Doing modulo ensures we get a number in the 0-align-1 range.
- U64 post_align_pos = (arena->pos + (arena->align-1)):
- post_align_pos = post_align_pos % arena->align;
- // What's happening here? Almost certainly the align will overflow here?
- // Are we filling the allocated space backwards or what's up?
- // TODO(anton): UNDERSTAND
- U64 align = post_align_pos - arena->pos;
- result = base + arena->pos + align;
- arena->pos += size + align;*/
- // Do Allen4th version until I understand the above.
- result = ((U8*) arena) + arena->pos;
- arena->pos += size; // increment pos by what we want to push
-
- U64 p = arena->pos;
- U64 commit_p = arena->commit_pos;
- if (p > commit_p) {
- U64 p_aligned = AlignUpToPow2(p, M_COMMIT_BLOCK_SIZE);
- U64 next_commit_p = ClampTop(p_aligned, arena->capacity); // Make sure new commit_p won't overshoot capacity
- U64 commit_size = next_commit_p - commit_p;
- m_commit((U8 *)arena + commit_p, commit_size);
- arena->commit_pos = next_commit_p;
- }
- } else {
- // NOTE(anton): Should implement some fallback but now we fail.
- }
- return result;
-}
-
-root_function void
-m_arena_pop_to(Arena *arena, U64 pos) {
- if (pos < arena->pos) {
- arena->pos = pos;
-
- U64 p = arena->pos;
- U64 p_aligned = AlignUpToPow2(p, M_COMMIT_BLOCK_SIZE);
- U64 next_commit_p = ClampTop(p_aligned, arena->capacity);
-
- U64 commit_p = arena->commit_pos;
- if (next_commit_p < commit_p) {
- U64 decommit_size = commit_p - next_commit_p;
- m_decommit((U8 *)arena + next_commit_p, decommit_size);
- arena->commit_pos = next_commit_p;
- }
- }
-}
-
-root_function void m_arena_pop(Arena* arena, U64 size) {
- U64 min_pos = sizeof(Arena);
- U64 size_to_pop = Min(size, arena->pos);
- U64 new_pos = arena->pos - size_to_pop;
- new_pos = Max(new_pos, min_pos);
- m_arena_pop_to(arena, new_pos);
-}
-
-/** Push size and set the memory to zero. */
-root_function void*
-m_arena_push_zero(Arena *arena, U64 size) {
- void *result = m_arena_push(arena, size);
- MemoryZero(result, size);
- return result;
-}
-
-root_function void
-m_arena_clear(Arena *arena)
-{
- // We clear the input arena by popping off everything
- // after the actual Arena information.
- m_arena_pop_to(arena, sizeof(Arena));
-}
-
-root_function void
-m_arena_align(Arena *arena, U64 pow2_alignment) {
- U64 p = arena->pos;
- U64 p_aligned = AlignUpToPow2(p, pow2_alignment);
- U64 z = p_aligned - p;
- if (z > 0) {
- m_arena_push(arena, z);
- }
-}
-
-root_function void
-m_arena_release(Arena* arena) {
- m_release(arena, arena->capacity);
-}
-
-root_function ArenaTemp
-m_arena_temp_begin(Arena *arena) {
- ArenaTemp temp = { 0 };
- temp.arena = arena;
- temp.pos = arena->pos;
- return temp;
-}
-
-root_function void
-m_arena_temp_end(ArenaTemp temp) {
- m_arena_pop_to(temp.arena, temp.pos);
-}
diff --git a/src/base/base_memory.h b/src/base/base_memory.h
deleted file mode 100644
index 907a14c..0000000
--- a/src/base/base_memory.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* date = April 20th 2023 9:43 pm */
-
-#ifndef BASE_MEMORY_H
-#define BASE_MEMORY_H
-
-#if !defined(ARENA_COMMIT_GRANULARITY)
-#define ARENA_COMMIT_GRANULARITY Kilobytes(4)
-#endif
-
-#if !defined(ARENA_DECOMMIT_THRESHOLD)
-#define ARENA_DECOMMIT_THRESHOLD Megabytes(64)
-#endif
-
-#if !defined(M_DEFAULT_RESERVE_SIZE)
-#define M_DEFAULT_RESERVE_SIZE Megabytes(512)
-#endif
-
-#if !defined(M_COMMIT_BLOCK_SIZE)
-#define M_COMMIT_BLOCK_SIZE Megabytes(64)
-#endif
-
-// We store this information in the header of the allocated memory for the arena!!!
-typedef struct Arena Arena;
-struct Arena {
- U64 pos;
- U64 commit_pos;
- U64 capacity;
- U64 align;
-};
-
-typedef struct ArenaTemp ArenaTemp;
-struct ArenaTemp {
- Arena *arena;
- U64 pos;
-};
-
-root_function void m_change_memory_noop(void *ptr, U64 size);
-
-root_function Arena* m_make_arena_reserve(U64 reserve_size);
-root_function Arena* m_make_arena();
-
-root_function void m_arena_release(Arena *arena);
-root_function void* m_arena_push(Arena *arena, U64 size);
-root_function void m_arena_pop_to(Arena *arena, U64 pos);
-root_function void m_arena_pop(Arena* arena, U64 size);
-root_function void m_arena_align(Arena *arena, U64 pow2_alignment);
-root_function void* m_arena_push_zero(Arena *arena, U64 size);
-root_function void m_arena_clear(Arena *arena);
-
-#define PushArray(arena, type, count) (type *)m_arena_push((arena), sizeof(type)*(count))
-#define PushArrayZero(arena, type, count) (type *)m_arena_push_zero((arena), sizeof(type)*(count))
-
-//~ temp arena
-
-root_function ArenaTemp m_arena_temp_begin(Arena *arena);
-root_function void m_arena_temp_end(ArenaTemp temp);
-
-// TODO(anton): Not sure when I should use this?
-#define ArenaTempBlock(arena, name) ArenaTemp name = { 0 }; DeferLoop(name = m_arena_temp_begin(arena), m_arena_temp_end(name))
-
-#endif //BASE_MEMORY_H
diff --git a/src/base/base_strings.c b/src/base/base_strings.c
deleted file mode 100644
index 1e9be2f..0000000
--- a/src/base/base_strings.c
+++ /dev/null
@@ -1,510 +0,0 @@
-#include
-
-//~ Helpers
-root_function U64
-calculate_string_C_string_length(char *cstr) {
- /*U64 length = 0;
- for(char* p = cstr; p != '\0'; p += 1) {
- length += 1;
- }
- return length;*/
- // A cool way to write this is this while loop
- U64 length = 0;
- for (/* empty here means just while loop*/;
- /* While we're not at null terminator */ cstr[length];
- /* Increment */ length += 1);
-
- // Then we're actually done and just return length;
- return length;
-}
-
-
-//~ Constructors
-root_function String8
-str8(U8 *str, U64 size) {
- String8 string;
- string.str = str;
- string.size = size;
- return string;
-}
-
-root_function String8
-str8_range(U8 *first, U8 *one_past_last) {
- String8 string;
- string.str = first;
- string.size = (U64)(one_past_last - first);
- return string;
-}
-
-//~ Substrings
-//- String8
-root_function String8
-str8_substr(String8 string, U64 first, U64 one_past_last) {
- // We get a substring from the range one_past_last - first
- U64 min = first;
- U64 max = one_past_last;
- // Logic to prepare for swithing input to a range instead of first/one_past_last
- if (max > string.size) {
- max = string.size;
- }
- if (min > string.size) {
- min = string.size;
- }
- if (min > max) {
- U64 swap = min;
- min = max;
- max = swap;
- }
- string.size = max - min;
- string.str += min; // Increment the pointer of the String8 to the min.
- return string;
-}
-
-root_function String8 str8_prefix(String8 string, U64 size) { return str8_substr(string, 0, size); }
-root_function String8 str8_chop(String8 string, U64 amount) { return str8_substr(string, 0, string.size-amount); }
-root_function String8 str8_suffix(String8 string, U64 size) { return str8_substr(string, string.size-size, string.size); }
-root_function String8 str8_skip(String8 string, U64 amount) { return str8_substr(string, amount, string.size); }
-
-// String16
-// String32
-
-//~ Lists
-//- String8
-root_function void
-str8_list_push_node(String8List *list, String8Node *n) {
- QueuePush(list->first, list->last, n);
- list->node_count += 1;
- list->total_size += n->string.size;
-}
-
-root_function void
-str8_list_push_node_front(String8List *list, String8Node *n) {
- QueuePushFront(list->first, list->last, n);
- list->node_count += 1;
- list->total_size += n->string.size;
-}
-
-// Wrapper that pushes the memory for a node onto the arena, and then puts the node in the linked list (in the back).
-root_function void
-str8_list_push(Arena *arena, String8List *list, String8 string) {
- String8Node *n = PushArrayZero(arena, String8Node, 1);
- n->string = string;
- str8_list_push_node(list, n);
-}
-
-// Wrapper that pushes the memory for a node onto the arena, and then puts the node in the linked list (in the front).
-root_function void
-str8_list_push_front(Arena *arena, String8List *list, String8 string) {
- String8Node *n = PushArrayZero(arena, String8Node, 1);
- n->string = string;
- str8_list_push_node_front(list, n);
-}
-
-root_function void
-str8_list_concat(String8List *list, String8List *to_push) {
- // If to_push is a non-zero length String8List,
- // we add it to the input list.
- if (to_push->first) {
- list->node_count += to_push->node_count;
- list->total_size += to_push->total_size;
- // If the input list's last element is null
- // we had a zero length input list, and we just set the input list equal to to_push
- if (list->last == 0) {
- *list = *to_push;
- } else {
- // Else we append the to_push list to the input list.
- list->last->next = to_push->first;
- list->last = to_push->last;
- }
- }
- // TODO(anton): Why are we zeroing the memory here?
- MemoryZero(to_push, sizeof(*to_push));
- //LOG_NOT_IMPLEMENTED;
-}
-
-// TODO(anton): Understand this function and write comments about the logic.
-root_function String8List
-str8_split(Arena *arena, String8 string, int split_count, String8 *splits) {
-
- String8List list = { 0 };
-
- U64 split_start = 0;
- for (U64 i = 0; i < string.size; i += 1)
- {
- B32 was_split = 0;
- for (int split_idx = 0; split_idx < split_count; split_idx += 1)
- {
- B32 match = 0;
- if (i + splits[split_idx].size <= string.size)
- {
- match = 1;
- for (U64 split_i = 0; split_i < splits[split_idx].size && i + split_i < string.size; split_i += 1)
- {
- if (splits[split_idx].str[split_i] != string.str[i + split_i])
- {
- match = 0;
- break;
-
- }
- }
- }
- if (match)
- {
- String8 split_string = str8(string.str + split_start, i - split_start);
- str8_list_push(arena, &list, split_string);
- split_start = i + splits[split_idx].size;
- i += splits[split_idx].size - 1;
- was_split = 1;
- break;
- }
- }
-
- if (was_split == 0 && i == string.size - 1)
- {
- String8 split_string = str8(string.str + split_start, i + 1 - split_start);
- str8_list_push(arena, &list, split_string);
- break;
- }
- }
-
- return list;
-}
-
-// TODO(anton): Understand this function and write good comments explaining.
-root_function String8
-str8_list_join(Arena *arena, String8List list, StringJoin *optional_params) {
- // rjf: setup join parameters
- StringJoin join = { 0 };
- if (optional_params != 0)
- {
- MemoryCopy(&join, optional_params, sizeof(join));
- }
-
- // rjf: calculate size & allocate
- U64 sep_count = 0;
- if (list.node_count > 1)
- {
- sep_count = list.node_count - 1;
- }
- String8 result = { 0 };
- result.size = (list.total_size + join.pre.size +
- sep_count*join.sep.size + join.post.size);
- result.str = PushArray(arena, U8, result.size + 1);
-
- // rjf: fill
- U8 *ptr = result.str;
- MemoryCopy(ptr, join.pre.str, join.pre.size);
- ptr += join.pre.size;
- for (String8Node *node = list.first; node; node = node->next)
- {
- MemoryCopy(ptr, node->string.str, node->string.size);
- ptr += node->string.size;
- if (node != list.last)
- {
- MemoryCopy(ptr, join.sep.str, join.sep.size);
- ptr += join.sep.size;
- }
- }
- MemoryCopy(ptr, join.post.str, join.post.size);
- ptr += join.post.size;
-
- // rjf: add null
- result.str[result.size] = 0;
-
- return result;
-}
-
-//~ Allocation and format strings
-root_function String8
-str8_copy(Arena *arena, String8 string) {
- String8 result;
- result.size = string.size;
- result.str = PushArray(arena, U8, string.size + 1);
- MemoryCopy(result.str, string.str, string.size);
- result.str[string.size] = 0; // TODO(anton): What is this?
- return result;
-}
-
-root_function String8
-str8_pushfv(Arena *arena, char *fmt, va_list args) {
-
- // Might need to try a second time so copy args
- va_list args2;
- va_copy(args2, args);
-
- // Try to build string using 1024 bytes
- U64 buffer_size = 1024;
- U8 *buffer = PushArray(arena, U8, buffer_size);
- // The vsnprintf takes the bundled arguments list args and puts the format strings it into buffer.
- U64 actual_size = vsnprintf((char*)buffer, buffer_size, fmt, args);
-
- String8 result = { 0 };
- if (actual_size < buffer_size) {
- // The first try worked and we can pop whatever wasn't used from the buffer
- // and get our resulting string.
- m_arena_pop(arena, buffer_size - actual_size - 1); // -1 because of null terminated in char *fmt?
- result = str8(buffer, actual_size);
- } else {
- // If first try failed we try again with better size
- m_arena_pop(arena, buffer_size);
- U8 *fixed_buffer = PushArray(arena, U8, actual_size + 1);
- U64 final_size = vsnprintf((char*)fixed_buffer, actual_size + 1, fmt, args2);
- result = str8(fixed_buffer, final_size);
- }
-
- // va_end to help compiler do its thing.
- va_end(args2);
-
- return result;
-}
-
-root_function String8
-str8_pushf(Arena *arena, char*fmt, ...) {
- String8 result = { 0 };
- va_list args;
- va_start(args, fmt);
- result = str8_pushfv(arena, fmt, args);
- va_end(args);
- return result;
-}
-
-root_function void
-str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...) {
- va_list args;
- va_start(args, fmt);
- String8 string = str8_pushfv(arena, fmt, args);
- va_end(args);
- str8_list_push(arena, list, string);
-}
-
-//~ Unicode conversions
-
-#define bitmask1 0x01 // Mask first bit
-#define bitmask2 0x03 // Mask 2 bits, 3 = 0x03 = 0000 0011 = 2^2 - 1
-#define bitmask3 0x07 // Mask 3 bits, 7 = 0x07 = 0000 0111 = 2^3 - 1
-#define bitmask4 0x0F // Mask 4 bits, 15 = 0x0F = 0000 1111 = 2^4 - 1
-#define bitmask5 0x1F // Mask 5 bits, 31 = 0x1F = 0001 1111 = 2^5 - 1
-#define bitmask6 0x3F // Mask 6 bits, 63 = 0x3F = 0011 1111 = 2^6 - 1
-#define bitmask7 0x7F // Mask 7 bits, 127 = 0x7F = 0111 1111 = 2^7 - 1
-#define bitmask8 0xFF // Mask 8 bits, 255 = 0xFF = 1111 1111 = 2^8 - 1
-
-// Note that we're only decoding valid cases and not handling invalid/errors
-root_function DecodeCodepoint
-decode_from_utf8(U8 *str, U64 max) {
- // This table will give us wheter or not we have a codepoint encoded by one, two, three or four bytes.
- local_persist U8 utf8_class[] = {
- 1, 1, 1, 1,
- 1, 1, 1, 1,
- 1, 1, 1, 1,
- 1, 1, 1, 1,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 2, 2, 2, 2,
- 3, 3,
- 4,
- 5 // error
- };
-
- DecodeCodepoint result = { ~((U32)0), 1 };
- // We'll shift out the lowest 3 bits since those are not important in the decoding.
- // This is the byte >> 3 into the static array.
- U8 byte = str[0];
- U8 byte_class = utf8_class[byte >> 3];
-
- switch (byte_class) {
- case 1: {
- // Just a single byte encoding.
- result.codepoint = byte; // Actually the 8th bit must be zero for valid UTF encoding.
- } break;
-
- case 2: {
- if (2 <= max) {
- U8 cont_byte = str[1];
- // Check the second byte
- if (utf8_class[cont_byte >> 3] == 0) {
- // codepoint is 32-bits
- // The case with two bytes has byte1 110xxxxx, ie encoded in the last 5 bits.
- // and byte2 is 10xxxxxx, encoded in the last 6 bits. So we use mask5 on first byte, shift by 6,
- // and mask6 on second byte.
- result.codepoint = (byte & bitmask5) << 6;
- result.codepoint |= (cont_byte & bitmask6);
- result.advance = 2;
- }
- }
- } break;
-
- case 3: {
- if (3 <= max) {
- // encoded by 3 bytes, so we have two more cont_bytes.
- U8 cont_byte[2] = { str[1], str[2] };
- if (utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0) {
- // For this case the first byte is encoded in the last 4 bits, 1110xxxx
- // The second and third is 10xxxxxx (last 6 bits)
- result.codepoint = (byte & bitmask4) << 12;
- result.codepoint |= (cont_byte[0] & bitmask6) << 6;
- result.codepoint |= (cont_byte[1] & bitmask6);
- result.advance = 3;
- }
- }
- } break;
-
- case 4: {
- if (4 <= max) {
- U8 cont_byte[3] = { str[1], str[2], str[3] };
- if (utf8_class[cont_byte[0] >> 3] == 0 &&
- utf8_class[cont_byte[1] >> 3] == 0 &&
- utf8_class[cont_byte[2] >> 3] == 0) {
- // Here first byte is encoded in last 3 bits, and byte 2,3,4 are encoded in last 6 bits.
- // Thus we shift the first byte by 3*6 = 18 bits into the 32 bit codepoint;
- result.codepoint = (byte & bitmask3) << 18;
- result.codepoint |= (cont_byte[0] & bitmask6) << 12;
- result.codepoint |= (cont_byte[1] & bitmask6) << 6;
- result.codepoint |= (cont_byte[2] & bitmask6);
- result.advance = 4;
- }
- }
- } break;
- }
-
- return result;
-}
-
-// Encode function
-root_function U32
-utf8_from_codepoint(U8* out, U32 codepoint) {
- U8 bit8 = 0x80;
- U32 advance = 0;
-
- if (codepoint <= bitmask7 /* 0111 1111 */) {
- // We know that the whole encoding is in the last 7 bits, so it's a 1 byte encoding
- out[0] = (U8)codepoint;
- advance = 1;
-
- } else if (codepoint <= 0x07FF /*0000 0111 1111 1111*/) {
- // The case with two bytes has byte1 110xxxxx, ie encoded in the last 5 bits.
- // and byte2 is 10xxxxxx, encoded in the last 6 bits.
- out[0] = (bitmask2 << 6) | ((codepoint >> 6) & bitmask5);
- out[1] = bit8 | (codepoint & bitmask6);
- advance = 2;
-
- } else if (codepoint <= 0xFFFF /* 1111 1111 1111 1111 */) {
- // For this case the first byte is encoded in the last 4 bits, 1110xxxx
- // The second and third is 10xxxxxx (last 6 bits)
- out[0] = (bitmask3 << 5) | ((codepoint >> 12) & bitmask4);
- out[1] = bit8 | ((codepoint >> 6) & bitmask6);
- out[2] = bit8 | ((codepoint) & bitmask6);
- advance = 3;
-
- } else if (codepoint <= 0x10FFFF /*0001 0000 1111 1111 1111 1111 */) {
- // Here first byte is encoded in last 3 bits, and byte 2,3,4 are encoded in last 6 bits.
- // Thus we shift the first byte by 3*6 = 18 bits into the 32 bit codepoint;
- out[0] = (bitmask4 << 4) | ((codepoint >> 18) & bitmask3);
- out[1] = bit8 | ((codepoint >> 12) & bitmask6);
- out[2] = bit8 | ((codepoint >> 6) & bitmask6);
- out[3] = bit8 | ((codepoint) & bitmask6);
- advance = 4;
- } else {
- out[0] = '?'; // ERrror?
- advance = 1;
- }
-
- return advance;
-}
-
-root_function DecodeCodepoint decode_from_utf16(U16 *str, U64 max) {
- DecodeCodepoint result = { ~((U32)0), 1 };
- result.codepoint = str[0];
- result.advance = 1;
- // Usually codepoints fit into a single 16 bit chunk.
- // But when we're not in the ranges 0x0000 to 0xD7FF and 0xE000 to 0xFFFF,
- // we need two 16 bit stores.
- // So what we have in str[0] = W1 is the "high surrogate", and
- // str[1] = W2 is the "low surrogate". We then get the codepoint U = U' + 0x10000,
- // where U' is a 20-bit number with the 10 lower bits from W1 in the high bits, and 10 lower bits of W2 in the lower.
- if (max > 1) {
- U16 w1 = str[0];
- U16 w2 = str[1];
- if (0xD800 <= w1 && w1 < 0xDC00 && 0xDC00 <= w2 && w2 < 0xE000) {
- // Get W1 ten bits
- U16 y = w1 - 0xD800;
- U16 x = w2 - 0xDC00;
- U32 uprim = (y << 10) | x;
- result.codepoint = uprim + 0x10000;
- result.advance = 2;
- }
- }
- return result;
-}
-
-root_function U32 utf16_from_codepoint(U16* out, U32 codepoint) {
-
- U32 advance = 1;
- if (codepoint == ~((U32)0)) {
- // Error?
- out[0] = (U16)'?';
- } else if (codepoint < 0x10000) {
- // single 16 bit code unit
- out[0] = (U16)codepoint;
- } else {
- // store 20 bits in uprim
- U32 uprim = codepoint - 0x10000;
- // create W1
- out[0] = 0xD800 + (uprim >> 10);
- // 0x03FF = bitmask for 10 lowest bits
- // create W2
- out[1] = 0xDC00 + (uprim & 0x03FF);
- advance = 2;
- }
- return advance;
-}
-
-// TODO(anton): understand this and write comments on steps
-root_function String8
-str8_from16(Arena *arena, String16 string) {
- U64 cap = string.size*3;
- U8 *str = PushArray(arena, U8, cap + 1);
- U16 *ptr = string.str;
- U16 *one_past_last = ptr + string.size;
- U64 size = 0;
- DecodeCodepoint consume;
- for (; ptr < one_past_last;) {
- consume = decode_from_utf16(ptr, one_past_last - ptr);
- ptr += consume.advance;
- size += utf8_from_codepoint(str + size, consume.codepoint);
- }
- str[size] = 0;
- m_arena_pop(arena, cap - size);
- return str8(str, size);
-}
-
-root_function String8
-str8_from32(Arena *arena, String32 string) {
-
-}
-
-// TODO(anton): understand this and write comments on steps
-root_function String16
-str16_from8(Arena* arena, String8 string) {
- U64 cap = string.size*2;
- U16 *str = PushArray(arena, U16, cap + 1);
- U8 *ptr = string.str;
- U8 *one_past_last = ptr + string.size;
- U64 size = 0;
- DecodeCodepoint consume;
- for (; ptr < one_past_last;) {
- consume = decode_from_utf8(ptr, one_past_last - ptr);
- ptr += consume.advance;
- size += utf16_from_codepoint(str + size, consume.codepoint);
- }
- str[size] = 0;
- m_arena_pop(arena, 2*(cap - size));
- String16 result;
- result.str = str;
- result.size = size;
- return result;
-}
-
-root_function String32
-str32_from8(Arena *arena, String8 string) {
-
-}
\ No newline at end of file
diff --git a/src/base/base_strings.h b/src/base/base_strings.h
deleted file mode 100644
index acdaec7..0000000
--- a/src/base/base_strings.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* date = April 23rd 2023 10:47 am */
-
-#ifndef BASE_STRINGS_H
-#define BASE_STRINGS_H
-
-// We decide that the basic string handling will be immutable.
-// This means that whatever memory we got when initialising the string is what we have to live with.
-// This will give us easy interfaces and work for most cases.
-// The downside is that it might not have the best performance, always.
-// In such cases we will develop special code for handling the special cases.
-
-/////////////////////////
-//~ Basic string types, lists and arrays
-
-typedef struct String8 String8;
-struct String8 {
- U8* str;
- U64 size;
-};
-
-typedef struct String16 String16;
-struct String16 {
- U16 *str;
- U64 size;
-};
-
-typedef struct String32 String32;
-struct String32 {
- U32 *str;
- U64 size;
-};
-
-typedef struct String8Node String8Node;
-struct String8Node {
- String8Node *next;
- String8 string;
-};
-
-typedef struct String8List String8List;
-struct String8List {
- String8Node *first;
- String8Node *last;
- U64 node_count;
- U64 total_size;
-};
-
-typedef struct String8Array String8Array;
-struct String8Array {
- U64 count;
- String8 *v;
-};
-
-/////////////////////////
-//~ String operations
-typedef struct StringJoin StringJoin;
-struct StringJoin {
- String8 pre;
- String8 sep;
- String8 post;
-};
-
-typedef struct DecodeCodepoint DecodeCodepoint;
-struct DecodeCodepoint {
- U32 codepoint;
- U32 advance;
-};
-
-
-/////////////////////////
-//~ String operations
-//~ String functions
-
-//- Helpers
-root_function U64 calculate_string_C_string_length(char *cstr);
-
-//- Constructors
-root_function String8 str8(U8 *str, U64 size);
-// Get a String8 from a C-string.
-#define str8_C(cstring) str8((U8 *)cstring,calculate_string_C_string_length(cstring))
-// Get a String8 from a literal
-#define str8_lit(s) str8((U8*)(s), sizeof(s) - 1) // -1 since we don't want null terminated,
- // but this still stores the null char for interop with APIs
- // that expect Cstrings.
-// Specify a Str8 as just its struct members
-#define str8_lit_comp(s) {(U8*)(s), sizeof(s)-1}
-root_function String8 str8_range(U8 *first, U8 *one_past_last);
-
-#define str8_struct(ptr) str8((U8 *)(ptr), sizeof(*(ptr)))
-
-//- Substrings
-root_function String8 str8_substr(String8 string, U64 first, U64 one_past_last);
-root_function String8 str8_prefix(String8 string, U64 size);
-root_function String8 str8_chop(String8 string, U64 amount);
-root_function String8 str8_suffix(String8 string, U64 size);
-root_function String8 str8_skip(String8 string, U64 amount);
-
-// Used in format strings!
-#define str8_expand(s) (int)((s).size), ((s).str)
-
-//- Lists
-root_function void str8_list_push_node(String8List *list, String8Node *n);
-root_function void str8_list_push_node_front(String8List *list, String8Node *n);
-root_function void str8_list_push(Arena *arena, String8List *list, String8 string);
-root_function void str8_list_push_front(Arena *arena, String8List *list, String8 string);
-root_function void str8_list_concat(String8List *list, String8List *to_push);
-root_function String8List str8_split(Arena *arena, String8 string, int split_count, String8 *splits);
-root_function String8 str8_list_join(Arena *arena, String8List list, StringJoin *optional_params);
-
-//- Allocation and format strings
-root_function String8 str8_copy(Arena *arena, String8 string);
-root_function String8 str8_pushfv(Arena *arena, char *fmt, va_list args);
-root_function String8 str8_pushf(Arena *arena, char* fmt, ...);
-root_function void str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...);
-
-//~ Unicode conversions
-root_function DecodeCodepoint decode_from_utf8(U8 *str, U64 max);
-root_function U32 utf8_from_codepoint(U8* out, U32 codepoint);
-root_function DecodeCodepoint decode_from_utf16(U16 *str, U64 max);
-root_function U32 utf16_from_codepoint(U16* out, U32 codepoint);
-root_function String8 str8_from16(Arena *arena, String16 string);
-root_function String8 str8_from32(Arena *arena, String32 string);
-root_function String16 str16_from8(Arena* arena, String8 string);
-root_function String32 str32_from8(Arena *arena, String8 string);
-#endif //BASE_STRINGS_H
diff --git a/src/base/base_thread_context.c b/src/base/base_thread_context.c
deleted file mode 100644
index 124d84f..0000000
--- a/src/base/base_thread_context.c
+++ /dev/null
@@ -1,82 +0,0 @@
-
-root_function ThreadContext
-thread_context_alloc(void)
-{
- ThreadContext result = { 0 };
-
- for (U64 arena_index = 0; arena_index < ArrayCount(result.arenas); arena_index += 1)
- {
- result.arenas[arena_index] = m_make_arena_reserve(Gigabytes(8));
- }
- return result;
-}
-
-root_function void
-thread_context_release(ThreadContext *context)
-{
- for (U64 arena_index = 0; arena_index < ArrayCount(context->arenas); arena_index += 1)
- {
- m_arena_release(context->arenas[arena_index]);
- }
-}
-
-
-per_thread ThreadContext *tl_thread_context;
-
-no_name_mangle void
-thread_context_set(ThreadContext *context)
-{
- tl_thread_context = context;
-}
-
-no_name_mangle ThreadContext *
-thread_context_get(void)
-{
- return tl_thread_context;
-}
-
-
-root_function B32 is_main_thread(void)
-{
- ThreadContext *context = thread_context_get();
- return context->is_main_thread;
-}
-
-root_function ArenaTemp
-scratch_get(Arena **conflicts, U64 conflict_count)
-{
- ArenaTemp scratch = { 0 };
- ThreadContext *thread_context = thread_context_get();
- for (U64 arena_index = 0; arena_index < ArrayCount(thread_context->arenas); arena_index += 1)
- {
- B32 is_conflicting = 0;
- for(Arena **conflict = conflicts; conflict < conflicts+conflict_count; conflict += 1)
- {
- if(*conflict == thread_context->arenas[arena_index])
- {
- is_conflicting = 1;
- break;
- }
- }
- if(is_conflicting == 0)
- {
- scratch.arena = thread_context->arenas[arena_index];
- scratch.pos = scratch.arena->pos;
- break;
- }
- }
- return scratch;
-}
-
-root_function void
-base_main_thread_entry(void (*entry)(void), U64 argument_count, char **arguments)
-{
- // Here we get memory for the thread arenas, and notify that it's a main thread.
- ThreadContext thread_context = thread_context_alloc();
- thread_context.is_main_thread = 1;
- // Here we set it to the global thread context variable
- thread_context_set(&thread_context);
- // Then call the entry point function for our program
- entry();
- thread_context_release(&thread_context);
-}
\ No newline at end of file
diff --git a/src/base/base_thread_context.h b/src/base/base_thread_context.h
deleted file mode 100644
index 42a0776..0000000
--- a/src/base/base_thread_context.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* date = April 29th 2023 9:18 pm */
-
-#ifndef BASE_THREAD_CONTEXT_H
-#define BASE_THREAD_CONTEXT_H
-
-typedef struct ThreadContext ThreadContext;
-struct ThreadContext
-{
- Arena *arenas[2]; // WHy 2 arenas?
- char *file_name;
- U64 line_number;
- U8 thread_name[32];
- U64 thread_name_size;
- B32 is_main_thread;
-};
-
-//root_function ThreadContext make_thread_context(void);
-
-root_function ThreadContext thread_context_alloc(void);
-root_function void thread_context_release(ThreadContext *context);
-
-no_name_mangle void
-thread_context_set(ThreadContext *context);
-no_name_mangle ThreadContext *
-thread_context_gett(void);
-
-
-root_function B32 is_main_thread(void);
-
-//~ scratch memory
-root_function ArenaTemp scratch_get(Arena **conflicts, U64 conflict_count);
-#define scratch_release(temp) m_arena_temp_end(temp)
-
-//~ entry
-// Takes a function pointer to the app entry function.
-root_function void
-base_main_thread_entry(void (*entry)(void), U64 argument_count, char **arguments);
-
-#endif //BASE_THREAD_CONTEXT_H
diff --git a/src/draw/draw.c b/src/draw/draw.c
deleted file mode 100644
index 9968281..0000000
--- a/src/draw/draw.c
+++ /dev/null
@@ -1,263 +0,0 @@
-
-
-/////////////////////////
-//~ Draw globals
-global D_State *d_state = 0;
-per_thread D_ThreadCtx *d_thread_ctx = 0;
-
-// temp color stuff
-global F32 g_text_color[4] = {0.95f, 0.9f, 0.94f, 1.0f};
-global F32 g_rect_color[4] = {0.6f, 0.5f, 0.6f, 1.0f};
-
-
-////////////////////////////////
-//~ Stack helper macros
-
-#define D_StackPush(node_type, val_type, name, new_val) \
-{\
-Arena *arena = D_active_arena();\
-D_Bucket *bucket = D_active_bucket();\
-node_type *node_v = bucket->name##_free;\
-if(node_v != 0) {StackPop(bucket->name##_free);}\
-else {node_v = PushArray(arena, node_type, 1);}\
-node_v->v = new_val;\
-new_val = bucket->name##_stack_top->v;\
-StackPush(bucket->name##_stack_top, node_v);\
-bucket->last_cmd_stack_gen = bucket->current_stack_gen;\
-bucket->current_stack_gen += 1;\
-return new_val;\
-}
-
-#define D_StackPop(node_type, val_type, name) \
-{\
-val_type result = d_thread_ctx->name##_nil_stack_top.v;\
-D_Bucket *bucket = D_active_bucket();\
-if(bucket->name##_stack_top != &d_thread_ctx->name##_nil_stack_top)\
-{\
-node_type *node = bucket->name##_stack_top;\
-result = node->v;\
-StackPop(bucket->name##_stack_top);\
-StackPush(bucket->name##_free, node);\
-bucket->last_cmd_stack_gen = bucket->current_stack_gen;\
-bucket->current_stack_gen += 1;\
-}\
-return result;\
-}
-
-#define D_StackTop(node_type, val_type, name) \
-{\
-D_Bucket *bucket = D_active_bucket();\
-val_type result = bucket->name##_stack_top->v;\
-return result;\
-}
-
-/////////////////////////
-//~ "Generated" code
-#include "draw_meta.c"
-
-/////////////////////////
-//~ Layer init
-root_function D_InitReceipt
-D_init(R_InitReceipt r_init_receipt, F_InitReceipt f_init_receipt)
-{
- if(is_main_thread() && d_state == 0)
- {
- Arena* arena = m_make_arena_reserve(Megabytes(2));
- d_state = PushArrayZero(arena, D_State, 1);
- d_state->arena = arena;
- d_state->font_texture = F_atlas_texture_handle();
- D_ensure_thread_initialised();
- }
- D_InitReceipt receipt = {0};
- return receipt;
-}
-
-root_function void
-D_ensure_thread_initialised(void)
-{
- if(d_thread_ctx == 0)
- {
- Arena *arena = m_make_arena_reserve(Megabytes(1));
- d_thread_ctx = PushArrayZero(arena, D_ThreadCtx, 1);
- d_thread_ctx->arena = arena;
- d_thread_ctx->fallback_arena = m_make_arena_reserve(Megabytes(256));
- D_InitBucketStacks(&d_thread_ctx->fallback_bucket);
- d_thread_ctx->bucket_selection_fallback.arena = d_thread_ctx->fallback_arena;
- d_thread_ctx->bucket_selection_fallback.bucket = &d_thread_ctx->fallback_bucket;
- d_thread_ctx->bucket_selection_top = &d_thread_ctx->bucket_selection_fallback;
- D_InitThreadStackTops;
- }
-}
-
-/////////////////////////
-//~ Draw functions
-
-
-root_function void
-D_frame_begin() {
- D_ensure_thread_initialised();
-}
-
-root_function void
-D_frame_end()
-{
-
-}
-
-//- Rect
-root_function R_Rect2DInst *
-D_rect2D_(Rng2_F32 rect, D_RectParams *rect_params)
-{
- Arena* arena = D_active_arena();
- D_Bucket *bucket = D_active_bucket();
- R_Pass *pass = D_pass_from_bucket(arena, bucket, R_PassKind_UI);
- R_PassParams_UI *pass_params = pass->params_ui;
- R_BatchGroup2DNode *batch_group = pass_params->rects.last;
- R_Handle tex = d_state->font_texture;
-
- // If we don't have a batch group yet we initialise it here.
- // Eventually we will also check for what different textures we have, since
- // we batch by texture. What about transform?
- // TODO(anton): understand buckets in rjf codebase.
- if(batch_group == 0 || bucket->last_cmd_stack_gen != bucket->current_stack_gen)
- {
- batch_group = PushArrayZero(arena, R_BatchGroup2DNode, 1);
- QueuePush(pass_params->rects.first, pass_params->rects.last, batch_group);
- pass_params->rects.count += 1;
- batch_group->params.albedo_tex = tex;
- batch_group->params.albedo_tex_sample_kind = bucket->tex2d_sample_kind_stack_top->v;
- Mat3x3_F32 xform2d = {0.0f};
- batch_group->params.xform2d = xform2d;
- }
- // Here we get the available memory in a batch of memory that can be filled with differen things.
- // We get a chunk of that memory of the appropriate size for a R_Rect2DInst and fill it out.
- R_Rect2DInst *inst = R_batch_list_push_struct(arena, &batch_group->batches, 256 /* capacity */, R_Rect2DInst);
- inst->dst_rect = rect;
- inst->src_rect = rect_params->src_rect;
- inst->colors[Corner_00] = rect_params->color;//vec4_F32(0.6f, 0.5f, 0.6f, 1.0f);
- inst->colors[Corner_01] = rect_params->color;//vec4_F32(0.6f, 0.5f, 0.6f, 1.0f);
- inst->colors[Corner_10] = rect_params->color;//vec4_F32(0.6f, 0.5f, 0.6f, 1.0f);
- inst->colors[Corner_11] = rect_params->color;//vec4_F32(0.6f, 0.5f, 0.6f, 1.0f);
- inst->corner_radii[Corner_00] = rect_params->corner_radius;
- inst->corner_radii[Corner_01] = rect_params->corner_radius;
- inst->corner_radii[Corner_10] = rect_params->corner_radius;
- inst->corner_radii[Corner_11] = rect_params->corner_radius;
- inst->softness = rect_params->softness;
- inst->border_thickness = rect_params->border_thickness;
- inst->omit_texture = rect_params->omit_texture;
-
- return inst;
-}
-
-root_function F32
-D_text2D(Vec2_F32 position, String8 string, Vec4_F32 color)
-{
- Arena *arena = D_active_arena();
- ArenaTemp scratch = scratch_get(&arena, 1);
- F_Run run = F_run_from_string(scratch.arena, string, position);
- // The position we get in will be the start of where we want to put the text.
- // Then we put a draw rectangle for each glyph in the string, and advance the pos.
- // The return value from this function then is the length of the text string.
- Vec2_F32 p = position;
- for(F_Piece *piece = run.first_piece; piece != 0; piece = piece->next)
- {
- //break_debugger();
- D_RectParams params;
- params.src_rect = piece->src_rect;
- params.omit_texture = 0;
- params.color = color;
- Vec2_F32 dst_p0 = piece->dst_p0;
- Vec2_F32 dst_p1 = piece->dst_p1;
- Rng2_F32 rect = rng2_F32(dst_p0, dst_p1);
- D_rect2D_(rect, ¶ms);
- p.x += piece->advance;
- }
- scratch_release(scratch);
- F32 result = p.x - position.x;
- return result;
-}
-
-///////////////////////////////////////////////////
-//~ Buckets
-
-root_function D_Bucket *
-D_bucket_make(Arena *arena)
-{
- D_Bucket *bucket = PushArrayZero(arena, D_Bucket, 1);
- D_InitBucketStacks(bucket);
- String8 name = str8_pushf(arena, "HejBucket");
- bucket->bucket_name = name;
- return bucket;
-}
-// TODO(anton): bucket and pass list concat in place when needed
-
-root_function void
-D_push_bucket(Arena *arena, D_Bucket *bucket)
-{
- D_BucketSelectionNode *node = d_thread_ctx->bucket_selection_free;
- if(node != 0)
- {
- StackPop(d_thread_ctx->bucket_selection_free);
- }
- else
- {
- node = PushArray(d_thread_ctx->arena, D_BucketSelectionNode, 1);
- }
- node->arena = arena;
- node->bucket = bucket;
- StackPush(d_thread_ctx->bucket_selection_top, node);
-}
-
-root_function void
-D_pop_bucket(void)
-{
- // Get the top bucket node, pop it and put it on the free list.
- // If the top node is the fallback arena we will clear and reinit the fallback.
- D_BucketSelectionNode *node = d_thread_ctx->bucket_selection_top;
- if(node != &d_thread_ctx->bucket_selection_fallback)
- {
- StackPop(d_thread_ctx->bucket_selection_top);
- StackPush(d_thread_ctx->bucket_selection_free, node);
- }
- if(d_thread_ctx->bucket_selection_top == &d_thread_ctx->bucket_selection_fallback)
- {
- m_arena_clear(d_thread_ctx->fallback_arena);
- MemoryZeroStruct(&d_thread_ctx->fallback_bucket);
- D_InitBucketStacks(&d_thread_ctx->fallback_bucket);
- }
-}
-
-root_function R_Pass *
-D_pass_from_bucket(Arena *arena, D_Bucket *bucket, R_PassKind kind)
-{
- R_PassNode *node = bucket->passes.last;
- R_Pass *pass = 0;
- // If we dont have a pass node at the last position, we push the pass to the list.
- if(node == 0)
- {
- pass = R_pass_list_push(arena, &bucket->passes, kind);
- }
- else
- {
- pass = &node->v;
- }
- return pass;
-}
-
-root_function Arena *
-D_active_arena()
-{
- return d_thread_ctx->bucket_selection_top->arena;
-}
-
-root_function D_Bucket *
-D_active_bucket(void)
-{
- return d_thread_ctx->bucket_selection_top->bucket;
-}
-
-root_function void
-D_submit(R_Handle window_r, D_Bucket *bucket)
-{
- R_window_submit(window_r, &bucket->passes);
-}
\ No newline at end of file
diff --git a/src/draw/draw.h b/src/draw/draw.h
deleted file mode 100644
index 4355e67..0000000
--- a/src/draw/draw.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* date = March 19th 2024 10:21 am */
-
-#ifndef DRAW_H
-#define DRAW_H
-
-typedef struct D_InitReceipt D_InitReceipt;
-struct D_InitReceipt
-{
- U64 u64[1];
-};
-
-
-///////////////////////////////////////////////////
-//~ "Generated" code.
-#include "draw_meta.h"
-
-// The drawing bucket contains whatever should be drawn for this frame.
-// And we can have several buckets that we submit.
-// Each bucket has a list of passes. Each pass has a set of batch groups, ie
-// a collection of the data that is supposed to be rendered for that pass. We can have
-// several render batches per pass.
-typedef struct D_Bucket D_Bucket;
-struct D_Bucket
-{
- R_PassList passes;
- String8 bucket_name;
- U64 last_cmd_stack_gen;
- U64 current_stack_gen;
- D_DeclBucketStacks;
-};
-
-typedef struct D_State D_State;
-struct D_State
-{
- Arena *arena;
- R_Handle font_texture;
-};
-
-
-typedef struct D_BucketSelectionNode D_BucketSelectionNode;
-struct D_BucketSelectionNode
-{
- D_BucketSelectionNode *next;
- D_Bucket *bucket;
- Arena *arena;
-};
-
-typedef struct D_ThreadCtx D_ThreadCtx;
-struct D_ThreadCtx
-{
- Arena *arena;
- Arena *fallback_arena;
- D_Bucket fallback_bucket;
- D_BucketSelectionNode bucket_selection_fallback;
- D_BucketSelectionNode *bucket_selection_top;
- D_BucketSelectionNode *bucket_selection_free;
- D_DeclThreadStackTops;
-};
-
-typedef struct D_RectParams D_RectParams;
-struct D_RectParams
-{
- R_Handle albedo_texture;
- Rng2_F32 src_rect;
- Vec4_F32 color;
- F32 corner_radius;
- F32 softness;
- F32 border_thickness;
- F32 omit_texture;
-};
-
-///////////////////////////////////////////////////
-//~ Draw fwd declarations
-root_function D_InitReceipt D_init(R_InitReceipt r_init_receipt, F_InitReceipt f_init_receipt);
-root_function void D_ensure_thread_initialised(void);
-root_function void D_frame_begin();
-root_function void D_frame_end();
-
-///////////////////////////////////////////////////
-//~ Buckets
-root_function Arena *D_active_arena();
-root_function D_Bucket *D_bucket_make(Arena *arena);
-root_function void D_bucket_concat_in_place(D_Bucket *to_push);
-root_function void D_push_bucket(Arena *arena, D_Bucket *bucket);
-root_function void D_pop_bucket(void);
-#define D_BucketScope(arena, bucket) DeferLoop(D_push_bucket((arena), (bucket)), D_pop_bucket())
-root_function D_Bucket *D_active_bucket(void);
-root_function void D_submit(R_Handle window_r, D_Bucket *bucket);
-
-///////////////////////////////////////////////////
-//~ Pass helpers
-root_function R_Pass *D_pass_from_bucket(Arena *arena, D_Bucket *bucket, R_PassKind kind);
-
-///////////////////////////////////////////////////
-//~ UI pass build commands
-
-//- Rect
-root_function R_Rect2DInst *D_rect2D_(Rng2_F32 rect, D_RectParams *p);
-#define D_rect2D(r, ...) D_rect2D_((r), &(D_RectParams){.color = {1, 1, 1, 1}, __VA_ARGS__})
-//- Text
-root_function F32 D_text2D(Vec2_F32 pos, String8 string, Vec4_F32 color);
-
-///////////////////////////////////////////////////
-//~ Grid build commands
-
-
-///////////////////////////////////////////////////
-//~ Draw stacks.
-// The nodes are generated by metadesk code in Ryan's codebase, I will do it manually here first.
-// TODO(anton): generate this.
-root_function R_Tex2DSampleKind D_push_tex2D_sample_kind(R_Tex2DSampleKind v);
-
-#endif //DRAW_H
diff --git a/src/draw/draw_inc.c b/src/draw/draw_inc.c
deleted file mode 100644
index 609b7f0..0000000
--- a/src/draw/draw_inc.c
+++ /dev/null
@@ -1 +0,0 @@
-#include "draw.c"
\ No newline at end of file
diff --git a/src/draw/draw_inc.h b/src/draw/draw_inc.h
deleted file mode 100644
index 373be01..0000000
--- a/src/draw/draw_inc.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* date = March 19th 2024 7:46 pm */
-
-#ifndef DRAW_INC_H
-#define DRAW_INC_H
-
-#include "draw.h"
-
-#endif //DRAW_INC_H
diff --git a/src/draw/draw_meta.c b/src/draw/draw_meta.c
deleted file mode 100644
index 784bc59..0000000
--- a/src/draw/draw_meta.c
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-root_function R_Tex2DSampleKind D_push_tex2D_sample_kind(R_Tex2DSampleKind v) D_StackPush(D_Tex2DSampleKindNode, R_Tex2DSampleKind, tex2d_sample_kind, v)
\ No newline at end of file
diff --git a/src/draw/draw_meta.h b/src/draw/draw_meta.h
deleted file mode 100644
index 76fad8e..0000000
--- a/src/draw/draw_meta.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* date = April 6th 2024 11:04 am */
-
-#ifndef DRAW_META_H
-#define DRAW_META_H
-
-typedef struct D_Tex2DSampleKindNode D_Tex2DSampleKindNode; struct D_Tex2DSampleKindNode {D_Tex2DSampleKindNode *next; R_Tex2DSampleKind v;};
-
-#define D_DeclThreadStackTops \
-struct\
-{\
-D_Tex2DSampleKindNode tex2d_sample_kind_nil_stack_top;\
-}
-
-#define D_InitThreadStackTops \
-d_thread_ctx->tex2d_sample_kind_nil_stack_top.v = R_Tex2DSampleKind_Nearest;\
-
-#define D_DeclBucketStacks \
-struct\
-{\
-D_Tex2DSampleKindNode *tex2d_sample_kind_stack_top; D_Tex2DSampleKindNode *tex2d_sample_kind_free;\
-}
-
-
-#define D_InitBucketStacks(b) \
-(b)->tex2d_sample_kind_stack_top = &d_thread_ctx->tex2d_sample_kind_nil_stack_top;\
-
-
-
-
-#endif //DRAW_META_H
diff --git a/src/font/font.c b/src/font/font.c
deleted file mode 100644
index 606517c..0000000
--- a/src/font/font.c
+++ /dev/null
@@ -1,135 +0,0 @@
-
-global F_State f_state;
-
-root_function F_State *
-F_get_state()
-{
- return &f_state;
-}
-
-root_function Arena *
-F_get_arena()
-{
- return f_state.arena;
-}
-
-root_function F_InitReceipt
-F_init() {
- //String8 font_path = str8_lit("D:\\dev\\app_codebase\\data\\LiberationMono-Regular.ttf");
- String8 font_path = str8_lit("D:\\dev\\app_codebase\\data\\arial.ttf");
-
- // Load the ttf data into a simple buffer which is just temporary
- ArenaTemp scratch = scratch_get(0, 0);
- OS_Handle font_file = OS_file_open(OS_AccessFlag_Read, font_path);
- OS_FileAttributes attrs = OS_attributes_from_file(font_file);
- String8 ttf_temp = OS_file_read(scratch.arena, font_file, 0, attrs.size);
-
- f_state.arena = m_make_arena_reserve(Megabytes(FONT_ARENA_MEMORY_SIZE_MB));
- Arena* arena = f_state.arena;
-
- U64 pixel_height = 16;
- // ASCII 32..126, 96 glyphs
- U64 num_glyphs = 96;
- U64 start_glyph = 32;
- U64 atlas_size_x = 512;
- U64 atlas_size_y = atlas_size_x;
-
- stbtt_bakedchar *cdata = PushArrayZero(arena, stbtt_bakedchar, num_glyphs);
- U8 *baked_atlas = PushArrayZero(arena, U8, atlas_size_x*atlas_size_y);
-
- stbtt_BakeFontBitmap(ttf_temp.str, /* loaded font data from file */
- 0, /* offset */
- (float)pixel_height, /* pixel height */
- baked_atlas, /* pixel bitmap */
- atlas_size_x, atlas_size_y, /* pixel width and height */
- start_glyph, num_glyphs,
- cdata);
-
- f_state.cdata = cdata;
- f_state.baked_atlas = baked_atlas;
-
- //U8 color = 0;
- //for(U32 i = 0; i < atlas_size_x; i++)
- //{
- //for(U32 j = 0; j < atlas_size_y; j++)
- //{
- //U32 index = j+i*atlas_size_x;
- //if(index % 32 == 0) {
- //if(color != 0) {
- //color = 0;
- //} else {
- //color = 255;
- //}
- //}
- //baked_atlas[index] = Max(index, 255);
- //
- //}
- //}
-
- Vec2_S64 atlas_size = vec2_S64(atlas_size_x, atlas_size_y);
- f_state.atlas.texture = R_tex2d_font_atlas(atlas_size, baked_atlas);
- f_state.atlas.size = atlas_size;
- f_state.atlas.start_glyph = start_glyph;
- f_state.atlas.last_glyph = start_glyph + num_glyphs;
-
- F_InitReceipt result = {0};
- scratch_release(scratch);
- return result;
-}
-
-root_function U8 *
-F_get_baked_atlas()
-{
- return f_state.baked_atlas;
-}
-
-root_function R_Handle
-F_atlas_texture_handle()
-{
- return f_state.atlas.texture;
-}
-
-root_function F_Run
-F_run_from_string(Arena *arena, String8 string, Vec2_F32 pos)
-{
- F_Run run = {0};
- U64 start_glyph = f_state.atlas.start_glyph;
- U64 end_glyph = f_state.atlas.last_glyph;
- U64 width = f_state.atlas.size.x;
- U64 height = f_state.atlas.size.y;
-
- float xpos = pos.x;
- float ypos = pos.y;
- int fill_rule = 1;
- for(U64 i = 0; i < string.size; i++)
- {
- char c = (char)string.str[i];
- if(c < start_glyph || c >= end_glyph) {
- continue;
- }
- stbtt_aligned_quad q;
- int glyph_index = c-start_glyph;
-
- stbtt_GetBakedQuad(f_state.cdata, width, height, glyph_index,
- &xpos, &ypos, &q, fill_rule);
- Vec2_F32 src_p0 = vec2_F32(width*q.s0, height*q.t0);
- Vec2_F32 src_p1 = vec2_F32(width*q.s1, height*q.t1);
- F_Piece *piece = PushArrayZero(arena, F_Piece, 1);
- QueuePush(run.first_piece, run.last_piece, piece);
-
- piece->texture = f_state.atlas.texture;
- piece->src_rect = rng2_F32(src_p0, src_p1);
- piece->advance = xpos;
- piece->offset = vec2_F32(0.0f, ypos);
-
-
- piece->dst_p0 = vec2_F32(q.x0, q.y0);
- piece->dst_p1 = vec2_F32(q.x1, q.y1);
- run.piece_count += 1;
- run.advance += piece->advance;
-
-
- }
-
- return run;
-}
diff --git a/src/font/font.h b/src/font/font.h
deleted file mode 100644
index 0991f3e..0000000
--- a/src/font/font.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#define STB_TRUETYPE_IMPLEMENTATION
-#define STBTT_STATIC
-
-#define FONT_ARENA_MEMORY_SIZE_MB 16
-
-#include "stb_truetype.h"
-
-typedef struct F_InitReceipt F_InitReceipt;
-struct F_InitReceipt
-{
- U64 u64[1];
-};
-
-typedef struct F_Atlas F_Atlas;
-struct F_Atlas
-{
- R_Handle texture;
- U64 start_glyph;
- U64 last_glyph;
- Vec2_S64 size;
-};
-
-
-typedef struct F_State F_State;
-struct F_State
-{
- Arena* arena;
- U8 *baked_atlas;
- F_Atlas atlas;
- stbtt_bakedchar *cdata;
-};
-
-typedef struct F_Piece F_Piece;
-struct F_Piece
-{
- F_Piece *next;
- R_Handle texture;
- Rng2_F32 src_rect;
- Vec2_F32 dst_p0;
- Vec2_F32 dst_p1;
- Vec2_F32 offset;
- F32 advance;
- U32 decode_size;
-};
-
-// A sequence of glyphs to render, linked list implementation
-typedef struct F_Run F_Run;
-struct F_Run
-{
- F_Piece *first_piece;
- F_Piece *last_piece;
- U64 piece_count;
- F32 advance;
-};
-
-
-
-
-
-
-
-////////////////////////////
-//~ Font forward declarations
-root_function Arena *F_get_font_arena();
-root_function F_InitReceipt F_init();
-root_function U8 *F_get_baked_atlas();
-root_function R_Handle F_atlas_texture_handle();
-root_function F_Run F_run_from_string(Arena *arena, String8 string, Vec2_F32 position);
-root_function F_State *F_get_state(); // TODO remove this its only for d3d11 shutdown crap
\ No newline at end of file
diff --git a/src/font/font_inc.c b/src/font/font_inc.c
deleted file mode 100644
index 863d67b..0000000
--- a/src/font/font_inc.c
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-#include "font.c"
diff --git a/src/font/font_inc.h b/src/font/font_inc.h
deleted file mode 100644
index f1fd063..0000000
--- a/src/font/font_inc.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef FONT_INC_H
-#define FONT_INC_H
-
-#include "font.h"
-
-
-#endif /* FONT_INC_H */
diff --git a/src/font/stb_truetype.h b/src/font/stb_truetype.h
deleted file mode 100644
index 4df0aac..0000000
--- a/src/font/stb_truetype.h
+++ /dev/null
@@ -1,5078 +0,0 @@
-// stb_truetype.h - v1.26 - public domain
-// authored from 2009-2021 by Sean Barrett / RAD Game Tools
-//
-// =======================================================================
-//
-// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
-//
-// This library does no range checking of the offsets found in the file,
-// meaning an attacker can use it to read arbitrary memory.
-//
-// =======================================================================
-//
-// This library processes TrueType files:
-// parse files
-// extract glyph metrics
-// extract glyph shapes
-// render glyphs to one-channel bitmaps with antialiasing (box filter)
-// render glyphs to one-channel SDF bitmaps (signed-distance field/function)
-//
-// Todo:
-// non-MS cmaps
-// crashproof on bad data
-// hinting? (no longer patented)
-// cleartype-style AA?
-// optimize: use simple memory allocator for intermediates
-// optimize: build edge-list directly from curves
-// optimize: rasterize directly from curves?
-//
-// ADDITIONAL CONTRIBUTORS
-//
-// Mikko Mononen: compound shape support, more cmap formats
-// Tor Andersson: kerning, subpixel rendering
-// Dougall Johnson: OpenType / Type 2 font handling
-// Daniel Ribeiro Maciel: basic GPOS-based kerning
-//
-// Misc other:
-// Ryan Gordon
-// Simon Glass
-// github:IntellectualKitty
-// Imanol Celaya
-// Daniel Ribeiro Maciel
-//
-// Bug/warning reports/fixes:
-// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe
-// Cass Everitt Martins Mozeiko github:aloucks
-// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam
-// Brian Hook Omar Cornut github:vassvik
-// Walter van Niftrik Ryan Griege
-// David Gow Peter LaValle
-// David Given Sergey Popov
-// Ivan-Assen Ivanov Giumo X. Clanjor
-// Anthony Pesch Higor Euripedes
-// Johan Duparc Thomas Fields
-// Hou Qiming Derek Vinyard
-// Rob Loach Cort Stratton
-// Kenney Phillis Jr. Brian Costabile
-// Ken Voskuil (kaesve)
-//
-// VERSION HISTORY
-//
-// 1.26 (2021-08-28) fix broken rasterizer
-// 1.25 (2021-07-11) many fixes
-// 1.24 (2020-02-05) fix warning
-// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
-// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
-// 1.21 (2019-02-25) fix warning
-// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
-// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
-// 1.18 (2018-01-29) add missing function
-// 1.17 (2017-07-23) make more arguments const; doc fix
-// 1.16 (2017-07-12) SDF support
-// 1.15 (2017-03-03) make more arguments const
-// 1.14 (2017-01-16) num-fonts-in-TTC function
-// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
-// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
-// 1.11 (2016-04-02) fix unused-variable warning
-// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
-// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
-// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
-// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
-// variant PackFontRanges to pack and render in separate phases;
-// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
-// fixed an assert() bug in the new rasterizer
-// replace assert() with STBTT_assert() in new rasterizer
-//
-// Full history can be found at the end of this file.
-//
-// LICENSE
-//
-// See end of file for license information.
-//
-// USAGE
-//
-// Include this file in whatever places need to refer to it. In ONE C/C++
-// file, write:
-// #define STB_TRUETYPE_IMPLEMENTATION
-// before the #include of this file. This expands out the actual
-// implementation into that C/C++ file.
-//
-// To make the implementation private to the file that generates the implementation,
-// #define STBTT_STATIC
-//
-// Simple 3D API (don't ship this, but it's fine for tools and quick start)
-// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
-// stbtt_GetBakedQuad() -- compute quad to draw for a given char
-//
-// Improved 3D API (more shippable):
-// #include "stb_rect_pack.h" -- optional, but you really want it
-// stbtt_PackBegin()
-// stbtt_PackSetOversampling() -- for improved quality on small fonts
-// stbtt_PackFontRanges() -- pack and renders
-// stbtt_PackEnd()
-// stbtt_GetPackedQuad()
-//
-// "Load" a font file from a memory buffer (you have to keep the buffer loaded)
-// stbtt_InitFont()
-// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections
-// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections
-//
-// Render a unicode codepoint to a bitmap
-// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
-// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
-// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
-//
-// Character advance/positioning
-// stbtt_GetCodepointHMetrics()
-// stbtt_GetFontVMetrics()
-// stbtt_GetFontVMetricsOS2()
-// stbtt_GetCodepointKernAdvance()
-//
-// Starting with version 1.06, the rasterizer was replaced with a new,
-// faster and generally-more-precise rasterizer. The new rasterizer more
-// accurately measures pixel coverage for anti-aliasing, except in the case
-// where multiple shapes overlap, in which case it overestimates the AA pixel
-// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
-// this turns out to be a problem, you can re-enable the old rasterizer with
-// #define STBTT_RASTERIZER_VERSION 1
-// which will incur about a 15% speed hit.
-//
-// ADDITIONAL DOCUMENTATION
-//
-// Immediately after this block comment are a series of sample programs.
-//
-// After the sample programs is the "header file" section. This section
-// includes documentation for each API function.
-//
-// Some important concepts to understand to use this library:
-//
-// Codepoint
-// Characters are defined by unicode codepoints, e.g. 65 is
-// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
-// the hiragana for "ma".
-//
-// Glyph
-// A visual character shape (every codepoint is rendered as
-// some glyph)
-//
-// Glyph index
-// A font-specific integer ID representing a glyph
-//
-// Baseline
-// Glyph shapes are defined relative to a baseline, which is the
-// bottom of uppercase characters. Characters extend both above
-// and below the baseline.
-//
-// Current Point
-// As you draw text to the screen, you keep track of a "current point"
-// which is the origin of each character. The current point's vertical
-// position is the baseline. Even "baked fonts" use this model.
-//
-// Vertical Font Metrics
-// The vertical qualities of the font, used to vertically position
-// and space the characters. See docs for stbtt_GetFontVMetrics.
-//
-// Font Size in Pixels or Points
-// The preferred interface for specifying font sizes in stb_truetype
-// is to specify how tall the font's vertical extent should be in pixels.
-// If that sounds good enough, skip the next paragraph.
-//
-// Most font APIs instead use "points", which are a common typographic
-// measurement for describing font size, defined as 72 points per inch.
-// stb_truetype provides a point API for compatibility. However, true
-// "per inch" conventions don't make much sense on computer displays
-// since different monitors have different number of pixels per
-// inch. For example, Windows traditionally uses a convention that
-// there are 96 pixels per inch, thus making 'inch' measurements have
-// nothing to do with inches, and thus effectively defining a point to
-// be 1.333 pixels. Additionally, the TrueType font data provides
-// an explicit scale factor to scale a given font's glyphs to points,
-// but the author has observed that this scale factor is often wrong
-// for non-commercial fonts, thus making fonts scaled in points
-// according to the TrueType spec incoherently sized in practice.
-//
-// DETAILED USAGE:
-//
-// Scale:
-// Select how high you want the font to be, in points or pixels.
-// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
-// a scale factor SF that will be used by all other functions.
-//
-// Baseline:
-// You need to select a y-coordinate that is the baseline of where
-// your text will appear. Call GetFontBoundingBox to get the baseline-relative
-// bounding box for all characters. SF*-y0 will be the distance in pixels
-// that the worst-case character could extend above the baseline, so if
-// you want the top edge of characters to appear at the top of the
-// screen where y=0, then you would set the baseline to SF*-y0.
-//
-// Current point:
-// Set the current point where the first character will appear. The
-// first character could extend left of the current point; this is font
-// dependent. You can either choose a current point that is the leftmost
-// point and hope, or add some padding, or check the bounding box or
-// left-side-bearing of the first character to be displayed and set
-// the current point based on that.
-//
-// Displaying a character:
-// Compute the bounding box of the character. It will contain signed values
-// relative to . I.e. if it returns x0,y0,x1,y1,
-// then the character should be displayed in the rectangle from
-// to = 32 && *text < 128) {
- stbtt_aligned_quad q;
- stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
- glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
- glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
- glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
- glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
- }
- ++text;
- }
- glEnd();
-}
-#endif
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-// Complete program (this compiles): get a single bitmap, print as ASCII art
-//
-#if 0
-#include
-#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
-#include "stb_truetype.h"
-
-char ttf_buffer[1<<25];
-
-int main(int argc, char **argv)
-{
- stbtt_fontinfo font;
- unsigned char *bitmap;
- int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
-
- fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
-
- stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
- bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
-
- for (j=0; j < h; ++j) {
- for (i=0; i < w; ++i)
- putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
- putchar('\n');
- }
- return 0;
-}
-#endif
-//
-// Output:
-//
-// .ii.
-// @@@@@@.
-// V@Mio@@o
-// :i. V@V
-// :oM@@M
-// :@@@MM@M
-// @@o o@M
-// :@@. M@M
-// @@@o@@@@
-// :M@@V:@@.
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-// Complete program: print "Hello World!" banner, with bugs
-//
-#if 0
-char buffer[24<<20];
-unsigned char screen[20][79];
-
-int main(int arg, char **argv)
-{
- stbtt_fontinfo font;
- int i,j,ascent,baseline,ch=0;
- float scale, xpos=2; // leave a little padding in case the character extends left
- char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
-
- fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
- stbtt_InitFont(&font, buffer, 0);
-
- scale = stbtt_ScaleForPixelHeight(&font, 15);
- stbtt_GetFontVMetrics(&font, &ascent,0,0);
- baseline = (int) (ascent*scale);
-
- while (text[ch]) {
- int advance,lsb,x0,y0,x1,y1;
- float x_shift = xpos - (float) floor(xpos);
- stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
- stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
- stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
- // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
- // because this API is really for baking character bitmaps into textures. if you want to render
- // a sequence of characters, you really need to render each bitmap to a temp buffer, then
- // "alpha blend" that into the working buffer
- xpos += (advance * scale);
- if (text[ch+1])
- xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
- ++ch;
- }
-
- for (j=0; j < 20; ++j) {
- for (i=0; i < 78; ++i)
- putchar(" .:ioVM@"[screen[j][i]>>5]);
- putchar('\n');
- }
-
- return 0;
-}
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-////
-//// INTEGRATION WITH YOUR CODEBASE
-////
-//// The following sections allow you to supply alternate definitions
-//// of C library functions used by stb_truetype, e.g. if you don't
-//// link with the C runtime library.
-
-#ifdef STB_TRUETYPE_IMPLEMENTATION
- // #define your own (u)stbtt_int8/16/32 before including to override this
- #ifndef stbtt_uint8
- typedef unsigned char stbtt_uint8;
- typedef signed char stbtt_int8;
- typedef unsigned short stbtt_uint16;
- typedef signed short stbtt_int16;
- typedef unsigned int stbtt_uint32;
- typedef signed int stbtt_int32;
- #endif
-
- typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
- typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
-
- // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
- #ifndef STBTT_ifloor
- #include
- #define STBTT_ifloor(x) ((int) floor(x))
- #define STBTT_iceil(x) ((int) ceil(x))
- #endif
-
- #ifndef STBTT_sqrt
- #include
- #define STBTT_sqrt(x) sqrt(x)
- #define STBTT_pow(x,y) pow(x,y)
- #endif
-
- #ifndef STBTT_fmod
- #include
- #define STBTT_fmod(x,y) fmod(x,y)
- #endif
-
- #ifndef STBTT_cos
- #include
- #define STBTT_cos(x) cos(x)
- #define STBTT_acos(x) acos(x)
- #endif
-
- #ifndef STBTT_fabs
- #include
- #define STBTT_fabs(x) fabs(x)
- #endif
-
- // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
- #ifndef STBTT_malloc
- #include
- #define STBTT_malloc(x,u) ((void)(u),malloc(x))
- #define STBTT_free(x,u) ((void)(u),free(x))
- #endif
-
- #ifndef STBTT_assert
- #include
- #define STBTT_assert(x) assert(x)
- #endif
-
- #ifndef STBTT_strlen
- #include
- #define STBTT_strlen(x) strlen(x)
- #endif
-
- #ifndef STBTT_memcpy
- #include
- #define STBTT_memcpy memcpy
- #define STBTT_memset memset
- #endif
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-////
-//// INTERFACE
-////
-////
-
-#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
-#define __STB_INCLUDE_STB_TRUETYPE_H__
-
-#ifdef STBTT_STATIC
-#define STBTT_DEF static
-#else
-#define STBTT_DEF extern
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// private structure
-typedef struct
-{
- unsigned char *data;
- int cursor;
- int size;
-} stbtt__buf;
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// TEXTURE BAKING API
-//
-// If you use this API, you only have to call two functions ever.
-//
-
-typedef struct
-{
- unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
- float xoff,yoff,xadvance;
-} stbtt_bakedchar;
-
-STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
- float pixel_height, // height of font in pixels
- unsigned char *pixels, int pw, int ph, // bitmap to be filled in
- int first_char, int num_chars, // characters to bake
- stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
-// if return is positive, the first unused row of the bitmap
-// if return is negative, returns the negative of the number of characters that fit
-// if return is 0, no characters fit and no rows were used
-// This uses a very crappy packing.
-
-typedef struct
-{
- float x0,y0,s0,t0; // top-left
- float x1,y1,s1,t1; // bottom-right
-} stbtt_aligned_quad;
-
-STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above
- int char_index, // character to display
- float *xpos, float *ypos, // pointers to current position in screen pixel space
- stbtt_aligned_quad *q, // output: quad to draw
- int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
-// Call GetBakedQuad with char_index = 'character - first_char', and it
-// creates the quad you need to draw and advances the current position.
-//
-// The coordinate system used assumes y increases downwards.
-//
-// Characters will extend both above and below the current position;
-// see discussion of "BASELINE" above.
-//
-// It's inefficient; you might want to c&p it and optimize it.
-
-STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
-// Query the font vertical metrics without having to create a font first.
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// NEW TEXTURE BAKING API
-//
-// This provides options for packing multiple fonts into one atlas, not
-// perfectly but better than nothing.
-
-typedef struct
-{
- unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
- float xoff,yoff,xadvance;
- float xoff2,yoff2;
-} stbtt_packedchar;
-
-typedef struct stbtt_pack_context stbtt_pack_context;
-typedef struct stbtt_fontinfo stbtt_fontinfo;
-#ifndef STB_RECT_PACK_VERSION
-typedef struct stbrp_rect stbrp_rect;
-#endif
-
-STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
-// Initializes a packing context stored in the passed-in stbtt_pack_context.
-// Future calls using this context will pack characters into the bitmap passed
-// in here: a 1-channel bitmap that is width * height. stride_in_bytes is
-// the distance from one row to the next (or 0 to mean they are packed tightly
-// together). "padding" is the amount of padding to leave between each
-// character (normally you want '1' for bitmaps you'll use as textures with
-// bilinear filtering).
-//
-// Returns 0 on failure, 1 on success.
-
-STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
-// Cleans up the packing context and frees all memory.
-
-#define STBTT_POINT_SIZE(x) (-(x))
-
-STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
- int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
-// Creates character bitmaps from the font_index'th font found in fontdata (use
-// font_index=0 if you don't know what that is). It creates num_chars_in_range
-// bitmaps for characters with unicode values starting at first_unicode_char_in_range
-// and increasing. Data for how to render them is stored in chardata_for_range;
-// pass these to stbtt_GetPackedQuad to get back renderable quads.
-//
-// font_size is the full height of the character from ascender to descender,
-// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
-// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
-// and pass that result as 'font_size':
-// ..., 20 , ... // font max minus min y is 20 pixels tall
-// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
-
-typedef struct
-{
- float font_size;
- int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint
- int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints
- int num_chars;
- stbtt_packedchar *chardata_for_range; // output
- unsigned char h_oversample, v_oversample; // don't set these, they're used internally
-} stbtt_pack_range;
-
-STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
-// Creates character bitmaps from multiple ranges of characters stored in
-// ranges. This will usually create a better-packed bitmap than multiple
-// calls to stbtt_PackFontRange. Note that you can call this multiple
-// times within a single PackBegin/PackEnd.
-
-STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
-// Oversampling a font increases the quality by allowing higher-quality subpixel
-// positioning, and is especially valuable at smaller text sizes.
-//
-// This function sets the amount of oversampling for all following calls to
-// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
-// pack context. The default (no oversampling) is achieved by h_oversample=1
-// and v_oversample=1. The total number of pixels required is
-// h_oversample*v_oversample larger than the default; for example, 2x2
-// oversampling requires 4x the storage of 1x1. For best results, render
-// oversampled textures with bilinear filtering. Look at the readme in
-// stb/tests/oversample for information about oversampled fonts
-//
-// To use with PackFontRangesGather etc., you must set it before calls
-// call to PackFontRangesGatherRects.
-
-STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
-// If skip != 0, this tells stb_truetype to skip any codepoints for which
-// there is no corresponding glyph. If skip=0, which is the default, then
-// codepoints without a glyph recived the font's "missing character" glyph,
-// typically an empty box by convention.
-
-STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
- int char_index, // character to display
- float *xpos, float *ypos, // pointers to current position in screen pixel space
- stbtt_aligned_quad *q, // output: quad to draw
- int align_to_integer);
-
-STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
-STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
-STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
-// Calling these functions in sequence is roughly equivalent to calling
-// stbtt_PackFontRanges(). If you more control over the packing of multiple
-// fonts, or if you want to pack custom data into a font texture, take a look
-// at the source to of stbtt_PackFontRanges() and create a custom version
-// using these functions, e.g. call GatherRects multiple times,
-// building up a single array of rects, then call PackRects once,
-// then call RenderIntoRects repeatedly. This may result in a
-// better packing than calling PackFontRanges multiple times
-// (or it may not).
-
-// this is an opaque structure that you shouldn't mess with which holds
-// all the context needed from PackBegin to PackEnd.
-struct stbtt_pack_context {
- void *user_allocator_context;
- void *pack_info;
- int width;
- int height;
- int stride_in_bytes;
- int padding;
- int skip_missing;
- unsigned int h_oversample, v_oversample;
- unsigned char *pixels;
- void *nodes;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// FONT LOADING
-//
-//
-
-STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
-// This function will determine the number of fonts in a font file. TrueType
-// collection (.ttc) files may contain multiple fonts, while TrueType font
-// (.ttf) files only contain one font. The number of fonts can be used for
-// indexing with the previous function where the index is between zero and one
-// less than the total fonts. If an error occurs, -1 is returned.
-
-STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
-// Each .ttf/.ttc file may have more than one font. Each font has a sequential
-// index number starting from 0. Call this function to get the font offset for
-// a given index; it returns -1 if the index is out of range. A regular .ttf
-// file will only define one font and it always be at offset 0, so it will
-// return '0' for index 0, and -1 for all other indices.
-
-// The following structure is defined publicly so you can declare one on
-// the stack or as a global or etc, but you should treat it as opaque.
-struct stbtt_fontinfo
-{
- void * userdata;
- unsigned char * data; // pointer to .ttf file
- int fontstart; // offset of start of font
-
- int numGlyphs; // number of glyphs, needed for range checking
-
- int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
- int index_map; // a cmap mapping for our chosen character encoding
- int indexToLocFormat; // format needed to map from glyph index to glyph
-
- stbtt__buf cff; // cff font data
- stbtt__buf charstrings; // the charstring index
- stbtt__buf gsubrs; // global charstring subroutines index
- stbtt__buf subrs; // private charstring subroutines index
- stbtt__buf fontdicts; // array of font dicts
- stbtt__buf fdselect; // map from glyph to fontdict
-};
-
-STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
-// Given an offset into the file that defines a font, this function builds
-// the necessary cached info for the rest of the system. You must allocate
-// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
-// need to do anything special to free it, because the contents are pure
-// value data with no additional data structures. Returns 0 on failure.
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// CHARACTER TO GLYPH-INDEX CONVERSIOn
-
-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
-// If you're going to perform multiple operations on the same character
-// and you want a speed-up, call this function with the character you're
-// going to process, then use glyph-based functions instead of the
-// codepoint-based functions.
-// Returns 0 if the character codepoint is not defined in the font.
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// CHARACTER PROPERTIES
-//
-
-STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
-// computes a scale factor to produce a font whose "height" is 'pixels' tall.
-// Height is measured as the distance from the highest ascender to the lowest
-// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
-// and computing:
-// scale = pixels / (ascent - descent)
-// so if you prefer to measure height by the ascent only, use a similar calculation.
-
-STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
-// computes a scale factor to produce a font whose EM size is mapped to
-// 'pixels' tall. This is probably what traditional APIs compute, but
-// I'm not positive.
-
-STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
-// ascent is the coordinate above the baseline the font extends; descent
-// is the coordinate below the baseline the font extends (i.e. it is typically negative)
-// lineGap is the spacing between one row's descent and the next row's ascent...
-// so you should advance the vertical position by "*ascent - *descent + *lineGap"
-// these are expressed in unscaled coordinates, so you must multiply by
-// the scale factor for a given size
-
-STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
-// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
-// table (specific to MS/Windows TTF files).
-//
-// Returns 1 on success (table present), 0 on failure.
-
-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
-// the bounding box around all possible characters
-
-STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
-// leftSideBearing is the offset from the current horizontal position to the left edge of the character
-// advanceWidth is the offset from the current horizontal position to the next horizontal position
-// these are expressed in unscaled coordinates
-
-STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
-// an additional amount to add to the 'advance' value between ch1 and ch2
-
-STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
-// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
-
-STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
-STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
-// as above, but takes one or more glyph indices for greater efficiency
-
-typedef struct stbtt_kerningentry
-{
- int glyph1; // use stbtt_FindGlyphIndex
- int glyph2;
- int advance;
-} stbtt_kerningentry;
-
-STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
-STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
-// Retrieves a complete list of all of the kerning pairs provided by the font
-// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
-// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// GLYPH SHAPES (you probably don't need these, but they have to go before
-// the bitmaps for C declaration-order reasons)
-//
-
-#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
- enum {
- STBTT_vmove=1,
- STBTT_vline,
- STBTT_vcurve,
- STBTT_vcubic
- };
-#endif
-
-#ifndef stbtt_vertex // you can predefine this to use different values
- // (we share this with other code at RAD)
- #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
- typedef struct
- {
- stbtt_vertex_type x,y,cx,cy,cx1,cy1;
- unsigned char type,padding;
- } stbtt_vertex;
-#endif
-
-STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
-// returns non-zero if nothing is drawn for this glyph
-
-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
-// returns # of vertices and fills *vertices with the pointer to them
-// these are expressed in "unscaled" coordinates
-//
-// The shape is a series of contours. Each one starts with
-// a STBTT_moveto, then consists of a series of mixed
-// STBTT_lineto and STBTT_curveto segments. A lineto
-// draws a line from previous endpoint to its x,y; a curveto
-// draws a quadratic bezier from previous endpoint to
-// its x,y, using cx,cy as the bezier control point.
-
-STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
-// frees the data allocated above
-
-STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
-STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
-STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
-// fills svg with the character's SVG data.
-// returns data size or 0 if SVG not found.
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// BITMAP RENDERING
-//
-
-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
-// frees the bitmap allocated below
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
-// allocates a large-enough single-channel 8bpp bitmap and renders the
-// specified character/glyph at the specified scale into it, with
-// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
-// *width & *height are filled out with the width & height of the bitmap,
-// which is stored left-to-right, top-to-bottom.
-//
-// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
-// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
-// shift for the character
-
-STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
-// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
-// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
-// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
-// width and height and positioning info for it first.
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
-// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
-// shift for the character
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
-// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
-// is performed (see stbtt_PackSetOversampling)
-
-STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
-// get the bbox of the bitmap centered around the glyph origin; so the
-// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
-// the bitmap top left is (leftSideBearing*scale,iy0).
-// (Note that the bitmap uses y-increases-down, but the shape uses
-// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
-
-STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
-// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
-// shift for the character
-
-// the following functions are equivalent to the above functions, but operate
-// on glyph indices instead of Unicode codepoints (for efficiency)
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
-STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
-STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
-STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
-
-
-// @TODO: don't expose this structure
-typedef struct
-{
- int w,h,stride;
- unsigned char *pixels;
-} stbtt__bitmap;
-
-// rasterize a shape with quadratic beziers into a bitmap
-STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into
- float flatness_in_pixels, // allowable error of curve in pixels
- stbtt_vertex *vertices, // array of vertices defining shape
- int num_verts, // number of vertices in above array
- float scale_x, float scale_y, // scale applied to input vertices
- float shift_x, float shift_y, // translation applied to input vertices
- int x_off, int y_off, // another translation applied to input
- int invert, // if non-zero, vertically flip shape
- void *userdata); // context for to STBTT_MALLOC
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Signed Distance Function (or Field) rendering
-
-STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
-// frees the SDF bitmap allocated below
-
-STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
-STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
-// These functions compute a discretized SDF field for a single character, suitable for storing
-// in a single-channel texture, sampling with bilinear filtering, and testing against
-// larger than some threshold to produce scalable fonts.
-// info -- the font
-// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
-// glyph/codepoint -- the character to generate the SDF for
-// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0),
-// which allows effects like bit outlines
-// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
-// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
-// if positive, > onedge_value is inside; if negative, < onedge_value is inside
-// width,height -- output height & width of the SDF bitmap (including padding)
-// xoff,yoff -- output origin of the character
-// return value -- a 2D array of bytes 0..255, width*height in size
-//
-// pixel_dist_scale & onedge_value are a scale & bias that allows you to make
-// optimal use of the limited 0..255 for your application, trading off precision
-// and special effects. SDF values outside the range 0..255 are clamped to 0..255.
-//
-// Example:
-// scale = stbtt_ScaleForPixelHeight(22)
-// padding = 5
-// onedge_value = 180
-// pixel_dist_scale = 180/5.0 = 36.0
-//
-// This will create an SDF bitmap in which the character is about 22 pixels
-// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
-// shape, sample the SDF at each pixel and fill the pixel if the SDF value
-// is greater than or equal to 180/255. (You'll actually want to antialias,
-// which is beyond the scope of this example.) Additionally, you can compute
-// offset outlines (e.g. to stroke the character border inside & outside,
-// or only outside). For example, to fill outside the character up to 3 SDF
-// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
-// choice of variables maps a range from 5 pixels outside the shape to
-// 2 pixels inside the shape to 0..255; this is intended primarily for apply
-// outside effects only (the interior range is needed to allow proper
-// antialiasing of the font at *smaller* sizes)
-//
-// The function computes the SDF analytically at each SDF pixel, not by e.g.
-// building a higher-res bitmap and approximating it. In theory the quality
-// should be as high as possible for an SDF of this size & representation, but
-// unclear if this is true in practice (perhaps building a higher-res bitmap
-// and computing from that can allow drop-out prevention).
-//
-// The algorithm has not been optimized at all, so expect it to be slow
-// if computing lots of characters or very large sizes.
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Finding the right font...
-//
-// You should really just solve this offline, keep your own tables
-// of what font is what, and don't try to get it out of the .ttf file.
-// That's because getting it out of the .ttf file is really hard, because
-// the names in the file can appear in many possible encodings, in many
-// possible languages, and e.g. if you need a case-insensitive comparison,
-// the details of that depend on the encoding & language in a complex way
-// (actually underspecified in truetype, but also gigantic).
-//
-// But you can use the provided functions in two possible ways:
-// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
-// unicode-encoded names to try to find the font you want;
-// you can run this before calling stbtt_InitFont()
-//
-// stbtt_GetFontNameString() lets you get any of the various strings
-// from the file yourself and do your own comparisons on them.
-// You have to have called stbtt_InitFont() first.
-
-
-STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
-// returns the offset (not index) of the font that matches, or -1 if none
-// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
-// if you use any other flag, use a font name like "Arial"; this checks
-// the 'macStyle' header field; i don't know if fonts set this consistently
-#define STBTT_MACSTYLE_DONTCARE 0
-#define STBTT_MACSTYLE_BOLD 1
-#define STBTT_MACSTYLE_ITALIC 2
-#define STBTT_MACSTYLE_UNDERSCORE 4
-#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
-
-STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
-// returns 1/0 whether the first string interpreted as utf8 is identical to
-// the second string interpreted as big-endian utf16... useful for strings from next func
-
-STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
-// returns the string (which may be big-endian double byte, e.g. for unicode)
-// and puts the length in bytes in *length.
-//
-// some of the values for the IDs are below; for more see the truetype spec:
-// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
-// http://www.microsoft.com/typography/otspec/name.htm
-
-enum { // platformID
- STBTT_PLATFORM_ID_UNICODE =0,
- STBTT_PLATFORM_ID_MAC =1,
- STBTT_PLATFORM_ID_ISO =2,
- STBTT_PLATFORM_ID_MICROSOFT =3
-};
-
-enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
- STBTT_UNICODE_EID_UNICODE_1_0 =0,
- STBTT_UNICODE_EID_UNICODE_1_1 =1,
- STBTT_UNICODE_EID_ISO_10646 =2,
- STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
- STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
-};
-
-enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
- STBTT_MS_EID_SYMBOL =0,
- STBTT_MS_EID_UNICODE_BMP =1,
- STBTT_MS_EID_SHIFTJIS =2,
- STBTT_MS_EID_UNICODE_FULL =10
-};
-
-enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
- STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
- STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
- STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
- STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
-};
-
-enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
- // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
- STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
- STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
- STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
- STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
- STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
- STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
-};
-
-enum { // languageID for STBTT_PLATFORM_ID_MAC
- STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
- STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
- STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
- STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
- STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
- STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
- STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __STB_INCLUDE_STB_TRUETYPE_H__
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-////
-//// IMPLEMENTATION
-////
-////
-
-#ifdef STB_TRUETYPE_IMPLEMENTATION
-
-#ifndef STBTT_MAX_OVERSAMPLE
-#define STBTT_MAX_OVERSAMPLE 8
-#endif
-
-#if STBTT_MAX_OVERSAMPLE > 255
-#error "STBTT_MAX_OVERSAMPLE cannot be > 255"
-#endif
-
-typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
-
-#ifndef STBTT_RASTERIZER_VERSION
-#define STBTT_RASTERIZER_VERSION 2
-#endif
-
-#ifdef _MSC_VER
-#define STBTT__NOTUSED(v) (void)(v)
-#else
-#define STBTT__NOTUSED(v) (void)sizeof(v)
-#endif
-
-//////////////////////////////////////////////////////////////////////////
-//
-// stbtt__buf helpers to parse data from file
-//
-
-static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
-{
- if (b->cursor >= b->size)
- return 0;
- return b->data[b->cursor++];
-}
-
-static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
-{
- if (b->cursor >= b->size)
- return 0;
- return b->data[b->cursor];
-}
-
-static void stbtt__buf_seek(stbtt__buf *b, int o)
-{
- STBTT_assert(!(o > b->size || o < 0));
- b->cursor = (o > b->size || o < 0) ? b->size : o;
-}
-
-static void stbtt__buf_skip(stbtt__buf *b, int o)
-{
- stbtt__buf_seek(b, b->cursor + o);
-}
-
-static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
-{
- stbtt_uint32 v = 0;
- int i;
- STBTT_assert(n >= 1 && n <= 4);
- for (i = 0; i < n; i++)
- v = (v << 8) | stbtt__buf_get8(b);
- return v;
-}
-
-static stbtt__buf stbtt__new_buf(const void *p, size_t size)
-{
- stbtt__buf r;
- STBTT_assert(size < 0x40000000);
- r.data = (stbtt_uint8*) p;
- r.size = (int) size;
- r.cursor = 0;
- return r;
-}
-
-#define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
-#define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
-
-static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
-{
- stbtt__buf r = stbtt__new_buf(NULL, 0);
- if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
- r.data = b->data + o;
- r.size = s;
- return r;
-}
-
-static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
-{
- int count, start, offsize;
- start = b->cursor;
- count = stbtt__buf_get16(b);
- if (count) {
- offsize = stbtt__buf_get8(b);
- STBTT_assert(offsize >= 1 && offsize <= 4);
- stbtt__buf_skip(b, offsize * count);
- stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
- }
- return stbtt__buf_range(b, start, b->cursor - start);
-}
-
-static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
-{
- int b0 = stbtt__buf_get8(b);
- if (b0 >= 32 && b0 <= 246) return b0 - 139;
- else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
- else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
- else if (b0 == 28) return stbtt__buf_get16(b);
- else if (b0 == 29) return stbtt__buf_get32(b);
- STBTT_assert(0);
- return 0;
-}
-
-static void stbtt__cff_skip_operand(stbtt__buf *b) {
- int v, b0 = stbtt__buf_peek8(b);
- STBTT_assert(b0 >= 28);
- if (b0 == 30) {
- stbtt__buf_skip(b, 1);
- while (b->cursor < b->size) {
- v = stbtt__buf_get8(b);
- if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
- break;
- }
- } else {
- stbtt__cff_int(b);
- }
-}
-
-static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
-{
- stbtt__buf_seek(b, 0);
- while (b->cursor < b->size) {
- int start = b->cursor, end, op;
- while (stbtt__buf_peek8(b) >= 28)
- stbtt__cff_skip_operand(b);
- end = b->cursor;
- op = stbtt__buf_get8(b);
- if (op == 12) op = stbtt__buf_get8(b) | 0x100;
- if (op == key) return stbtt__buf_range(b, start, end-start);
- }
- return stbtt__buf_range(b, 0, 0);
-}
-
-static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
-{
- int i;
- stbtt__buf operands = stbtt__dict_get(b, key);
- for (i = 0; i < outcount && operands.cursor < operands.size; i++)
- out[i] = stbtt__cff_int(&operands);
-}
-
-static int stbtt__cff_index_count(stbtt__buf *b)
-{
- stbtt__buf_seek(b, 0);
- return stbtt__buf_get16(b);
-}
-
-static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
-{
- int count, offsize, start, end;
- stbtt__buf_seek(&b, 0);
- count = stbtt__buf_get16(&b);
- offsize = stbtt__buf_get8(&b);
- STBTT_assert(i >= 0 && i < count);
- STBTT_assert(offsize >= 1 && offsize <= 4);
- stbtt__buf_skip(&b, i*offsize);
- start = stbtt__buf_get(&b, offsize);
- end = stbtt__buf_get(&b, offsize);
- return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
-}
-
-//////////////////////////////////////////////////////////////////////////
-//
-// accessors to parse data from file
-//
-
-// on platforms that don't allow misaligned reads, if we want to allow
-// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
-
-#define ttBYTE(p) (* (stbtt_uint8 *) (p))
-#define ttCHAR(p) (* (stbtt_int8 *) (p))
-#define ttFixed(p) ttLONG(p)
-
-static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
-static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
-
-#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
-#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
-
-static int stbtt__isfont(stbtt_uint8 *font)
-{
- // check the version number
- if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1
- if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
- if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
- if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
- if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
- return 0;
-}
-
-// @OPTIMIZE: binary search
-static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
-{
- stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
- stbtt_uint32 tabledir = fontstart + 12;
- stbtt_int32 i;
- for (i=0; i < num_tables; ++i) {
- stbtt_uint32 loc = tabledir + 16*i;
- if (stbtt_tag(data+loc+0, tag))
- return ttULONG(data+loc+8);
- }
- return 0;
-}
-
-static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
-{
- // if it's just a font, there's only one valid index
- if (stbtt__isfont(font_collection))
- return index == 0 ? 0 : -1;
-
- // check if it's a TTC
- if (stbtt_tag(font_collection, "ttcf")) {
- // version 1?
- if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
- stbtt_int32 n = ttLONG(font_collection+8);
- if (index >= n)
- return -1;
- return ttULONG(font_collection+12+index*4);
- }
- }
- return -1;
-}
-
-static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
-{
- // if it's just a font, there's only one valid font
- if (stbtt__isfont(font_collection))
- return 1;
-
- // check if it's a TTC
- if (stbtt_tag(font_collection, "ttcf")) {
- // version 1?
- if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
- return ttLONG(font_collection+8);
- }
- }
- return 0;
-}
-
-static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
-{
- stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
- stbtt__buf pdict;
- stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
- if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
- pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
- stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
- if (!subrsoff) return stbtt__new_buf(NULL, 0);
- stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
- return stbtt__cff_get_index(&cff);
-}
-
-// since most people won't use this, find this table the first time it's needed
-static int stbtt__get_svg(stbtt_fontinfo *info)
-{
- stbtt_uint32 t;
- if (info->svg < 0) {
- t = stbtt__find_table(info->data, info->fontstart, "SVG ");
- if (t) {
- stbtt_uint32 offset = ttULONG(info->data + t + 2);
- info->svg = t + offset;
- } else {
- info->svg = 0;
- }
- }
- return info->svg;
-}
-
-static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
-{
- stbtt_uint32 cmap, t;
- stbtt_int32 i,numTables;
-
- info->data = data;
- info->fontstart = fontstart;
- info->cff = stbtt__new_buf(NULL, 0);
-
- cmap = stbtt__find_table(data, fontstart, "cmap"); // required
- info->loca = stbtt__find_table(data, fontstart, "loca"); // required
- info->head = stbtt__find_table(data, fontstart, "head"); // required
- info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
- info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
- info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
- info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
- info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
-
- if (!cmap || !info->head || !info->hhea || !info->hmtx)
- return 0;
- if (info->glyf) {
- // required for truetype
- if (!info->loca) return 0;
- } else {
- // initialization for CFF / Type2 fonts (OTF)
- stbtt__buf b, topdict, topdictidx;
- stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
- stbtt_uint32 cff;
-
- cff = stbtt__find_table(data, fontstart, "CFF ");
- if (!cff) return 0;
-
- info->fontdicts = stbtt__new_buf(NULL, 0);
- info->fdselect = stbtt__new_buf(NULL, 0);
-
- // @TODO this should use size from table (not 512MB)
- info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
- b = info->cff;
-
- // read the header
- stbtt__buf_skip(&b, 2);
- stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
-
- // @TODO the name INDEX could list multiple fonts,
- // but we just use the first one.
- stbtt__cff_get_index(&b); // name INDEX
- topdictidx = stbtt__cff_get_index(&b);
- topdict = stbtt__cff_index_get(topdictidx, 0);
- stbtt__cff_get_index(&b); // string INDEX
- info->gsubrs = stbtt__cff_get_index(&b);
-
- stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
- stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
- stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
- stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
- info->subrs = stbtt__get_subrs(b, topdict);
-
- // we only support Type 2 charstrings
- if (cstype != 2) return 0;
- if (charstrings == 0) return 0;
-
- if (fdarrayoff) {
- // looks like a CID font
- if (!fdselectoff) return 0;
- stbtt__buf_seek(&b, fdarrayoff);
- info->fontdicts = stbtt__cff_get_index(&b);
- info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
- }
-
- stbtt__buf_seek(&b, charstrings);
- info->charstrings = stbtt__cff_get_index(&b);
- }
-
- t = stbtt__find_table(data, fontstart, "maxp");
- if (t)
- info->numGlyphs = ttUSHORT(data+t+4);
- else
- info->numGlyphs = 0xffff;
-
- info->svg = -1;
-
- // find a cmap encoding table we understand *now* to avoid searching
- // later. (todo: could make this installable)
- // the same regardless of glyph.
- numTables = ttUSHORT(data + cmap + 2);
- info->index_map = 0;
- for (i=0; i < numTables; ++i) {
- stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
- // find an encoding we understand:
- switch(ttUSHORT(data+encoding_record)) {
- case STBTT_PLATFORM_ID_MICROSOFT:
- switch (ttUSHORT(data+encoding_record+2)) {
- case STBTT_MS_EID_UNICODE_BMP:
- case STBTT_MS_EID_UNICODE_FULL:
- // MS/Unicode
- info->index_map = cmap + ttULONG(data+encoding_record+4);
- break;
- }
- break;
- case STBTT_PLATFORM_ID_UNICODE:
- // Mac/iOS has these
- // all the encodingIDs are unicode, so we don't bother to check it
- info->index_map = cmap + ttULONG(data+encoding_record+4);
- break;
- }
- }
- if (info->index_map == 0)
- return 0;
-
- info->indexToLocFormat = ttUSHORT(data+info->head + 50);
- return 1;
-}
-
-STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
-{
- stbtt_uint8 *data = info->data;
- stbtt_uint32 index_map = info->index_map;
-
- stbtt_uint16 format = ttUSHORT(data + index_map + 0);
- if (format == 0) { // apple byte encoding
- stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
- if (unicode_codepoint < bytes-6)
- return ttBYTE(data + index_map + 6 + unicode_codepoint);
- return 0;
- } else if (format == 6) {
- stbtt_uint32 first = ttUSHORT(data + index_map + 6);
- stbtt_uint32 count = ttUSHORT(data + index_map + 8);
- if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
- return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
- return 0;
- } else if (format == 2) {
- STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
- return 0;
- } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
- stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
- stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
- stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
- stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
-
- // do a binary search of the segments
- stbtt_uint32 endCount = index_map + 14;
- stbtt_uint32 search = endCount;
-
- if (unicode_codepoint > 0xffff)
- return 0;
-
- // they lie from endCount .. endCount + segCount
- // but searchRange is the nearest power of two, so...
- if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
- search += rangeShift*2;
-
- // now decrement to bias correctly to find smallest
- search -= 2;
- while (entrySelector) {
- stbtt_uint16 end;
- searchRange >>= 1;
- end = ttUSHORT(data + search + searchRange*2);
- if (unicode_codepoint > end)
- search += searchRange*2;
- --entrySelector;
- }
- search += 2;
-
- {
- stbtt_uint16 offset, start, last;
- stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
-
- start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
- last = ttUSHORT(data + endCount + 2*item);
- if (unicode_codepoint < start || unicode_codepoint > last)
- return 0;
-
- offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
- if (offset == 0)
- return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
-
- return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
- }
- } else if (format == 12 || format == 13) {
- stbtt_uint32 ngroups = ttULONG(data+index_map+12);
- stbtt_int32 low,high;
- low = 0; high = (stbtt_int32)ngroups;
- // Binary search the right group.
- while (low < high) {
- stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
- stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
- stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
- if ((stbtt_uint32) unicode_codepoint < start_char)
- high = mid;
- else if ((stbtt_uint32) unicode_codepoint > end_char)
- low = mid+1;
- else {
- stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
- if (format == 12)
- return start_glyph + unicode_codepoint-start_char;
- else // format == 13
- return start_glyph;
- }
- }
- return 0; // not found
- }
- // @TODO
- STBTT_assert(0);
- return 0;
-}
-
-STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
-{
- return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
-}
-
-static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
-{
- v->type = type;
- v->x = (stbtt_int16) x;
- v->y = (stbtt_int16) y;
- v->cx = (stbtt_int16) cx;
- v->cy = (stbtt_int16) cy;
-}
-
-static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
-{
- int g1,g2;
-
- STBTT_assert(!info->cff.size);
-
- if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
- if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
-
- if (info->indexToLocFormat == 0) {
- g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
- g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
- } else {
- g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
- g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
- }
-
- return g1==g2 ? -1 : g1; // if length is 0, return -1
-}
-
-static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
-
-STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
-{
- if (info->cff.size) {
- stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
- } else {
- int g = stbtt__GetGlyfOffset(info, glyph_index);
- if (g < 0) return 0;
-
- if (x0) *x0 = ttSHORT(info->data + g + 2);
- if (y0) *y0 = ttSHORT(info->data + g + 4);
- if (x1) *x1 = ttSHORT(info->data + g + 6);
- if (y1) *y1 = ttSHORT(info->data + g + 8);
- }
- return 1;
-}
-
-STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
-{
- return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
-}
-
-STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
-{
- stbtt_int16 numberOfContours;
- int g;
- if (info->cff.size)
- return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
- g = stbtt__GetGlyfOffset(info, glyph_index);
- if (g < 0) return 1;
- numberOfContours = ttSHORT(info->data + g);
- return numberOfContours == 0;
-}
-
-static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
- stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
-{
- if (start_off) {
- if (was_off)
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
- } else {
- if (was_off)
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
- else
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
- }
- return num_vertices;
-}
-
-static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
- stbtt_int16 numberOfContours;
- stbtt_uint8 *endPtsOfContours;
- stbtt_uint8 *data = info->data;
- stbtt_vertex *vertices=0;
- int num_vertices=0;
- int g = stbtt__GetGlyfOffset(info, glyph_index);
-
- *pvertices = NULL;
-
- if (g < 0) return 0;
-
- numberOfContours = ttSHORT(data + g);
-
- if (numberOfContours > 0) {
- stbtt_uint8 flags=0,flagcount;
- stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
- stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
- stbtt_uint8 *points;
- endPtsOfContours = (data + g + 10);
- ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
- points = data + g + 10 + numberOfContours * 2 + 2 + ins;
-
- n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
-
- m = n + 2*numberOfContours; // a loose bound on how many vertices we might need
- vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
- if (vertices == 0)
- return 0;
-
- next_move = 0;
- flagcount=0;
-
- // in first pass, we load uninterpreted data into the allocated array
- // above, shifted to the end of the array so we won't overwrite it when
- // we create our final data starting from the front
-
- off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
-
- // first load flags
-
- for (i=0; i < n; ++i) {
- if (flagcount == 0) {
- flags = *points++;
- if (flags & 8)
- flagcount = *points++;
- } else
- --flagcount;
- vertices[off+i].type = flags;
- }
-
- // now load x coordinates
- x=0;
- for (i=0; i < n; ++i) {
- flags = vertices[off+i].type;
- if (flags & 2) {
- stbtt_int16 dx = *points++;
- x += (flags & 16) ? dx : -dx; // ???
- } else {
- if (!(flags & 16)) {
- x = x + (stbtt_int16) (points[0]*256 + points[1]);
- points += 2;
- }
- }
- vertices[off+i].x = (stbtt_int16) x;
- }
-
- // now load y coordinates
- y=0;
- for (i=0; i < n; ++i) {
- flags = vertices[off+i].type;
- if (flags & 4) {
- stbtt_int16 dy = *points++;
- y += (flags & 32) ? dy : -dy; // ???
- } else {
- if (!(flags & 32)) {
- y = y + (stbtt_int16) (points[0]*256 + points[1]);
- points += 2;
- }
- }
- vertices[off+i].y = (stbtt_int16) y;
- }
-
- // now convert them to our format
- num_vertices=0;
- sx = sy = cx = cy = scx = scy = 0;
- for (i=0; i < n; ++i) {
- flags = vertices[off+i].type;
- x = (stbtt_int16) vertices[off+i].x;
- y = (stbtt_int16) vertices[off+i].y;
-
- if (next_move == i) {
- if (i != 0)
- num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
-
- // now start the new one
- start_off = !(flags & 1);
- if (start_off) {
- // if we start off with an off-curve point, then when we need to find a point on the curve
- // where we can start, and we need to save some state for when we wraparound.
- scx = x;
- scy = y;
- if (!(vertices[off+i+1].type & 1)) {
- // next point is also a curve point, so interpolate an on-point curve
- sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
- sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
- } else {
- // otherwise just use the next point as our start point
- sx = (stbtt_int32) vertices[off+i+1].x;
- sy = (stbtt_int32) vertices[off+i+1].y;
- ++i; // we're using point i+1 as the starting point, so skip it
- }
- } else {
- sx = x;
- sy = y;
- }
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
- was_off = 0;
- next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
- ++j;
- } else {
- if (!(flags & 1)) { // if it's a curve
- if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
- cx = x;
- cy = y;
- was_off = 1;
- } else {
- if (was_off)
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
- else
- stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
- was_off = 0;
- }
- }
- }
- num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
- } else if (numberOfContours < 0) {
- // Compound shapes.
- int more = 1;
- stbtt_uint8 *comp = data + g + 10;
- num_vertices = 0;
- vertices = 0;
- while (more) {
- stbtt_uint16 flags, gidx;
- int comp_num_verts = 0, i;
- stbtt_vertex *comp_verts = 0, *tmp = 0;
- float mtx[6] = {1,0,0,1,0,0}, m, n;
-
- flags = ttSHORT(comp); comp+=2;
- gidx = ttSHORT(comp); comp+=2;
-
- if (flags & 2) { // XY values
- if (flags & 1) { // shorts
- mtx[4] = ttSHORT(comp); comp+=2;
- mtx[5] = ttSHORT(comp); comp+=2;
- } else {
- mtx[4] = ttCHAR(comp); comp+=1;
- mtx[5] = ttCHAR(comp); comp+=1;
- }
- }
- else {
- // @TODO handle matching point
- STBTT_assert(0);
- }
- if (flags & (1<<3)) { // WE_HAVE_A_SCALE
- mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
- mtx[1] = mtx[2] = 0;
- } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
- mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
- mtx[1] = mtx[2] = 0;
- mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
- } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
- mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
- mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
- mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
- mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
- }
-
- // Find transformation scales.
- m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
- n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
-
- // Get indexed glyph.
- comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
- if (comp_num_verts > 0) {
- // Transform vertices.
- for (i = 0; i < comp_num_verts; ++i) {
- stbtt_vertex* v = &comp_verts[i];
- stbtt_vertex_type x,y;
- x=v->x; y=v->y;
- v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
- v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
- x=v->cx; y=v->cy;
- v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
- v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
- }
- // Append vertices.
- tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
- if (!tmp) {
- if (vertices) STBTT_free(vertices, info->userdata);
- if (comp_verts) STBTT_free(comp_verts, info->userdata);
- return 0;
- }
- if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
- STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
- if (vertices) STBTT_free(vertices, info->userdata);
- vertices = tmp;
- STBTT_free(comp_verts, info->userdata);
- num_vertices += comp_num_verts;
- }
- // More components ?
- more = flags & (1<<5);
- }
- } else {
- // numberOfCounters == 0, do nothing
- }
-
- *pvertices = vertices;
- return num_vertices;
-}
-
-typedef struct
-{
- int bounds;
- int started;
- float first_x, first_y;
- float x, y;
- stbtt_int32 min_x, max_x, min_y, max_y;
-
- stbtt_vertex *pvertices;
- int num_vertices;
-} stbtt__csctx;
-
-#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
-
-static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
-{
- if (x > c->max_x || !c->started) c->max_x = x;
- if (y > c->max_y || !c->started) c->max_y = y;
- if (x < c->min_x || !c->started) c->min_x = x;
- if (y < c->min_y || !c->started) c->min_y = y;
- c->started = 1;
-}
-
-static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
-{
- if (c->bounds) {
- stbtt__track_vertex(c, x, y);
- if (type == STBTT_vcubic) {
- stbtt__track_vertex(c, cx, cy);
- stbtt__track_vertex(c, cx1, cy1);
- }
- } else {
- stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
- c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
- c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
- }
- c->num_vertices++;
-}
-
-static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
-{
- if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
- stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
-}
-
-static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
-{
- stbtt__csctx_close_shape(ctx);
- ctx->first_x = ctx->x = ctx->x + dx;
- ctx->first_y = ctx->y = ctx->y + dy;
- stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
-}
-
-static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
-{
- ctx->x += dx;
- ctx->y += dy;
- stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
-}
-
-static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
-{
- float cx1 = ctx->x + dx1;
- float cy1 = ctx->y + dy1;
- float cx2 = cx1 + dx2;
- float cy2 = cy1 + dy2;
- ctx->x = cx2 + dx3;
- ctx->y = cy2 + dy3;
- stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
-}
-
-static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
-{
- int count = stbtt__cff_index_count(&idx);
- int bias = 107;
- if (count >= 33900)
- bias = 32768;
- else if (count >= 1240)
- bias = 1131;
- n += bias;
- if (n < 0 || n >= count)
- return stbtt__new_buf(NULL, 0);
- return stbtt__cff_index_get(idx, n);
-}
-
-static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
-{
- stbtt__buf fdselect = info->fdselect;
- int nranges, start, end, v, fmt, fdselector = -1, i;
-
- stbtt__buf_seek(&fdselect, 0);
- fmt = stbtt__buf_get8(&fdselect);
- if (fmt == 0) {
- // untested
- stbtt__buf_skip(&fdselect, glyph_index);
- fdselector = stbtt__buf_get8(&fdselect);
- } else if (fmt == 3) {
- nranges = stbtt__buf_get16(&fdselect);
- start = stbtt__buf_get16(&fdselect);
- for (i = 0; i < nranges; i++) {
- v = stbtt__buf_get8(&fdselect);
- end = stbtt__buf_get16(&fdselect);
- if (glyph_index >= start && glyph_index < end) {
- fdselector = v;
- break;
- }
- start = end;
- }
- }
- if (fdselector == -1) stbtt__new_buf(NULL, 0);
- return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
-}
-
-static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
-{
- int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
- int has_subrs = 0, clear_stack;
- float s[48];
- stbtt__buf subr_stack[10], subrs = info->subrs, b;
- float f;
-
-#define STBTT__CSERR(s) (0)
-
- // this currently ignores the initial width value, which isn't needed if we have hmtx
- b = stbtt__cff_index_get(info->charstrings, glyph_index);
- while (b.cursor < b.size) {
- i = 0;
- clear_stack = 1;
- b0 = stbtt__buf_get8(&b);
- switch (b0) {
- // @TODO implement hinting
- case 0x13: // hintmask
- case 0x14: // cntrmask
- if (in_header)
- maskbits += (sp / 2); // implicit "vstem"
- in_header = 0;
- stbtt__buf_skip(&b, (maskbits + 7) / 8);
- break;
-
- case 0x01: // hstem
- case 0x03: // vstem
- case 0x12: // hstemhm
- case 0x17: // vstemhm
- maskbits += (sp / 2);
- break;
-
- case 0x15: // rmoveto
- in_header = 0;
- if (sp < 2) return STBTT__CSERR("rmoveto stack");
- stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
- break;
- case 0x04: // vmoveto
- in_header = 0;
- if (sp < 1) return STBTT__CSERR("vmoveto stack");
- stbtt__csctx_rmove_to(c, 0, s[sp-1]);
- break;
- case 0x16: // hmoveto
- in_header = 0;
- if (sp < 1) return STBTT__CSERR("hmoveto stack");
- stbtt__csctx_rmove_to(c, s[sp-1], 0);
- break;
-
- case 0x05: // rlineto
- if (sp < 2) return STBTT__CSERR("rlineto stack");
- for (; i + 1 < sp; i += 2)
- stbtt__csctx_rline_to(c, s[i], s[i+1]);
- break;
-
- // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
- // starting from a different place.
-
- case 0x07: // vlineto
- if (sp < 1) return STBTT__CSERR("vlineto stack");
- goto vlineto;
- case 0x06: // hlineto
- if (sp < 1) return STBTT__CSERR("hlineto stack");
- for (;;) {
- if (i >= sp) break;
- stbtt__csctx_rline_to(c, s[i], 0);
- i++;
- vlineto:
- if (i >= sp) break;
- stbtt__csctx_rline_to(c, 0, s[i]);
- i++;
- }
- break;
-
- case 0x1F: // hvcurveto
- if (sp < 4) return STBTT__CSERR("hvcurveto stack");
- goto hvcurveto;
- case 0x1E: // vhcurveto
- if (sp < 4) return STBTT__CSERR("vhcurveto stack");
- for (;;) {
- if (i + 3 >= sp) break;
- stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
- i += 4;
- hvcurveto:
- if (i + 3 >= sp) break;
- stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
- i += 4;
- }
- break;
-
- case 0x08: // rrcurveto
- if (sp < 6) return STBTT__CSERR("rcurveline stack");
- for (; i + 5 < sp; i += 6)
- stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
- break;
-
- case 0x18: // rcurveline
- if (sp < 8) return STBTT__CSERR("rcurveline stack");
- for (; i + 5 < sp - 2; i += 6)
- stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
- if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
- stbtt__csctx_rline_to(c, s[i], s[i+1]);
- break;
-
- case 0x19: // rlinecurve
- if (sp < 8) return STBTT__CSERR("rlinecurve stack");
- for (; i + 1 < sp - 6; i += 2)
- stbtt__csctx_rline_to(c, s[i], s[i+1]);
- if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
- stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
- break;
-
- case 0x1A: // vvcurveto
- case 0x1B: // hhcurveto
- if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
- f = 0.0;
- if (sp & 1) { f = s[i]; i++; }
- for (; i + 3 < sp; i += 4) {
- if (b0 == 0x1B)
- stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
- else
- stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
- f = 0.0;
- }
- break;
-
- case 0x0A: // callsubr
- if (!has_subrs) {
- if (info->fdselect.size)
- subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
- has_subrs = 1;
- }
- // FALLTHROUGH
- case 0x1D: // callgsubr
- if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
- v = (int) s[--sp];
- if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
- subr_stack[subr_stack_height++] = b;
- b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
- if (b.size == 0) return STBTT__CSERR("subr not found");
- b.cursor = 0;
- clear_stack = 0;
- break;
-
- case 0x0B: // return
- if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
- b = subr_stack[--subr_stack_height];
- clear_stack = 0;
- break;
-
- case 0x0E: // endchar
- stbtt__csctx_close_shape(c);
- return 1;
-
- case 0x0C: { // two-byte escape
- float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
- float dx, dy;
- int b1 = stbtt__buf_get8(&b);
- switch (b1) {
- // @TODO These "flex" implementations ignore the flex-depth and resolution,
- // and always draw beziers.
- case 0x22: // hflex
- if (sp < 7) return STBTT__CSERR("hflex stack");
- dx1 = s[0];
- dx2 = s[1];
- dy2 = s[2];
- dx3 = s[3];
- dx4 = s[4];
- dx5 = s[5];
- dx6 = s[6];
- stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
- stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
- break;
-
- case 0x23: // flex
- if (sp < 13) return STBTT__CSERR("flex stack");
- dx1 = s[0];
- dy1 = s[1];
- dx2 = s[2];
- dy2 = s[3];
- dx3 = s[4];
- dy3 = s[5];
- dx4 = s[6];
- dy4 = s[7];
- dx5 = s[8];
- dy5 = s[9];
- dx6 = s[10];
- dy6 = s[11];
- //fd is s[12]
- stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
- stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
- break;
-
- case 0x24: // hflex1
- if (sp < 9) return STBTT__CSERR("hflex1 stack");
- dx1 = s[0];
- dy1 = s[1];
- dx2 = s[2];
- dy2 = s[3];
- dx3 = s[4];
- dx4 = s[5];
- dx5 = s[6];
- dy5 = s[7];
- dx6 = s[8];
- stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
- stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
- break;
-
- case 0x25: // flex1
- if (sp < 11) return STBTT__CSERR("flex1 stack");
- dx1 = s[0];
- dy1 = s[1];
- dx2 = s[2];
- dy2 = s[3];
- dx3 = s[4];
- dy3 = s[5];
- dx4 = s[6];
- dy4 = s[7];
- dx5 = s[8];
- dy5 = s[9];
- dx6 = dy6 = s[10];
- dx = dx1+dx2+dx3+dx4+dx5;
- dy = dy1+dy2+dy3+dy4+dy5;
- if (STBTT_fabs(dx) > STBTT_fabs(dy))
- dy6 = -dy;
- else
- dx6 = -dx;
- stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
- stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
- break;
-
- default:
- return STBTT__CSERR("unimplemented");
- }
- } break;
-
- default:
- if (b0 != 255 && b0 != 28 && b0 < 32)
- return STBTT__CSERR("reserved operator");
-
- // push immediate
- if (b0 == 255) {
- f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
- } else {
- stbtt__buf_skip(&b, -1);
- f = (float)(stbtt_int16)stbtt__cff_int(&b);
- }
- if (sp >= 48) return STBTT__CSERR("push stack overflow");
- s[sp++] = f;
- clear_stack = 0;
- break;
- }
- if (clear_stack) sp = 0;
- }
- return STBTT__CSERR("no endchar");
-
-#undef STBTT__CSERR
-}
-
-static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
- // runs the charstring twice, once to count and once to output (to avoid realloc)
- stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
- stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
- if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
- *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
- output_ctx.pvertices = *pvertices;
- if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
- STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
- return output_ctx.num_vertices;
- }
- }
- *pvertices = NULL;
- return 0;
-}
-
-static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
-{
- stbtt__csctx c = STBTT__CSCTX_INIT(1);
- int r = stbtt__run_charstring(info, glyph_index, &c);
- if (x0) *x0 = r ? c.min_x : 0;
- if (y0) *y0 = r ? c.min_y : 0;
- if (x1) *x1 = r ? c.max_x : 0;
- if (y1) *y1 = r ? c.max_y : 0;
- return r ? c.num_vertices : 0;
-}
-
-STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
-{
- if (!info->cff.size)
- return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
- else
- return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
-}
-
-STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
-{
- stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
- if (glyph_index < numOfLongHorMetrics) {
- if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
- if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
- } else {
- if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
- if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
- }
-}
-
-STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
-{
- stbtt_uint8 *data = info->data + info->kern;
-
- // we only look at the first table. it must be 'horizontal' and format 0.
- if (!info->kern)
- return 0;
- if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
- return 0;
- if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
- return 0;
-
- return ttUSHORT(data+10);
-}
-
-STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
-{
- stbtt_uint8 *data = info->data + info->kern;
- int k, length;
-
- // we only look at the first table. it must be 'horizontal' and format 0.
- if (!info->kern)
- return 0;
- if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
- return 0;
- if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
- return 0;
-
- length = ttUSHORT(data+10);
- if (table_length < length)
- length = table_length;
-
- for (k = 0; k < length; k++)
- {
- table[k].glyph1 = ttUSHORT(data+18+(k*6));
- table[k].glyph2 = ttUSHORT(data+20+(k*6));
- table[k].advance = ttSHORT(data+22+(k*6));
- }
-
- return length;
-}
-
-static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
-{
- stbtt_uint8 *data = info->data + info->kern;
- stbtt_uint32 needle, straw;
- int l, r, m;
-
- // we only look at the first table. it must be 'horizontal' and format 0.
- if (!info->kern)
- return 0;
- if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
- return 0;
- if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
- return 0;
-
- l = 0;
- r = ttUSHORT(data+10) - 1;
- needle = glyph1 << 16 | glyph2;
- while (l <= r) {
- m = (l + r) >> 1;
- straw = ttULONG(data+18+(m*6)); // note: unaligned read
- if (needle < straw)
- r = m - 1;
- else if (needle > straw)
- l = m + 1;
- else
- return ttSHORT(data+22+(m*6));
- }
- return 0;
-}
-
-static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
-{
- stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
- switch (coverageFormat) {
- case 1: {
- stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
-
- // Binary search.
- stbtt_int32 l=0, r=glyphCount-1, m;
- int straw, needle=glyph;
- while (l <= r) {
- stbtt_uint8 *glyphArray = coverageTable + 4;
- stbtt_uint16 glyphID;
- m = (l + r) >> 1;
- glyphID = ttUSHORT(glyphArray + 2 * m);
- straw = glyphID;
- if (needle < straw)
- r = m - 1;
- else if (needle > straw)
- l = m + 1;
- else {
- return m;
- }
- }
- break;
- }
-
- case 2: {
- stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
- stbtt_uint8 *rangeArray = coverageTable + 4;
-
- // Binary search.
- stbtt_int32 l=0, r=rangeCount-1, m;
- int strawStart, strawEnd, needle=glyph;
- while (l <= r) {
- stbtt_uint8 *rangeRecord;
- m = (l + r) >> 1;
- rangeRecord = rangeArray + 6 * m;
- strawStart = ttUSHORT(rangeRecord);
- strawEnd = ttUSHORT(rangeRecord + 2);
- if (needle < strawStart)
- r = m - 1;
- else if (needle > strawEnd)
- l = m + 1;
- else {
- stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
- return startCoverageIndex + glyph - strawStart;
- }
- }
- break;
- }
-
- default: return -1; // unsupported
- }
-
- return -1;
-}
-
-static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
-{
- stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
- switch (classDefFormat)
- {
- case 1: {
- stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
- stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
- stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
-
- if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
- return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
- break;
- }
-
- case 2: {
- stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
- stbtt_uint8 *classRangeRecords = classDefTable + 4;
-
- // Binary search.
- stbtt_int32 l=0, r=classRangeCount-1, m;
- int strawStart, strawEnd, needle=glyph;
- while (l <= r) {
- stbtt_uint8 *classRangeRecord;
- m = (l + r) >> 1;
- classRangeRecord = classRangeRecords + 6 * m;
- strawStart = ttUSHORT(classRangeRecord);
- strawEnd = ttUSHORT(classRangeRecord + 2);
- if (needle < strawStart)
- r = m - 1;
- else if (needle > strawEnd)
- l = m + 1;
- else
- return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
- }
- break;
- }
-
- default:
- return -1; // Unsupported definition type, return an error.
- }
-
- // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
- return 0;
-}
-
-// Define to STBTT_assert(x) if you want to break on unimplemented formats.
-#define STBTT_GPOS_TODO_assert(x)
-
-static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
-{
- stbtt_uint16 lookupListOffset;
- stbtt_uint8 *lookupList;
- stbtt_uint16 lookupCount;
- stbtt_uint8 *data;
- stbtt_int32 i, sti;
-
- if (!info->gpos) return 0;
-
- data = info->data + info->gpos;
-
- if (ttUSHORT(data+0) != 1) return 0; // Major version 1
- if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
-
- lookupListOffset = ttUSHORT(data+8);
- lookupList = data + lookupListOffset;
- lookupCount = ttUSHORT(lookupList);
-
- for (i=0; i= pairSetCount) return 0;
-
- needle=glyph2;
- r=pairValueCount-1;
- l=0;
-
- // Binary search.
- while (l <= r) {
- stbtt_uint16 secondGlyph;
- stbtt_uint8 *pairValue;
- m = (l + r) >> 1;
- pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
- secondGlyph = ttUSHORT(pairValue);
- straw = secondGlyph;
- if (needle < straw)
- r = m - 1;
- else if (needle > straw)
- l = m + 1;
- else {
- stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
- return xAdvance;
- }
- }
- } else
- return 0;
- break;
- }
-
- case 2: {
- stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
- stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
- if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
- stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
- stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
- int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
- int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
-
- stbtt_uint16 class1Count = ttUSHORT(table + 12);
- stbtt_uint16 class2Count = ttUSHORT(table + 14);
- stbtt_uint8 *class1Records, *class2Records;
- stbtt_int16 xAdvance;
-
- if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
- if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
-
- class1Records = table + 16;
- class2Records = class1Records + 2 * (glyph1class * class2Count);
- xAdvance = ttSHORT(class2Records + 2 * glyph2class);
- return xAdvance;
- } else
- return 0;
- break;
- }
-
- default:
- return 0; // Unsupported position format
- }
- }
- }
-
- return 0;
-}
-
-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
-{
- int xAdvance = 0;
-
- if (info->gpos)
- xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
- else if (info->kern)
- xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
-
- return xAdvance;
-}
-
-STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
-{
- if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
- return 0;
- return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
-}
-
-STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
-{
- stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
-}
-
-STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
-{
- if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
- if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
- if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
-}
-
-STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
-{
- int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
- if (!tab)
- return 0;
- if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
- if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
- if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
- return 1;
-}
-
-STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
-{
- *x0 = ttSHORT(info->data + info->head + 36);
- *y0 = ttSHORT(info->data + info->head + 38);
- *x1 = ttSHORT(info->data + info->head + 40);
- *y1 = ttSHORT(info->data + info->head + 42);
-}
-
-STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
-{
- int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
- return (float) height / fheight;
-}
-
-STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
-{
- int unitsPerEm = ttUSHORT(info->data + info->head + 18);
- return pixels / unitsPerEm;
-}
-
-STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
-{
- STBTT_free(v, info->userdata);
-}
-
-STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
-{
- int i;
- stbtt_uint8 *data = info->data;
- stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
-
- int numEntries = ttUSHORT(svg_doc_list);
- stbtt_uint8 *svg_docs = svg_doc_list + 2;
-
- for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
- return svg_doc;
- }
- return 0;
-}
-
-STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
-{
- stbtt_uint8 *data = info->data;
- stbtt_uint8 *svg_doc;
-
- if (info->svg == 0)
- return 0;
-
- svg_doc = stbtt_FindSVGDoc(info, gl);
- if (svg_doc != NULL) {
- *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
- return ttULONG(svg_doc + 8);
- } else {
- return 0;
- }
-}
-
-STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
-{
- return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// antialiasing software rasterizer
-//
-
-STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
- int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
- if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
- // e.g. space character
- if (ix0) *ix0 = 0;
- if (iy0) *iy0 = 0;
- if (ix1) *ix1 = 0;
- if (iy1) *iy1 = 0;
- } else {
- // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
- if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
- if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
- if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
- if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
- }
-}
-
-STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
- stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
-}
-
-STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
- stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
-}
-
-STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
-{
- stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Rasterizer
-
-typedef struct stbtt__hheap_chunk
-{
- struct stbtt__hheap_chunk *next;
-} stbtt__hheap_chunk;
-
-typedef struct stbtt__hheap
-{
- struct stbtt__hheap_chunk *head;
- void *first_free;
- int num_remaining_in_head_chunk;
-} stbtt__hheap;
-
-static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
-{
- if (hh->first_free) {
- void *p = hh->first_free;
- hh->first_free = * (void **) p;
- return p;
- } else {
- if (hh->num_remaining_in_head_chunk == 0) {
- int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
- stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
- if (c == NULL)
- return NULL;
- c->next = hh->head;
- hh->head = c;
- hh->num_remaining_in_head_chunk = count;
- }
- --hh->num_remaining_in_head_chunk;
- return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
- }
-}
-
-static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
-{
- *(void **) p = hh->first_free;
- hh->first_free = p;
-}
-
-static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
-{
- stbtt__hheap_chunk *c = hh->head;
- while (c) {
- stbtt__hheap_chunk *n = c->next;
- STBTT_free(c, userdata);
- c = n;
- }
-}
-
-typedef struct stbtt__edge {
- float x0,y0, x1,y1;
- int invert;
-} stbtt__edge;
-
-
-typedef struct stbtt__active_edge
-{
- struct stbtt__active_edge *next;
- #if STBTT_RASTERIZER_VERSION==1
- int x,dx;
- float ey;
- int direction;
- #elif STBTT_RASTERIZER_VERSION==2
- float fx,fdx,fdy;
- float direction;
- float sy;
- float ey;
- #else
- #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
- #endif
-} stbtt__active_edge;
-
-#if STBTT_RASTERIZER_VERSION == 1
-#define STBTT_FIXSHIFT 10
-#define STBTT_FIX (1 << STBTT_FIXSHIFT)
-#define STBTT_FIXMASK (STBTT_FIX-1)
-
-static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
-{
- stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
- float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
- STBTT_assert(z != NULL);
- if (!z) return z;
-
- // round dx down to avoid overshooting
- if (dxdy < 0)
- z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
- else
- z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
-
- z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
- z->x -= off_x * STBTT_FIX;
-
- z->ey = e->y1;
- z->next = 0;
- z->direction = e->invert ? 1 : -1;
- return z;
-}
-#elif STBTT_RASTERIZER_VERSION == 2
-static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
-{
- stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
- float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
- STBTT_assert(z != NULL);
- //STBTT_assert(e->y0 <= start_point);
- if (!z) return z;
- z->fdx = dxdy;
- z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
- z->fx = e->x0 + dxdy * (start_point - e->y0);
- z->fx -= off_x;
- z->direction = e->invert ? 1.0f : -1.0f;
- z->sy = e->y0;
- z->ey = e->y1;
- z->next = 0;
- return z;
-}
-#else
-#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
-#endif
-
-#if STBTT_RASTERIZER_VERSION == 1
-// note: this routine clips fills that extend off the edges... ideally this
-// wouldn't happen, but it could happen if the truetype glyph bounding boxes
-// are wrong, or if the user supplies a too-small bitmap
-static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
-{
- // non-zero winding fill
- int x0=0, w=0;
-
- while (e) {
- if (w == 0) {
- // if we're currently at zero, we need to record the edge start point
- x0 = e->x; w += e->direction;
- } else {
- int x1 = e->x; w += e->direction;
- // if we went to zero, we need to draw
- if (w == 0) {
- int i = x0 >> STBTT_FIXSHIFT;
- int j = x1 >> STBTT_FIXSHIFT;
-
- if (i < len && j >= 0) {
- if (i == j) {
- // x0,x1 are the same pixel, so compute combined coverage
- scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
- } else {
- if (i >= 0) // add antialiasing for x0
- scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
- else
- i = -1; // clip
-
- if (j < len) // add antialiasing for x1
- scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
- else
- j = len; // clip
-
- for (++i; i < j; ++i) // fill pixels between x0 and x1
- scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
- }
- }
- }
- }
-
- e = e->next;
- }
-}
-
-static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
-{
- stbtt__hheap hh = { 0, 0, 0 };
- stbtt__active_edge *active = NULL;
- int y,j=0;
- int max_weight = (255 / vsubsample); // weight per vertical scanline
- int s; // vertical subsample index
- unsigned char scanline_data[512], *scanline;
-
- if (result->w > 512)
- scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
- else
- scanline = scanline_data;
-
- y = off_y * vsubsample;
- e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
-
- while (j < result->h) {
- STBTT_memset(scanline, 0, result->w);
- for (s=0; s < vsubsample; ++s) {
- // find center of pixel for this scanline
- float scan_y = y + 0.5f;
- stbtt__active_edge **step = &active;
-
- // update all active edges;
- // remove all active edges that terminate before the center of this scanline
- while (*step) {
- stbtt__active_edge * z = *step;
- if (z->ey <= scan_y) {
- *step = z->next; // delete from list
- STBTT_assert(z->direction);
- z->direction = 0;
- stbtt__hheap_free(&hh, z);
- } else {
- z->x += z->dx; // advance to position for current scanline
- step = &((*step)->next); // advance through list
- }
- }
-
- // resort the list if needed
- for(;;) {
- int changed=0;
- step = &active;
- while (*step && (*step)->next) {
- if ((*step)->x > (*step)->next->x) {
- stbtt__active_edge *t = *step;
- stbtt__active_edge *q = t->next;
-
- t->next = q->next;
- q->next = t;
- *step = q;
- changed = 1;
- }
- step = &(*step)->next;
- }
- if (!changed) break;
- }
-
- // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
- while (e->y0 <= scan_y) {
- if (e->y1 > scan_y) {
- stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
- if (z != NULL) {
- // find insertion point
- if (active == NULL)
- active = z;
- else if (z->x < active->x) {
- // insert at front
- z->next = active;
- active = z;
- } else {
- // find thing to insert AFTER
- stbtt__active_edge *p = active;
- while (p->next && p->next->x < z->x)
- p = p->next;
- // at this point, p->next->x is NOT < z->x
- z->next = p->next;
- p->next = z;
- }
- }
- }
- ++e;
- }
-
- // now process all active edges in XOR fashion
- if (active)
- stbtt__fill_active_edges(scanline, result->w, active, max_weight);
-
- ++y;
- }
- STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
- ++j;
- }
-
- stbtt__hheap_cleanup(&hh, userdata);
-
- if (scanline != scanline_data)
- STBTT_free(scanline, userdata);
-}
-
-#elif STBTT_RASTERIZER_VERSION == 2
-
-// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
-// (i.e. it has already been clipped to those)
-static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
-{
- if (y0 == y1) return;
- STBTT_assert(y0 < y1);
- STBTT_assert(e->sy <= e->ey);
- if (y0 > e->ey) return;
- if (y1 < e->sy) return;
- if (y0 < e->sy) {
- x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
- y0 = e->sy;
- }
- if (y1 > e->ey) {
- x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
- y1 = e->ey;
- }
-
- if (x0 == x)
- STBTT_assert(x1 <= x+1);
- else if (x0 == x+1)
- STBTT_assert(x1 >= x);
- else if (x0 <= x)
- STBTT_assert(x1 <= x);
- else if (x0 >= x+1)
- STBTT_assert(x1 >= x+1);
- else
- STBTT_assert(x1 >= x && x1 <= x+1);
-
- if (x0 <= x && x1 <= x)
- scanline[x] += e->direction * (y1-y0);
- else if (x0 >= x+1 && x1 >= x+1)
- ;
- else {
- STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
- scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
- }
-}
-
-static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
-{
- STBTT_assert(top_width >= 0);
- STBTT_assert(bottom_width >= 0);
- return (top_width + bottom_width) / 2.0f * height;
-}
-
-static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
-{
- return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
-}
-
-static float stbtt__sized_triangle_area(float height, float width)
-{
- return height * width / 2;
-}
-
-static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
-{
- float y_bottom = y_top+1;
-
- while (e) {
- // brute force every pixel
-
- // compute intersection points with top & bottom
- STBTT_assert(e->ey >= y_top);
-
- if (e->fdx == 0) {
- float x0 = e->fx;
- if (x0 < len) {
- if (x0 >= 0) {
- stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
- stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
- } else {
- stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
- }
- }
- } else {
- float x0 = e->fx;
- float dx = e->fdx;
- float xb = x0 + dx;
- float x_top, x_bottom;
- float sy0,sy1;
- float dy = e->fdy;
- STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
-
- // compute endpoints of line segment clipped to this scanline (if the
- // line segment starts on this scanline. x0 is the intersection of the
- // line with y_top, but that may be off the line segment.
- if (e->sy > y_top) {
- x_top = x0 + dx * (e->sy - y_top);
- sy0 = e->sy;
- } else {
- x_top = x0;
- sy0 = y_top;
- }
- if (e->ey < y_bottom) {
- x_bottom = x0 + dx * (e->ey - y_top);
- sy1 = e->ey;
- } else {
- x_bottom = xb;
- sy1 = y_bottom;
- }
-
- if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
- // from here on, we don't have to range check x values
-
- if ((int) x_top == (int) x_bottom) {
- float height;
- // simple case, only spans one pixel
- int x = (int) x_top;
- height = (sy1 - sy0) * e->direction;
- STBTT_assert(x >= 0 && x < len);
- scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
- scanline_fill[x] += height; // everything right of this pixel is filled
- } else {
- int x,x1,x2;
- float y_crossing, y_final, step, sign, area;
- // covers 2+ pixels
- if (x_top > x_bottom) {
- // flip scanline vertically; signed area is the same
- float t;
- sy0 = y_bottom - (sy0 - y_top);
- sy1 = y_bottom - (sy1 - y_top);
- t = sy0, sy0 = sy1, sy1 = t;
- t = x_bottom, x_bottom = x_top, x_top = t;
- dx = -dx;
- dy = -dy;
- t = x0, x0 = xb, xb = t;
- }
- STBTT_assert(dy >= 0);
- STBTT_assert(dx >= 0);
-
- x1 = (int) x_top;
- x2 = (int) x_bottom;
- // compute intersection with y axis at x1+1
- y_crossing = y_top + dy * (x1+1 - x0);
-
- // compute intersection with y axis at x2
- y_final = y_top + dy * (x2 - x0);
-
- // x1 x_top x2 x_bottom
- // y_top +------|-----+------------+------------+--------|---+------------+
- // | | | | | |
- // | | | | | |
- // sy0 | Txxxxx|............|............|............|............|
- // y_crossing | *xxxxx.......|............|............|............|
- // | | xxxxx..|............|............|............|
- // | | /- xx*xxxx........|............|............|
- // | | dy < | xxxxxx..|............|............|
- // y_final | | \- | xx*xxx.........|............|
- // sy1 | | | | xxxxxB...|............|
- // | | | | | |
- // | | | | | |
- // y_bottom +------------+------------+------------+------------+------------+
- //
- // goal is to measure the area covered by '.' in each pixel
-
- // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
- // @TODO: maybe test against sy1 rather than y_bottom?
- if (y_crossing > y_bottom)
- y_crossing = y_bottom;
-
- sign = e->direction;
-
- // area of the rectangle covered from sy0..y_crossing
- area = sign * (y_crossing-sy0);
-
- // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
- scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
-
- // check if final y_crossing is blown up; no test case for this
- if (y_final > y_bottom) {
- y_final = y_bottom;
- dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
- }
-
- // in second pixel, area covered by line segment found in first pixel
- // is always a rectangle 1 wide * the height of that line segment; this
- // is exactly what the variable 'area' stores. it also gets a contribution
- // from the line segment within it. the THIRD pixel will get the first
- // pixel's rectangle contribution, the second pixel's rectangle contribution,
- // and its own contribution. the 'own contribution' is the same in every pixel except
- // the leftmost and rightmost, a trapezoid that slides down in each pixel.
- // the second pixel's contribution to the third pixel will be the
- // rectangle 1 wide times the height change in the second pixel, which is dy.
-
- step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
- // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
- // so the area advances by 'step' every time
-
- for (x = x1+1; x < x2; ++x) {
- scanline[x] += area + step/2; // area of trapezoid is 1*step/2
- area += step;
- }
- STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
- STBTT_assert(sy1 > y_final-0.01f);
-
- // area covered in the last pixel is the rectangle from all the pixels to the left,
- // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
- scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
-
- // the rest of the line is filled based on the total height of the line segment in this pixel
- scanline_fill[x2] += sign * (sy1-sy0);
- }
- } else {
- // if edge goes outside of box we're drawing, we require
- // clipping logic. since this does not match the intended use
- // of this library, we use a different, very slow brute
- // force implementation
- // note though that this does happen some of the time because
- // x_top and x_bottom can be extrapolated at the top & bottom of
- // the shape and actually lie outside the bounding box
- int x;
- for (x=0; x < len; ++x) {
- // cases:
- //
- // there can be up to two intersections with the pixel. any intersection
- // with left or right edges can be handled by splitting into two (or three)
- // regions. intersections with top & bottom do not necessitate case-wise logic.
- //
- // the old way of doing this found the intersections with the left & right edges,
- // then used some simple logic to produce up to three segments in sorted order
- // from top-to-bottom. however, this had a problem: if an x edge was epsilon
- // across the x border, then the corresponding y position might not be distinct
- // from the other y segment, and it might ignored as an empty segment. to avoid
- // that, we need to explicitly produce segments based on x positions.
-
- // rename variables to clearly-defined pairs
- float y0 = y_top;
- float x1 = (float) (x);
- float x2 = (float) (x+1);
- float x3 = xb;
- float y3 = y_bottom;
-
- // x = e->x + e->dx * (y-y_top)
- // (y-y_top) = (x - e->x) / e->dx
- // y = (x - e->x) / e->dx + y_top
- float y1 = (x - x0) / dx + y_top;
- float y2 = (x+1 - x0) / dx + y_top;
-
- if (x0 < x1 && x3 > x2) { // three segments descending down-right
- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
- } else if (x3 < x1 && x0 > x2) { // three segments descending down-left
- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
- } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right
- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
- } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left
- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
- stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
- } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right
- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
- } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left
- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
- stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
- } else { // one segment
- stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
- }
- }
- }
- }
- e = e->next;
- }
-}
-
-// directly AA rasterize edges w/o supersampling
-static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
-{
- stbtt__hheap hh = { 0, 0, 0 };
- stbtt__active_edge *active = NULL;
- int y,j=0, i;
- float scanline_data[129], *scanline, *scanline2;
-
- STBTT__NOTUSED(vsubsample);
-
- if (result->w > 64)
- scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
- else
- scanline = scanline_data;
-
- scanline2 = scanline + result->w;
-
- y = off_y;
- e[n].y0 = (float) (off_y + result->h) + 1;
-
- while (j < result->h) {
- // find center of pixel for this scanline
- float scan_y_top = y + 0.0f;
- float scan_y_bottom = y + 1.0f;
- stbtt__active_edge **step = &active;
-
- STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
- STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
-
- // update all active edges;
- // remove all active edges that terminate before the top of this scanline
- while (*step) {
- stbtt__active_edge * z = *step;
- if (z->ey <= scan_y_top) {
- *step = z->next; // delete from list
- STBTT_assert(z->direction);
- z->direction = 0;
- stbtt__hheap_free(&hh, z);
- } else {
- step = &((*step)->next); // advance through list
- }
- }
-
- // insert all edges that start before the bottom of this scanline
- while (e->y0 <= scan_y_bottom) {
- if (e->y0 != e->y1) {
- stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
- if (z != NULL) {
- if (j == 0 && off_y != 0) {
- if (z->ey < scan_y_top) {
- // this can happen due to subpixel positioning and some kind of fp rounding error i think
- z->ey = scan_y_top;
- }
- }
- STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
- // insert at front
- z->next = active;
- active = z;
- }
- }
- ++e;
- }
-
- // now process all active edges
- if (active)
- stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
-
- {
- float sum = 0;
- for (i=0; i < result->w; ++i) {
- float k;
- int m;
- sum += scanline2[i];
- k = scanline[i] + sum;
- k = (float) STBTT_fabs(k)*255 + 0.5f;
- m = (int) k;
- if (m > 255) m = 255;
- result->pixels[j*result->stride + i] = (unsigned char) m;
- }
- }
- // advance all the edges
- step = &active;
- while (*step) {
- stbtt__active_edge *z = *step;
- z->fx += z->fdx; // advance to position for current scanline
- step = &((*step)->next); // advance through list
- }
-
- ++y;
- ++j;
- }
-
- stbtt__hheap_cleanup(&hh, userdata);
-
- if (scanline != scanline_data)
- STBTT_free(scanline, userdata);
-}
-#else
-#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
-#endif
-
-#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
-
-static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
-{
- int i,j;
- for (i=1; i < n; ++i) {
- stbtt__edge t = p[i], *a = &t;
- j = i;
- while (j > 0) {
- stbtt__edge *b = &p[j-1];
- int c = STBTT__COMPARE(a,b);
- if (!c) break;
- p[j] = p[j-1];
- --j;
- }
- if (i != j)
- p[j] = t;
- }
-}
-
-static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
-{
- /* threshold for transitioning to insertion sort */
- while (n > 12) {
- stbtt__edge t;
- int c01,c12,c,m,i,j;
-
- /* compute median of three */
- m = n >> 1;
- c01 = STBTT__COMPARE(&p[0],&p[m]);
- c12 = STBTT__COMPARE(&p[m],&p[n-1]);
- /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
- if (c01 != c12) {
- /* otherwise, we'll need to swap something else to middle */
- int z;
- c = STBTT__COMPARE(&p[0],&p[n-1]);
- /* 0>mid && midn => n; 0 0 */
- /* 0n: 0>n => 0; 0 n */
- z = (c == c12) ? 0 : n-1;
- t = p[z];
- p[z] = p[m];
- p[m] = t;
- }
- /* now p[m] is the median-of-three */
- /* swap it to the beginning so it won't move around */
- t = p[0];
- p[0] = p[m];
- p[m] = t;
-
- /* partition loop */
- i=1;
- j=n-1;
- for(;;) {
- /* handling of equality is crucial here */
- /* for sentinels & efficiency with duplicates */
- for (;;++i) {
- if (!STBTT__COMPARE(&p[i], &p[0])) break;
- }
- for (;;--j) {
- if (!STBTT__COMPARE(&p[0], &p[j])) break;
- }
- /* make sure we haven't crossed */
- if (i >= j) break;
- t = p[i];
- p[i] = p[j];
- p[j] = t;
-
- ++i;
- --j;
- }
- /* recurse on smaller side, iterate on larger */
- if (j < (n-i)) {
- stbtt__sort_edges_quicksort(p,j);
- p = p+i;
- n = n-i;
- } else {
- stbtt__sort_edges_quicksort(p+i, n-i);
- n = j;
- }
- }
-}
-
-static void stbtt__sort_edges(stbtt__edge *p, int n)
-{
- stbtt__sort_edges_quicksort(p, n);
- stbtt__sort_edges_ins_sort(p, n);
-}
-
-typedef struct
-{
- float x,y;
-} stbtt__point;
-
-static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
-{
- float y_scale_inv = invert ? -scale_y : scale_y;
- stbtt__edge *e;
- int n,i,j,k,m;
-#if STBTT_RASTERIZER_VERSION == 1
- int vsubsample = result->h < 8 ? 15 : 5;
-#elif STBTT_RASTERIZER_VERSION == 2
- int vsubsample = 1;
-#else
- #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
-#endif
- // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
-
- // now we have to blow out the windings into explicit edge lists
- n = 0;
- for (i=0; i < windings; ++i)
- n += wcount[i];
-
- e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
- if (e == 0) return;
- n = 0;
-
- m=0;
- for (i=0; i < windings; ++i) {
- stbtt__point *p = pts + m;
- m += wcount[i];
- j = wcount[i]-1;
- for (k=0; k < wcount[i]; j=k++) {
- int a=k,b=j;
- // skip the edge if horizontal
- if (p[j].y == p[k].y)
- continue;
- // add edge from j to k to the list
- e[n].invert = 0;
- if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
- e[n].invert = 1;
- a=j,b=k;
- }
- e[n].x0 = p[a].x * scale_x + shift_x;
- e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
- e[n].x1 = p[b].x * scale_x + shift_x;
- e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
- ++n;
- }
- }
-
- // now sort the edges by their highest point (should snap to integer, and then by x)
- //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
- stbtt__sort_edges(e, n);
-
- // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
- stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
-
- STBTT_free(e, userdata);
-}
-
-static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
-{
- if (!points) return; // during first pass, it's unallocated
- points[n].x = x;
- points[n].y = y;
-}
-
-// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
-static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
-{
- // midpoint
- float mx = (x0 + 2*x1 + x2)/4;
- float my = (y0 + 2*y1 + y2)/4;
- // versus directly drawn line
- float dx = (x0+x2)/2 - mx;
- float dy = (y0+y2)/2 - my;
- if (n > 16) // 65536 segments on one curve better be enough!
- return 1;
- if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
- stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
- stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
- } else {
- stbtt__add_point(points, *num_points,x2,y2);
- *num_points = *num_points+1;
- }
- return 1;
-}
-
-static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
-{
- // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
- float dx0 = x1-x0;
- float dy0 = y1-y0;
- float dx1 = x2-x1;
- float dy1 = y2-y1;
- float dx2 = x3-x2;
- float dy2 = y3-y2;
- float dx = x3-x0;
- float dy = y3-y0;
- float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
- float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
- float flatness_squared = longlen*longlen-shortlen*shortlen;
-
- if (n > 16) // 65536 segments on one curve better be enough!
- return;
-
- if (flatness_squared > objspace_flatness_squared) {
- float x01 = (x0+x1)/2;
- float y01 = (y0+y1)/2;
- float x12 = (x1+x2)/2;
- float y12 = (y1+y2)/2;
- float x23 = (x2+x3)/2;
- float y23 = (y2+y3)/2;
-
- float xa = (x01+x12)/2;
- float ya = (y01+y12)/2;
- float xb = (x12+x23)/2;
- float yb = (y12+y23)/2;
-
- float mx = (xa+xb)/2;
- float my = (ya+yb)/2;
-
- stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
- stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
- } else {
- stbtt__add_point(points, *num_points,x3,y3);
- *num_points = *num_points+1;
- }
-}
-
-// returns number of contours
-static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
-{
- stbtt__point *points=0;
- int num_points=0;
-
- float objspace_flatness_squared = objspace_flatness * objspace_flatness;
- int i,n=0,start=0, pass;
-
- // count how many "moves" there are to get the contour count
- for (i=0; i < num_verts; ++i)
- if (vertices[i].type == STBTT_vmove)
- ++n;
-
- *num_contours = n;
- if (n == 0) return 0;
-
- *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
-
- if (*contour_lengths == 0) {
- *num_contours = 0;
- return 0;
- }
-
- // make two passes through the points so we don't need to realloc
- for (pass=0; pass < 2; ++pass) {
- float x=0,y=0;
- if (pass == 1) {
- points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
- if (points == NULL) goto error;
- }
- num_points = 0;
- n= -1;
- for (i=0; i < num_verts; ++i) {
- switch (vertices[i].type) {
- case STBTT_vmove:
- // start the next contour
- if (n >= 0)
- (*contour_lengths)[n] = num_points - start;
- ++n;
- start = num_points;
-
- x = vertices[i].x, y = vertices[i].y;
- stbtt__add_point(points, num_points++, x,y);
- break;
- case STBTT_vline:
- x = vertices[i].x, y = vertices[i].y;
- stbtt__add_point(points, num_points++, x, y);
- break;
- case STBTT_vcurve:
- stbtt__tesselate_curve(points, &num_points, x,y,
- vertices[i].cx, vertices[i].cy,
- vertices[i].x, vertices[i].y,
- objspace_flatness_squared, 0);
- x = vertices[i].x, y = vertices[i].y;
- break;
- case STBTT_vcubic:
- stbtt__tesselate_cubic(points, &num_points, x,y,
- vertices[i].cx, vertices[i].cy,
- vertices[i].cx1, vertices[i].cy1,
- vertices[i].x, vertices[i].y,
- objspace_flatness_squared, 0);
- x = vertices[i].x, y = vertices[i].y;
- break;
- }
- }
- (*contour_lengths)[n] = num_points - start;
- }
-
- return points;
-error:
- STBTT_free(points, userdata);
- STBTT_free(*contour_lengths, userdata);
- *contour_lengths = 0;
- *num_contours = 0;
- return NULL;
-}
-
-STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
-{
- float scale = scale_x > scale_y ? scale_y : scale_x;
- int winding_count = 0;
- int *winding_lengths = NULL;
- stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
- if (windings) {
- stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
- STBTT_free(winding_lengths, userdata);
- STBTT_free(windings, userdata);
- }
-}
-
-STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
-{
- STBTT_free(bitmap, userdata);
-}
-
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
-{
- int ix0,iy0,ix1,iy1;
- stbtt__bitmap gbm;
- stbtt_vertex *vertices;
- int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
-
- if (scale_x == 0) scale_x = scale_y;
- if (scale_y == 0) {
- if (scale_x == 0) {
- STBTT_free(vertices, info->userdata);
- return NULL;
- }
- scale_y = scale_x;
- }
-
- stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
-
- // now we get the size
- gbm.w = (ix1 - ix0);
- gbm.h = (iy1 - iy0);
- gbm.pixels = NULL; // in case we error
-
- if (width ) *width = gbm.w;
- if (height) *height = gbm.h;
- if (xoff ) *xoff = ix0;
- if (yoff ) *yoff = iy0;
-
- if (gbm.w && gbm.h) {
- gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
- if (gbm.pixels) {
- gbm.stride = gbm.w;
-
- stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
- }
- }
- STBTT_free(vertices, info->userdata);
- return gbm.pixels;
-}
-
-STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
-{
- return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
-}
-
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
-{
- int ix0,iy0;
- stbtt_vertex *vertices;
- int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
- stbtt__bitmap gbm;
-
- stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
- gbm.pixels = output;
- gbm.w = out_w;
- gbm.h = out_h;
- gbm.stride = out_stride;
-
- if (gbm.w && gbm.h)
- stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
-
- STBTT_free(vertices, info->userdata);
-}
-
-STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
-{
- stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
-}
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
-{
- return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
-}
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
-{
- stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
-}
-
-STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
-{
- stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
-}
-
-STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
-{
- return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
-}
-
-STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
-{
- stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// bitmap baking
-//
-// This is SUPER-CRAPPY packing to keep source code small
-
-static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
- float pixel_height, // height of font in pixels
- unsigned char *pixels, int pw, int ph, // bitmap to be filled in
- int first_char, int num_chars, // characters to bake
- stbtt_bakedchar *chardata)
-{
- float scale;
- int x,y,bottom_y, i;
- stbtt_fontinfo f;
- f.userdata = NULL;
- if (!stbtt_InitFont(&f, data, offset))
- return -1;
- STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
- x=y=1;
- bottom_y = 1;
-
- scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
-
- for (i=0; i < num_chars; ++i) {
- int advance, lsb, x0,y0,x1,y1,gw,gh;
- int g = stbtt_FindGlyphIndex(&f, first_char + i);
- stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
- stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
- gw = x1-x0;
- gh = y1-y0;
- if (x + gw + 1 >= pw)
- y = bottom_y, x = 1; // advance to next row
- if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
- return -i;
- STBTT_assert(x+gw < pw);
- STBTT_assert(y+gh < ph);
- stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
- chardata[i].x0 = (stbtt_int16) x;
- chardata[i].y0 = (stbtt_int16) y;
- chardata[i].x1 = (stbtt_int16) (x + gw);
- chardata[i].y1 = (stbtt_int16) (y + gh);
- chardata[i].xadvance = scale * advance;
- chardata[i].xoff = (float) x0;
- chardata[i].yoff = (float) y0;
- x = x + gw + 1;
- if (y+gh+1 > bottom_y)
- bottom_y = y+gh+1;
- }
- return bottom_y;
-}
-
-STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos,
- float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
-{
- float d3d_bias = opengl_fillrule ? 0 : -0.5f;
- float ipw = 1.0f / pw, iph = 1.0f / ph;
- const stbtt_bakedchar *b = chardata + char_index;
- int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
- int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
-
- q->x0 = round_x + d3d_bias;
- q->y0 = round_y + d3d_bias;
- q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
- q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
-
- q->s0 = b->x0 * ipw;
- q->t0 = b->y0 * iph;
- q->s1 = b->x1 * ipw;
- q->t1 = b->y1 * iph;
-
- *xpos += b->xadvance;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// rectangle packing replacement routines if you don't have stb_rect_pack.h
-//
-
-#ifndef STB_RECT_PACK_VERSION
-
-typedef int stbrp_coord;
-
-////////////////////////////////////////////////////////////////////////////////////
-// //
-// //
-// COMPILER WARNING ?!?!? //
-// //
-// //
-// if you get a compile warning due to these symbols being defined more than //
-// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
-// //
-////////////////////////////////////////////////////////////////////////////////////
-
-typedef struct
-{
- int width,height;
- int x,y,bottom_y;
-} stbrp_context;
-
-typedef struct
-{
- unsigned char x;
-} stbrp_node;
-
-struct stbrp_rect
-{
- stbrp_coord x,y;
- int id,w,h,was_packed;
-};
-
-static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
-{
- con->width = pw;
- con->height = ph;
- con->x = 0;
- con->y = 0;
- con->bottom_y = 0;
- STBTT__NOTUSED(nodes);
- STBTT__NOTUSED(num_nodes);
-}
-
-static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
-{
- int i;
- for (i=0; i < num_rects; ++i) {
- if (con->x + rects[i].w > con->width) {
- con->x = 0;
- con->y = con->bottom_y;
- }
- if (con->y + rects[i].h > con->height)
- break;
- rects[i].x = con->x;
- rects[i].y = con->y;
- rects[i].was_packed = 1;
- con->x += rects[i].w;
- if (con->y + rects[i].h > con->bottom_y)
- con->bottom_y = con->y + rects[i].h;
- }
- for ( ; i < num_rects; ++i)
- rects[i].was_packed = 0;
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// bitmap baking
-//
-// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
-// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
-
-STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
-{
- stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
- int num_nodes = pw - padding;
- stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
-
- if (context == NULL || nodes == NULL) {
- if (context != NULL) STBTT_free(context, alloc_context);
- if (nodes != NULL) STBTT_free(nodes , alloc_context);
- return 0;
- }
-
- spc->user_allocator_context = alloc_context;
- spc->width = pw;
- spc->height = ph;
- spc->pixels = pixels;
- spc->pack_info = context;
- spc->nodes = nodes;
- spc->padding = padding;
- spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
- spc->h_oversample = 1;
- spc->v_oversample = 1;
- spc->skip_missing = 0;
-
- stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
-
- if (pixels)
- STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
-
- return 1;
-}
-
-STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
-{
- STBTT_free(spc->nodes , spc->user_allocator_context);
- STBTT_free(spc->pack_info, spc->user_allocator_context);
-}
-
-STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
-{
- STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
- STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
- if (h_oversample <= STBTT_MAX_OVERSAMPLE)
- spc->h_oversample = h_oversample;
- if (v_oversample <= STBTT_MAX_OVERSAMPLE)
- spc->v_oversample = v_oversample;
-}
-
-STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
-{
- spc->skip_missing = skip;
-}
-
-#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
-
-static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
-{
- unsigned char buffer[STBTT_MAX_OVERSAMPLE];
- int safe_w = w - kernel_width;
- int j;
- STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
- for (j=0; j < h; ++j) {
- int i;
- unsigned int total;
- STBTT_memset(buffer, 0, kernel_width);
-
- total = 0;
-
- // make kernel_width a constant in common cases so compiler can optimize out the divide
- switch (kernel_width) {
- case 2:
- for (i=0; i <= safe_w; ++i) {
- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
- pixels[i] = (unsigned char) (total / 2);
- }
- break;
- case 3:
- for (i=0; i <= safe_w; ++i) {
- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
- pixels[i] = (unsigned char) (total / 3);
- }
- break;
- case 4:
- for (i=0; i <= safe_w; ++i) {
- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
- pixels[i] = (unsigned char) (total / 4);
- }
- break;
- case 5:
- for (i=0; i <= safe_w; ++i) {
- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
- pixels[i] = (unsigned char) (total / 5);
- }
- break;
- default:
- for (i=0; i <= safe_w; ++i) {
- total += pixels[i] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
- pixels[i] = (unsigned char) (total / kernel_width);
- }
- break;
- }
-
- for (; i < w; ++i) {
- STBTT_assert(pixels[i] == 0);
- total -= buffer[i & STBTT__OVER_MASK];
- pixels[i] = (unsigned char) (total / kernel_width);
- }
-
- pixels += stride_in_bytes;
- }
-}
-
-static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
-{
- unsigned char buffer[STBTT_MAX_OVERSAMPLE];
- int safe_h = h - kernel_width;
- int j;
- STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
- for (j=0; j < w; ++j) {
- int i;
- unsigned int total;
- STBTT_memset(buffer, 0, kernel_width);
-
- total = 0;
-
- // make kernel_width a constant in common cases so compiler can optimize out the divide
- switch (kernel_width) {
- case 2:
- for (i=0; i <= safe_h; ++i) {
- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
- pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
- }
- break;
- case 3:
- for (i=0; i <= safe_h; ++i) {
- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
- pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
- }
- break;
- case 4:
- for (i=0; i <= safe_h; ++i) {
- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
- pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
- }
- break;
- case 5:
- for (i=0; i <= safe_h; ++i) {
- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
- pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
- }
- break;
- default:
- for (i=0; i <= safe_h; ++i) {
- total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
- buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
- pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
- }
- break;
- }
-
- for (; i < h; ++i) {
- STBTT_assert(pixels[i*stride_in_bytes] == 0);
- total -= buffer[i & STBTT__OVER_MASK];
- pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
- }
-
- pixels += 1;
- }
-}
-
-static float stbtt__oversample_shift(int oversample)
-{
- if (!oversample)
- return 0.0f;
-
- // The prefilter is a box filter of width "oversample",
- // which shifts phase by (oversample - 1)/2 pixels in
- // oversampled space. We want to shift in the opposite
- // direction to counter this.
- return (float)-(oversample - 1) / (2.0f * (float)oversample);
-}
-
-// rects array must be big enough to accommodate all characters in the given ranges
-STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
-{
- int i,j,k;
- int missing_glyph_added = 0;
-
- k=0;
- for (i=0; i < num_ranges; ++i) {
- float fh = ranges[i].font_size;
- float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
- ranges[i].h_oversample = (unsigned char) spc->h_oversample;
- ranges[i].v_oversample = (unsigned char) spc->v_oversample;
- for (j=0; j < ranges[i].num_chars; ++j) {
- int x0,y0,x1,y1;
- int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
- int glyph = stbtt_FindGlyphIndex(info, codepoint);
- if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
- rects[k].w = rects[k].h = 0;
- } else {
- stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
- scale * spc->h_oversample,
- scale * spc->v_oversample,
- 0,0,
- &x0,&y0,&x1,&y1);
- rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
- rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
- if (glyph == 0)
- missing_glyph_added = 1;
- }
- ++k;
- }
- }
-
- return k;
-}
-
-STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
-{
- stbtt_MakeGlyphBitmapSubpixel(info,
- output,
- out_w - (prefilter_x - 1),
- out_h - (prefilter_y - 1),
- out_stride,
- scale_x,
- scale_y,
- shift_x,
- shift_y,
- glyph);
-
- if (prefilter_x > 1)
- stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
-
- if (prefilter_y > 1)
- stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
-
- *sub_x = stbtt__oversample_shift(prefilter_x);
- *sub_y = stbtt__oversample_shift(prefilter_y);
-}
-
-// rects array must be big enough to accommodate all characters in the given ranges
-STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
-{
- int i,j,k, missing_glyph = -1, return_value = 1;
-
- // save current values
- int old_h_over = spc->h_oversample;
- int old_v_over = spc->v_oversample;
-
- k = 0;
- for (i=0; i < num_ranges; ++i) {
- float fh = ranges[i].font_size;
- float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
- float recip_h,recip_v,sub_x,sub_y;
- spc->h_oversample = ranges[i].h_oversample;
- spc->v_oversample = ranges[i].v_oversample;
- recip_h = 1.0f / spc->h_oversample;
- recip_v = 1.0f / spc->v_oversample;
- sub_x = stbtt__oversample_shift(spc->h_oversample);
- sub_y = stbtt__oversample_shift(spc->v_oversample);
- for (j=0; j < ranges[i].num_chars; ++j) {
- stbrp_rect *r = &rects[k];
- if (r->was_packed && r->w != 0 && r->h != 0) {
- stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
- int advance, lsb, x0,y0,x1,y1;
- int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
- int glyph = stbtt_FindGlyphIndex(info, codepoint);
- stbrp_coord pad = (stbrp_coord) spc->padding;
-
- // pad on left and top
- r->x += pad;
- r->y += pad;
- r->w -= pad;
- r->h -= pad;
- stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
- stbtt_GetGlyphBitmapBox(info, glyph,
- scale * spc->h_oversample,
- scale * spc->v_oversample,
- &x0,&y0,&x1,&y1);
- stbtt_MakeGlyphBitmapSubpixel(info,
- spc->pixels + r->x + r->y*spc->stride_in_bytes,
- r->w - spc->h_oversample+1,
- r->h - spc->v_oversample+1,
- spc->stride_in_bytes,
- scale * spc->h_oversample,
- scale * spc->v_oversample,
- 0,0,
- glyph);
-
- if (spc->h_oversample > 1)
- stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
- r->w, r->h, spc->stride_in_bytes,
- spc->h_oversample);
-
- if (spc->v_oversample > 1)
- stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
- r->w, r->h, spc->stride_in_bytes,
- spc->v_oversample);
-
- bc->x0 = (stbtt_int16) r->x;
- bc->y0 = (stbtt_int16) r->y;
- bc->x1 = (stbtt_int16) (r->x + r->w);
- bc->y1 = (stbtt_int16) (r->y + r->h);
- bc->xadvance = scale * advance;
- bc->xoff = (float) x0 * recip_h + sub_x;
- bc->yoff = (float) y0 * recip_v + sub_y;
- bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
- bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
-
- if (glyph == 0)
- missing_glyph = j;
- } else if (spc->skip_missing) {
- return_value = 0;
- } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
- ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
- } else {
- return_value = 0; // if any fail, report failure
- }
-
- ++k;
- }
- }
-
- // restore original values
- spc->h_oversample = old_h_over;
- spc->v_oversample = old_v_over;
-
- return return_value;
-}
-
-STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
-{
- stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
-}
-
-STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
-{
- stbtt_fontinfo info;
- int i,j,n, return_value = 1;
- //stbrp_context *context = (stbrp_context *) spc->pack_info;
- stbrp_rect *rects;
-
- // flag all characters as NOT packed
- for (i=0; i < num_ranges; ++i)
- for (j=0; j < ranges[i].num_chars; ++j)
- ranges[i].chardata_for_range[j].x0 =
- ranges[i].chardata_for_range[j].y0 =
- ranges[i].chardata_for_range[j].x1 =
- ranges[i].chardata_for_range[j].y1 = 0;
-
- n = 0;
- for (i=0; i < num_ranges; ++i)
- n += ranges[i].num_chars;
-
- rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
- if (rects == NULL)
- return 0;
-
- info.userdata = spc->user_allocator_context;
- stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
-
- n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
-
- stbtt_PackFontRangesPackRects(spc, rects, n);
-
- return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
-
- STBTT_free(rects, spc->user_allocator_context);
- return return_value;
-}
-
-STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
- int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
-{
- stbtt_pack_range range;
- range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
- range.array_of_unicode_codepoints = NULL;
- range.num_chars = num_chars_in_range;
- range.chardata_for_range = chardata_for_range;
- range.font_size = font_size;
- return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
-}
-
-STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
-{
- int i_ascent, i_descent, i_lineGap;
- float scale;
- stbtt_fontinfo info;
- stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
- scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
- stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
- *ascent = (float) i_ascent * scale;
- *descent = (float) i_descent * scale;
- *lineGap = (float) i_lineGap * scale;
-}
-
-STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
-{
- float ipw = 1.0f / pw, iph = 1.0f / ph;
- const stbtt_packedchar *b = chardata + char_index;
-
- if (align_to_integer) {
- float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
- float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
- q->x0 = x;
- q->y0 = y;
- q->x1 = x + b->xoff2 - b->xoff;
- q->y1 = y + b->yoff2 - b->yoff;
- } else {
- q->x0 = *xpos + b->xoff;
- q->y0 = *ypos + b->yoff;
- q->x1 = *xpos + b->xoff2;
- q->y1 = *ypos + b->yoff2;
- }
-
- q->s0 = b->x0 * ipw;
- q->t0 = b->y0 * iph;
- q->s1 = b->x1 * ipw;
- q->t1 = b->y1 * iph;
-
- *xpos += b->xadvance;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// sdf computation
-//
-
-#define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
-#define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
-
-static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
-{
- float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
- float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
- float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
- float roperp = orig[1]*ray[0] - orig[0]*ray[1];
-
- float a = q0perp - 2*q1perp + q2perp;
- float b = q1perp - q0perp;
- float c = q0perp - roperp;
-
- float s0 = 0., s1 = 0.;
- int num_s = 0;
-
- if (a != 0.0) {
- float discr = b*b - a*c;
- if (discr > 0.0) {
- float rcpna = -1 / a;
- float d = (float) STBTT_sqrt(discr);
- s0 = (b+d) * rcpna;
- s1 = (b-d) * rcpna;
- if (s0 >= 0.0 && s0 <= 1.0)
- num_s = 1;
- if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
- if (num_s == 0) s0 = s1;
- ++num_s;
- }
- }
- } else {
- // 2*b*s + c = 0
- // s = -c / (2*b)
- s0 = c / (-2 * b);
- if (s0 >= 0.0 && s0 <= 1.0)
- num_s = 1;
- }
-
- if (num_s == 0)
- return 0;
- else {
- float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
- float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
-
- float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
- float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
- float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
- float rod = orig[0]*rayn_x + orig[1]*rayn_y;
-
- float q10d = q1d - q0d;
- float q20d = q2d - q0d;
- float q0rd = q0d - rod;
-
- hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
- hits[0][1] = a*s0+b;
-
- if (num_s > 1) {
- hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
- hits[1][1] = a*s1+b;
- return 2;
- } else {
- return 1;
- }
- }
-}
-
-static int equal(float *a, float *b)
-{
- return (a[0] == b[0] && a[1] == b[1]);
-}
-
-static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
-{
- int i;
- float orig[2], ray[2] = { 1, 0 };
- float y_frac;
- int winding = 0;
-
- // make sure y never passes through a vertex of the shape
- y_frac = (float) STBTT_fmod(y, 1.0f);
- if (y_frac < 0.01f)
- y += 0.01f;
- else if (y_frac > 0.99f)
- y -= 0.01f;
-
- orig[0] = x;
- orig[1] = y;
-
- // test a ray from (-infinity,y) to (x,y)
- for (i=0; i < nverts; ++i) {
- if (verts[i].type == STBTT_vline) {
- int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
- int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
- if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
- float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
- if (x_inter < x)
- winding += (y0 < y1) ? 1 : -1;
- }
- }
- if (verts[i].type == STBTT_vcurve) {
- int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
- int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
- int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
- int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
- int by = STBTT_max(y0,STBTT_max(y1,y2));
- if (y > ay && y < by && x > ax) {
- float q0[2],q1[2],q2[2];
- float hits[2][2];
- q0[0] = (float)x0;
- q0[1] = (float)y0;
- q1[0] = (float)x1;
- q1[1] = (float)y1;
- q2[0] = (float)x2;
- q2[1] = (float)y2;
- if (equal(q0,q1) || equal(q1,q2)) {
- x0 = (int)verts[i-1].x;
- y0 = (int)verts[i-1].y;
- x1 = (int)verts[i ].x;
- y1 = (int)verts[i ].y;
- if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
- float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
- if (x_inter < x)
- winding += (y0 < y1) ? 1 : -1;
- }
- } else {
- int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
- if (num_hits >= 1)
- if (hits[0][0] < 0)
- winding += (hits[0][1] < 0 ? -1 : 1);
- if (num_hits >= 2)
- if (hits[1][0] < 0)
- winding += (hits[1][1] < 0 ? -1 : 1);
- }
- }
- }
- }
- return winding;
-}
-
-static float stbtt__cuberoot( float x )
-{
- if (x<0)
- return -(float) STBTT_pow(-x,1.0f/3.0f);
- else
- return (float) STBTT_pow( x,1.0f/3.0f);
-}
-
-// x^3 + a*x^2 + b*x + c = 0
-static int stbtt__solve_cubic(float a, float b, float c, float* r)
-{
- float s = -a / 3;
- float p = b - a*a / 3;
- float q = a * (2*a*a - 9*b) / 27 + c;
- float p3 = p*p*p;
- float d = q*q + 4*p3 / 27;
- if (d >= 0) {
- float z = (float) STBTT_sqrt(d);
- float u = (-q + z) / 2;
- float v = (-q - z) / 2;
- u = stbtt__cuberoot(u);
- v = stbtt__cuberoot(v);
- r[0] = s + u + v;
- return 1;
- } else {
- float u = (float) STBTT_sqrt(-p/3);
- float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
- float m = (float) STBTT_cos(v);
- float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
- r[0] = s + u * 2 * m;
- r[1] = s - u * (m + n);
- r[2] = s - u * (m - n);
-
- //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
- //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
- //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
- return 3;
- }
-}
-
-STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
-{
- float scale_x = scale, scale_y = scale;
- int ix0,iy0,ix1,iy1;
- int w,h;
- unsigned char *data;
-
- if (scale == 0) return NULL;
-
- stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
-
- // if empty, return NULL
- if (ix0 == ix1 || iy0 == iy1)
- return NULL;
-
- ix0 -= padding;
- iy0 -= padding;
- ix1 += padding;
- iy1 += padding;
-
- w = (ix1 - ix0);
- h = (iy1 - iy0);
-
- if (width ) *width = w;
- if (height) *height = h;
- if (xoff ) *xoff = ix0;
- if (yoff ) *yoff = iy0;
-
- // invert for y-downwards bitmaps
- scale_y = -scale_y;
-
- {
- int x,y,i,j;
- float *precompute;
- stbtt_vertex *verts;
- int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
- data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
- precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
-
- for (i=0,j=num_verts-1; i < num_verts; j=i++) {
- if (verts[i].type == STBTT_vline) {
- float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
- float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
- float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
- precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
- } else if (verts[i].type == STBTT_vcurve) {
- float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
- float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
- float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
- float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
- float len2 = bx*bx + by*by;
- if (len2 != 0.0f)
- precompute[i] = 1.0f / (bx*bx + by*by);
- else
- precompute[i] = 0.0f;
- } else
- precompute[i] = 0.0f;
- }
-
- for (y=iy0; y < iy1; ++y) {
- for (x=ix0; x < ix1; ++x) {
- float val;
- float min_dist = 999999.0f;
- float sx = (float) x + 0.5f;
- float sy = (float) y + 0.5f;
- float x_gspace = (sx / scale_x);
- float y_gspace = (sy / scale_y);
-
- int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
-
- for (i=0; i < num_verts; ++i) {
- float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
-
- if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
- float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
-
- float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
- if (dist2 < min_dist*min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
-
- // coarse culling against bbox
- //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
- // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
- dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
- STBTT_assert(i != 0);
- if (dist < min_dist) {
- // check position along line
- // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
- // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
- float dx = x1-x0, dy = y1-y0;
- float px = x0-sx, py = y0-sy;
- // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
- // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
- float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
- if (t >= 0.0f && t <= 1.0f)
- min_dist = dist;
- }
- } else if (verts[i].type == STBTT_vcurve) {
- float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
- float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
- float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
- float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
- float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
- float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
- // coarse culling against bbox to avoid computing cubic unnecessarily
- if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
- int num=0;
- float ax = x1-x0, ay = y1-y0;
- float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
- float mx = x0 - sx, my = y0 - sy;
- float res[3] = {0.f,0.f,0.f};
- float px,py,t,it,dist2;
- float a_inv = precompute[i];
- if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
- float a = 3*(ax*bx + ay*by);
- float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
- float c = mx*ax+my*ay;
- if (a == 0.0) { // if a is 0, it's linear
- if (b != 0.0) {
- res[num++] = -c/b;
- }
- } else {
- float discriminant = b*b - 4*a*c;
- if (discriminant < 0)
- num = 0;
- else {
- float root = (float) STBTT_sqrt(discriminant);
- res[0] = (-b - root)/(2*a);
- res[1] = (-b + root)/(2*a);
- num = 2; // don't bother distinguishing 1-solution case, as code below will still work
- }
- }
- } else {
- float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
- float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
- float d = (mx*ax+my*ay) * a_inv;
- num = stbtt__solve_cubic(b, c, d, res);
- }
- dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
- if (dist2 < min_dist*min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
-
- if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
- t = res[0], it = 1.0f - t;
- px = it*it*x0 + 2*t*it*x1 + t*t*x2;
- py = it*it*y0 + 2*t*it*y1 + t*t*y2;
- dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
- if (dist2 < min_dist * min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
- }
- if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
- t = res[1], it = 1.0f - t;
- px = it*it*x0 + 2*t*it*x1 + t*t*x2;
- py = it*it*y0 + 2*t*it*y1 + t*t*y2;
- dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
- if (dist2 < min_dist * min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
- }
- if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
- t = res[2], it = 1.0f - t;
- px = it*it*x0 + 2*t*it*x1 + t*t*x2;
- py = it*it*y0 + 2*t*it*y1 + t*t*y2;
- dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
- if (dist2 < min_dist * min_dist)
- min_dist = (float) STBTT_sqrt(dist2);
- }
- }
- }
- }
- if (winding == 0)
- min_dist = -min_dist; // if outside the shape, value is negative
- val = onedge_value + pixel_dist_scale * min_dist;
- if (val < 0)
- val = 0;
- else if (val > 255)
- val = 255;
- data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
- }
- }
- STBTT_free(precompute, info->userdata);
- STBTT_free(verts, info->userdata);
- }
- return data;
-}
-
-STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
-{
- return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
-}
-
-STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
-{
- STBTT_free(bitmap, userdata);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// font name matching -- recommended not to use this
-//
-
-// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
-static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
-{
- stbtt_int32 i=0;
-
- // convert utf16 to utf8 and compare the results while converting
- while (len2) {
- stbtt_uint16 ch = s2[0]*256 + s2[1];
- if (ch < 0x80) {
- if (i >= len1) return -1;
- if (s1[i++] != ch) return -1;
- } else if (ch < 0x800) {
- if (i+1 >= len1) return -1;
- if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
- if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
- } else if (ch >= 0xd800 && ch < 0xdc00) {
- stbtt_uint32 c;
- stbtt_uint16 ch2 = s2[2]*256 + s2[3];
- if (i+3 >= len1) return -1;
- c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
- if (s1[i++] != 0xf0 + (c >> 18)) return -1;
- if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
- if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
- if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
- s2 += 2; // plus another 2 below
- len2 -= 2;
- } else if (ch >= 0xdc00 && ch < 0xe000) {
- return -1;
- } else {
- if (i+2 >= len1) return -1;
- if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
- if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
- if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
- }
- s2 += 2;
- len2 -= 2;
- }
- return i;
-}
-
-static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
-{
- return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
-}
-
-// returns results in whatever encoding you request... but note that 2-byte encodings
-// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
-STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
-{
- stbtt_int32 i,count,stringOffset;
- stbtt_uint8 *fc = font->data;
- stbtt_uint32 offset = font->fontstart;
- stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
- if (!nm) return NULL;
-
- count = ttUSHORT(fc+nm+2);
- stringOffset = nm + ttUSHORT(fc+nm+4);
- for (i=0; i < count; ++i) {
- stbtt_uint32 loc = nm + 6 + 12 * i;
- if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
- && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
- *length = ttUSHORT(fc+loc+8);
- return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
- }
- }
- return NULL;
-}
-
-static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
-{
- stbtt_int32 i;
- stbtt_int32 count = ttUSHORT(fc+nm+2);
- stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
-
- for (i=0; i < count; ++i) {
- stbtt_uint32 loc = nm + 6 + 12 * i;
- stbtt_int32 id = ttUSHORT(fc+loc+6);
- if (id == target_id) {
- // find the encoding
- stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
-
- // is this a Unicode encoding?
- if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
- stbtt_int32 slen = ttUSHORT(fc+loc+8);
- stbtt_int32 off = ttUSHORT(fc+loc+10);
-
- // check if there's a prefix match
- stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
- if (matchlen >= 0) {
- // check for target_id+1 immediately following, with same encoding & language
- if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
- slen = ttUSHORT(fc+loc+12+8);
- off = ttUSHORT(fc+loc+12+10);
- if (slen == 0) {
- if (matchlen == nlen)
- return 1;
- } else if (matchlen < nlen && name[matchlen] == ' ') {
- ++matchlen;
- if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
- return 1;
- }
- } else {
- // if nothing immediately following
- if (matchlen == nlen)
- return 1;
- }
- }
- }
-
- // @TODO handle other encodings
- }
- }
- return 0;
-}
-
-static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
-{
- stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
- stbtt_uint32 nm,hd;
- if (!stbtt__isfont(fc+offset)) return 0;
-
- // check italics/bold/underline flags in macStyle...
- if (flags) {
- hd = stbtt__find_table(fc, offset, "head");
- if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
- }
-
- nm = stbtt__find_table(fc, offset, "name");
- if (!nm) return 0;
-
- if (flags) {
- // if we checked the macStyle flags, then just check the family and ignore the subfamily
- if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
- if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
- if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
- } else {
- if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
- if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
- if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
- }
-
- return 0;
-}
-
-static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
-{
- stbtt_int32 i;
- for (i=0;;++i) {
- stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
- if (off < 0) return off;
- if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
- return off;
- }
-}
-
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-qual"
-#endif
-
-STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
- float pixel_height, unsigned char *pixels, int pw, int ph,
- int first_char, int num_chars, stbtt_bakedchar *chardata)
-{
- return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
-}
-
-STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
-{
- return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
-}
-
-STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
-{
- return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
-}
-
-STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
-{
- return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
-}
-
-STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
-{
- return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
-}
-
-STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
-{
- return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
-}
-
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
-#endif // STB_TRUETYPE_IMPLEMENTATION
-
-
-// FULL VERSION HISTORY
-//
-// 1.25 (2021-07-11) many fixes
-// 1.24 (2020-02-05) fix warning
-// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
-// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
-// 1.21 (2019-02-25) fix warning
-// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
-// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
-// 1.18 (2018-01-29) add missing function
-// 1.17 (2017-07-23) make more arguments const; doc fix
-// 1.16 (2017-07-12) SDF support
-// 1.15 (2017-03-03) make more arguments const
-// 1.14 (2017-01-16) num-fonts-in-TTC function
-// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
-// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
-// 1.11 (2016-04-02) fix unused-variable warning
-// 1.10 (2016-04-02) allow user-defined fabs() replacement
-// fix memory leak if fontsize=0.0
-// fix warning from duplicate typedef
-// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
-// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
-// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
-// allow PackFontRanges to pack and render in separate phases;
-// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
-// fixed an assert() bug in the new rasterizer
-// replace assert() with STBTT_assert() in new rasterizer
-// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
-// also more precise AA rasterizer, except if shapes overlap
-// remove need for STBTT_sort
-// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
-// 1.04 (2015-04-15) typo in example
-// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
-// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
-// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
-// non-oversampled; STBTT_POINT_SIZE for packed case only
-// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
-// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
-// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
-// 0.8b (2014-07-07) fix a warning
-// 0.8 (2014-05-25) fix a few more warnings
-// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
-// 0.6c (2012-07-24) improve documentation
-// 0.6b (2012-07-20) fix a few more warnings
-// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
-// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
-// 0.5 (2011-12-09) bugfixes:
-// subpixel glyph renderer computed wrong bounding box
-// first vertex of shape can be off-curve (FreeSans)
-// 0.4b (2011-12-03) fixed an error in the font baking example
-// 0.4 (2011-12-01) kerning, subpixel rendering (tor)
-// bugfixes for:
-// codepoint-to-glyph conversion using table fmt=12
-// codepoint-to-glyph conversion using table fmt=4
-// stbtt_GetBakedQuad with non-square texture (Zer)
-// updated Hello World! sample to use kerning and subpixel
-// fixed some warnings
-// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
-// userdata, malloc-from-userdata, non-zero fill (stb)
-// 0.2 (2009-03-11) Fix unsigned/signed char warnings
-// 0.1 (2009-03-09) First public release
-//
-
-/*
-------------------------------------------------------------------------------
-This software is available under 2 licenses -- choose whichever you prefer.
-------------------------------------------------------------------------------
-ALTERNATIVE A - MIT License
-Copyright (c) 2017 Sean Barrett
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-------------------------------------------------------------------------------
-ALTERNATIVE B - Public Domain (www.unlicense.org)
-This is free and unencumbered software released into the public domain.
-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
-software, either in source code form or as a compiled binary, for any purpose,
-commercial or non-commercial, and by any means.
-In jurisdictions that recognize copyright laws, the author or authors of this
-software dedicate any and all copyright interest in the software to the public
-domain. We make this dedication for the benefit of the public at large and to
-the detriment of our heirs and successors. We intend this dedication to be an
-overt act of relinquishment in perpetuity of all present and future rights to
-this software under copyright law.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
-*/
diff --git a/src/main.c b/src/main.c
index d0a19f5..77dacf3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,245 +1,10 @@
-// header includes
-#include "base/base_inc.h"
-#include "os/os_inc.h"
-#include "render/render_inc.h"
-#include "font/font_inc.h"
-#include "draw/draw_inc.h"
-#include "ui/ui_inc.h"
-
-// .c includes
-#include "base/base_inc.c"
-#include "os/os_inc.c"
-#include "os/os_entry_point.c"
-#include "render/render_inc.c"
-#include "font/font_inc.c"
-#include "draw/draw_inc.c"
-#include "ui/ui_inc.c"
-
-#define APP_WINDOW_WIDTH 1280
-#define APP_WINDOW_HEIGHT 720
-#define OS_REFRESH_RATE 60.0f
-#define FRAME_DT 1.0f/OS_REFRESH_RATE
-void EntryPoint()
+
+int main()
{
-
- OS_InitReceipt os_receipt = OS_init();
- OS_InitGfxReceipt os_gfx_receipt = OS_gfx_init(os_receipt);
- //unused_variable(os_gfx_receipt);
- R_InitReceipt r_init_receipt = R_init(os_receipt, os_gfx_receipt);
- F_InitReceipt f_init_receipt = F_init();
- D_InitReceipt d_init_receipt = D_init(r_init_receipt, f_init_receipt);
- unused_variable(d_init_receipt);
-
- UI_State *ui = UI_state_alloc();
- UI_state_set(ui);
-
- OS_Handle window_handle = OS_window_open(0, vec2_S64(APP_WINDOW_WIDTH, APP_WINDOW_HEIGHT), str8_lit("ello"));
- R_Handle window_r = R_window_equip(window_handle);
-
- //break_debugger();
- //~ Main loop
- MSG msg = {0};
- U64 frame_idx = 0;
- for (B32 quit = 0; quit == 0;)
- {
- ArenaTemp scratch = scratch_get(0, 0);
- OS_EventList events = OS_get_events(scratch.arena);
-
- if(window_handle.u64[0] == 0)
- {
- break_debugger();
- }
-
- F32 dt = FRAME_DT;
- Rng2_F32 client_rect = OS_client_rect_from_window(window_handle);
- Vec2_F32 client_rect_dim = dim2_F32(client_rect);
- Vec2_S64 resolution = vec2_S64_from_vec(client_rect_dim);
-
- //- Begin frame
- R_frame_begin();
- D_frame_begin();
- UI_frame_begin(dt);
- R_window_start(window_r, resolution);
- D_Bucket *bucket = D_bucket_make(scratch.arena);
- // Anthing within this bucket scope will be pushed onto this the bucket.
- D_BucketScope(scratch.arena, bucket)
- {
-
-
- //~ Build UI
- UI_build_begin(window_handle, &events); // TODO(anton): events
-
- U64 top_pane_height = 25;
- Vec2_F32 top_bar_p0 = vec2_F32(client_rect.x0, client_rect.y0);
- Vec2_F32 top_bar_p1 = vec2_F32(client_rect.x0 + client_rect_dim.x, client_rect.y0 + top_pane_height);
- Rng2_F32 top_bar_rect = rng2_F32(top_bar_p0, top_bar_p1);
- unused_variable(top_bar_rect);
-
- U64 left_pane_width = 0.2f*APP_WINDOW_WIDTH;
-
- ///////////////////////////
- //- Top bar
- {
- UI_push_fixed_rect(top_bar_rect);
- UI_Box *top_bar_box = UI_box_make(UI_BoxFlag_DrawDropShadow|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, str8_lit("top_bar_pane"));
- UI_pop_fixed_rect();
- UI_push_parent(top_bar_box);
-
- // Top pane
- //UI_pane(top_bar_rect, str8_lit("top_bar_pane"))
- //UI_width_fill
- {
- UI_Key file_menu_key = UI_key_from_string(UI_key_zero(), str8_lit("_file_menu_key_"));
- UI_ctx_menu(file_menu_key)
- {
- UI_pref_width(UI_pixels(100, 0.0))
- UI_pref_height(UI_pixels(25, 0.0f))
- {
- String8 buttons[] = {str8_lit("Open"), str8_lit("Exit")};
-
- for(U64 i = 0; i < ArrayCount(buttons); i++)
- {
- UI_Signal sig = UI_button(buttons[i]);
- if(UI_pressed(sig))
- {
- UI_ctx_menu_close();
- }
- }
-
- }
- }
-
- // Buttons
- {
- B32 menu_open = 0;
- if(ui_state->ctx_menu_open && UI_key_match(file_menu_key, ui_state->ctx_menu_key))
- {
- menu_open = 1;
- }
-
- UI_set_next_pref_width(UI_pixels(100, 0));
- UI_set_next_pref_height(UI_pixels(25, 0));
- UI_Signal file_button = UI_button(str8_lit("File"));
- F32 button_size_y_px = file_button.box->rect.y1-file_button.box->rect.y0;
- Vec2_F32 menu_offset = vec2_F32(0, button_size_y_px);
-
- if(menu_open)
- {
- if(UI_hovering(file_button) && !UI_ctx_menu_is_open(file_menu_key))
- {
- UI_ctx_menu_open(file_menu_key, file_button.box->key, menu_offset);
- }
- }
- else if(UI_pressed(file_button))
- {
- if(UI_ctx_menu_is_open(file_menu_key))
- {
- UI_ctx_menu_close();
- }
- else
- {
- UI_ctx_menu_open(file_menu_key, file_button.box->key, menu_offset);
- }
- }
- //UI_ctx_menu_close();
-
- }
-
- }
- UI_pop_parent();
-
- }
-
-
-
- UI_build_end();
-
-
-
-
- //~ Submit and end frame
- UI_draw();
-
- //
- //Rng2_F32 range = rng2_F32(vec2_F32(10,10), vec2_F32(100, 35));
- //D_rect2D(range, .color = vec4_F32(0, 0, 0, 1.f),
- //.corner_radius = 0,
- //.softness = 0,
- //.omit_texture = 1);
- //D_text2D(vec2_F32(range.p0.x, range.p1.y), str8_lit("Testing text"));
- //
- D_submit(window_r, bucket);
- R_window_finish(window_r);
- UI_frame_end();
- }
-
- //~ Handle Events
- for(OS_Event *event = events.first; event != 0; event = event->next)
- {
- if(event->kind == OS_EventKind_WindowClose)
- {
- quit = 1;
- break;
- }
- if(event->kind == OS_EventKind_Press && OS_handle_match(event->window, window_handle) &&
- event->key == OS_Key_Esc)
- {
- quit = 1;
- break;
- }
- }
-
- // TODO(anton): Understand this? What is going on?
- if(frame_idx == 0)
- {
- OS_window_first_paint(window_handle);
- }
-
- frame_idx += 1;
- if(frame_idx == U64Max)
- {
- frame_idx = 0;
- }
-
- scratch_release(scratch);
- }
-
- //~ Shutdown
- R_window_unequip(window_handle, window_r);
- R_shutdown();
+ return 0;
}
-
-
-
-//
-//
-//UI_padding(UI_pixels(10, 0))
-//UI_width_fill
-//UI_row
-//{
- //UI_spacer(UI_pixels(10, 0));
- //
- //UI_set_next_pref_size(Axis2_X, UI_pixels(100, 1));
- //UI_set_next_pref_size(Axis2_Y, UI_pixels(30, 1));
- //UI_Signal button1 = UI_button(str8_lit("Button1"));
- //unused_variable(button1);
- //
- //UI_spacer(UI_pixels(10, 0));
- //UI_set_next_pref_size(Axis2_X, UI_pixels(100, 0));
- //UI_set_next_pref_size(Axis2_Y, UI_pixels(30, 1));
- //UI_Signal button2 = UI_button(str8_lit("Button2"));
- //unused_variable(button2);
- //
- //UI_spacer(UI_pixels(10, 0));
- //UI_set_next_pref_size(Axis2_X, UI_pixels(100, 0));
- //UI_set_next_pref_size(Axis2_Y, UI_pixels(30, 1));
- //UI_Signal button3 = UI_button(str8_lit("Button3"));
- //unused_variable(button3);
- //
-//}
-//
diff --git a/src/os/os_core.c b/src/os/os_core.c
deleted file mode 100644
index 24db847..0000000
--- a/src/os/os_core.c
+++ /dev/null
@@ -1,5 +0,0 @@
-root_function B32
-OS_handle_match(OS_Handle a, OS_Handle b)
-{
- return a.u64[0] == b.u64[0];
-}
\ No newline at end of file
diff --git a/src/os/os_core.h b/src/os/os_core.h
deleted file mode 100644
index a2d297c..0000000
--- a/src/os/os_core.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef OS_CORE_H
-#define OS_CORE_H
-
-typedef U32 OS_AccessFlags;
-enum {
- OS_AccessFlag_Read = (1<<0),
- OS_AccessFlag_Write = (1<<1),
- OS_AccessFlag_Execute = (1<<2),
- OS_AccessFlag_CreateNew = (1<<3),
- OS_AccessFlag_All = 0xFFFFFFFF,
-};
-
-typedef struct OS_Handle OS_Handle;
-struct OS_Handle {
- U64 u64[1];
-};
-
-typedef enum OS_ErrorCode
-{
- OS_ErrorCode_Null,
- OS_ErrorCode_COUNT
-} OS_ErrorCode;
-
-typedef struct OS_Error OS_Error;
-struct OS_Error {
- OS_Error *next;
- OS_ErrorCode code;
-};
-
-typedef struct OS_ErrorList OS_ErrorList;
-struct OS_ErrorList {
- OS_Error *first;
- OS_Error *last;
- U64 count;
-};
-
-typedef struct OS_InitReceipt OS_InitReceipt;
-struct OS_InitReceipt
-{
- U64 u64[1];
-};
-
-typedef U64 OS_Timestamp;
-
-typedef struct OS_FileAttributes OS_FileAttributes;
-struct OS_FileAttributes
-{
- U64 size;
- OS_Timestamp last_modified;
-};
-
-////////////////////////////////
-//~ Helpers
-root_function B32 OS_handle_match(OS_Handle a, OS_Handle b);
-
-////////////////////////////////
-//~ @os_per_backend Memory
-
-root_function U64 OS_page_size(void);
-root_function void* OS_reserve(U64 size);
-root_function void OS_release(void *ptr, U64 size);
-root_function void OS_commit(void *ptr, U64 size);
-root_function void OS_decommit(void *ptr, U64 size);
-root_function void OS_set_memory_access_flags(void *ptr, U64 size, OS_AccessFlags flags);
-
-////////////////////////////////
-//~ Thread and process types
-
-typedef void OS_Thread_Function(void *params); // void function pointer ?
-
-root_function OS_InitReceipt OS_init(void);
-root_function void OS_thread_context_set(void *ptr);
-root_function void* OS_thread_context_get(void);
-
-////////////////////////////////
-//~ @os_per_backend File System
-root_function OS_Handle OS_file_open(OS_AccessFlags access_flags, String8 path);
-root_function void OS_file_close(OS_Handle file);
-root_function String8 OS_file_read(Arena *arena, OS_Handle file, U64 min, U64 max);
-// We supply whatever we want to write as a String8List,
-// so we can pull data from different places with no intermediate buffer.
-root_function void OS_file_write(Arena *arena, OS_Handle file, U64 off,
- String8List data, OS_ErrorList *out_errors);
-root_function OS_FileAttributes OS_attributes_from_file(OS_Handle file);
-
-
-
-
-#endif /* OS_CORE_H */
diff --git a/src/os/os_entry_point.c b/src/os/os_entry_point.c
deleted file mode 100644
index cab9923..0000000
--- a/src/os/os_entry_point.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#if OS_WINDOWS
-#include "win32/os_entry_point_win32.c"
-#else
-#error Entry point not defined
-#endif
\ No newline at end of file
diff --git a/src/os/os_gfx.c b/src/os/os_gfx.c
deleted file mode 100644
index 4cb7229..0000000
--- a/src/os/os_gfx.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "os_gfx_meta.c"
-
-
-root_function B32
-OS_key_press(OS_EventList *events, OS_Handle window, OS_Key key)
-{
- B32 result = 0;
- for(OS_Event *e = events->first; e != 0; e = e->next)
- {
-
- if(e->kind == OS_EventKind_Press && OS_handle_match(window, e->window) && e->key == key)
- // TODO(anton): modifiers
- {
- OS_consume_event(events, e);
- result = 1;
- break;
- }
- }
- return result;
-}
\ No newline at end of file
diff --git a/src/os/os_gfx.h b/src/os/os_gfx.h
deleted file mode 100644
index 6eea74e..0000000
--- a/src/os/os_gfx.h
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef OS_GFX_H
-#define OS_GFX_H
-
-typedef U32 OS_Window_Flags;
-
-typedef struct OS_InitGfxReceipt OS_InitGfxReceipt;
-struct OS_InitGfxReceipt
-{
- U64 u64[1];
-};
-
-#include "os_gfx_meta.h"
-
-////////////////////////////////
-//~ Cursor Types
-
-typedef enum OS_Cursor
-{
- OS_Cursor_Pointer,
- OS_Cursor_IBar,
- OS_Cursor_LeftRight,
- OS_Cursor_UpDown,
- OS_Cursor_DownRight,
- OS_Cursor_UpRight,
- OS_Cursor_UpDownLeftRight,
- OS_Cursor_HandPoint,
- OS_Cursor_Disabled,
- OS_Cursor_COUNT,
-}
-OS_Cursor;
-
-////////////////////////////////
-//~ Events
-typedef enum OS_EventKind
-{
- OS_EventKind_Null,
- OS_EventKind_Press,
- OS_EventKind_Release,
- OS_EventKind_MouseMove,
- OS_EventKind_Text,
- OS_EventKind_Scroll,
- OS_EventKind_WindowLoseFocus,
- OS_EventKind_WindowClose,
- OS_EventKind_FileDrop,
- OS_EventKind_Wakeup,
- OS_EventKind_COUNT
-}
-OS_EventKind;
-
-
-typedef struct OS_Event OS_Event;
-struct OS_Event
-{
- OS_Event *next;
- OS_Event *prev;
- OS_Handle window;
- OS_EventKind kind;
- //OS_Modifiers modifiers;
- OS_Key key;
- U32 character;
- Vec2_F32 position;
- Vec2_F32 scroll;
- String8 path;
-};
-
-typedef struct OS_EventList OS_EventList;
-struct OS_EventList
-{
- OS_Event *first;
- OS_Event *last;
- U64 count;
-};
-
-////////////////////////////////
-//~ Event Helpers
-root_function U64 OS_character_from_key(OS_Key key);
-root_function String8 OS_string_from_event(Arena *arena, OS_Event *event);
-root_function B32 OS_key_press(OS_EventList *events, OS_Handle window, OS_Key key);
-root_function B32 OS_key_release(OS_EventList *events, OS_Handle window);
-root_function B32 OS_text_codepoint(OS_EventList *events, OS_Handle window, U32 codepoint);
-root_function Vec2_F32 OS_mouse_from_window(OS_Handle handle);
-
-////////////////////////////////
-//~ @os_per_backend Init and windowing
-root_function OS_InitGfxReceipt OS_gfx_init(OS_InitReceipt os_init_receipt);
-root_function OS_Handle OS_window_open(OS_Window_Flags flags, Vec2_S64 size, String8 title);
-root_function Rng2_F32 OS_client_rect_from_window(OS_Handle window_handle);
-
-////////////////////////////////
-//~ @os_per_backend Events
-root_function OS_EventList OS_get_events(Arena *arena);
-root_function void OS_consume_event(OS_EventList *events, OS_Event *event);
-
-#endif /* OS_GFX_H */
diff --git a/src/os/os_gfx_meta.c b/src/os/os_gfx_meta.c
deleted file mode 100644
index 5df8d70..0000000
--- a/src/os/os_gfx_meta.c
+++ /dev/null
@@ -1,95 +0,0 @@
-String8 os_g_key_string_table[92] =
-{
- str8_lit_comp("Null"),
- str8_lit_comp("Escape"),
- str8_lit_comp("F1"),
- str8_lit_comp("F2"),
- str8_lit_comp("F3"),
- str8_lit_comp("F4"),
- str8_lit_comp("F5"),
- str8_lit_comp("F6"),
- str8_lit_comp("F7"),
- str8_lit_comp("F8"),
- str8_lit_comp("F9"),
- str8_lit_comp("F10"),
- str8_lit_comp("F11"),
- str8_lit_comp("F12"),
- str8_lit_comp("F13"),
- str8_lit_comp("F14"),
- str8_lit_comp("F15"),
- str8_lit_comp("F16"),
- str8_lit_comp("F17"),
- str8_lit_comp("F18"),
- str8_lit_comp("F19"),
- str8_lit_comp("F20"),
- str8_lit_comp("F21"),
- str8_lit_comp("F22"),
- str8_lit_comp("F23"),
- str8_lit_comp("F24"),
- str8_lit_comp("Grave Accent"),
- str8_lit_comp("0"),
- str8_lit_comp("1"),
- str8_lit_comp("2"),
- str8_lit_comp("3"),
- str8_lit_comp("4"),
- str8_lit_comp("5"),
- str8_lit_comp("6"),
- str8_lit_comp("7"),
- str8_lit_comp("8"),
- str8_lit_comp("9"),
- str8_lit_comp("Minus"),
- str8_lit_comp("Equal"),
- str8_lit_comp("Backspace"),
- str8_lit_comp("Delete"),
- str8_lit_comp("Tab"),
- str8_lit_comp("A"),
- str8_lit_comp("B"),
- str8_lit_comp("C"),
- str8_lit_comp("D"),
- str8_lit_comp("E"),
- str8_lit_comp("F"),
- str8_lit_comp("G"),
- str8_lit_comp("H"),
- str8_lit_comp("I"),
- str8_lit_comp("J"),
- str8_lit_comp("K"),
- str8_lit_comp("L"),
- str8_lit_comp("M"),
- str8_lit_comp("N"),
- str8_lit_comp("O"),
- str8_lit_comp("P"),
- str8_lit_comp("Q"),
- str8_lit_comp("R"),
- str8_lit_comp("S"),
- str8_lit_comp("T"),
- str8_lit_comp("U"),
- str8_lit_comp("V"),
- str8_lit_comp("W"),
- str8_lit_comp("X"),
- str8_lit_comp("Y"),
- str8_lit_comp("Z"),
- str8_lit_comp("Space"),
- str8_lit_comp("Enter"),
- str8_lit_comp("Ctrl"),
- str8_lit_comp("Shift"),
- str8_lit_comp("Alt"),
- str8_lit_comp("Up"),
- str8_lit_comp("Left"),
- str8_lit_comp("Down"),
- str8_lit_comp("Right"),
- str8_lit_comp("Page Up"),
- str8_lit_comp("Page Down"),
- str8_lit_comp("Home"),
- str8_lit_comp("End"),
- str8_lit_comp("Forward Slash"),
- str8_lit_comp("Period"),
- str8_lit_comp("Comma"),
- str8_lit_comp("Quote"),
- str8_lit_comp("Left Bracket"),
- str8_lit_comp("Right Bracket"),
- str8_lit_comp("Insert"),
- str8_lit_comp("Left Mouse Button"),
- str8_lit_comp("Middle Mouse Button"),
- str8_lit_comp("Right Mouse Button"),
- str8_lit_comp("Semicolon"),
-};
diff --git a/src/os/os_gfx_meta.h b/src/os/os_gfx_meta.h
deleted file mode 100644
index 1cc6b07..0000000
--- a/src/os/os_gfx_meta.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* date = April 5th 2024 7:56 pm */
-
-#ifndef OS_GFX_META_H
-#define OS_GFX_META_H
-
-// TODO(anton): This is generated code in Ryans codebase. I just copy it here now and make some generation
-// myself later.
-
-
-typedef enum OS_Key
-{
- OS_Key_Null,
- OS_Key_Esc,
- OS_Key_F1,
- OS_Key_F2,
- OS_Key_F3,
- OS_Key_F4,
- OS_Key_F5,
- OS_Key_F6,
- OS_Key_F7,
- OS_Key_F8,
- OS_Key_F9,
- OS_Key_F10,
- OS_Key_F11,
- OS_Key_F12,
- OS_Key_F13,
- OS_Key_F14,
- OS_Key_F15,
- OS_Key_F16,
- OS_Key_F17,
- OS_Key_F18,
- OS_Key_F19,
- OS_Key_F20,
- OS_Key_F21,
- OS_Key_F22,
- OS_Key_F23,
- OS_Key_F24,
- OS_Key_GraveAccent,
- OS_Key_0,
- OS_Key_1,
- OS_Key_2,
- OS_Key_3,
- OS_Key_4,
- OS_Key_5,
- OS_Key_6,
- OS_Key_7,
- OS_Key_8,
- OS_Key_9,
- OS_Key_Minus,
- OS_Key_Equal,
- OS_Key_Backspace,
- OS_Key_Delete,
- OS_Key_Tab,
- OS_Key_A,
- OS_Key_B,
- OS_Key_C,
- OS_Key_D,
- OS_Key_E,
- OS_Key_F,
- OS_Key_G,
- OS_Key_H,
- OS_Key_I,
- OS_Key_J,
- OS_Key_K,
- OS_Key_L,
- OS_Key_M,
- OS_Key_N,
- OS_Key_O,
- OS_Key_P,
- OS_Key_Q,
- OS_Key_R,
- OS_Key_S,
- OS_Key_T,
- OS_Key_U,
- OS_Key_V,
- OS_Key_W,
- OS_Key_X,
- OS_Key_Y,
- OS_Key_Z,
- OS_Key_Space,
- OS_Key_Enter,
- OS_Key_Ctrl,
- OS_Key_Shift,
- OS_Key_Alt,
- OS_Key_Up,
- OS_Key_Left,
- OS_Key_Down,
- OS_Key_Right,
- OS_Key_PageUp,
- OS_Key_PageDown,
- OS_Key_Home,
- OS_Key_End,
- OS_Key_ForwardSlash,
- OS_Key_Period,
- OS_Key_Comma,
- OS_Key_Quote,
- OS_Key_LeftBracket,
- OS_Key_RightBracket,
- OS_Key_Insert,
- OS_Key_MouseLeft,
- OS_Key_MouseMiddle,
- OS_Key_MouseRight,
- OS_Key_Semicolon,
- OS_Key_COUNT,
-}
-OS_Key;
-
-root_global String8 os_g_key_string_table[92];
-
-
-
-
-
-#endif //OS_GFX_META_H
diff --git a/src/os/os_inc.c b/src/os/os_inc.c
deleted file mode 100644
index 9fa5346..0000000
--- a/src/os/os_inc.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "os/os_core.c"
-#include "os/os_gfx.c"
-
-#if OS_WINDOWS
-#include "win32/os_core_win32.c"
-#include "win32/os_gfx_win32.c"
-#else
-# error OS layer for this platform not implemented yet
-#endif
\ No newline at end of file
diff --git a/src/os/os_inc.h b/src/os/os_inc.h
deleted file mode 100644
index 876d7b4..0000000
--- a/src/os/os_inc.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef OS_INC_H
-#define OS_INC_H
-
-// TODO(anton): Change this to OS implementations of the memory
-#if !defined(m_reserve)
-#define m_reserve OS_reserve
-#endif
-#if !defined(m_commit)
-#define m_commit OS_commit
-#endif
-#if !defined(m_decommit)
-#define m_decommit OS_decommit
-#endif
-#if !defined(m_release)
-#define m_release OS_release
-#endif
-
-#include "os/os_core.h"
-#include "os/os_gfx.h"
-
-#if OS_WINDOWS
-# include "win32/os_core_win32.h"
-# include "win32/os_gfx_win32.h"
-#else
-# error OS layer for this platform not implemented yet
-#endif
-
-#endif //OS_INC_H
diff --git a/src/os/win32/os_core_win32.c b/src/os/win32/os_core_win32.c
deleted file mode 100644
index d5cf17f..0000000
--- a/src/os/win32/os_core_win32.c
+++ /dev/null
@@ -1,260 +0,0 @@
-#pragma comment(lib, "user32")
-#pragma comment(lib, "winmm")
-#pragma comment(lib, "shell32")
-
-//~ Memory
-root_function U64
-OS_page_size(void) {
- SYSTEM_INFO info;
- GetSystemInfo(&info);
- return info.dwPageSize;
-}
-
-root_function void
-*OS_reserve(U64 size) {
- U64 gb_snapped_size = size;
- // Align the reserved memory to nearest gigabyte?
- gb_snapped_size += M_DEFAULT_RESERVE_SIZE - 1;
- gb_snapped_size -= gb_snapped_size % M_DEFAULT_RESERVE_SIZE;
- void *ptr = VirtualAlloc(0, gb_snapped_size, MEM_RESERVE, PAGE_NOACCESS);
- return ptr;
-}
-
-root_function void
-OS_release(void *ptr, U64 size) {
- VirtualFree(ptr, 0, MEM_RELEASE);
-}
-
-root_function void
-OS_commit(void *ptr, U64 size) {
- U64 page_snapped_size = size;
- page_snapped_size += OS_page_size() - 1;
- page_snapped_size -= page_snapped_size%OS_page_size();
- VirtualAlloc(ptr, page_snapped_size, MEM_COMMIT, PAGE_READWRITE);
-}
-
-root_function void
-OS_decommit(void *ptr, U64 size){
- VirtualFree(ptr, size, MEM_DECOMMIT);
-}
-
-//~ Thread
-root_function OS_InitReceipt OS_init(void)
-{
- if (is_main_thread() && os_g_w32_state == 0)
- {
- Arena *arena = m_make_arena_reserve(Gigabytes(1));
- os_g_w32_state = PushArray(arena, OS_W32_State, 1);
- os_g_w32_state->arena = arena;
-
- os_g_w32_state->thread_arena = m_make_arena_reserve(Kilobytes(256));
-
- }
-
- OS_InitReceipt out;
- out.u64[0] = 1;
- return out;
-}
-
-
-root_function void OS_thread_context_set(void *ptr) {
- TlsSetValue(os_g_w32_state->thread_context_index, ptr);
-}
-
-root_function void* OS_thread_context_get(void) {
- void *result = TlsGetValue(os_g_w32_state->thread_context_index);
- return result;
-}
-
-/* // TODO(anton): This is an interesting function to protect virtual allocs, but it doesn't look like it's
-used in the app template right now. I'll add it when I need it.
-root_function void
-OS_set_memory_access_flags(void *ptr, U64 size, OS_AccessFlags flags) {
-
- U64 page_snapped_size = size;
- page_snapped_size += OS_page_size() - 1;
- page_snapped_size -= page_snapped_size%OS_page_size();
-
-
- DWORD new_flags = 0;
- {
- switch(flags)
- {
- default:
- {
- new_flags = PAGE_NOACCESS;
- }break;
-#define Map(win32_code, bitflags) case bitflags:{new_flags = win32_code;}break
- Map(PAGE_EXECUTE, OS_AccessFlag_Execute);
- Map(PAGE_EXECUTE_READ, OS_AccessFlag_Execute|OS_AccessFlag_Read);
- Map(PAGE_EXECUTE_READWRITE, OS_AccessFlag_Execute|OS_AccessFlag_Read|OS_AccessFlag_Write);
- Map(PAGE_EXECUTE_WRITECOPY, OS_AccessFlag_Execute|OS_AccessFlag_Write);
- Map(PAGE_READONLY, OS_AccessFlag_Read);
- Map(PAGE_READWRITE, OS_AccessFlag_Read|OS_AccessFlag_Write);
-#undef Map
- }
- }
-
-
- DWORD old_flags = 0;
- VirtualProtect(ptr, page_snapped_size, new_flags, &old_flags);
-}
-*/
-
-
-
-//~ @os_per_backend File System
-root_function OS_Handle
-OS_file_open(OS_AccessFlags access_flags, String8 path) {
- ArenaTemp scratch = scratch_get(0, 0);
- String16 path16 = str16_from8(scratch.arena, path);
-
- // Map to win32 access flags
- DWORD desired_access = 0;
- if(access_flags & OS_AccessFlag_Read) { desired_access |= GENERIC_READ; }
- if(access_flags & OS_AccessFlag_Write) { desired_access |= GENERIC_WRITE; }
-
- DWORD share_mode = 0;
-
- SECURITY_ATTRIBUTES security_attributes = {
- (DWORD)sizeof(SECURITY_ATTRIBUTES),
- 0,
- 0,
- };
-
- // Map to win32 creation disposition
- DWORD creation_disposition = 0;
- if(!(access_flags & OS_AccessFlag_CreateNew)) {
- creation_disposition = OPEN_EXISTING;
- }
-
- DWORD flags_and_attribs = 0;
- HANDLE template_file = 0;
-
- HANDLE file = CreateFileW((WCHAR*)path16.str,
- desired_access,
- share_mode,
- &security_attributes,
- creation_disposition,
- flags_and_attribs,
- template_file);
-
- if(file == INVALID_HANDLE_VALUE) {
- // TODO(anton): Append to errors
- break_debugger();
- }
-
- // Map to abstract handle
- OS_Handle handle = {0};
- handle.u64[0] = (U64)file;
-
- scratch_release(scratch);
- return handle;
-}
-
-root_function void
-OS_file_close(OS_Handle file) {
- HANDLE handle = (HANDLE)file.u64[0];
- if(handle != INVALID_HANDLE_VALUE) {
- CloseHandle(handle);
- }
-}
-
-root_function String8
-OS_file_read(Arena *arena, OS_Handle file, U64 min, U64 max) {
- String8 result = {0};
-
- HANDLE handle = (HANDLE)file.u64[0];
- if(handle == INVALID_HANDLE_VALUE) {
- // TODO(anton): accumulate errors
- } else {
- U64 bytes_to_read = AbsoluteValueU64(max - min);
- U64 bytes_actually_read = 0;
- result.str = PushArray(arena, U8, bytes_to_read);
- result.size = 0;
- U8 *ptr = result.str;
- U8 *one_past_last = result.str + bytes_to_read;
-
- for(;;) {
- U64 unread = (U64)(one_past_last - ptr);
- DWORD to_read = (DWORD)(ClampTop(unread, U32Max));
- DWORD did_read = 0;
- // TODO(anton): Understand WINAPI
- if(!ReadFile(handle, ptr, to_read, &did_read, 0)) {
- break;
- }
- ptr += did_read;
- result.size += did_read;
- if(ptr >= one_past_last) {
- break;
- }
-
- }
- }
- return result;
-}
-
-root_function OS_FileAttributes
-OS_attributes_from_file(OS_Handle file)
-{
- HANDLE handle = (HANDLE)file.u64[0];
- OS_FileAttributes attrs = {0};
- U32 high_bits = 0;
- U32 low_bits = GetFileSize(handle, (DWORD *)&high_bits);
- FILETIME last_write_time = {0};
- GetFileTime(handle, 0, 0, &last_write_time);
- attrs.size = (U64)low_bits | (((U64)high_bits) << 32);
- attrs.last_modified = ((U64)last_write_time.dwLowDateTime) |
- (((U64)last_write_time.dwHighDateTime) << 32);
- return attrs;
-}
-
-root_function void
-OS_file_write(Arena *arena, OS_Handle file, U64 off, String8List data, OS_ErrorList *out_errors) {
- HANDLE handle = (HANDLE)file.u64[0];
- if(handle == 0 || handle == INVALID_HANDLE_VALUE)
- {
- // TODO(anton): accumulate errors
- }
- else for(String8Node *node = data.first; node != 0; node = node->next)
- {
- U8 *ptr = node->string.str;
- U8 *opl = ptr + node->string.size;
- for(;;)
- {
- U64 unwritten = (U64)(opl - ptr);
- DWORD to_write = (DWORD)(ClampTop(unwritten, U32Max));
- DWORD did_write = 0;
- // TODO(anton): understand winapi
- if(!WriteFile(handle, ptr, to_write, &did_write, 0))
- {
- goto fail_out;
- }
- ptr += did_write;
- if(ptr >= opl)
- {
- break;
- }
- }
- }
- fail_out:;
-}
-
-root_function Rng2_F32
-OS_client_rect_from_window(OS_Handle window_handle)
-{
- Rng2_F32 rect = {0};
- OS_W32_Window *window = (OS_W32_Window *)window_handle.u64[0];
- if(window != 0)
- {
- RECT w32_rect = {0};
- if(GetClientRect(window->hwnd, &w32_rect))
- {
- rect.x0 = (F32)w32_rect.left;
- rect.y0 = (F32)w32_rect.top;
- rect.x1 = (F32)w32_rect.right;
- rect.y1 = (F32)w32_rect.bottom;
- }
- }
- return rect;
-}
\ No newline at end of file
diff --git a/src/os/win32/os_core_win32.h b/src/os/win32/os_core_win32.h
deleted file mode 100644
index dde3102..0000000
--- a/src/os/win32/os_core_win32.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* date = April 25th 2023 9:46 pm */
-
-#ifndef OS_CORE_WIN32_H
-#define OS_CORE_WIN32_H
-
-// To avoid C4042 error when including windows we use some
-// preprocessor praga macro things.. So when including the windows headers we
-// won't have defined the "function" keyword (we define it in base_core.h),
-// and then we redefine it after when popping.
-#pragma push_macro("function")
-#undef function
-#define WIN32_LEAN_AND_MEAN
-#include
-#pragma pop_macro("function")
-
-
-// We have a nice debugbreak assert macro, but it is nice to have one also specifically for windows HRESULT
-#define AssertHR(hr) Assert(SUCCEEDED(hr))
-
-/////////////////////////////////////
-
-// Processes and threads
-typedef struct OS_W32_Thread OS_W32_Thread;
-struct OS_W32_Thread
-{
- OS_W32_Thread *next;
- HANDLE handle;
- DWORD thread_id;
- void *params;
- OS_Thread_Function *func;
-};
-
-
-/////////////////////////////////////
-// Global state
-typedef struct OS_W32_State OS_W32_State;
-struct OS_W32_State
-{
- Arena *arena;
-
- Arena *thread_arena;
- DWORD thread_context_index;
-};
-
-global HINSTANCE os_g_w32_hinstance;
-global OS_W32_State *os_g_w32_state;
-
-//root_function OS_W32_Window* OS_W32_window_from_handle(OS_Handle handle);
-#endif //OS_CORE_WIN32_H
diff --git a/src/os/win32/os_entry_point_win32.c b/src/os/win32/os_entry_point_win32.c
deleted file mode 100644
index fa4078e..0000000
--- a/src/os/win32/os_entry_point_win32.c
+++ /dev/null
@@ -1,9 +0,0 @@
-function void EntryPoint(void);
-
-
-int WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR lp_cmd_line, int n_show_cmd)
-{
- os_g_w32_hinstance = instance;
- base_main_thread_entry(EntryPoint, (U64)__argc, __argv);
- return 0;
-}
\ No newline at end of file
diff --git a/src/os/win32/os_gfx_win32.c b/src/os/win32/os_gfx_win32.c
deleted file mode 100644
index 5d0a28f..0000000
--- a/src/os/win32/os_gfx_win32.c
+++ /dev/null
@@ -1,328 +0,0 @@
-#pragma comment(lib, "gdi32")
-
-#define OS_W32_GraphicalWindowClassName L"ApplicationWindowClass"
-
-root_function OS_InitGfxReceipt
-OS_gfx_init(OS_InitReceipt os_init_receipt)
-{
- if (is_main_thread() && os_g_w32_gfx_state == 0)
- {
-
- {
- // Global state
- Arena *arena = m_make_arena_reserve(Gigabytes(1));
- os_g_w32_gfx_state = PushArray(arena, OS_W32_Gfx_State, 1);
- os_g_w32_gfx_state->arena = arena;
- os_g_w32_gfx_state->window_arena = m_make_arena_reserve(Gigabytes(1));
- }
- // TODO(antonl) DPI awareness
-
- // Register window class
- {
- /* WNDCLASSW window_class = { 0 }; */
- /* window_class.style = CS_HREDRAW | CS_VREDRAW; */
- /* window_class.lpfnWndProc = OS_W32_WindowProc; */
- /* window_class.hInstance = g_os_w32_hinstance; */
- /* window_class.lpszClassName = OS_W32_GraphicalWindowClassName; */
- /* window_class.hCursor = LoadCursor(0, IDC_ARROW); */
- /* RegisterClassW(&window_class); */
- WNDCLASSEXW window_class = {0};
- window_class.cbSize = sizeof(WNDCLASSEXW);
- window_class.lpfnWndProc = OS_W32_window_proc;
- window_class.hInstance = os_g_w32_hinstance;
- window_class.lpszClassName = OS_W32_GraphicalWindowClassName;
- if(!RegisterClassExW(&window_class))
- {
- break_debugger();
- }
- }
-
- // Rjf makes a "global invisible window", but why?
- {
- os_g_w32_gfx_state->global_hwnd = CreateWindowExW(0,
- OS_W32_GraphicalWindowClassName,
- L"",
- WS_OVERLAPPEDWINDOW,
- 100,100,
- 0,0,
- 0,0,
- os_g_w32_hinstance, 0);
- os_g_w32_gfx_state->global_hdc = GetDC(os_g_w32_gfx_state->global_hwnd);
- }
- }
-
- OS_InitGfxReceipt out;
- out.u64[0] = 1;
- return out;
-}
-
-root_function OS_Handle
-OS_W32_handle_from_window(OS_W32_Window *window)
-{
- OS_Handle handle = { 0 };
- handle.u64[0] = (U64)window;
- return handle;
-}
-
-root_function OS_W32_Window*
-OS_W32_window_from_handle(OS_Handle handle)
-{
- OS_W32_Window *window = (OS_W32_Window *)handle.u64[0];
- return window;
-}
-
-root_function OS_Handle
-OS_window_open(OS_Window_Flags flags, Vec2_S64 size, String8 title)
-{
- OS_Handle handle = { 0 };
-
- {
- // Window allocation
- OS_W32_Window *window = os_g_w32_gfx_state->free_window;
- {
- // Windows are stored in a stack on the gfx state
- if (window != 0)
- {
- StackPop(os_g_w32_gfx_state->free_window);
- }
- else
- {
- window = PushArray(os_g_w32_gfx_state->window_arena, OS_W32_Window, 1);
- }
- MemoryZeroStruct(window);
- DLLPushBack(os_g_w32_gfx_state->first_window, os_g_w32_gfx_state->last_window, window);
- }
-
- // Open window
- HWND hwnd = 0;
- HDC hdc = 0;
- {
- ArenaTemp scratch = scratch_get(0, 0);
- String16 title16 = str16_from8(scratch.arena, title);
- hwnd = CreateWindowExW(0,
- OS_W32_GraphicalWindowClassName, (LPCWSTR)title16.str,
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- 100, 100,
- size.x, size.y, 0, 0, os_g_w32_hinstance, 0);
- hdc = GetDC(hwnd);
- SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)window);
- scratch_release(scratch);
- }
-
- {
- window->hwnd = hwnd;
- window->hdc = hdc;
- }
-
- handle = OS_W32_handle_from_window(window);
- }
- return handle;
-}
-
-function LRESULT
-OS_W32_window_proc(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param)
-{
- LRESULT result = 0;
-
- OS_Event *event = 0;
- OS_W32_Window *window = (OS_W32_Window *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
- OS_Handle window_handle = OS_W32_handle_from_window(window);
- ArenaTemp scratch = scratch_get(&os_w32_tl_events_arena, 1);
- OS_EventList fallback_event_list = {0};
- if(os_w32_tl_events_arena == 0)
- {
- os_w32_tl_events_arena = scratch.arena;
- os_w32_tl_events_list = &fallback_event_list;
- }
-
- B32 is_release = 0;
- Axis2 scroll_axis = Axis2_Y;
- switch(message)
- {
- default:
- {
- result = DefWindowProcW(hwnd, message, w_param, l_param);
- } break;
-
- //- General window events
- case WM_CLOSE:
- {
- event = PushArray(os_w32_tl_events_arena, OS_Event, 1);
- event->kind = OS_EventKind_WindowClose;
- event->window = window_handle;
- } break;
-
- //- Mouse buttons
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP:
- {
- ReleaseCapture();
- is_release = 1;
- } fallthrough;
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN:
- {
- if(is_release == 0)
- {
- SetCapture(hwnd);
- }
- OS_EventKind kind = is_release ? OS_EventKind_Release : OS_EventKind_Press;
- OS_Key key = OS_Key_MouseLeft;
- switch(message)
- {
- case WM_MBUTTONUP: case WM_MBUTTONDOWN: key = OS_Key_MouseMiddle; break;
- case WM_RBUTTONUP: case WM_RBUTTONDOWN: key = OS_Key_MouseRight; break;
- }
- event = PushArray(os_w32_tl_events_arena, OS_Event, 1);
- event->kind = kind;
- event->window = window_handle;
- event->key = key;
- event->position = OS_mouse_from_window(window_handle);
- } break;
-
- //- Keyboard events
- case WM_SYSKEYDOWN: case WM_SYSKEYUP:
- {
- result = DefWindowProcW(hwnd, message, w_param, l_param);
- } fallthrough;
- case WM_KEYDOWN:
- case WM_KEYUP:
- {
- // TODO(anton): Just check this thing with was down, is down.., WINAPI crap
- B32 was_down = !!(l_param & (1 << 30));
- B32 is_down = !(l_param & (1 << 31));
- OS_EventKind kind = is_down ? OS_EventKind_Press : OS_EventKind_Release;
-
- // TODO(anton): Here we use statics but maybe we should not...
- // Could just move this out and pre-init or generate it and include or whatever...
- // probably should just be in some meta header.
- local_persist OS_Key key_table[256] = {0};
- local_persist B32 key_table_initialised = 0;
- if(!key_table_initialised)
- {
- key_table_initialised = 1;
-
- for (U32 i = 'A', j = OS_Key_A; i <= 'Z'; i += 1, j += 1)
- {
- key_table[i] = (OS_Key)j;
- }
- for (U32 i = '0', j = OS_Key_0; i <= '9'; i += 1, j += 1)
- {
- key_table[i] = (OS_Key)j;
- }
- for (U32 i = VK_F1, j = OS_Key_F1; i <= VK_F24; i += 1, j += 1)
- {
- key_table[i] = (OS_Key)j;
- }
-
- key_table[VK_ESCAPE] = OS_Key_Esc;
- key_table[VK_OEM_3] = OS_Key_GraveAccent;
- key_table[VK_OEM_MINUS] = OS_Key_Minus;
- key_table[VK_OEM_PLUS] = OS_Key_Equal;
- key_table[VK_BACK] = OS_Key_Backspace;
- key_table[VK_TAB] = OS_Key_Tab;
- key_table[VK_SPACE] = OS_Key_Space;
- key_table[VK_RETURN] = OS_Key_Enter;
- key_table[VK_CONTROL] = OS_Key_Ctrl;
- key_table[VK_SHIFT] = OS_Key_Shift;
- key_table[VK_MENU] = OS_Key_Alt;
- key_table[VK_UP] = OS_Key_Up;
- key_table[VK_LEFT] = OS_Key_Left;
- key_table[VK_DOWN] = OS_Key_Down;
- key_table[VK_RIGHT] = OS_Key_Right;
- key_table[VK_DELETE] = OS_Key_Delete;
- key_table[VK_PRIOR] = OS_Key_PageUp;
- key_table[VK_NEXT] = OS_Key_PageDown;
- key_table[VK_HOME] = OS_Key_Home;
- key_table[VK_END] = OS_Key_End;
- key_table[VK_OEM_2] = OS_Key_ForwardSlash;
- key_table[VK_OEM_PERIOD] = OS_Key_Period;
- key_table[VK_OEM_COMMA] = OS_Key_Comma;
- key_table[VK_OEM_7] = OS_Key_Quote;
- key_table[VK_OEM_4] = OS_Key_LeftBracket;
- key_table[VK_OEM_6] = OS_Key_RightBracket;
- key_table[VK_INSERT] = OS_Key_Insert;
- key_table[VK_OEM_1] = OS_Key_Semicolon;
- }
-
- OS_Key key = OS_Key_Null;
- if(w_param < ArrayCount(key_table))
- {
- key = key_table[w_param];
- }
-
- event = PushArray(os_w32_tl_events_arena, OS_Event, 1);
- event->kind = kind;
- event->window = window_handle;
- event->key = key;
- } break;
-
-
- }
- // If we registered an event we push it to the event list.
- if(event)
- {
- DLLPushBack(os_w32_tl_events_list->first, os_w32_tl_events_list->last, event);
- os_w32_tl_events_list->count += 1;
- }
-
- scratch_release(scratch);
- return result;
-}
-
-root_function Vec2_F32
-OS_mouse_from_window(OS_Handle handle)
-{
- Vec2_F32 result = vec2_F32(-100, -100);
- OS_W32_Window *window = OS_W32_window_from_handle(handle);
- if(window != 0)
- {
- POINT point;
- if(GetCursorPos(&point))
- {
- if(ScreenToClient(window->hwnd, &point))
- {
- result = vec2_F32(point.x, point.y);
- }
- }
- }
-
- return result;
-}
-
-root_function OS_EventList
-OS_get_events(Arena* arena)
-{
- OS_EventList list = {0};
- os_w32_tl_events_arena = arena;
- os_w32_tl_events_list = &list;
- for(MSG message; PeekMessage(&message, 0, 0, 0, PM_REMOVE);)
- {
- TranslateMessage(&message);
- DispatchMessage(&message);
- }
- os_w32_tl_events_arena = 0;
- os_w32_tl_events_list = 0;
-
- return list;
-}
-
-root_function void
-OS_consume_event(OS_EventList *events, OS_Event *event)
-{
- DLLRemove(events->first, events->last, event);
- events->count -= 1;
- event->kind = OS_EventKind_Null;
-}
-
-root_function void
-OS_window_first_paint(OS_Handle handle)
-{
- ArenaTemp scratch = scratch_get(0,0);
- OS_W32_Window *window = OS_W32_window_from_handle(handle);
- ShowWindow(window->hwnd, SW_SHOW);
- UpdateWindow(window->hwnd);
- scratch_release(scratch);
-}
\ No newline at end of file
diff --git a/src/os/win32/os_gfx_win32.h b/src/os/win32/os_gfx_win32.h
deleted file mode 100644
index 76a0f06..0000000
--- a/src/os/win32/os_gfx_win32.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef OS_GFX_WIN32_H
-#define OS_GFX_WIN32_H
-
-typedef struct OS_W32_Window OS_W32_Window;
-struct OS_W32_Window
-{
- OS_W32_Window *next;
- OS_W32_Window *prev;
- HWND hwnd;
- HDC hdc;
-};
-
-typedef struct OS_W32_Gfx_State OS_W32_Gfx_State;
-struct OS_W32_Gfx_State
-{
- Arena *arena;
- HWND global_hwnd;
- HDC global_hdc;
-
- Arena *window_arena;
- OS_W32_Window *first_window;
- OS_W32_Window *last_window;
- OS_W32_Window *free_window;
-};
-
-root_global OS_W32_Gfx_State *os_g_w32_gfx_state = 0;
-extern per_thread Arena *os_w32_tl_events_arena = 0;
-extern per_thread OS_EventList *os_w32_tl_events_list = 0;
-
-root_function OS_Handle OS_W32_handle_from_window(OS_W32_Window *window);
-root_function OS_W32_Window *OS_W32_window_from_handle(OS_Handle handle);
-function LRESULT OS_W32_window_proc(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param);
-
-
-
-#endif // OS_GFX_WIN32_H
diff --git a/src/render/d3d11/render_d3d11.c b/src/render/d3d11/render_d3d11.c
deleted file mode 100644
index c2ebc1f..0000000
--- a/src/render/d3d11/render_d3d11.c
+++ /dev/null
@@ -1,798 +0,0 @@
-// Global tables generated by the metadesk code in Ryan's codebase,
-// here I do them by hand, for now
-
-//////////////////////////////////
-//~ Input element descriptions
-
-global D3D11_INPUT_ELEMENT_DESC r_d3d11_g_rect2d_input_layout_elems[] =
-{
- {"POS", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- 0, D3D11_INPUT_PER_INSTANCE_DATA, 1},
- {"TEX", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
- {"COL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
- {"COL", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
- {"COL", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
- {"COL", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
- { "CRAD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
- {"STY", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
- D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
-};
-
-
-
-global R_D3D11_CmdGlobalKindInfo r_d3d11_g_cmd_global_kind_info_table[R_D3D11_CmdGlobalKind_COUNT] =
-{
- {0}, // Nil
- {sizeof(R_D3D11_CmdGlobals_Rect2D)},
-};
-
-
-R_D3D11_ShaderPairKindInfo r_d3d11_g_shader_pair_kind_info_table[R_D3D11_ShaderPairKind_COUNT] = {0};
-
-global R_D3D11_State *r_d3d11_state;
-
-
-
-//////////////////////////////////
-//~ Render helpers
-
-// Create a buffer holding all the instance data for a current batch
-r_function ID3D11Buffer *
-R_D3D11_instance_buffer_from_batch_list(R_BatchList *list)
-{
- U64 needed_size = list->byte_count;
- if(needed_size > Kilobytes(64))
- {
- break_debugger();
- }
-
- ID3D11Buffer *buffer = r_d3d11_state->scratch_buffer_64kb;
-
- D3D11_MAPPED_SUBRESOURCE sub_resource = {0};
- ID3D11DeviceContext_Map(r_d3d11_state->base_device_context, (ID3D11Resource *)buffer, 0,
- D3D11_MAP_WRITE_DISCARD, 0, &sub_resource);
- U8 *ptr = (U8 *)sub_resource.pData;
- for(R_Batch *batch = list->first; batch != 0; batch = batch->next)
- {
- MemoryCopy(ptr, batch->v, batch->byte_count);
- ptr += batch->byte_count;
- }
- ID3D11DeviceContext_Unmap(r_d3d11_state->base_device_context, (ID3D11Resource *)buffer, 0);
-
-
-
- return buffer;
-}
-
-
-// Temporary initialisation of the shader table, probably we just keep reading the shader src from file here
-// in the end, and we generate a table through metaprogramming.
-r_function void
-R_D3D11_initialise_shader_table(Arena* shader_src_arena)
-{
- String8 shader_paths[R_D3D11_ShaderPairKind_COUNT] = {0};
- shader_paths[R_D3D11_ShaderPairKind_Rect2D] =
- str8_lit("D:\\dev\\app_codebase\\src\\render\\d3d11\\shaders\\rect2d.hlsl");
-
-
-
- String8 shader_name[R_D3D11_ShaderPairKind_COUNT] = {0};
- shader_name[R_D3D11_ShaderPairKind_Rect2D] = str8_lit("r_d3d11_g_rect2d_shader_src");
-
-
- for(R_D3D11_ShaderPairKind kind = (R_D3D11_ShaderPairKind)(R_D3D11_ShaderPairKind_Nil+1);
- kind < R_D3D11_ShaderPairKind_COUNT;
- kind = (R_D3D11_ShaderPairKind)(kind+1))
- {
- // We're on windows anyway so might as well
- OS_Handle file = OS_file_open(OS_AccessFlag_Read, shader_paths[kind]);
- OS_FileAttributes attrs = OS_attributes_from_file(file);
- String8 shader_src = OS_file_read(shader_src_arena, file, 0, attrs.size);
- r_d3d11_g_shader_pair_kind_info_table[kind].name = shader_name[kind];
- r_d3d11_g_shader_pair_kind_info_table[kind].shader_blob = shader_src;
- if(kind == R_D3D11_ShaderPairKind_Rect2D) {
- r_d3d11_g_shader_pair_kind_info_table[kind].element_description = r_d3d11_g_rect2d_input_layout_elems;
- r_d3d11_g_shader_pair_kind_info_table[kind].element_description_count =
- ArrayCount(r_d3d11_g_rect2d_input_layout_elems);
- }
- OS_file_close(file);
- }
-}
-
-r_function DXGI_FORMAT
-R_D3D11_DXGI_format_from_tex2d_format(R_Tex2DFormat format)
-{
- DXGI_FORMAT result = DXGI_FORMAT_R8G8B8A8_UNORM;
- switch(format)
- {
- case R_Tex2DFormat_R8: { result = DXGI_FORMAT_R8_UNORM; } break;
- default:
- case R_Tex2DFormat_RGBA8: {} break;
- }
-
- return result;
-}
-
-r_function R_D3D11_Tex2D
-R_D3D11_tex2d_from_handle(R_Handle handle)
-{
- R_D3D11_Tex2D tex = {0};
- tex.texture = (ID3D11Texture2D *)handle.u64[0];
- tex.view = (ID3D11ShaderResourceView *)handle.u64[1];
- tex.size.x = handle.u32[4];
- tex.size.y = handle.u32[5];
- tex.format = (R_Tex2DFormat)handle.u32[6];
- tex.kind = (R_Tex2DKind)handle.u32[7];
- return tex;
-}
-
-r_function R_Handle
-R_D3D11_handle_from_tex2d(R_D3D11_Tex2D texture)
-{
- R_Handle result = {0};
- result.u64[0] = (U64)texture.texture;
- result.u64[1] = (U64)texture.view;
- result.u32[4] = texture.size.x;
- result.u32[5] = texture.size.y;
- result.u32[6] = texture.format;
- result.u32[7] = texture.kind;
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////
-//~ Backend hooks, ie implementations of the render backend abstraction (render_core.h)
-//
-
-// This initialises the D3D11 layer. We have a big struct that holds all the state.
-// How this is done in RJFs codebase really looks like the mmozeiko example but with the big
-// global struct holding the state. The Hidden Grove (rjf) uses the C++ style though, and
-// also the d3d11_1 header which extends d3d11 in some way... But I will reproduce mmozeiko's C example here.
-r_function R_InitReceipt
-R_init(OS_InitReceipt os_init, OS_InitGfxReceipt os_gfx_init)
-{
-
- if(is_main_thread() && r_d3d11_state == 0)
- {
- Arena *arena = m_make_arena_reserve(Gigabytes(16));
- r_d3d11_state = PushArray(arena, R_D3D11_State, 1);
- r_d3d11_state->arena = arena;
-
- HRESULT hr;
-
- // Create D3D11 device & context
- UINT flags = 0;
-#if BUILD_DEBUG
- flags |= D3D11_CREATE_DEVICE_DEBUG;
-#endif
- D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_0 };
- hr = D3D11CreateDevice(
- 0, // Primary adapter chosen automatically if null
- D3D_DRIVER_TYPE_HARDWARE,
- 0, // null for non-softweare driver types
- flags,
- feature_levels,
- ArrayCount(feature_levels),
- D3D11_SDK_VERSION,
- &r_d3d11_state->base_device,
- 0,
- &r_d3d11_state->base_device_context
- );
- AssertHR(hr);
-
- // Enable useful debug messages and breaks
-#if BUILD_DEBUG
- // for debug builds enable VERY USEFUL debug break on API errors
- {
- ID3D11InfoQueue* info;
- ID3D11Device_QueryInterface(r_d3d11_state->base_device, &IID_ID3D11InfoQueue, (void**)&info);
- ID3D11InfoQueue_SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_CORRUPTION, TRUE);
- ID3D11InfoQueue_SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_ERROR, TRUE);
- ID3D11InfoQueue_Release(info);
- }
-
- // enable debug break for DXGI too
- {
- IDXGIInfoQueue* dxgiInfo;
- hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void**)&dxgiInfo);
- AssertHR(hr);
- IDXGIInfoQueue_SetBreakOnSeverity(dxgiInfo, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
- IDXGIInfoQueue_SetBreakOnSeverity(dxgiInfo, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
- IDXGIInfoQueue_Release(dxgiInfo);
- }
-
- // NOTE(anton): from mmozeiko's gist:
- // "after this there's no need to check for any errors on device functions manually
- // so all HRESULT return values in this code will be ignored
- // debugger will break on errors anyway"
- // TODO(anton): Remove AssertHR and use of hr below to check this.
-#endif
-
-
- // Create objects for swapchain-creation (dxgi)
- {
- hr = ID3D11Device_QueryInterface(r_d3d11_state->base_device,
- &IID_IDXGIDevice, (void **)&r_d3d11_state->dxgi_device);
- AssertHR(hr);
-
- hr = IDXGIDevice_GetAdapter(r_d3d11_state->dxgi_device, &r_d3d11_state->dxgi_adapter);
- AssertHR(hr);
-
- hr = IDXGIAdapter_GetParent(r_d3d11_state->dxgi_adapter, &IID_IDXGIFactory2,
- (void **)&r_d3d11_state->dxgi_factory2);
- AssertHR(hr);
-
- }
- }
-
- //- Set up initial pipeline state
- {
- D3D11_RASTERIZER_DESC desc =
- {
- .FillMode = D3D11_FILL_SOLID,
- .CullMode = D3D11_CULL_NONE,
- .DepthClipEnable = TRUE,
- };
- ID3D11Device_CreateRasterizerState(r_d3d11_state->base_device, &desc, &r_d3d11_state->rasterizer_state);
- }
- {
- {
- D3D11_SAMPLER_DESC desc = {0};
- {
- desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
- desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
- }
- //r_d3d11_state->device->CreateSamplerState(&desc, &r_d3d11_state->nearest_sampler);
- ID3D11Device_CreateSamplerState(r_d3d11_state->base_device, &desc, &r_d3d11_state->nearest_sampler);
- }
- {
- D3D11_SAMPLER_DESC desc = {0};
- {
- desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
- desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
- }
- //r_d3d11_state->device->CreateSamplerState(&desc, &r_d3d11_state->linear_sampler);
- ID3D11Device_CreateSamplerState(r_d3d11_state->base_device, &desc, &r_d3d11_state->linear_sampler);
- }
- }
- {
- D3D11_BLEND_DESC desc =
- {
- .RenderTarget[0] =
- {
- .BlendEnable = TRUE,
- .SrcBlend = D3D11_BLEND_SRC_ALPHA,
- .DestBlend = D3D11_BLEND_INV_SRC_ALPHA,
- .BlendOp = D3D11_BLEND_OP_ADD,
- .SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA,
- .DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA,
- .BlendOpAlpha = D3D11_BLEND_OP_ADD,
- .RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL,
- },
- };
- ID3D11Device_CreateBlendState(r_d3d11_state->base_device, &desc, &r_d3d11_state->main_blend_state);
- }
-
- {
- D3D11_DEPTH_STENCIL_DESC desc =
- {
- .DepthEnable = FALSE,
- .DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL,
- .DepthFunc = D3D11_COMPARISON_LESS,
- .StencilEnable = FALSE,
- .StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK,
- .StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK
- };
- ID3D11Device_CreateDepthStencilState(r_d3d11_state->base_device, &desc,
- &r_d3d11_state->depth_stencil_state);
- }
-
- //- Global command buffer creation
- // Loop over the kind enums that are also the indices into the tables
- for(R_D3D11_CmdGlobalKind kind = (R_D3D11_CmdGlobalKind)(R_D3D11_CmdGlobalKind_Nil+1);
- kind < R_D3D11_CmdGlobalKind_COUNT;
- kind = (R_D3D11_CmdGlobalKind)(kind + 1))
- {
- D3D11_BUFFER_DESC desc = {0};
- // The ByteWidth of the buffer is the size of the CmdGlobalKind struct as defined in the table.
- // Then we align it to 16 bytes by adding 15 and subtracting the size mod 16.
- desc.ByteWidth = r_d3d11_g_cmd_global_kind_info_table[kind].size;
- desc.ByteWidth += 15;
- desc.ByteWidth -= desc.ByteWidth % 16;
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- ID3D11Device_CreateBuffer(r_d3d11_state->base_device, &desc, 0 /* subresource data*/,
- &r_d3d11_state->cmd_global_buffer_table[kind]);
- }
-
- // Temporary hold the source code of the shaders so we can compile them
- Arena* shader_src_arena = m_make_arena_reserve(Megabytes(8));
- R_D3D11_initialise_shader_table(shader_src_arena);
-
- //- Create shader objects
- for(R_D3D11_ShaderPairKind kind = (R_D3D11_ShaderPairKind)(R_D3D11_ShaderPairKind_Nil+1);
- kind < R_D3D11_ShaderPairKind_COUNT;
- kind = (R_D3D11_ShaderPairKind)(kind + 1))
- {
- R_D3D11_ShaderPairKindInfo *info = &r_d3d11_g_shader_pair_kind_info_table[kind];
-
- // Compile vertex shader
- ID3DBlob *vs_src_blob = 0;
- ID3DBlob *vs_src_errors = 0;
- ID3D11VertexShader *vs = 0;
- String8 vs_errors = {0};
-
- HRESULT hr;
- {
- hr = D3DCompile(info->shader_blob.str, info->shader_blob.size, (char *)info->name.str, 0, 0,
- "vs_main", "vs_5_0", 0 /* flags */, 0, &vs_src_blob, &vs_src_errors);
- if(vs_src_errors)
- {
- vs_errors = str8( (U8 *)ID3D10Blob_GetBufferPointer(vs_src_errors),
- (U64)ID3D10Blob_GetBufferSize(vs_src_errors));
- break_debugger();
- }
- else
- {
- ID3D11Device_CreateVertexShader(r_d3d11_state->base_device, ID3D10Blob_GetBufferPointer(vs_src_blob),
- ID3D10Blob_GetBufferSize(vs_src_blob), 0, &vs);
- }
- }
-
- // Make input layout
- ID3D11InputLayout *input_layout = 0;
- if(info->element_description != 0)
- {
- ID3D11Device_CreateInputLayout(r_d3d11_state->base_device, info->element_description,
- info->element_description_count,
- ID3D10Blob_GetBufferPointer(vs_src_blob), ID3D10Blob_GetBufferSize(vs_src_blob),
- &input_layout);
- }
-
- // Compile pixel shader
- ID3DBlob *ps_src_blob = 0;
- ID3DBlob *ps_src_errors = 0;
- ID3D11PixelShader *ps = 0;
- String8 ps_errors = {0};
- {
- hr = D3DCompile(info->shader_blob.str, info->shader_blob.size, (char *)info->name.str, 0, 0,
- "ps_main", "ps_5_0", 0, 0, &ps_src_blob, &ps_src_errors);
- if(ps_src_errors)
- {
- ps_errors = str8( (U8 *)ID3D10Blob_GetBufferPointer(ps_src_errors),
- (U64)ID3D10Blob_GetBufferSize(ps_src_errors));
- break_debugger();
- }
- else
- {
- ID3D11Device_CreatePixelShader(r_d3d11_state->base_device, ID3D10Blob_GetBufferPointer(ps_src_blob),
- ID3D10Blob_GetBufferSize(ps_src_blob), 0, &ps);
- }
- }
-
- // Store in state
- r_d3d11_state->input_layout_table[kind] = input_layout;
- r_d3d11_state->vs_table[kind] = vs;
- r_d3d11_state->ps_table[kind] = ps;
-
- ID3D10Blob_Release(vs_src_blob);
- ID3D10Blob_Release(ps_src_blob);
- }
- m_arena_release(shader_src_arena);
-
- //- Scratch buffer resources
- // 64k
- {
- D3D11_BUFFER_DESC desc = {0};
- {
- desc.ByteWidth = Kilobytes(64);
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- }
- ID3D11Device_CreateBuffer(r_d3d11_state->base_device, &desc, 0, &r_d3d11_state->scratch_buffer_64kb);
- }
-
- R_InitReceipt out = {0};
- return out;
-}
-
-
-// This creates the swapchain and attaches it to the OS handle.
-// Since we want to be able to do this dynamically we will store the necessary creation objects in
-// the D3D11 state struct (dxgi device, adapter, factory2).
- r_function R_Handle
-R_window_equip(OS_Handle window_handle)
-{
- // We are just doing regular OS alloc for this, ie no arena.
- R_D3D11_WindowEquip *equip = (R_D3D11_WindowEquip *)OS_reserve(sizeof(R_D3D11_WindowEquip));
- OS_commit(equip, sizeof(*equip));
- OS_W32_Window *window = (OS_W32_Window *)window_handle.u64[0];
- HWND hwnd = window->hwnd;
- DXGI_SWAP_CHAIN_DESC1 swapchain_desc =
- {
- // default 0 value for width & height means to get it from HWND automatically
- //.Width = 0,
- //.Height = 0,
-
- // or use DXGI_FORMAT_R8G8B8A8_UNORM_SRGB for storing sRGB
- .Format = DXGI_FORMAT_R8G8B8A8_UNORM,
-
- // FLIP presentation model does not allow MSAA framebuffer
- // if you want MSAA then you'll need to render offscreen and manually
- // resolve to non-MSAA framebuffer
- .SampleDesc = { 1, 0 },
-
- .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
- .BufferCount = 2,
-
- // we don't want any automatic scaling of window content
- // this is supported only on FLIP presentation model
- .Scaling = DXGI_SCALING_NONE,
-
- // use more efficient FLIP presentation model
- // Windows 10 allows to use DXGI_SWAP_EFFECT_FLIP_DISCARD
- // for Windows 8 compatibility use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
- // for Windows 7 compatibility use DXGI_SWAP_EFFECT_DISCARD
- .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
- };
-
- HRESULT hr = IDXGIFactory2_CreateSwapChainForHwnd(
- r_d3d11_state->dxgi_factory2,
- (IUnknown *)r_d3d11_state->base_device,
- hwnd,
- &swapchain_desc,
- 0, 0,
- &equip->swapchain
- );
-
- IDXGISwapChain1_GetBuffer(equip->swapchain, 0, &IID_ID3D11Texture2D, (void **)(&equip->framebuffer));
- ID3D11Device_CreateRenderTargetView(r_d3d11_state->base_device, (ID3D11Resource*)equip->framebuffer,
- 0, &equip->framebuffer_rtv);
-
-
- IDXGIFactory_MakeWindowAssociation(r_d3d11_state->dxgi_factory2, hwnd, DXGI_MWA_NO_ALT_ENTER);
-
- return R_D3D11_handle_from_window_equip(equip);
-}
-
-r_function void
-R_window_unequip(OS_Handle window, R_Handle window_equip)
-{
- R_D3D11_WindowEquip *equip = R_D3D11_window_equip_from_handle(window_equip);
- if(equip->framebuffer_rtv) { ID3D11RenderTargetView_Release(equip->framebuffer_rtv); }
- if(equip->framebuffer) { ID3D11Texture2D_Release(equip->framebuffer); }
- if(equip->swapchain) { IDXGISwapChain_Release(equip->swapchain); }
- OS_release(equip, sizeof(*equip));
-}
-
-// The render handle is a nice way to abstract way whatever different ways to describe the
-// swapchain we have in different graphics APIs... so we just get and set a pointer with these utilities.
-r_function R_Handle
-R_D3D11_handle_from_window_equip(R_D3D11_WindowEquip *equip)
-{
- R_Handle handle = {0};
- handle.u64[0] = (U64)equip;
- return handle;
-}
-
-r_function R_D3D11_WindowEquip *
-R_D3D11_window_equip_from_handle(R_Handle handle)
-{
- R_D3D11_WindowEquip *result = (R_D3D11_WindowEquip *)handle.u64[0];
- return result;
-}
-
-r_function void
-R_frame_begin(void)
-{
- // NOTE(anton): No-op
- // TODO(anton): But why is there no-op here? Comment this
-}
-
- r_function void
-R_frame_end(void)
-{
- // TODO(anton): Implement and understand OverflowBufferNode stuff
-}
-
- r_function void
-R_window_start(R_Handle window_equip_handle, Vec2_S64 resolution)
-{
- R_D3D11_WindowEquip *wnd = R_D3D11_window_equip_from_handle(window_equip_handle);
- // TODO(anton): Ryan uses Device1 and Context1 here, I need to understand why and know the difference.
- ID3D11Device *device = r_d3d11_state->base_device;
- ID3D11DeviceContext *d_ctx = r_d3d11_state->base_device_context;
-
- B32 resolution_changed = (wnd->last_resolution.x != resolution.x ||
- wnd->last_resolution.y != resolution.y);
- wnd->last_resolution = resolution;
-
- // If the resolution changed we need to remake
- // the swap chain and framebuffer.
- if(resolution_changed)
- {
- ID3D11RenderTargetView_Release(wnd->framebuffer_rtv);
- ID3D11Texture2D_Release(wnd->framebuffer);
- // NOTE(anton): Since we are getting the buffers again I think we can resize it to zero here rather
- // than to the resolution as is done in mmozeiko example?
- HRESULT hr = IDXGISwapChain1_ResizeBuffers(wnd->swapchain, 0,
- /* width*/0, /* height */0, DXGI_FORMAT_UNKNOWN, 0);
- if(FAILED(hr))
- {
- break_debugger();
- }
-
- IDXGISwapChain1_GetBuffer(wnd->swapchain, 0, &IID_ID3D11Texture2D, (void**)(&wnd->framebuffer));
- ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource*)wnd->framebuffer,
- 0, &wnd->framebuffer_rtv);
-
- }
-
-
-
-
- // Clear color
- Vec4_F32 clear_color = {0};
- clear_color.x = 0.2f;
- clear_color.y = 0.4f;
- clear_color.z = 0.6f;
-
- ID3D11DeviceContext_ClearRenderTargetView(d_ctx, wnd->framebuffer_rtv, clear_color.v);
-}
-
-
- r_function void
-R_window_submit(R_Handle window_equip, R_PassList *pass_list)
-{
-
- R_D3D11_WindowEquip *wnd = R_D3D11_window_equip_from_handle(window_equip);
- ID3D11DeviceContext *d_ctx = r_d3d11_state->base_device_context;
-
- R_PassNode *pass_node = pass_list->first;
- R_Pass *pass = &pass_node->v;
- R_PassParams_UI* params = pass->params_ui;
-
- //- Draw rectangle batches
- for(R_BatchGroup2DNode *group_node = params->rects.first; group_node != 0; group_node = group_node->next)
- {
-
- // Unpack node
- R_BatchList *batches = &group_node->batches;
- R_BatchGroup2DParams *batch_params = &group_node->params;
- ID3D11Buffer *instance_buffer = R_D3D11_instance_buffer_from_batch_list(batches);
- U64 instance_count = batches->instance_count;
- U64 bytes_per_instance = batches->byte_count/batches->instance_count;
- R_Handle albedo_texture_handle = batch_params->albedo_tex;
- R_D3D11_Tex2D albedo_texture = R_D3D11_tex2d_from_handle(albedo_texture_handle);
- if(R_handle_is_zero(batch_params->albedo_tex))
- {
- break_debugger();
- }
- ID3D11SamplerState *sampler = r_d3d11_state->linear_sampler;
- R_Tex2DSampleKind sample_kind = batch_params->albedo_tex_sample_kind;
- switch(sample_kind)
- {
- default:
- case R_Tex2DSampleKind_Nearest: { sampler = r_d3d11_state->nearest_sampler; } break;
- case R_Tex2DSampleKind_Linear: { sampler = r_d3d11_state->linear_sampler; } break;
- }
-
- /*
- Vec2_F32 clip_min = vec2_F32(
- Clamp(0, Min(batch_params->clip.x0, batch_params->clip.x1), wnd->last_resolution.x),
- Clamp(0, Min(batch_params->clip.y0, batch_params->clip.y1), wnd->last_resolution.y)
- );
- Vec2_F32 clip_max = vec2_F32(
- Clamp(0, Max(batch_params->clip.x0, batch_params->clip.x1), wnd->last_resolution.x),
- Clamp(0, Max(batch_params->clip.y0, batch_params->clip.y1), wnd->last_resolution.y)
- );
- */
- //Rng2_F32 clip = rng2_F32(vec2_F32(0,0), vec2_F32(wnd->last_resolution.x, wnd->last_resolution.y));
-
- // Viewport and rasteriser
- {
- Vec2_S64 resolution = wnd->last_resolution;
- D3D11_VIEWPORT d3d11_viewport = { 0.0f, 0.0f, (F32)resolution.x, (F32)resolution.y, 0.0f, 1.0f };
-
- if(params->viewport.x0 != 0 || params->viewport.x1 != 0 ||
- params->viewport.y0 != 0 || params->viewport.y1 != 0)
- {
- Vec2_F32 dim = dim2_F32(params->viewport);
- d3d11_viewport.TopLeftX = params->viewport.x0;
- d3d11_viewport.TopLeftY = params->viewport.y0;
- d3d11_viewport.Width = dim.x;
- d3d11_viewport.Height = dim.y;
- }
- ID3D11DeviceContext_RSSetViewports(d_ctx, 1, &d3d11_viewport);
- ID3D11DeviceContext_RSSetState(d_ctx, r_d3d11_state->rasterizer_state);
- }
-
- // Scissor rect
- {
- D3D11_RECT rect =
- {
- /* .left = */ 0,
- /* .top = */ 0,
- /* .right = */ (LONG)wnd->last_resolution.x,
- /* .bottom = */ (LONG)wnd->last_resolution.y,
- };
- /* if(clip.x0 != 0 || clip.y0 != 0 || clip.x1 != 0 || clip.y1 != 0) */
- /* { */
- /* rect.left = (LONG)clip.x0; */
- /* rect.right = (LONG)clip.x1; */
- /* rect.top = (LONG)clip.y0; */
- /* rect.bottom = (LONG)clip.y1; */
- /* } */
- ID3D11DeviceContext_RSSetScissorRects(d_ctx, 1, &rect);
- }
-
- // Output merger
- {
- ID3D11DeviceContext_OMSetRenderTargets(d_ctx, 1, &wnd->framebuffer_rtv, 0);
- ID3D11DeviceContext_OMSetBlendState(d_ctx, r_d3d11_state->main_blend_state, 0, 0xffffffff);
- ID3D11DeviceContext_OMSetDepthStencilState(d_ctx, r_d3d11_state->depth_stencil_state, 0);
- }
-
- // Get pipeline objects
- ID3D11Buffer *cmd_global_buffer = r_d3d11_state->cmd_global_buffer_table[R_D3D11_CmdGlobalKind_Rect2D];
- ID3D11VertexShader *vs = r_d3d11_state->vs_table[R_D3D11_ShaderPairKind_Rect2D];
- ID3D11PixelShader *ps = r_d3d11_state->ps_table[R_D3D11_ShaderPairKind_Rect2D];
- ID3D11InputLayout *input_layout = r_d3d11_state->input_layout_table[R_D3D11_ShaderPairKind_Rect2D];
-
- // Send per-cmd globals
- R_D3D11_CmdGlobals_Rect2D cmd_globals = {0};
- {
- cmd_globals.viewport_size = vec2_F32_from_vec(wnd->last_resolution);
- cmd_globals.albedo_t2d_size = vec2_F32_from_vec(albedo_texture.size);
- cmd_globals.transform[0] = vec3_F32(batch_params->xform2d.elements[0][0],
- batch_params->xform2d.elements[1][0],
- batch_params->xform2d.elements[2][0]);
- cmd_globals.transform[1] = vec3_F32(batch_params->xform2d.elements[0][1],
- batch_params->xform2d.elements[1][1],
- batch_params->xform2d.elements[2][1]);
- cmd_globals.transform[2] = vec3_F32(batch_params->xform2d.elements[0][2],
- batch_params->xform2d.elements[1][2],
- batch_params->xform2d.elements[2][2]);
- }
-
- // TODO(anton): Make this into a function
- {
- D3D11_MAPPED_SUBRESOURCE sub_resource = {0};
- ID3D11DeviceContext_Map(d_ctx, (ID3D11Resource *)cmd_global_buffer, 0,
- D3D11_MAP_WRITE_DISCARD, 0, &sub_resource);
- String8 data = str8_struct(&cmd_globals);
- U8 *ptr = (U8 *)sub_resource.pData;
- MemoryCopy(ptr, data.str, data.size);
- ID3D11DeviceContext_Unmap(d_ctx, (ID3D11Resource *)cmd_global_buffer, 0);
- }
-
- // Setup input assembly
- U32 stride = bytes_per_instance;
- U32 offset = 0;
- ID3D11DeviceContext_IASetPrimitiveTopology(d_ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
- ID3D11DeviceContext_IASetInputLayout(d_ctx, input_layout);
- ID3D11DeviceContext_IASetVertexBuffers(d_ctx, 0, 1, &instance_buffer, &stride, &offset);
-
- // Setup shaders
- ID3D11DeviceContext_VSSetShader(d_ctx, vs, 0, 0);
- ID3D11DeviceContext_VSSetConstantBuffers(d_ctx, 0, 1, &cmd_global_buffer);
- ID3D11DeviceContext_PSSetShader(d_ctx, ps, 0, 0);
- ID3D11DeviceContext_PSSetConstantBuffers(d_ctx, 0, 1, &cmd_global_buffer);
- ID3D11DeviceContext_PSSetShaderResources(d_ctx, 0, 1, &albedo_texture.view);
- ID3D11DeviceContext_PSSetSamplers(d_ctx, 0, 1, &sampler);
-
- // Draw
- ID3D11DeviceContext_DrawInstanced(d_ctx, /* 4 vertices for a rect */4, instance_count, 0, 0);
- }
-
-}
-
-
-
- r_function void
-R_window_finish(R_Handle window_eqp)
-{
- R_D3D11_WindowEquip *wnd = R_D3D11_window_equip_from_handle(window_eqp);
- HRESULT hr = IDXGISwapChain1_Present(wnd->swapchain, 1, 0);
- if(FAILED(hr))
- {
- break_debugger();
- }
-
- ID3D11DeviceContext_ClearState(r_d3d11_state->base_device_context);
-}
-
-
-r_function R_Handle
-R_tex2d_font_atlas(Vec2_S64 size, U8 *data)
-{
- D3D11_USAGE usage = data ? D3D11_USAGE_IMMUTABLE : D3D11_USAGE_DEFAULT;
- UINT access_flags = 0;
- // TODO(anton): Make switch on Tex2DKind here when we generalise
- access_flags = 0;
-
- R_Tex2DFormat fmt = R_Tex2DFormat_R8;
-
- D3D11_TEXTURE2D_DESC tex_desc = {0};
- {
- tex_desc.Width = size.x;
- tex_desc.Height = size.y;
- tex_desc.MipLevels = 1;
- tex_desc.ArraySize = 1;
- tex_desc.Format = R_D3D11_DXGI_format_from_tex2d_format(fmt);
- tex_desc.SampleDesc.Count = 1;
- tex_desc.SampleDesc.Quality = 0;
- tex_desc.Usage = usage;
- tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- tex_desc.CPUAccessFlags = access_flags;
- }
-
- D3D11_SUBRESOURCE_DATA initial_data = {0};
- {
- initial_data.pSysMem = data;
- initial_data.SysMemPitch = R_bytes_per_pixel_from_tex2d_format(fmt) * size.x;
- initial_data.SysMemSlicePitch = 0;
- }
-
- R_D3D11_Tex2D texture = {0};
- ID3D11Device_CreateTexture2D(r_d3d11_state->base_device, &tex_desc, &initial_data, &texture.texture);
- ID3D11Device_CreateShaderResourceView(r_d3d11_state->base_device, (ID3D11Resource *)texture.texture, 0, &texture.view);
-
- texture.size = vec2_S32_from_vec(size);
- texture.format = fmt;
- return R_D3D11_handle_from_tex2d(texture);
-}
-
-
-// TODO I kind of dont want this release code but I also dont want the debug output when closing app.
-#define __ID3D11_Release(t, n) if(r_d3d11_state->##n) { t##_Release(r_d3d11_state->##n); }
-// This is mostly to avoid annoying error message from d3d11 debug layer?
-r_function void
-R_shutdown()
-{
- R_D3D11_Tex2D atlas_texture = R_D3D11_tex2d_from_handle(F_get_state()->atlas.texture);
- if(atlas_texture.texture) { ID3D11Texture2D_Release(atlas_texture.texture); }
- if(atlas_texture.view) { ID3D11ShaderResourceView_Release(atlas_texture.view); }
-
- for(R_D3D11_ShaderPairKind kind = (R_D3D11_ShaderPairKind)(R_D3D11_ShaderPairKind_Nil+1);
- kind < R_D3D11_ShaderPairKind_COUNT;
- kind = (R_D3D11_ShaderPairKind)(kind + 1))
- {
- __ID3D11_Release(ID3D11InputLayout, input_layout_table[kind]);
- __ID3D11_Release(ID3D11VertexShader, vs_table[kind]);
- __ID3D11_Release(ID3D11PixelShader, ps_table[kind]);
- }
-
- for(R_D3D11_CmdGlobalKind kind = (R_D3D11_CmdGlobalKind)(R_D3D11_CmdGlobalKind_Nil+1);
- kind < R_D3D11_CmdGlobalKind_COUNT;
- kind = (R_D3D11_CmdGlobalKind)(kind + 1))
- {
- __ID3D11_Release(ID3D11Buffer, cmd_global_buffer_table[kind]);
- }
-
- __ID3D11_Release(ID3D11Buffer, scratch_buffer_64kb);
- __ID3D11_Release(ID3D11Buffer, scratch_buffer_8mb);
- __ID3D11_Release(ID3D11SamplerState, nearest_sampler);//ID3D11SamplerState_Release(r_d3d11_state->nearest_sampler);
- __ID3D11_Release(ID3D11SamplerState, linear_sampler);//ID3D11SamplerState_Release(r_d3d11_state->linear_sampler);
- __ID3D11_Release(ID3D11DepthStencilState, depth_stencil_state);
- __ID3D11_Release(ID3D11BlendState, main_blend_state);
- __ID3D11_Release(ID3D11RasterizerState, rasterizer_state);//ID3D11RasterizerState_Release(r_d3d11_state->rasterizer_state);
- __ID3D11_Release(IDXGIFactory2, dxgi_factory2);
- __ID3D11_Release(IDXGIAdapter, dxgi_adapter);
- __ID3D11_Release(IDXGIDevice, dxgi_device);
- __ID3D11_Release(ID3D11Device, base_device);
- __ID3D11_Release(ID3D11DeviceContext, base_device_context);
-}
diff --git a/src/render/d3d11/render_d3d11.h b/src/render/d3d11/render_d3d11.h
deleted file mode 100644
index 5d908af..0000000
--- a/src/render/d3d11/render_d3d11.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef RENDER_D3D11_H
-#define RENDER_D3D11_H
-
-#define COBJMACROS
-#include
-#include
-#include
-#include
-
-#pragma comment(lib, "user32")
-#pragma comment(lib, "dxguid")
-#pragma comment(lib, "dxgi")
-#pragma comment(lib, "d3d11")
-#pragma comment(lib, "d3dcompiler")
-
-/////////////////////////////////
-//~ Metadata types. Ryan uses metadesk to generate tables, but I hardcode it for now.
-// TODO(anton): Use metaprogramming to generate what is necessary here.
-
-typedef struct R_D3D11_CmdGlobalKindInfo R_D3D11_CmdGlobalKindInfo;
-struct R_D3D11_CmdGlobalKindInfo
-{
- U64 size;
-};
-
-typedef enum R_D3D11_CmdGlobalKind
-{
- R_D3D11_CmdGlobalKind_Nil,
- R_D3D11_CmdGlobalKind_Rect2D,
- R_D3D11_CmdGlobalKind_Grid,
- R_D3D11_CmdGlobalKind_COUNT
-}
-R_D3D11_CmdGlobalKind;
-
-typedef struct R_D3D11_ShaderPairKindInfo R_D3D11_ShaderPairKindInfo;
-struct R_D3D11_ShaderPairKindInfo
-{
- String8 name;
- String8 shader_blob; //String8 shader_blob;
- D3D11_INPUT_ELEMENT_DESC *element_description;
- U64 element_description_count;
-};
-
-typedef enum R_D3D11_ShaderPairKind
-{
- R_D3D11_ShaderPairKind_Nil,
- R_D3D11_ShaderPairKind_Rect2D,
- R_D3D11_ShaderPairKind_Grid,
- R_D3D11_ShaderPairKind_COUNT
-}
-R_D3D11_ShaderPairKind;
-
-
-/////////////////////////////////
-//~ Pipeline data types
-typedef struct R_D3D11_CmdGlobals_Rect2D R_D3D11_CmdGlobals_Rect2D;
-struct R_D3D11_CmdGlobals_Rect2D
-{
- Vec2_F32 viewport_size;
- Vec2_F32 albedo_t2d_size;
- Vec3_F32 transform[3];
- Vec2_F32 _16byte_padding0_;
-};
-
-
-
-/////////////////////////////////
-//~ Resource types
-
-typedef struct R_D3D11_Tex2D R_D3D11_Tex2D;
-struct R_D3D11_Tex2D
-{
- ID3D11Texture2D *texture;
- ID3D11ShaderResourceView *view;
- Vec2_S32 size;
- R_Tex2DFormat format;
- R_Tex2DKind kind;
-};
-
-typedef struct R_D3D11_Buffer R_D3D11_Buffer;
-struct R_D3D11_Buffer
-{
- ID3D11Buffer *obj;
- U64 size;
-};
-
-/////////////////////////////////
-//~ Main state bundle
-typedef struct R_D3D11_State R_D3D11_State;
-struct R_D3D11_State
-{
- Arena *arena;
-
- //- Base d3d11 objects
- ID3D11Device *base_device;
- ID3D11DeviceContext *base_device_context;
- IDXGIDevice *dxgi_device;
- IDXGIAdapter *dxgi_adapter;
- IDXGIFactory2 *dxgi_factory2;
- ID3D11RasterizerState *rasterizer_state;
- ID3D11BlendState *main_blend_state;
- ID3D11DepthStencilState *depth_stencil_state;
- ID3D11SamplerState *nearest_sampler;
- ID3D11SamplerState *linear_sampler;
-
- //- Global buffers
- // NOTE(anton): We have an extra space for the nil buffer, which is how it will work with nil structs etc.
- // That's "wasting" a bit of space, but with huge benefits in terms of codepaths and error handling.
- // Nil is a valid state that does nothing.
- ID3D11Buffer *cmd_global_buffer_table[R_D3D11_CmdGlobalKind_COUNT];
-
- //- Shader tables
- ID3D11InputLayout *input_layout_table[R_D3D11_ShaderPairKind_COUNT];
- ID3D11VertexShader *vs_table[R_D3D11_ShaderPairKind_COUNT];
- ID3D11PixelShader *ps_table[R_D3D11_ShaderPairKind_COUNT];
-
- // Scratch buffers
- ID3D11Buffer *scratch_buffer_64kb;
- ID3D11Buffer *scratch_buffer_8mb;
-};
-
-typedef struct R_D3D11_WindowEquip R_D3D11_WindowEquip;
-struct R_D3D11_WindowEquip
-{
- IDXGISwapChain1 *swapchain;
- ID3D11Texture2D *framebuffer;
- ID3D11RenderTargetView *framebuffer_rtv;
-
- Vec2_S64 last_resolution;
-};
-
-/////////////////////////////////
-//~ D3D11 Functions
-r_function R_Handle R_D3D11_handle_from_window_equip(R_D3D11_WindowEquip *equip);
-r_function R_D3D11_WindowEquip *R_D3D11_window_equip_from_handle(R_Handle handle);
-r_function R_Handle R_D3D11_handle_from_tex2d(R_D3D11_Tex2D texture);
-#endif /* RENDER_D3D11_H */
diff --git a/src/render/d3d11/shaders/rect2d.hlsl b/src/render/d3d11/shaders/rect2d.hlsl
deleted file mode 100644
index 5db1ccd..0000000
--- a/src/render/d3d11/shaders/rect2d.hlsl
+++ /dev/null
@@ -1,173 +0,0 @@
-cbuffer CmdGlobals : register(b0)
-{
- float2 viewport_size_px;
- float2 albedo_t2d_size_px;
- row_major float3x3 transform;
-}
-
-Texture2D albedo_t2d : register(t0);
-SamplerState albedo_t2d_sampler : register(s0);
-
-struct CPU2Vertex
-{
- float4 dst_rect_px : POS; // Here we have two sets of 2D points, first is the top left corner of the rectnagle, and second is the bottom right corner.
- float4 src_rect_px : TEX;
- float4 color00 : COL0;
- float4 color01 : COL1;
- float4 color10 : COL2;
- float4 color11 : COL3;
- float4 corner_radii_px : CRAD;
- float4 style_params : STY; // border_thickness_px, softness_px, omit_texture, unused
- uint vertex_id : SV_VertexID;
-};
-
-struct Vertex2Pixel
-{
- float4 position : SV_POSITION;
- float2 rect_half_size_px : PSIZE;
- float2 texcoord_pct : TEX;
- float2 cornercoord_pct : CORC;
- float4 color00 : COL0;
- float4 color01 : COL1;
- float4 color10 : COL2;
- float4 color11 : COL3;
- float corner_radius_px : CRAD;
- float border_thickness_px : BTHC;
- float softness_px : SFT;
- float omit_texture : OTX;
-};
-
-//- Helpers
-
-float rect_SDF(float2 sample_pos, float2 rect_half_size, float radius)
-{
- return length(max(abs(sample_pos) - rect_half_size + radius, 0.0)) - radius;
-}
-
-//~ Vertex shader
-Vertex2Pixel
-vs_main(CPU2Vertex cpu2vertex)
-{
- // Here we statically define the vertex as a rectangle over the entire NDC space [-1, 1] for x and y, I think?
- // From debugging in RenderDoc I can confirm that -1,-1 is top left corner, and 1,1 bottom right corner.
- // Then we can use the input data to scale these points to get proper screen space vertex coordinates for what we want to render.
- static float2 vertices[] =
- {
- {-1, -1},
- {-1, +1},
- {+1, -1},
- {+1, +1},
- };
-
- // Unpack input
- float2 dst_p0_px = cpu2vertex.dst_rect_px.xy; // top left corner
- float2 dst_p1_px = cpu2vertex.dst_rect_px.zw; // bottom right corner
- float2 src_p0_px = cpu2vertex.src_rect_px.xy;
- float2 src_p1_px = cpu2vertex.src_rect_px.zw;
- float2 dst_size_px = abs(dst_p1_px - dst_p0_px);
-
- // unpack style
- float border_thickness_px = cpu2vertex.style_params.x;
- float softness_px = cpu2vertex.style_params.y;
- float omit_texture = cpu2vertex.style_params.z;
-
- // Transform input points to screen destination coordinates
- float2 dst_half_size = (dst_p1_px - dst_p0_px) / 2;
- float2 dst_center = (dst_p1_px + dst_p0_px) / 2;
- // transform the vertex according to the input points
- float2 dst_pos = (vertices[cpu2vertex.vertex_id] * dst_half_size + dst_center);
-
- // Swap y-coordinate to have -1,-1 in top left
- dst_pos.y = viewport_size_px.y - dst_pos.y;
-
- float2 src_pos[] =
- {
- float2(src_p0_px.x/albedo_t2d_size_px.x, src_p0_px.y/albedo_t2d_size_px.y),
- float2(src_p0_px.x/albedo_t2d_size_px.x, src_p1_px.y/albedo_t2d_size_px.y),
- float2(src_p1_px.x/albedo_t2d_size_px.x, src_p0_px.y/albedo_t2d_size_px.y),
- float2(src_p1_px.x/albedo_t2d_size_px.x, src_p1_px.y/albedo_t2d_size_px.y),
- };
-
- float2 dst_c_verts_pct[] =
- {
- float2(0, 0),
- float2(0, 1),
- float2(1, 0),
- float2(1, 1),
- };
-
- float dst_r_verts_px[] =
- {
- cpu2vertex.corner_radii_px.x,
- cpu2vertex.corner_radii_px.y,
- cpu2vertex.corner_radii_px.z,
- cpu2vertex.corner_radii_px.w,
- };
-
- // Package output
- Vertex2Pixel vertex2pixel;
- {
- vertex2pixel.position.x = 2 * dst_pos.x / viewport_size_px.x - 1.f;
- vertex2pixel.position.y = 2 * dst_pos.y / viewport_size_px.y - 1.f;
- vertex2pixel.position.z = 0.f;
- vertex2pixel.position.w = 1.f;
- vertex2pixel.rect_half_size_px = dst_size_px/2.0f;
- vertex2pixel.texcoord_pct.x = src_pos[cpu2vertex.vertex_id].x;
- vertex2pixel.texcoord_pct.y = src_pos[cpu2vertex.vertex_id].y;
- vertex2pixel.cornercoord_pct = dst_c_verts_pct[cpu2vertex.vertex_id];
- vertex2pixel.color00 = cpu2vertex.color00;
- vertex2pixel.color01 = cpu2vertex.color01;
- vertex2pixel.color10 = cpu2vertex.color10;
- vertex2pixel.color11 = cpu2vertex.color11;
- vertex2pixel.corner_radius_px = dst_r_verts_px[cpu2vertex.vertex_id];
- vertex2pixel.border_thickness_px = border_thickness_px;
- vertex2pixel.softness_px = softness_px;
- vertex2pixel.omit_texture = omit_texture;
- }
- return vertex2pixel;
-}
-
-//~ Pixel shader
-float4
-ps_main(Vertex2Pixel vertex2pixel) : SV_TARGET
-{
- float4 top_color = (1 - vertex2pixel.cornercoord_pct.x)*vertex2pixel.color00 + (vertex2pixel.cornercoord_pct.x)*vertex2pixel.color10;
- float4 bot_color = (1 - vertex2pixel.cornercoord_pct.x)*vertex2pixel.color01 + (vertex2pixel.cornercoord_pct.x)*vertex2pixel.color11;
- float4 tint = (1 - vertex2pixel.cornercoord_pct.y)*top_color + (vertex2pixel.cornercoord_pct.y)*bot_color;
-
- float4 albedo_sample = float4(1, 1, 1, 1);
- albedo_sample = albedo_t2d.Sample(albedo_t2d_sampler, vertex2pixel.texcoord_pct) * albedo_sample;
-
-
- // Corners
- float2 sdf_sample_pos = float2(
- (2*vertex2pixel.cornercoord_pct.x - 1)*vertex2pixel.rect_half_size_px.x,
- (2*vertex2pixel.cornercoord_pct.y - 1)*vertex2pixel.rect_half_size_px.y
- );
-
- float2 half_size = vertex2pixel.rect_half_size_px - float2(vertex2pixel.softness_px*2.f, vertex2pixel.softness_px*2.f);
- float corner_sdf_s = rect_SDF(sdf_sample_pos, half_size, vertex2pixel.corner_radius_px);
- float corner_sdf_t = 1-smoothstep(0, 2*vertex2pixel.softness_px, corner_sdf_s);
-
- // Borders
- float border_radius = max(vertex2pixel.corner_radius_px-vertex2pixel.border_thickness_px, 0);
- float border_sdf_s = rect_SDF(sdf_sample_pos, half_size - vertex2pixel.border_thickness_px, border_radius);
- float border_sdf_t = smoothstep(0, 2*vertex2pixel.softness_px, border_sdf_s);
-
- if(vertex2pixel.border_thickness_px == 0)
- {
- border_sdf_t = 1;
- }
-
- float4 final_color = float4(1, 1, 1, 1);
- final_color *= tint;
- final_color *= corner_sdf_t;
- final_color *= border_sdf_t;
- if(vertex2pixel.omit_texture < 1)
- {
- final_color = float4(1, 1, 1, albedo_sample.r);
- }
- //float4 final_color = vertex2pixel.color;
- return final_color;
-}
-
diff --git a/src/render/render_core.h b/src/render/render_core.h
deleted file mode 100644
index 6c308fa..0000000
--- a/src/render/render_core.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef RENDER_CORE_H
-#define RENDER_CORE_H
-
-// NOTE(anton):
-// The Render layer is an abstraction over whatever rendering backend is chosen.
-// Right now I will only support D3D11.
-
-//////////////////////////////////////////
-//~ Backend asbtraction
-//
-r_function R_InitReceipt R_init(OS_InitReceipt os_init, OS_InitGfxReceipt os_gfx_init);
-r_function R_Handle R_window_equip(OS_Handle window);
-r_function void R_window_unequip(OS_Handle window, R_Handle window_equip);
-r_function void R_shutdown();
-r_function void R_frame_begin(void);
-r_function void R_frame_end(void);
-r_function void R_window_start(R_Handle window_equip, Vec2_S64 resolution);
-r_function void R_window_submit(R_Handle window_equip, R_PassList *pass_list);
-r_function void R_window_finish(R_Handle window_equip);
-r_function R_Handle R_tex2d_font_atlas(Vec2_S64 size, U8 *data);
-
-#endif /* RENDER_CORE_H */
diff --git a/src/render/render_inc.c b/src/render/render_inc.c
deleted file mode 100644
index 29d9da6..0000000
--- a/src/render/render_inc.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// Main includes
-//
-
-#include "render_types.c"
-//#include "render_core.c" // render_core is really whatever backend we have, ie the actual implementations.
-// So render_d3d11.c should implement R_init, R_window_equip etc
-
-///////
-/// Direct include D3D11 ??
-///
-#include "d3d11/render_d3d11.c"
diff --git a/src/render/render_inc.h b/src/render/render_inc.h
deleted file mode 100644
index 122a612..0000000
--- a/src/render/render_inc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef RENDER_INC_H
-#define RENDER_INC_H
-
-// Backend constants
-#define R_BACKEND_D3D11 1
-
-// Pick backend
-//
-#if !defined(R_BACKEND)
-# if OS_WINDOWS
-# define R_BACKEND R_BACKEND_D3D11
-# else
-# error No rendering backend defined for this operating system.
-# endif
-#endif
-
-////////////////
-
-#include "render_types.h"
-#include "render_core.h"
-
-
-// NOTE(anton): Ryan is doing some thing where he is only directly including d3d11
-// if he is doing a C++ build. I think I always want to directly include?
-// But why is he doing like this? Because of templating?
-// Apparently there is no official C headers for DirectWrite?
-#include "d3d11/render_d3d11.h"
-
-#endif /* RENDER_INC_H */
diff --git a/src/render/render_types.c b/src/render/render_types.c
deleted file mode 100644
index 182705a..0000000
--- a/src/render/render_types.c
+++ /dev/null
@@ -1,92 +0,0 @@
-root_function R_Handle
-R_handle_zero(void)
-{
- R_Handle out = {0};
- return out;
-}
-
-root_function B32
-R_handle_match(R_Handle a, R_Handle b)
-{
- return (a.u64[0] == b.u64[0] &&
- a.u64[1] == b.u64[1] &&
- a.u64[2] == b.u64[2] &&
- a.u64[3] == b.u64[3]);
-}
-
-root_function B32
-R_handle_is_zero(R_Handle handle)
-{
- return R_handle_match(handle, R_handle_zero());
-}
-
-root_function U64
-R_bytes_per_pixel_from_tex2d_format(R_Tex2DFormat fmt)
-{
- U64 result = 0;
- switch(fmt)
- {
- default:
- case R_Tex2DFormat_R8: {result = 1;} break;
- case R_Tex2DFormat_RGBA8: {result = 4;} break;
- }
- return result;
-}
-
-root_function R_Pass *
-R_pass_list_push(Arena *arena, R_PassList *list, R_PassKind kind)
-{
- R_PassNode *node = PushArrayZero(arena, R_PassNode, 1);
- QueuePush(list->first, list->last, node);
- list->count += 1;
- R_Pass *pass = &node->v;
- pass->kind = kind;
- switch(kind)
- {
- default:{} break;
- case R_PassKind_UI: { pass->params_ui = PushArrayZero(arena, R_PassParams_UI, 1); } break;
- }
-
- return pass;
-}
-
-root_function void *
-R_batch_list_push(Arena *arena, R_BatchList *list, U64 cap, U64 instance_size)
-{
- void *result = 0;
- // TODO(anton):
- // A batch is a collection of instances. We should make something
- // that checks so we can grow batches if possible, or makes a new batch if
- // the current batch is full.
- // Right now we just have a single batch and we should fit cap number of instances in it.
- R_Batch *batch = list->last;
- if(batch == 0)
- {
- batch = PushArrayZero(arena, R_Batch, 1);
- // v is just the collection of bytes for this batch.
- batch->v = PushArray(arena, U8, instance_size*cap);
- batch->instance_cap = cap;
- batch->byte_cap = instance_size*cap;
- QueuePush(list->first, list->last, batch);
- list->batch_count += 1;
- }
-
- // Catch full batch
- if(batch->instance_count >= cap)
- {
- break_debugger();
- }
-
- // Grab pointer to the memory that holds the new instance.
- // This is indexed by the current instance count (previous count)
- // and the size in bytes of the instance type.
- U64 instance_count = batch->instance_count;
- result = &batch->v[instance_count*instance_size];
- // Increment count afterwards
- batch->instance_count += 1;
- batch->byte_count += instance_size;
- list->instance_count += 1;
- list->byte_count += instance_size;
-
- return result;
-}
\ No newline at end of file
diff --git a/src/render/render_types.h b/src/render/render_types.h
deleted file mode 100644
index 25b7e57..0000000
--- a/src/render/render_types.h
+++ /dev/null
@@ -1,211 +0,0 @@
-#ifndef RENDER_TYPES_H
-#define RENDER_TYPES_H
-
-
-//////////////////////////////
-//~
-#if LANG_C
-# define r_global extern
-#else
-# define r_global no_name_mangle
-#endif
-#define r_function no_name_mangle
-
-//////////////////////////////
-//~ Basic types
-
-typedef struct R_InitReceipt R_InitReceipt;
-struct R_InitReceipt
-{
- U64 u64[1];
-};
-
-//////////////////////////////
-//~ Handle types
-
-typedef union R_Handle R_Handle;
-union R_Handle
-{
- U64 u64[4];
- U32 u32[8];
-};
-
-//////////////////////////////
-//~ Blending types
-typedef enum R_BlendMode
-{
- R_BlendMode_Normal,
- R_BlendMode_Additive,
- R_BlendMode_COUNT
-}
-R_BlendMode;
-
-
-//////////////////////////////
-//~ Texture types
-typedef enum R_Tex2DFormat
-{
- R_Tex2DFormat_Null,
- R_Tex2DFormat_R8,
- R_Tex2DFormat_RGBA8,
- R_Tex2DFormat_COUNT
-}
-R_Tex2DFormat;
-
-typedef enum R_Tex2DSampleKind
-{
- R_Tex2DSampleKind_Nearest,
- R_Tex2DSampleKind_Linear,
- R_Tex2DSampleKind_COUNT
-}
-R_Tex2DSampleKind;
-
-typedef enum R_Tex2DKind
-{
- R_Tex2DKind_Static,
- R_Tex2DKind_Dynamic,
-}
-R_Tex2DKind;
-
-typedef struct R_Slice2F32 R_Slice2F32;
-struct R_Slice2F32
-{
- R_Handle texture;
- Rng2_F32 region;
-};
-
-
-//////////////////////////////
-//~ Instance types
-// These are the structures that pass information about render primitives down to the
-// render backend.
-typedef struct R_Rect2DInst R_Rect2DInst;
-struct R_Rect2DInst
-{
- Rng2_F32 dst_rect;
- Rng2_F32 src_rect;
- Vec4_F32 colors[Corner_COUNT];
- F32 corner_radii[Corner_COUNT];
- F32 border_thickness;
- F32 softness;
- F32 omit_texture;
- F32 _unused_[1];
-};
-
-
-//////////////////////////////
-//~ Batch type
-typedef struct R_Batch R_Batch;
-struct R_Batch
-{
- R_Batch *next;
- U8 *v;
- U64 byte_count;
- U64 byte_cap;
- U64 instance_count;
- U64 instance_cap;
-};
-
-typedef struct R_BatchList R_BatchList;
-struct R_BatchList
-{
- R_Batch *first;
- R_Batch *last;
- U64 batch_count;
- U64 instance_count;
- U64 byte_count;
-};
-
-typedef struct R_BatchGroup2DParams R_BatchGroup2DParams;
-struct R_BatchGroup2DParams
-{
- R_Handle albedo_tex; // Color texture to go with this batch of 2D renders
- R_Tex2DSampleKind albedo_tex_sample_kind;
- Mat3x3_F32 xform2d;
- Rng2_F32 clip;
-};
-
-typedef struct R_BatchGroup2DNode R_BatchGroup2DNode;
-struct R_BatchGroup2DNode
-{
- R_BatchGroup2DNode *next;
- R_BatchList batches;
- R_BatchGroup2DParams params;
-};
-
-typedef struct R_BatchGroup2DList R_BatchGroup2DList;
-struct R_BatchGroup2DList
-{
- R_BatchGroup2DNode *first;
- R_BatchGroup2DNode *last;
- U64 count;
-};
-
-
-
-
-//////////////////////////////
-//~ Pass types
-typedef enum R_PassKind
-{
- R_PassKind_Null,
- R_PassKind_UI,
- R_PassKind_COUNT
-}
-R_PassKind;
-
-typedef struct R_PassParams_UI R_PassParams_UI;
-struct R_PassParams_UI
-{
- Rng2_F32 viewport;
- R_BatchGroup2DList rects;
-};
-
-typedef struct R_Pass R_Pass;
-struct R_Pass
-{
- R_PassKind kind;
- union
- {
- void *params;
- R_PassParams_UI *params_ui;
- };
-};
-
-typedef struct R_PassNode R_PassNode;
-struct R_PassNode
-{
- R_PassNode *next;
- R_Pass v;
-};
-
-typedef struct R_PassList R_PassList;
-struct R_PassList
-{
- R_PassNode *first;
- R_PassNode *last;
- U64 count;
-};
-
-
-//////////////////////////////
-//~ Handle type functions
-
-root_function R_Handle R_handle_zero(void);
-root_function B32 R_handle_match(R_Handle a, R_Handle b);
-root_function B32 R_handle_is_zero(R_Handle handle);
-
-//////////////////////////////
-//~ Texture type functions
-root_function U64 R_bytes_per_pixel_from_tex2d_format(R_Tex2DFormat fmt);
-//////////////////////////////
-//~ Pass building helper functions
-root_function R_Pass *R_pass_list_push(Arena *arena, R_PassList *list, R_PassKind kind);
-root_function void *R_batch_list_push(Arena *arena, R_BatchList *list, U64 cap, U64 instance_size);
-#define R_batch_list_push_struct(arena, list, cap, type) (type *)R_batch_list_push((arena), (list), (cap), sizeof(type))
-
-//////////////////////////////
-//~ Other??
-
-
-#endif /* RENDER_TYPES_H */
diff --git a/src/ui/ui_basic_widgets.c b/src/ui/ui_basic_widgets.c
deleted file mode 100644
index 6024cc3..0000000
--- a/src/ui/ui_basic_widgets.c
+++ /dev/null
@@ -1,90 +0,0 @@
-
-// We create a box with no flags of size size, and push it to
-// the hierarchy.
-root_function void
-UI_spacer(UI_Size size)
-{
- UI_Box *parent = UI_top_parent();
- Axis2 parent_axis = parent->child_layout_axis;
- UI_set_next_pref_size(parent_axis, size);
- UI_set_next_pref_size(Axis2_flip(parent_axis), UI_pixels(0, 0));
- UI_Box *box = UI_box_make(0, str8_lit(""));
- unused_variable(box);
-}
-
-root_function UI_Signal
-UI_button(String8 string)
-{
- UI_Box *box = UI_box_make(UI_BoxFlag_DrawBorder |
- UI_BoxFlag_DrawBackground |
- UI_BoxFlag_DrawText |
- UI_BoxFlag_DrawHotEffects |
- UI_BoxFlag_DrawActiveEffects |
- //UI_BoxFlag_DrawDropShadow |
- UI_BoxFlag_Clickable,
- string);
- UI_Signal result = UI_signal_from_box(box);
- return result;
-}
-
-root_function void
-UI_named_column_begin(String8 name)
-{
- UI_set_next_child_layout_axis(Axis2_Y);
- UI_Box *box = UI_box_make(0, name);
- UI_push_parent(box);
-}
-
-root_function void
-UI_column_begin(void)
-{
- UI_named_column_begin(str8_lit(""));
-}
-
-root_function void
-UI_column_end(void)
-{
- UI_pop_parent();
-}
-
-root_function void
-UI_named_row_begin(String8 name)
-{
- UI_set_next_child_layout_axis(Axis2_X);
- UI_Box *box = UI_box_make(0, name);
- UI_push_parent(box);
-}
-
-root_function void
-UI_row_begin(void)
-{
- UI_named_row_begin(str8_lit(""));
-}
-
-root_function void
-UI_row_end(void)
-{
- UI_pop_parent();
-}
-
-
-root_function UI_Box *
-UI_pane_begin(Rng2_F32 rect, String8 string)
-{
- UI_push_rect(rect);
- UI_set_next_child_layout_axis(Axis2_Y);
-
- UI_Box *box = UI_box_make(UI_BoxFlag_Clickable|UI_BoxFlag_Clip|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground,
- string);
- UI_pop_rect();
- UI_push_parent(box);
- UI_push_pref_width(UI_pct(1, 0));
- return box;
-}
-
-root_function void
-UI_pane_end(void)
-{
- UI_pop_pref_width();
- UI_pop_parent();
-}
\ No newline at end of file
diff --git a/src/ui/ui_basic_widgets.h b/src/ui/ui_basic_widgets.h
deleted file mode 100644
index f928332..0000000
--- a/src/ui/ui_basic_widgets.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* date = April 2nd 2024 2:13 pm */
-
-#ifndef UI_BASIC_WIDGETS_H
-#define UI_BASIC_WIDGETS_H
-
-
-root_function void UI_spacer(UI_Size size);
-root_function UI_Signal UI_button(String8 string);
-root_function void UI_named_column_begin(String8 name);
-root_function void UI_column_begin(void);
-root_function void UI_column_end(void);
-root_function void UI_named_row_begin(String8 name);
-root_function void UI_row_begin(void);
-root_function void UI_row_end();
-
-#define UI_padding(size) DeferLoop(UI_spacer(size), UI_spacer(size))
-#define UI_column DeferLoop(UI_column_begin(), UI_column_end())
-#define UI_row DeferLoop(UI_row_begin(), UI_row_end())
-
-#endif //UI_BASIC_WIDGETS_H
diff --git a/src/ui/ui_colors.h b/src/ui/ui_colors.h
deleted file mode 100644
index 7e19073..0000000
--- a/src/ui/ui_colors.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* date = April 10th 2024 8:19 pm */
-
-#ifndef UI_COLORS_H
-#define UI_COLORS_H
-
-
-
-#endif //UI_COLORS_H
diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c
deleted file mode 100644
index 085eb3f..0000000
--- a/src/ui/ui_core.c
+++ /dev/null
@@ -1,975 +0,0 @@
-
-per_thread UI_State* ui_state;
-
-global F32 ui_g_dt;
-
-////////////////////////////////
-//~ "Generated"/meta functions
-#include "ui_meta.c"
-
-////////////////////////////////
-//~ Basic type functions
-
-//- Boxes
-root_function B32
-UI_box_is_nil(UI_Box *box)
-{
- return box == 0 || box == &ui_g_nil_box;
-}
-
-root_function UI_BoxRec
-UI_box_recurse_depth_first(UI_Box *box, UI_Box *stopper, MemberOffset sib, MemberOffset child)
-{
- UI_BoxRec rec = {0};
- rec.next = &ui_g_nil_box;
- // We check what we get from the child offset.
- // If it is not nil we set the next pointer to that box.
- if(!UI_box_is_nil(MemberFromOff(box, UI_Box *, child)))
- {
- rec.next = MemberFromOff(box, UI_Box *, child);
- rec.push_count = 1;
- }
- else
- {
- // If the child is nil, we loop over all boxes going up the parent chain,
- // until we hit stopper.
- // As soon as we hit a sibling that is non-nil, we put that in next and return.
- for(UI_Box *b = box; !UI_box_is_nil(b) && b != stopper; b = b->parent)
- {
- if(!UI_box_is_nil(MemberFromOff(b, UI_Box *, sib)))
- {
- rec.next = MemberFromOff(b, UI_Box *, sib);
- break;
- }
- rec.pop_count += 1;
- }
- }
-
- return rec;
-}
-
-//- sizes
-root_function UI_Size
-UI_size_make(UI_SizeKind kind, F32 value, F32 strictness)
-{
- UI_Size result = {0};
- result.kind = kind;
- result.value = value;
- result.strictness = strictness;
- return result;
-}
-
-
-
-//- ID strings
-root_function String8
-UI_hash_part_from_box_string(String8 string)
-{
- // TODO(anton): Implement ryans stuff here with substrings
- return string;
-}
-
-//- Keys
-root_function UI_Key
-UI_key_zero(void)
-{
- UI_Key key = {0};
- return key;
-}
-
-root_function UI_Key
-UI_key_from_string(UI_Key seed, String8 string)
-{
- UI_Key key = {0};
- if(string.size > 0)
- {
- MemoryCopyStruct(&key, &seed);
- for(U64 i = 0; i < string.size; i += 1)
- {
- key.u64[0] = ((key.u64[0] << 5) + key.u64[0]) + string.str[i];
- }
- }
- return key;
-}
-
-root_function B32
-UI_key_match(UI_Key a, UI_Key b)
-{
- return a.u64[0] == b.u64[0];
-}
-
-
-root_function UI_Signal UI_signal_from_box(UI_Box *box)
-{
- UI_Signal sig = {box};
- // TODO(anton): possibly clipped box rect
- Rng2_F32 rect = box->rect;
-
-
- B32 ctx_menu_is_ancestor = 0;
- {
- for(UI_Box *parent = box; !UI_box_is_nil(parent); parent = parent->parent)
- {
- if(parent == ui_state->ctx_menu_root)
- {
- ctx_menu_is_ancestor = 1;
- break;
- }
- }
- }
-
- for(OS_Event *event = ui_state->events->first, *next = 0; event !=0; event = next)
- {
- B32 taken = 0; // flag for consume
- next = event->next;
-
- //- unpack event
- Vec2_F32 event_mouse = event->position;
- B32 event_mouse_in_bounds = rng2_contains_vec2_F32(rect, event_mouse);
- UI_MouseButtonKind event_mouse_button_kind = (event->key == OS_Key_MouseLeft ? UI_MouseButtonKind_Left :
- event->key == OS_Key_MouseRight ? UI_MouseButtonKind_Right :
- event->key == OS_Key_MouseMiddle ? UI_MouseButtonKind_Middle :
- UI_MouseButtonKind_Left);
- B32 event_key_is_mouse = (event->key == OS_Key_MouseLeft ||
- event->key == OS_Key_MouseRight ||
- event->key == OS_Key_MouseMiddle);
- //- Mouse presses
- if(box->flags & UI_BoxFlag_MouseClickable &&
- event->kind == OS_EventKind_Press &&
- event_mouse_in_bounds &&
- event_key_is_mouse)
- {
- ui_state->hot_box_key = box->key;
- ui_state->active_box_key[event_mouse_button_kind] = box->key;
- sig.flag |= (UI_SignalFlag_LeftPressed<events, event);
- }
- }
-
-
- //////////////////////////////
- //- mouse is over this box's rect -> always mark mouse-over
- // But the rect may be non-visible
- Vec2_F32 mouse_pos = ui_state->mouse;
- B32 rect_contains_mouse = rng2_contains_vec2_F32(rect, mouse_pos);
- if(rect_contains_mouse)
- {
- sig.flag |= UI_SignalFlag_MouseOver;
- }
-
- //////////////////////////////
- //- mouse is over this box's rect, no other hot key? -> set hot key, mark hovering
- //
- if(box->flags & UI_BoxFlag_MouseClickable &&
- rect_contains_mouse) // &&
- //(UI_key_match(ui_state->hot_box_key, UI_key_zero()) || UI_key_match(ui_state->hot_box_key, box->key)) //&&
- //(UI_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], UI_key_zero()) || UI_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key)) &&
- //(UI_key_match(ui_state->active_box_key[UI_MouseButtonKind_Middle], UI_key_zero()) || UI_key_match(ui_state->active_box_key[UI_MouseButtonKind_Middle], box->key)) &&
- //(UI_key_match(ui_state->active_box_key[UI_MouseButtonKind_Right], UI_key_zero()) || UI_key_match(ui_state->active_box_key[UI_MouseButtonKind_Right], box->key)))
-
- {
- ui_state->hot_box_key = box->key;
- sig.flag |= UI_SignalFlag_Hovering;
- }
-
- //////////////////////////////
- //- rjf: clicking on something outside the context menu kills the context menu
- //
- if(!ctx_menu_is_ancestor && sig.flag & (UI_SignalFlag_LeftPressed|UI_SignalFlag_RightPressed|UI_SignalFlag_MiddlePressed))
- {
- UI_ctx_menu_close();
- }
-
- return sig;
-}
-
-////////////////////////////////
-//~ UI State functions
-root_function UI_State*
-UI_state_alloc(void)
-{
- ui_g_nil_box.hash_next = &ui_g_nil_box;
- ui_g_nil_box.hash_prev = &ui_g_nil_box;
- ui_g_nil_box.first = &ui_g_nil_box;
- ui_g_nil_box.last = &ui_g_nil_box;
- ui_g_nil_box.next = &ui_g_nil_box;
- ui_g_nil_box.prev = &ui_g_nil_box;
- ui_g_nil_box.parent = &ui_g_nil_box;
-
- Arena* arena = m_make_arena_reserve(Gigabytes(1));
- UI_State *state = PushArrayZero(arena, UI_State, 1);
- state->arena = arena;
- state->box_table_size = 4096;
- state->box_table = PushArrayZero(arena, UI_BoxSlot, state->box_table_size);
-
- // TODO(anton): make some better system for setting and getting theme colors
- state->colors[UI_Color_Null] = vec4_F32(0, 0, 0, 1);
- state->colors[UI_Color_PlainBackground] = vec4_F32(0.3f, 0.2f, 0.2f, 1);
- state->colors[UI_Color_PlainBorder] = vec4_F32(0.4f, 0.4f, 0.4f, 1);
- state->colors[UI_Color_PlainText] = vec4_F32(0.85f, 0.85f, 0.85f, 1);
- state->colors[UI_Color_PlainOverlay] = vec4_F32(0.9f, 0.6f, 0.3f, 1);
-
- for(U64 index = 0; index < ArrayCount(state->frame_arenas); index += 1)
- {
- state->frame_arenas[index] = m_make_arena_reserve(Gigabytes(1));
- }
- state->last_frame_arena_index = 1;
- state->current_frame_arena_index = 0;
- // TODO(anton): drag data arena
- UI_init_stack_nils(state);
- return state;
-}
-
-root_function void
-UI_state_set(UI_State *ui)
-{
- ui_state = ui;
-}
-
-////////////////////////////////
-//~ Build phase
-root_function void
-UI_build_begin(OS_Handle window, OS_EventList *events)
-{
-
- //- Reset per frame state
- {
- UI_init_stacks(ui_state);
- ui_state->build_gen += 1;
- m_arena_clear(UI_frame_arena());
- ui_state->root = &ui_g_nil_box;
- ui_state->ctx_menu_touched_this_frame = 0;
- ui_state->ctx_menu_changed = 0;
-
- }
-
- //- Fill per build parameters
- {
- ui_state->events = events;
- ui_state->window = window;
- ui_state->mouse = OS_mouse_from_window(window);// TODO(anton): window focused and last time moved stuff.
-
- }
-
- //- "Prune stale boxes"
-
- for(U64 slot = 0; slot < ui_state->box_table_size; slot += 1)
- {
- for(UI_Box *box = ui_state->box_table[slot].first, *next = 0;
- !UI_box_is_nil(box);
- box = next)
- {
- // Set the next box
- next = box->hash_next;
- // Any boxes existing in the hash table, that has a zero key or has a last_gen_touched+1 that is less
- // than the current build gen, are removed from the table. The resulting free slots in the table are pushed
- // onto the free list.
- if(UI_key_match(box->key, UI_key_zero()) || box->last_gen_touched+1 < ui_state->build_gen)
- {
- DLLRemove_NPZ(ui_state->box_table[slot].first, ui_state->box_table[slot].last,
- box, hash_next, hash_prev,
- UI_box_is_nil, UI_box_set_nil);
- StackPush(ui_state->first_free_box, box);
- ui_state->free_box_list_count += 1;
- }
- }
- }
-
- //- Build root
- // This is a UI box that extends the whole of the window.
-
- {
- Rng2_F32 client_rect = OS_client_rect_from_window(window);
- Vec2_F32 client_rect_size = dim2_F32(client_rect);
- UI_set_next_pref_width(UI_pixels(client_rect_size.x, 1));
- UI_set_next_pref_height(UI_pixels(client_rect_size.y, 1));
- UI_set_next_child_layout_axis(Axis2_Y);
- String8 root_name = str8_lit("root_box");
- UI_Box *root = UI_box_make(0 /* zero box flags for root box */, root_name);
- UI_push_parent(root);
- ui_state->root = root;
- }
- //- Context menu setup
- ui_state->ctx_menu_open = ui_state->next_ctx_menu_open;
- ui_state->ctx_menu_anchor_key = ui_state->next_ctx_menu_anchor_key;
- {
- UI_Box *anchor_box = UI_box_from_key(ui_state->ctx_menu_anchor_key);
- if(!UI_box_is_nil(anchor_box))
- {
- ui_state->ctx_menu_anchor_box_last_pos = anchor_box->rect.p0;
- }
- Vec2_F32 anchor = add2_F32(ui_state->ctx_menu_anchor_box_last_pos, ui_state->ctx_menu_anchor_offset);
-
- UI_fixed_x(anchor.x) UI_fixed_y(anchor.y)
- UI_pref_width(UI_size_by_children(0, 1)) UI_pref_height(UI_size_by_children(0, 1))
- {
- UI_set_next_child_layout_axis(Axis2_Y);
-
- ui_state->ctx_menu_root = UI_box_make(UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, str8_lit("ctx_menu"));
- }
-
- }
-
- // Reset hot if we don't have an active widget
- B32 has_active = 0;
- for(EachEnumVal(UI_MouseButtonKind, k))
- {
- if(!UI_key_match(ui_state->active_box_key[k], UI_key_zero()))
- {
- has_active = 1;
- }
- }
- if(!has_active)
- {
- ui_state->hot_box_key = UI_key_zero();
- }
-
- //- rjf: reset active keys if they have been pruned
- for(EachEnumVal(UI_MouseButtonKind, k))
- {
- UI_Box *box = UI_box_from_key(ui_state->active_box_key[k]);
- if(UI_box_is_nil(box))
- {
- ui_state->active_box_key[k] = UI_key_zero();
- }
- }
-
-}
-
-root_function void
-UI_build_end(void)
-{
-
- ui_state->ctx_menu_touched_this_frame = 1;
- if(ui_state->ctx_menu_open != 0 || ui_state->ctx_menu_touched_this_frame == 0)
- {
- //UI_ctx_menu_close();
- }
-
- UI_layout();
-
- // TODO(anton): When I need this and understand why
- //if(ui_state->ctx_menu_touched_this_frame && !ui_state->ctx_menu_changed)
- //{
- //UI_Box *anchor_box = UI_box_from_key(ui_state->ctx_menu_anchor_key);
- //if(!UI_box_is_nil(anchor_box))
- //{
- //Rng2_F32 root_rect = ui_state->ctx_menu_root->rect;
- //Vec2_F32 pos =
- //{
- //anchor_box->rect.x0 + ui_state->ctx_menu_anchor_offset.x,
- //anchor_box->rect.y0 + ui_state->ctx_menu_anchor_offset.y,
- //};
- //Vec2_F32 shift = sub2_F32(pos, root_rect.p0);
- //Rng2_F32 new_root_rect = shift2_F32(root_rect, shift);
- //ui_state->ctx_menu_root->fixed_position = new_root_rect.p0;
- //ui_state->ctx_menu_root->fixed_size = dim2_F32(new_root_rect);
- //ui_state->ctx_menu_root->rect = new_root_rect;
- //}
- //}
- //
-}
-
-////////////////////////////////
-//~ Context menu
-root_function void
-UI_ctx_menu_open(UI_Key key, UI_Key anchor_key, Vec2_F32 anchor_offset)
-{
- anchor_offset.x = (F32)(int)anchor_offset.x;
- anchor_offset.y = (F32)(int)anchor_offset.y;
- ui_state->next_ctx_menu_open = 1;
- ui_state->ctx_menu_changed = 1;
- // TODO(anton): time parameter for ctx menu animation
- ui_state->ctx_menu_key = key;
- ui_state->next_ctx_menu_anchor_key = anchor_key;
- ui_state->ctx_menu_anchor_offset = anchor_offset;
- ui_state->ctx_menu_touched_this_frame = 1;
- ui_state->ctx_menu_anchor_box_last_pos = vec2_F32(100, 100);
-}
-
-root_function void
-UI_ctx_menu_close(void)
-{
- ui_state->next_ctx_menu_open = 0;
-}
-
-root_function B32
-UI_begin_ctx_menu(UI_Key key)
-{
- UI_push_parent(ui_state->root);
- UI_push_parent(ui_state->ctx_menu_root);
- B32 result = UI_key_match(key, ui_state->ctx_menu_key) && ui_state->ctx_menu_open;
- if(result)
- {
- ui_state->ctx_menu_touched_this_frame = 1;
- ui_state->ctx_menu_root->flags |= UI_BoxFlag_DrawBackground;
- ui_state->ctx_menu_root->flags |= UI_BoxFlag_DrawDropShadow;
- UI_push_pref_width(UI_pixels(100, 0));
- UI_push_pref_height(UI_pixels(200, 0));
- }
-
-
- return result;
-}
-
-root_function B32
-UI_ctx_menu_is_open(UI_Key key)
-{
- return ui_state->ctx_menu_open && UI_key_match(key, ui_state->ctx_menu_key);
-}
-
-root_function void
-UI_end_ctx_menu(void)
-{
- //UI_Box* top_parent = UI_top_parent();
- UI_pop_pref_width();
- UI_pop_pref_height();
- UI_pop_parent();
- //top_parent = UI_top_parent();
- UI_pop_parent();
- //top_parent = UI_top_parent();
-}
-
-////////////////////////////////
-//~ UI Frame
-root_function Arena *
-UI_frame_arena(void)
-{
- return ui_state->frame_arenas[ui_state->current_frame_arena_index];
-}
-
-root_function void
-UI_frame_begin(F32 delta_time)
-{
- ui_g_dt = delta_time;
-}
-
-root_function void
-UI_frame_end(void)
-{
- U32 last = ui_state->last_frame_arena_index;
- ui_state->last_frame_arena_index = ui_state->current_frame_arena_index;
- ui_state->current_frame_arena_index = last;
-}
-
-
-////////////////////////////////
-//~ Box hierarchy construction
-
-root_function UI_Box *
-UI_box_from_key(UI_Key key)
-{
- UI_Box *result = &ui_g_nil_box;
- // The box table contains all the hashed boxes, so we mod by the size to get the slot in the table.
- U64 slot = key.u64[0] % ui_state->box_table_size;
- if(!UI_key_match(key, UI_key_zero()))
- {
- // We check if we have a box corresponding to the key in the hash table, and return that if we find it.
- for(UI_Box *b = ui_state->box_table[slot].first; !UI_box_is_nil(b); b = b->hash_next)
- {
- if(UI_key_match(b->key, key))
- {
- result = b;
- break;
- }
- }
- }
- return result;
-}
-
-root_function UI_Box *
-UI_box_make_from_key(UI_BoxFlags flags, UI_Key key)
-{
- // Get the nil box or a box from the hash table.
- UI_Box *box = UI_box_from_key(key);
-
- // If the key has already been used, we "trample" over the key/box pair to make an id-less box.
- if(box->last_gen_touched == ui_state->build_gen)
- {
- box = &ui_g_nil_box;
- key = UI_key_zero();
- }
-
- // Allocate the box if it's not allocated, or if it's a duplicate key
- B32 first_frame = 0;
- if(UI_box_is_nil(box))
- {
- U64 slot = key.u64[0] % ui_state->box_table_size;
- first_frame = 1;
- box = ui_state->first_free_box;
- // If the first free box is nil we push a new box on the arena.
- if(UI_box_is_nil(box))
- {
- box = PushArrayZero(ui_state->arena, UI_Box, 1);
- }
- else
- {
- // If the first free box is non-nil, we pop it from the stack.
- // This macro works since the first_free_box is a UI_Box type, which has a next member.
- // So this will but the ui_state->first_free_box pointer to the next member of the previous
- // element pointed to by ui_state->first_free_box.
- StackPop(ui_state->first_free_box);
- MemoryZeroStruct(box);
- ui_state->free_box_list_count -= 1;
- }
- // We push back the box to the doubly linked list in the table slot, using custom functions for
- // zero check and zero set.
- DLLPushBack_NPZ(ui_state->box_table[slot].first,
- ui_state->box_table[slot].last, box, hash_next, hash_prev,
- UI_box_is_nil, UI_box_set_nil);
- box->key = key;
- }
-
- //- Link to the tree by getting the parent. If the parent is nil, the current box should actually be the root.
- UI_Box *parent = UI_top_parent();
- if(UI_box_is_nil(parent))
- {
- ui_state->root = box;
- }
- else
- {
- DLLPushBack_NPZ(parent->first, parent->last, box, next, prev, UI_box_is_nil, UI_box_set_nil);
- parent->child_count += 1;
- box->parent = parent;
- }
-
- //- Fill the state of the current box
- if(!UI_box_is_nil(box))
- {
-
- if(first_frame)
- {
- box->first_gen_touched = ui_state->build_gen;
- }
-
- box->child_count = 0;
- box->first = box->last = &ui_g_nil_box;
- box->flags = flags | UI_top_flags();
-
- if(ui_state->fixed_width_stack.top != &ui_state->fixed_width_nil_stack_top)
- {
- box->flags |= UI_BoxFlag_FixedWidth;
- box->fixed_size.x = ui_state->fixed_width_stack.top->v;
- } else {
- box->pref_size[Axis2_X] = UI_top_pref_width();
- }
-
- if(ui_state->fixed_height_stack.top != &ui_state->fixed_height_nil_stack_top)
- {
- box->flags |= UI_BoxFlag_FixedHeight;
- box->fixed_size.y = ui_state->fixed_height_stack.top->v;
- } else {
- box->pref_size[Axis2_Y] = UI_top_pref_height();
- }
-
-
- box->calc_rel_pos.x = UI_top_fixed_x();
- box->calc_rel_pos.y = UI_top_fixed_y();
-
-
- box->child_layout_axis = UI_top_child_layout_axis();
- box->last_gen_touched = ui_state->build_gen;
-
- // TODO(anton): Text and color drawing properties here
- box->background_color = ui_state->colors[UI_Color_PlainBackground];
- box->text_color = ui_state->colors[UI_Color_PlainText];
- box->border_color = ui_state->colors[UI_Color_PlainBorder];
- box->overlay_color = ui_state->colors[UI_Color_PlainOverlay];
-
- }
-
- UI_auto_pop_stacks(ui_state);
-
- return box;
-}
-
-root_function UI_Box *
-UI_box_make(UI_BoxFlags flags, String8 string)
-{
- UI_Key seed = UI_top_seed_key();
-
- String8 string_hash_part = UI_hash_part_from_box_string(string);
- UI_Key key = UI_key_from_string(seed, string_hash_part);
-
- UI_Box *box = UI_box_make_from_key(flags, key);
-
- box->string = str8_copy(UI_frame_arena(), string);
-
- return box;
-}
-
-////////////////////////////////
-//~ layout
-
-root_function void
-UI_solve_independent_sizes(UI_Box *root, Axis2 axis)
-{
- switch(root->pref_size[axis].kind)
- {
- default:break;
- case UI_SizeKind_Pixels:
- {
- root->calc_size.v[axis] = root->pref_size[axis].value;
- root->calc_size.v[axis] = floor_F32(root->calc_size.v[axis]);
- } break;
- }
-
- // Recurse
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- UI_solve_independent_sizes(child, axis);
- }
-
-}
-
-root_function void
-UI_solve_upward_dependent_sizes(UI_Box *root, Axis2 axis)
-{
- switch(root->pref_size[axis].kind)
- {
- default:break;
- case UI_SizeKind_Percent:
- {
- UI_Box *ancestor = &ui_g_nil_box;
- // Move up the parents and get the first ancestor that does not have
- // size by children.
- for(UI_Box *p = root->parent; !UI_box_is_nil(p); p = p->parent)
- {
- if(p->pref_size[axis].kind != UI_SizeKind_SizeByChildren)
- {
- ancestor = p;
- break;
- }
- }
- // The calculated size of the argument box to this function is then
- // the ancestor calculated size, scaled by the preferred size of this box, which is
- // assumed to be given as a percentage by the SizeKind
- if(!UI_box_is_nil(ancestor))
- {
- root->calc_size.v[axis] = ancestor->calc_size.v[axis] * root->pref_size[axis].value;
- root->calc_size.v[axis] = floor_F32(root->calc_size.v[axis]);
- }
- } break;
- }
-
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- UI_solve_upward_dependent_sizes(child, axis);
- }
-}
-
-root_function void
-UI_solve_downward_dependent_sizes(UI_Box *root, Axis2 axis)
-{
- // Here we first recurse since we will depend on the result for this input.
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- UI_solve_downward_dependent_sizes(child, axis);
- }
-
- switch(root->pref_size[axis].kind)
- {
- default:break;
- case UI_SizeKind_SizeByChildren:
- {
- F32 value = 0;
- {
- // We will calculate the size to be the sum of the child sizes on this axis,
- // if we are on the layout axis.
- // If we are not on the layout axis the size will just be the maximum size of any child on that axis.
- if(axis == root->child_layout_axis)
- {
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- value += child->calc_size.v[axis];
- }
- }
- else
- {
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- value = Max(value, child->calc_size.v[axis]);
- }
- }
- }
- root->calc_size.v[axis] = value;
- root->calc_size.v[axis] = floor_F32(root->calc_size.v[axis]);
- } break;
- }
-}
-
-root_function void
-UI_solve_size_violations(UI_Box *root, Axis2 axis)
-{
- // Determine maximum available space from the root size.
- F32 available_space = root->calc_size.v[axis];
-
- F32 taken_space = 0.0f;
- F32 total_fix_budget = 0.0f;
- B32 is_overflow_x_on_axis = (root->flags & (UI_BoxFlag_OverflowX<first; !UI_box_is_nil(child); child = child->next)
- {
- if(!(child->flags & (UI_BoxFlag_FloatingX<child_layout_axis)
- {
- taken_space += child->calc_size.v[axis];
- }
- else
- {
- taken_space = Max(taken_space, child->calc_size.v[axis]);
- }
-
- F32 fix_budget_this_child = child->calc_size.v[axis] * (1.0f - child->pref_size[axis].strictness);
- total_fix_budget += fix_budget_this_child;
-
- }
- }
- }
-
- //- Fix children as much as possible within the calculated budget
- if(!is_overflow_x_on_axis)
- {
- F32 violation = taken_space - available_space;
- if(violation > 0 && total_fix_budget > 0)
- {
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- if(!(child->flags & (UI_BoxFlag_FloatingX<calc_size.v[axis] * (1.0f - child->pref_size[axis].strictness);
- F32 fix_size_this_child = 0.0f;
- if(axis == root->child_layout_axis)
- {
- fix_size_this_child = fix_budget_this_child * (violation / total_fix_budget);
- }
- else
- {
- fix_size_this_child = child->calc_size.v[axis] - available_space;
- }
- fix_size_this_child = Clamp(0, fix_size_this_child, fix_budget_this_child);
- child->calc_size.v[axis] -= fix_size_this_child;
- child->calc_size.v[axis] = floor_F32(child->calc_size.v[axis]);
- }
- }
- }
- }
-
- //- Position all children after fixup
- {
- if(axis == root->child_layout_axis)
- {
- // Determine the relative offset by incrementing p by the size of a child on the relevant axis.
- F32 p = 0.0f;
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- if(!(child->flags & (UI_BoxFlag_FloatingX<calc_rel_pos.v[axis] = p;
- p += child->calc_size.v[axis];
- }
- }
- }
- else
- {
- // If we're not on the layout axis the relative position is just zero
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- if(!(child->flags & (UI_BoxFlag_FloatingX<calc_rel_pos.v[axis] = 0;
- }
- }
- }
-
- // Set the actual position values and rectangles
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- Rng2_F32 last_rel_rect = child->rel_rect;
- unused_variable(last_rel_rect);
- // The relative rectangle starts at the relative position, and ends at the relative rectangle p0 + size.
- // TODO(anton): What does the relative rectangle mean?
- child->rel_rect.p0.v[axis] = child->calc_rel_pos.v[axis];
- child->rel_rect.p1.v[axis] = child->rel_rect.p0.v[axis] + child->calc_size.v[axis];
- // TODO(anton): Corner stuff here
- // The actual rectangle is the root rect p0, plus th relative p0, minus view offset of the root.
- // And the p1 is the p0 + the size of the child.
- child->rect.p0.v[axis] = root->rect.p0.v[axis] + child->rel_rect.p0.v[axis] - root->view_offset.v[axis];
- child->rect.p1.v[axis] = child->rect.p0.v[axis] + child->calc_size.v[axis];
- if(!(child->flags & (UI_BoxFlag_FloatingX<rect.p0.v[axis] = floor_F32(child->rect.p0.v[axis]);
- child->rect.p1.v[axis] = floor_F32(child->rect.p1.v[axis]);
- }
- }
- }
-
- // Recurse
- for(UI_Box *child = root->first; !UI_box_is_nil(child); child = child->next)
- {
- UI_solve_size_violations(child, axis);
- }
-
-}
-
-root_function void
-UI_layout_root(UI_Box *root, Axis2 axis)
-{
- UI_solve_independent_sizes(root, axis);
- UI_solve_upward_dependent_sizes(root, axis);
- UI_solve_downward_dependent_sizes(root, axis);
- UI_solve_size_violations(root, axis);
-}
-
-root_function void UI_layout(void)
-{
- for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis+1))
- {
- UI_layout_root(ui_state->root, axis);
- }
-}
-
-////////////////////////////////
-//~ Compositions
-root_function void
-UI_push_pref_size(Axis2 axis, UI_Size v)
-{
- if(axis == Axis2_X)
- {
- UI_push_pref_width(v);
- }
- else
- {
- UI_push_pref_height(v);
- }
-}
-
-root_function void UI_pop_pref_size(Axis2 axis)
-{
- if(axis == Axis2_X)
- {
- UI_pop_pref_width();
- }
- else
- {
- UI_pop_pref_height();
- }
-}
-
-root_function void
-UI_set_next_pref_size(Axis2 axis, UI_Size v)
-{
- if(axis == Axis2_X)
- {
- UI_set_next_pref_width(v);
- }
- else
- {
- UI_set_next_pref_height(v);
- }
-}
-
-root_function void
-UI_push_fixed_pos(Vec2_F32 v)
-{
- UI_push_fixed_x(v.x);
- UI_push_fixed_y(v.y);
-}
-
-root_function void
-UI_pop_fixed_pos()
-{
- UI_pop_fixed_x();
- UI_pop_fixed_y();
-}
-
-root_function void
-UI_set_next_fixed_pos(Vec2_F32 v)
-{
- UI_set_next_fixed_x(v.x);
- UI_set_next_fixed_y(v.y);
-}
-
-root_function void
-UI_push_fixed_rect(Rng2_F32 rect)
-{
- Vec2_F32 dim = dim2_F32(rect);
- UI_push_fixed_pos(rect.p0);
- UI_push_pref_size(Axis2_X, UI_pixels(dim.x, 1));
- UI_push_pref_size(Axis2_Y, UI_pixels(dim.y, 1));
-}
-
-root_function void
-UI_pop_fixed_rect()
-{
- UI_pop_fixed_pos();
- UI_pop_pref_size(Axis2_X);
- UI_pop_pref_size(Axis2_Y);
-}
-
-root_function void
-UI_set_next_fixed_rect(Rng2_F32 rect)
-{
- Vec2_F32 dim = dim2_F32(rect);
- UI_set_next_fixed_pos(rect.p0);
- UI_set_next_pref_size(Axis2_X, UI_pixels(dim.x, 1));
- UI_set_next_pref_size(Axis2_Y, UI_pixels(dim.y, 1));
-}
-
-root_function Rng2_F32
-UI_push_rect(Rng2_F32 rect)
-{
- Rng2_F32 replaced = {0};
- Vec2_F32 size = dim2_F32(rect);
- replaced.x0 = UI_push_fixed_x(rect.x0);
- replaced.y0 = UI_push_fixed_y(rect.y0);
- replaced.x1 = replaced.x0 + UI_push_fixed_width(size.x);
- replaced.y1 = replaced.y0 + UI_push_fixed_height(size.y);
-
- return replaced;
-}
-
-root_function Rng2_F32
-UI_pop_rect(void)
-{
- Rng2_F32 popped = {0};
- popped.x0 = UI_pop_fixed_x();
- popped.y0 = UI_pop_fixed_y();
- popped.x1 = popped.x0 + UI_pop_fixed_width();
- popped.y1 = popped.y0 + UI_pop_fixed_height();
- return popped;
-}
-
-////////////////////////////////
-//~ Drawing and text
-root_function Vec2_F32
-UI_text_pos_from_box(UI_Box *box)
-{
- // The stb assumes that the supplied start position will give
- // the _BASELINE_ of the text that is to be produced.
- // So the text position we give here is adjusted to x of the box rect's p0,
- // and to the y of the box rect's p1.
- F32 offset_x_pixels = 0.1f*(box->rect.x1-box->rect.x0);
- F32 offset_y_pixels = 0.30*(box->rect.y1-box->rect.y0);
- Vec2_F32 result = {0};
- result.x = box->rect.x0 + offset_x_pixels;
- result.y = box->rect.y1 - offset_y_pixels;
-
- return result;
-}
-
-root_function String8
-UI_display_string_from_box(UI_Box *box)
-{
- return box->string;
-
-}
\ No newline at end of file
diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h
deleted file mode 100644
index 6c8a9d6..0000000
--- a/src/ui/ui_core.h
+++ /dev/null
@@ -1,402 +0,0 @@
-/* date = March 25th 2024 10:14 pm */
-
-#ifndef UI_CORE_H
-#define UI_CORE_H
-
-////////////////////////////////
-//~ Keys
-typedef enum UI_Color
-{
- UI_Color_Null,
- UI_Color_PlainBackground,
- UI_Color_PlainText,
- UI_Color_PlainBorder,
- UI_Color_PlainOverlay,
- UI_Color_COUNT
-} UI_Color;
-
-
-
-////////////////////////////////
-//~ Keys
-
-// The UI Key is used to hash a "widget" so we can get events from it.
-typedef struct UI_Key UI_Key;
-struct UI_Key
-{
- U64 u64[1];
-};
-
-////////////////////////////////
-//~ Mouse Button Kinds
-
-typedef enum UI_MouseButtonKind
-{
- UI_MouseButtonKind_Left,
- UI_MouseButtonKind_Middle,
- UI_MouseButtonKind_Right,
- UI_MouseButtonKind_COUNT
-}
-UI_MouseButtonKind;
-
-////////////////////////////////
-//~ Focus Types (for hot, active widget states)
-
-typedef enum UI_FocusKind
-{
- UI_FocusKind_Null,
- UI_FocusKind_Off,
- UI_FocusKind_On,
- UI_FocusKind_Root,
- UI_FocusKind_COUNT
-}
-UI_FocusKind;
-
-////////////////////////////////
-//~ Semantic sizes
-
-// The size kind specifies how the size of a box should be computed
-typedef enum UI_SizeKind
-{
- UI_SizeKind_Pixels,
- UI_SizeKind_TextDim,
- UI_SizeKind_Percent,
- UI_SizeKind_SizeByChildren,
- UI_SizeKind_COUNT
-}
-UI_SizeKind;
-
-typedef struct UI_Size UI_Size;
-struct UI_Size
-{
- UI_SizeKind kind;
- F32 value;
- F32 strictness;
-};
-
-////////////////////////////////
-//~ Main UI hierarchy
-
-typedef enum UI_TextAlignment
-{
- UI_TextAlignment_Left,
- UI_TextAlignment_COUNT,
-}
-UI_TextAlignment;
-
-typedef U32 UI_BoxFlags;
-enum
-{
- // Interaction
- UI_BoxFlag_Disabled = (1<<0),
- UI_BoxFlag_MouseClickable = (1<<1),
- UI_BoxFlag_FocusHot = (1<<3),
- UI_BoxFlag_FocusActive = (1<<4),
-
- // Layout
- UI_BoxFlag_FloatingX = (1<<5),
- UI_BoxFlag_FloatingY = (1<<6),
- UI_BoxFlag_FixedWidth = (1<<7),
- UI_BoxFlag_FixedHeight = (1<<8),
- UI_BoxFlag_OverflowX = (1<<9),
- UI_BoxFlag_OverflowY = (1<<10),
-
- // Appearance
- UI_BoxFlag_Clip = (1<<11),
- UI_BoxFlag_DrawText = (1<<12),
- UI_BoxFlag_DrawBackground = (1<<13),
- UI_BoxFlag_DrawBorder = (1<<14),
- UI_BoxFlag_DrawHotEffects = (1<<15),
- UI_BoxFlag_DrawActiveEffects = (1<<16),
- UI_BoxFlag_DisableTextTruncate = (1<<17),
- UI_BoxFlag_DrawDropShadow = (1<<18),
-
- // Helpers, when either X or Y is active etc.
- UI_BoxFlag_Floating = UI_BoxFlag_FloatingX | UI_BoxFlag_FloatingY,
- UI_BoxFlag_Clickable = UI_BoxFlag_MouseClickable, //| UI_BoxFlag_KeyboardClickable,
-};
-
-// UI Box is the big struct that handles all of the information of a "node" in the ui hierarchy.
-// The box is a part of the composition that can be described as a "widget".
-// It has both the tree information adn the state information in it.
-typedef struct UI_Box UI_Box;
-struct UI_Box
-{
- // Hash links, persistent across frames
- UI_Box *hash_next;
- UI_Box *hash_prev;
-
- // Tree link data, updates every frame.
- // This enables us to encode an n-ary tree to describe the "box" hierarchy that defines the UI.
- UI_Box *first;
- UI_Box *last;
- UI_Box *next;
- UI_Box *prev;
- UI_Box *parent;
- U64 child_count;
-
- // Key and generation info
- UI_Key key;
- U64 last_frame_touched_index;
-
- // Per-build parameters
- UI_BoxFlags flags;
- String8 string;
- Vec2_F32 fixed_position;
- Vec2_F32 fixed_size;
- UI_Size pref_size[Axis2_COUNT];
- Axis2 child_layout_axis;
-
- Vec4_F32 background_color;
- Vec4_F32 text_color;
- Vec4_F32 border_color;
- Vec4_F32 overlay_color;
- F32 corner_radii[Corner_COUNT];
-
- // Post size determination
- Vec2_F32 calc_size;
- Vec2_F32 calc_rel_pos;
-
- // Post-layout data
- Rng2_F32 rel_rect;
- Rng2_F32 rect;
-
- // State that is persistent across frames
- F32 hot_t;
- F32 active_t;
- F32 disabled_t;
- F32 focus_hot_t;
- F32 focus_active_t;
- U64 first_gen_touched;
- U64 last_gen_touched;
- Vec2_F32 view_offset;
- Vec2_F32 target_view_offset;
-
-
-
-};
-
-typedef struct UI_BoxRec UI_BoxRec;
-struct UI_BoxRec
-{
- UI_Box *next;
- S32 push_count;
- S32 pop_count;
-};
-
-
-//~ Signal
-typedef U32 UI_SignalFlags;
-enum
-{
- // mouse press -> box was pressed while hovering
- UI_SignalFlag_LeftPressed = (1<<0),
- UI_SignalFlag_MiddlePressed = (1<<1),
- UI_SignalFlag_RightPressed = (1<<2),
-
- // released -> box was previously pressed & user released, in or out of bounds
- UI_SignalFlag_LeftReleased = (1<<12),
- UI_SignalFlag_MiddleReleased = (1<<13),
- UI_SignalFlag_RightReleased = (1<<14),
-
- // clicked -> box was previously pressed & user released, in bounds
- UI_SignalFlag_LeftClicked = (1<<15),
- UI_SignalFlag_MiddleClicked = (1<<16),
- UI_SignalFlag_RightClicked = (1<<17),
-
- UI_SignalFlag_Hovering = (1<<25), // hovering specifically this box
- UI_SignalFlag_MouseOver = (1<<26), // mouse is over, but may be occluded
-
- UI_SignalFlag_Pressed = UI_SignalFlag_LeftPressed | UI_SignalFlag_MiddlePressed | UI_SignalFlag_RightPressed,
- UI_SignalFlag_Clicked = UI_SignalFlag_LeftClicked | UI_SignalFlag_MiddleClicked | UI_SignalFlag_RightClicked
-};
-
-// The UI Signal is the struct which carries the information about user interaction with a box
-typedef struct UI_Signal UI_Signal;
-struct UI_Signal
-{
- UI_Box *box;
- UI_SignalFlags flag;
-};
-
-#define UI_hovering(s) !!((s).flag & UI_SignalFlag_Hovering)
-#define UI_pressed(s) !!((s).flag & UI_SignalFlag_Pressed)
-/////////////////////////////////
-//~ Generated/meta
-
-// This is "metaprogramming" code that eventually will be generated externally.
-// Right now I am doing some thing by hand, but it basically contains macros that define
-// different stack members for the UI state.
-#include "ui_meta.h"
-
-
-////////////////////////////////
-//~ UI State
-
-// This is a slot in the hash table that helps caching of UI boxes between frames.
-typedef struct UI_BoxSlot UI_BoxSlot;
-struct UI_BoxSlot
-{
- UI_Box *first;
- UI_Box *last;
-};
-
-typedef struct UI_State UI_State;
-struct UI_State
-{
- // Permanent state
- U64 build_gen;
- Arena *arena;
-
- // Frame arenas. We have two since we want to use information from the previous frame to
- // compute things in the current frame.
- U32 last_frame_arena_index;
- U32 current_frame_arena_index;
- Arena *frame_arenas[2];
-
- //- Persistent box state
- UI_Box *first_free_box;
- U64 free_box_list_count;
- UI_BoxSlot *box_table;
- U64 box_table_size;
-
- //- Per UI build parameters
- OS_Handle window;
- OS_EventList *events;
- UI_Box *root;
- UI_Box *ctx_menu_root;
- B32 ctx_menu_touched_this_frame;
- Vec2_F32 mouse;
-
- //- User interaction state
- UI_Key hot_box_key;
- UI_Key active_box_key[UI_MouseButtonKind_COUNT];
-
- //- Color, rendering properties
- Vec4_F32 colors[UI_Color_COUNT];
-
- //- Context menu state
- UI_Key ctx_menu_anchor_key;
- UI_Key next_ctx_menu_anchor_key;
- Vec2_F32 ctx_menu_anchor_box_last_pos;
- Vec2_F32 ctx_menu_anchor_offset;
- B32 ctx_menu_open;
- B32 next_ctx_menu_open;
- UI_Key ctx_menu_key;
- B32 ctx_menu_changed;
-
- // TODO(anton): tooltip root
-
- // Stack state. Here Ryan uses generated code from metadesk. I will do it by hand to start with.
- UI_declare_stack_nils;
- UI_declare_stacks;
-};
-
-////////////////////////////////
-//~ Globals
-
-// Nil structs
-
-global UI_Box ui_g_nil_box;
-
-////////////////////////////////
-//~ Basic type functions
-
-//- Boxes
-root_function B32 UI_box_is_nil(UI_Box *box);
-#define UI_box_set_nil(b) ((b) = &ui_g_nil_box)
-
-root_function UI_BoxRec UI_box_recurse_depth_first(UI_Box *box, UI_Box *stopper, MemberOffset sib, MemberOffset child);
-#define UI_box_recurse_depth_first_post(box, stopper) UI_box_recurse_depth_first((box), (stopper), MemberOff(UI_Box, prev), MemberOff(UI_Box, last));
-
-//- Sizes
-root_function UI_Size UI_size_make(UI_SizeKind kind, F32 value, F32 strictness);
-#define UI_pixels(v, strictness) UI_size_make(UI_SizeKind_Pixels, (v), (strictness))
-#define UI_size_by_children(v, strictness) UI_size_make(UI_SizeKind_SizeByChildren, (v), (strictness))
-#define UI_pct(v, strictness) UI_size_make(UI_SizeKind_Percent, (v), (strictness))
-
-//- ID strings
-root_function String8 UI_hash_part_from_box_string(String8 string);
-
-//- Keys
-root_function UI_Key UI_key_zero(void);
-root_function UI_Key UI_key_from_string(UI_Key seed, String8 string);
-root_function B32 UI_key_match(UI_Key a, UI_Key b);
-
-//- Signal
-root_function UI_Signal UI_signal_from_box(UI_Box *box);
-
-
-////////////////////////////////
-//~ UI State functions
-root_function UI_State *UI_state_alloc(void);
-root_function void UI_state_set(UI_State *ui);
-
-////////////////////////////////
-//~ Build phase
-root_function void UI_build_begin(OS_Handle window, OS_EventList *events);
-root_function void UI_build_end(void);
-
-////////////////////////////////
-//~ Context menu
-root_function void UI_ctx_menu_open(UI_Key key, UI_Key anchor_key, Vec2_F32 anchor_offset);
-root_function void UI_ctx_menu_close(void);
-root_function B32 UI_begin_ctx_menu(UI_Key key);
-root_function void UI_end_ctx_menu(void);
-
-////////////////////////////////
-//~ UI Frame
-root_function Arena *UI_frame_arena(void);
-root_function void UI_frame_begin(F32 delta_time);
-root_function void UI_frame_end(void);
-
-////////////////////////////////
-//~ Box hierarchy construction
-root_function UI_Box *UI_box_from_key(UI_Key key);
-root_function UI_Box *UI_box_make_from_key(UI_BoxFlags flags, UI_Key key);
-root_function UI_Box *UI_box_make(UI_BoxFlags flags, String8 string);
-
-////////////////////////////////
-//~ layout
-root_function void UI_solve_independent_sizes(UI_Box *root, Axis2 axis);
-root_function void UI_solve_upward_dependent_sizes(UI_Box *root, Axis2 axis);
-root_function void UI_solve_downward_dependent_sizes(UI_Box *root, Axis2 axis);
-root_function void UI_solve_size_violations(UI_Box *root, Axis2 axis);
-root_function void UI_layout_root(UI_Box *root, Axis2 axis);
-root_function void UI_layout(void);
-
-////////////////////////////////
-//~ Compositions
-root_function void UI_push_pref_size(Axis2 axis, UI_Size v);
-root_function void UI_pop_pref_size(Axis2 axis);
-root_function void UI_set_next_pref_size(Axis2 axis, UI_Size v);
-root_function void UI_push_fixed_pos(Vec2_F32 v);
-root_function void UI_pop_fixed_pos();
-root_function void UI_set_next_fixed_pos(Vec2_F32 v);
-root_function void UI_push_fixed_rect(Rng2_F32 rect);
-root_function void UI_pop_fixed_rect();
-root_function void UI_set_next_fixed_rect(Rng2_F32 rect);
-
-
-////////////////////////////////
-//~ Drawing and text
-root_function Vec2_F32 UI_text_pos_from_box(UI_Box *box);
-root_function String8 UI_display_string_from_box(UI_Box *box);
-////////////////////////////////
-//~ Defer helpers
-
-//- base
-#define UI_parent(v) DeferLoop(UI_push_parent(v), UI_pop_parent())
-#define UI_pref_width(v) DeferLoop(UI_push_pref_width(v), UI_pop_pref_width())
-#define UI_pref_height(v) DeferLoop(UI_push_pref_height(v), UI_pop_pref_height())
-
-//- pane
-#define UI_pane(r, s) DeferLoop(UI_pane_begin((r), (s)), UI_pane_end())
-//- compositions
-#define UI_width_fill UI_pref_width(UI_pct(1, 0))
-#define UI_height_fill UI_pref_height(UI_pct(1, 0))
-#define UI_fixed_x(v) DeferLoop(UI_push_fixed_x((v)), UI_pop_fixed_x())
-#define UI_fixed_y(v) DeferLoop(UI_push_fixed_y((v)), UI_pop_fixed_y())
-#define UI_fixed_pos(v) DeferLoop(UI_push_fixed_pos(v), UI_pop_fixed_pos())
-#define UI_ctx_menu(key) DeferLoopChecked(UI_begin_ctx_menu(key), UI_end_ctx_menu())
-#endif //UI_CORE_H
diff --git a/src/ui/ui_draw.c b/src/ui/ui_draw.c
deleted file mode 100644
index ac9019a..0000000
--- a/src/ui/ui_draw.c
+++ /dev/null
@@ -1,92 +0,0 @@
-
-root_function void
-UI_draw(void)
-{
-
-
- //OS_Handle window = ui_state->window;
- for(UI_Box *box = ui_state->root, *next_box = &ui_g_nil_box; !UI_box_is_nil(box); box = next_box)
- {
- // We do a depth first recursion to go through the nodes.
- // The post part means that the sibling is UI_Box prev, and the child is UI_Box last.
- // TODO(anton): Draw this with pen and paper and make sure I understand how this works
- UI_BoxRec rec = UI_box_recurse_depth_first_post(box, &ui_g_nil_box);
- next_box = rec.next;
-
- //- Draw shadow
- if(box->flags & UI_BoxFlag_DrawDropShadow)
- {
- F32 shift = 3.0f; // TODO make relative precent, is pixelsn ow
- Rng2_F32 shadow_rect = shift2_F32(pad2_F32(box->rect, 2), vec2_F32(shift, shift));
-
-
- R_Rect2DInst *rect = D_rect2D(shadow_rect,
- .color = vec4_F32(0, 0, 0, 1.f),
- .corner_radius = 1,
- .softness = 3.f,
- .omit_texture = 1);
- }
-
- //- Draw background
- if(box->flags & UI_BoxFlag_DrawBackground)
- {
-
- R_Rect2DInst *rect = D_rect2D(box->rect,
- .color = box->background_color,
- .corner_radius = 0.0f,
- .softness = 0.0f,
- .omit_texture = 1);
-
- if(box->flags & UI_BoxFlag_DrawHotEffects)
- {
- if(UI_key_match(ui_state->hot_box_key, box->key))
- {
-
- rect->colors[Corner_00] = box->overlay_color;
- rect->colors[Corner_10] = box->overlay_color;
- rect->colors[Corner_01] = box->background_color;
- rect->colors[Corner_11] = box->background_color;
- }
- }
-
- }
-
- //- Draw text
- if(box->flags & UI_BoxFlag_DrawText)
- {
- // The stb assumes that the supplied start position will give
- // the _BASELINE_ of the text that is to be produced.
- // So the text position we give here is adjusted to x of the box rect's p0,
- // and to the y of the box rect's p1.
- Vec2_F32 text_pos = UI_text_pos_from_box(box);
- String8 display_string = UI_display_string_from_box(box);
- B32 truncated = 0;
- if(!(box->flags & UI_BoxFlag_DisableTextTruncate))
- {
- // TODO(anton): Do stuff for truncating
- D_text2D(text_pos, display_string, box->text_color);
- }
- }
-
- //- Draw border
- if(box->flags & UI_BoxFlag_DrawBorder)
- {
- Rng2_F32 border_rect = pad2_F32(box->rect, 0);
- R_Rect2DInst *rect = D_rect2D(border_rect);
- Vec4_F32 border_top_color = box->border_color;
- Vec4_F32 border_bot_color = box->background_color;
- rect->colors[Corner_00] = border_top_color;
- rect->colors[Corner_10] = border_top_color;
- rect->colors[Corner_01] = border_bot_color;
- rect->colors[Corner_11] = border_bot_color;
- rect->corner_radii[Corner_00] = 1;
- rect->corner_radii[Corner_10] = 1;
- rect->corner_radii[Corner_01] = 1;
- rect->corner_radii[Corner_11] = 1;
- rect->border_thickness = 1.f;
- rect->softness = 0.f;
- rect->omit_texture = 1;
- }
-
- }
-}
diff --git a/src/ui/ui_draw.h b/src/ui/ui_draw.h
deleted file mode 100644
index 83cdc0d..0000000
--- a/src/ui/ui_draw.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* date = April 2nd 2024 3:11 pm */
-
-#ifndef UI_DRAW_H
-#define UI_DRAW_H
-root_function void UI_draw(void);
-#endif //UI_DRAW_H
diff --git a/src/ui/ui_inc.c b/src/ui/ui_inc.c
deleted file mode 100644
index 5aafb17..0000000
--- a/src/ui/ui_inc.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "ui_core.c"
-#include "ui_basic_widgets.c"
-#include "ui_draw.c"
diff --git a/src/ui/ui_inc.h b/src/ui/ui_inc.h
deleted file mode 100644
index 1300ca0..0000000
--- a/src/ui/ui_inc.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* date = March 25th 2024 10:14 pm */
-
-#ifndef UI_INC_H
-#define UI_INC_H
-
-#include "ui_core.h"
-#include "ui_basic_widgets.h"
-#include "ui_draw.h"
-
-#endif //UI_INC_H
diff --git a/src/ui/ui_meta.c b/src/ui/ui_meta.c
deleted file mode 100644
index 3314d0b..0000000
--- a/src/ui/ui_meta.c
+++ /dev/null
@@ -1,108 +0,0 @@
-// TODO(anton): This code should be generated by some metaprogram at some point.
-
-
-// Macro that generalises the code for setting the next implementation on
-// a particular stack.
-// The convention is that a node type has UI_Node,
-// and the corresponding stack struct in the UI state has a top pointer, a free pointer and an auto_pop B32 value.
-// And that struct is called _stack.
-// The nodes have values of different types, which the argument to this macro designates.
-// A ParentNode, for example, has a UI_Box *value, and the PrefWidth has a UI_Size value.
-#define UI_stack_top_impl(state, name_upper, name_lower) \
-return state->name_lower##_stack.top->v;
-
-#define UI_stack_push_impl(state, name_upper, name_lower, type, new_value) \
-UI_##name_upper##Node *node = state->name_lower##_stack.free; \
-if(node != 0) {StackPop(state->name_lower##_stack.free);} \
-else {node = PushArrayZero(UI_frame_arena(), UI_##name_upper##Node, 1);} \
-type old_value = state->name_lower##_stack.top->v; \
-node->v = new_value; \
-StackPush(state->name_lower##_stack.top, node); \
-state->name_lower##_stack.auto_pop = 0; \
-return old_value;
-
-#define UI_stack_pop_impl(state, name_upper, name_lower) \
-UI_##name_upper##Node *popped = state->name_lower##_stack.top;\
-if(popped != &state->name_lower##_nil_stack_top)\
-{\
-StackPop(state->name_lower##_stack.top);\
-StackPush(state->name_lower##_stack.free, popped);\
-state->name_lower##_stack.auto_pop = 0;\
-}\
-return popped->v;\
-
-// NOTE(anton): Only difference from push is auto pop = 1?
-#define UI_stack_set_next_impl(state, name_upper, name_lower, type, new_value) \
-UI_##name_upper##Node *node = state->name_lower##_stack.free; \
-if(node != 0) {StackPop(state->name_lower##_stack.free);}\
-else {node = PushArray(UI_frame_arena(), UI_##name_upper##Node, 1);}\
-type old_value = state->name_lower##_stack.top->v;\
-node->v = new_value;\
-StackPush(state->name_lower##_stack.top, node);\
-state->name_lower##_stack.auto_pop = 1;\
-return old_value;
-
-
-///////////////////////////////////////
-//~ Stack functions
-
-//- Top
-root_function UI_Box *UI_top_parent(void) { UI_stack_top_impl(ui_state, Parent, parent) }
-root_function UI_BoxFlags UI_top_flags(void) { UI_stack_top_impl(ui_state, Flags, flags) }
-root_function F32 UI_top_fixed_x(void) { UI_stack_top_impl(ui_state, FixedX, fixed_x) }
-root_function F32 UI_top_fixed_y(void) { UI_stack_top_impl(ui_state, FixedY, fixed_y) }
-root_function F32 UI_top_fixed_width(void) { UI_stack_top_impl(ui_state, FixedWidth, fixed_width) }
-root_function F32 UI_top_fixed_height(void) { UI_stack_top_impl(ui_state, FixedHeight, fixed_height) }
-root_function UI_Key UI_top_seed_key(void) { UI_stack_top_impl(ui_state, SeedKey, seed_key) }
-root_function UI_Size UI_top_pref_width(void) { UI_stack_top_impl(ui_state, PrefWidth, pref_width) }
-root_function UI_Size UI_top_pref_height(void) { UI_stack_top_impl(ui_state, PrefHeight, pref_height) }
-root_function Axis2 UI_top_child_layout_axis(void) { UI_stack_top_impl(ui_state, ChildLayoutAxis, child_layout_axis) }
-
-//- Push
-root_function UI_Box *UI_push_parent(UI_Box *v) { UI_stack_push_impl(ui_state, Parent, parent, UI_Box *, v) }
-root_function UI_BoxFlags UI_push_flags(UI_BoxFlags v) { UI_stack_push_impl(ui_state, Flags, flags, UI_BoxFlags, v) }
-root_function F32 UI_push_fixed_x(F32 v) { UI_stack_push_impl(ui_state, FixedX, fixed_x, F32, v) }
-root_function F32 UI_push_fixed_y(F32 v) { UI_stack_push_impl(ui_state, FixedY, fixed_y, F32, v) }
-root_function F32 UI_push_fixed_width(F32 v) { UI_stack_push_impl(ui_state, FixedWidth, fixed_width, F32, v) }
-root_function F32 UI_push_fixed_height(F32 v) { UI_stack_push_impl(ui_state, FixedHeight, fixed_height, F32, v) }
-root_function UI_Key UI_push_seed_key(UI_Key v) { UI_stack_push_impl(ui_state, SeedKey, seed_key, UI_Key, v) }
-root_function UI_Size UI_push_pref_width(UI_Size v) { UI_stack_push_impl(ui_state, PrefWidth, pref_width, UI_Size, v) }
-root_function UI_Size UI_push_pref_height(UI_Size v) { UI_stack_push_impl(ui_state, PrefHeight, pref_height, UI_Size, v) }
-root_function Axis2 UI_push_child_layout_axis(Axis2 v) { UI_stack_push_impl(ui_state, ChildLayoutAxis, child_layout_axis, Axis2, v) }
-
-//- Pop
-root_function UI_Box *UI_pop_parent(void) { UI_stack_pop_impl(ui_state, Parent, parent) }
-root_function UI_BoxFlags UI_pop_flags(void) { UI_stack_pop_impl(ui_state, Flags, flags) }
-root_function F32 UI_pop_fixed_x(void) { UI_stack_pop_impl(ui_state, FixedX, fixed_x) }
-root_function F32 UI_pop_fixed_y(void) { UI_stack_pop_impl(ui_state, FixedY, fixed_y) }
-root_function F32 UI_pop_fixed_width(void) { UI_stack_pop_impl(ui_state, FixedWidth, fixed_width) }
-root_function F32 UI_pop_fixed_height(void) { UI_stack_pop_impl(ui_state, FixedHeight, fixed_height) }
-root_function UI_Key UI_pop_seed_key(void) { UI_stack_pop_impl(ui_state, SeedKey, seed_key) }
-root_function UI_Size UI_pop_pref_width(void) { UI_stack_pop_impl(ui_state, PrefWidth, pref_width) }
-root_function UI_Size UI_pop_pref_height(void) { UI_stack_pop_impl(ui_state, PrefHeight, pref_height) }
-root_function Axis2 UI_pop_child_layout_axis(void) { UI_stack_pop_impl(ui_state, ChildLayoutAxis, child_layout_axis) }
-
-//- Set next
-root_function UI_Box *UI_set_next_parent(UI_Box *v) { UI_stack_set_next_impl(ui_state, Parent, parent, UI_Box *, v) }
-root_function UI_BoxFlags UI_set_next_flags(UI_BoxFlags v) { UI_stack_set_next_impl(ui_state, Flags, flags, UI_BoxFlags, v) }
-root_function F32 UI_set_next_fixed_x(F32 v) { UI_stack_set_next_impl(ui_state, FixedX, fixed_x, F32, v) }
-root_function F32 UI_set_next_fixed_y(F32 v) { UI_stack_set_next_impl(ui_state, FixedY, fixed_y, F32, v) }
-root_function F32 UI_set_next_fixed_width(F32 v) { UI_stack_set_next_impl(ui_state, FixedWidth, fixed_width, F32, v) }
-root_function F32 UI_set_next_fixed_height(F32 v) { UI_stack_set_next_impl(ui_state, FixedHeight, fixed_height, F32, v) }
-root_function UI_Key UI_set_next_seed_key(UI_Key v) { UI_stack_set_next_impl(ui_state, SeedKey, seed_key, UI_Key, v) }
-root_function UI_Size UI_set_next_pref_width(UI_Size v) { UI_stack_set_next_impl(ui_state, PrefWidth, pref_width, UI_Size, v) }
-root_function UI_Size UI_set_next_pref_height(UI_Size v) { UI_stack_set_next_impl(ui_state, PrefHeight, pref_height, UI_Size, v) }
-root_function Axis2 UI_set_next_child_layout_axis(Axis2 v) { UI_stack_set_next_impl(ui_state, ChildLayoutAxis, child_layout_axis, Axis2, v) }
-
-#define UI_auto_pop_stacks(state) \
-if(state->parent_stack.auto_pop) { UI_pop_parent(); state->parent_stack.auto_pop = 0; }\
-if(state->flags_stack.auto_pop) { UI_pop_flags(); state->flags_stack.auto_pop = 0; }\
-if(state->fixed_x_stack.auto_pop) { UI_pop_fixed_x(); state->fixed_x_stack.auto_pop = 0; }\
-if(state->fixed_y_stack.auto_pop) { UI_pop_fixed_y(); state->fixed_y_stack.auto_pop = 0; }\
-if(state->fixed_x_stack.auto_pop) { UI_pop_fixed_width(); state->fixed_width_stack.auto_pop = 0; }\
-if(state->fixed_y_stack.auto_pop) { UI_pop_fixed_height(); state->fixed_height_stack.auto_pop = 0; }\
-if(state->seed_key_stack.auto_pop) { UI_pop_seed_key(); state->seed_key_stack.auto_pop = 0; }\
-if(state->pref_width_stack.auto_pop) { UI_pop_pref_width(); state->pref_width_stack.auto_pop = 0; }\
-if(state->pref_height_stack.auto_pop) { UI_pop_pref_height(); state->pref_height_stack.auto_pop = 0; }\
-if(state->child_layout_axis_stack.auto_pop) { UI_pop_child_layout_axis(); state->child_layout_axis_stack.auto_pop = 0; }\
-
diff --git a/src/ui/ui_meta.h b/src/ui/ui_meta.h
deleted file mode 100644
index 58e0d06..0000000
--- a/src/ui/ui_meta.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* date = April 1st 2024 9:04 pm */
-
-#ifndef UI_META_H
-#define UI_META_H
-
-// TODO(anton): This code should be generated by a metaprogram at some point.
-
-//~ Node structs
-
-typedef struct UI_ParentNode UI_ParentNode; struct UI_ParentNode{UI_ParentNode *next; UI_Box * v;};
-typedef struct UI_FlagsNode UI_FlagsNode; struct UI_FlagsNode{UI_FlagsNode *next; UI_BoxFlags v;};
-typedef struct UI_FixedXNode UI_FixedXNode; struct UI_FixedXNode{UI_FixedXNode *next; F32 v;};
-typedef struct UI_FixedYNode UI_FixedYNode; struct UI_FixedYNode{UI_FixedYNode *next; F32 v;};
-typedef struct UI_FixedWidthNode UI_FixedWidthNode; struct UI_FixedWidthNode{UI_FixedWidthNode *next; F32 v;};
-typedef struct UI_FixedHeightNode UI_FixedHeightNode; struct UI_FixedHeightNode{UI_FixedHeightNode *next; F32 v;};
-typedef struct UI_PrefWidthNode UI_PrefWidthNode; struct UI_PrefWidthNode{UI_PrefWidthNode *next; UI_Size v;};
-typedef struct UI_PrefHeightNode UI_PrefHeightNode; struct UI_PrefHeightNode{UI_PrefHeightNode *next; UI_Size v;};
-typedef struct UI_ChildLayoutAxisNode UI_ChildLayoutAxisNode; struct UI_ChildLayoutAxisNode{UI_ChildLayoutAxisNode *next; Axis2 v;};
-typedef struct UI_SeedKeyNode UI_SeedKeyNode; struct UI_SeedKeyNode{UI_SeedKeyNode *next; UI_Key v;};
-
-
-//~ Declaration macros for use in the UI_State
-
-//- Stacks
-#define UI_declare_stacks \
-struct \
-{ \
-struct { UI_ParentNode *top; UI_ParentNode *free; B32 auto_pop; } parent_stack; \
-struct { UI_FlagsNode *top; UI_FlagsNode *free; B32 auto_pop; } flags_stack; \
-struct { UI_FixedXNode *top; UI_FixedXNode *free; B32 auto_pop; } fixed_x_stack; \
-struct { UI_FixedYNode *top; UI_FixedYNode *free; B32 auto_pop; } fixed_y_stack; \
-struct { UI_FixedWidthNode *top; UI_FixedWidthNode *free; B32 auto_pop; } fixed_width_stack; \
-struct { UI_FixedHeightNode *top; UI_FixedHeightNode *free; B32 auto_pop; } fixed_height_stack; \
-struct { UI_PrefWidthNode *top; UI_PrefWidthNode *free; B32 auto_pop; } pref_width_stack; \
-struct { UI_PrefHeightNode *top; UI_PrefHeightNode *free; B32 auto_pop; } pref_height_stack; \
-struct { UI_ChildLayoutAxisNode *top; UI_ChildLayoutAxisNode *free; B32 auto_pop; } child_layout_axis_stack; \
-struct { UI_SeedKeyNode *top; UI_SeedKeyNode *free; B32 auto_pop; } seed_key_stack; \
-}
-
-#define UI_init_stacks(state) \
-state->parent_stack.top = &state->parent_nil_stack_top; state->parent_stack.free = 0; state->parent_stack.auto_pop = 0; \
-state->flags_stack.top = &state->flags_nil_stack_top; state->flags_stack.free = 0; state->flags_stack.auto_pop = 0; \
-state->fixed_x_stack.top = &state->fixed_x_nil_stack_top; state->fixed_x_stack.free = 0; state->fixed_x_stack.auto_pop = 0;\
-state->fixed_y_stack.top = &state->fixed_y_nil_stack_top; state->fixed_y_stack.free = 0; state->fixed_y_stack.auto_pop = 0;\
-state->fixed_width_stack.top = &state->fixed_width_nil_stack_top; state->fixed_width_stack.free = 0; state->fixed_width_stack.auto_pop = 0;\
-state->fixed_height_stack.top = &state->fixed_height_nil_stack_top; state->fixed_height_stack.free = 0; state->fixed_height_stack.auto_pop = 0;\
-state->pref_width_stack.top = &state->pref_width_nil_stack_top; state->pref_width_stack.free = 0; state->pref_width_stack.auto_pop = 0; \
-state->pref_height_stack.top = &state->pref_height_nil_stack_top; state->pref_height_stack.free = 0; state->pref_height_stack.auto_pop = 0; \
-state->child_layout_axis_stack.top = &state->child_layout_axis_nil_stack_top; state->child_layout_axis_stack.free = 0; state->child_layout_axis_stack.auto_pop = 0; \
-state->seed_key_stack.top = &state->seed_key_nil_stack_top; state->seed_key_stack.free = 0; state->seed_key_stack.auto_pop = 0; \
-
-
-//- Stack nils
-#define UI_declare_stack_nils \
-struct \
-{ \
-UI_ParentNode parent_nil_stack_top; \
-UI_FlagsNode flags_nil_stack_top; \
-UI_FixedXNode fixed_x_nil_stack_top; \
-UI_FixedYNode fixed_y_nil_stack_top; \
-UI_FixedWidthNode fixed_width_nil_stack_top; \
-UI_FixedHeightNode fixed_height_nil_stack_top; \
-UI_PrefWidthNode pref_width_nil_stack_top; \
-UI_PrefHeightNode pref_height_nil_stack_top; \
-UI_ChildLayoutAxisNode child_layout_axis_nil_stack_top; \
-UI_SeedKeyNode seed_key_nil_stack_top; \
-}
-#define UI_init_stack_nils(state) \
-state->parent_nil_stack_top.v = &ui_g_nil_box; \
-state->flags_nil_stack_top.v = 0; \
-state->fixed_x_nil_stack_top.v = 0; \
-state->fixed_y_nil_stack_top.v = 0; \
-state->fixed_width_nil_stack_top.v = 0; \
-state->fixed_height_nil_stack_top.v = 0; \
-state->pref_width_nil_stack_top.v = UI_pixels(200.f, 1.f); \
-state->pref_height_nil_stack_top.v = UI_pixels(2.f, 1.f); \
-state->child_layout_axis_nil_stack_top.v = Axis2_X;\
-state->seed_key_nil_stack_top.v = UI_key_zero(); \
-
-#endif //UI_META_H